1 /////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/grid.cpp 
   3 // Purpose:     wxGrid and related classes 
   4 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn) 
   5 // Modified by: Robin Dunn, Vadim Zeitlin 
   8 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "grid.h" 
  24 // For compilers that support precompilatixon, includes "wx/wx.h". 
  25 #include "wx/wxprec.h" 
  35 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID) 
  37 #else // wxUSE_NEW_GRID 
  41     #include "wx/dcclient.h" 
  42     #include "wx/settings.h" 
  44     #include "wx/textctrl.h" 
  45     #include "wx/checkbox.h" 
  46     #include "wx/combobox.h" 
  47     #include "wx/valtext.h" 
  50 #include "wx/textfile.h" 
  51 #include "wx/spinctrl.h" 
  52 #include "wx/tokenzr.h" 
  55 #include "wx/generic/gridsel.h" 
  57 #if defined(__WXMOTIF__) 
  58     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier) 
  60     #define WXUNUSED_MOTIF(identifier)  identifier 
  63 #if defined(__WXGTK__) 
  64     #define WXUNUSED_GTK(identifier)    WXUNUSED(identifier) 
  66     #define WXUNUSED_GTK(identifier)    identifier 
  69 // Required for wxIs... functions 
  72 // ---------------------------------------------------------------------------- 
  74 // ---------------------------------------------------------------------------- 
  76 WX_DEFINE_EXPORTED_ARRAY(wxGridCellAttr 
*, wxArrayAttrs
); 
  78 struct wxGridCellWithAttr
 
  80     wxGridCellWithAttr(int row
, int col
, wxGridCellAttr 
*attr_
) 
  81         : coords(row
, col
), attr(attr_
) 
  90     wxGridCellCoords coords
; 
  94 WX_DECLARE_EXPORTED_OBJARRAY(wxGridCellWithAttr
, wxGridCellWithAttrArray
); 
  96 #include "wx/arrimpl.cpp" 
  98 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
) 
  99 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
) 
 101 // ---------------------------------------------------------------------------- 
 103 // ---------------------------------------------------------------------------- 
 105 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
) 
 106 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
) 
 107 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
) 
 108 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
) 
 109 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
) 
 110 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
) 
 111 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
) 
 112 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
) 
 113 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
) 
 114 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
) 
 115 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
) 
 116 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
) 
 117 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
) 
 118 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
) 
 119 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
) 
 120 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
) 
 122 // ---------------------------------------------------------------------------- 
 124 // ---------------------------------------------------------------------------- 
 126 class WXDLLEXPORT wxGridRowLabelWindow 
: public wxWindow
 
 129     wxGridRowLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 130     wxGridRowLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 131                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 136     void OnPaint( wxPaintEvent
& event 
); 
 137     void OnMouseEvent( wxMouseEvent
& event 
); 
 138     void OnMouseWheel( wxMouseEvent
& event 
); 
 139     void OnKeyDown( wxKeyEvent
& event 
); 
 140     void OnKeyUp( wxKeyEvent
& ); 
 142     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
) 
 143     DECLARE_EVENT_TABLE() 
 147 class WXDLLEXPORT wxGridColLabelWindow 
: public wxWindow
 
 150     wxGridColLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 151     wxGridColLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 152                           const wxPoint 
&pos
, const wxSize 
&size 
); 
 157     void OnPaint( wxPaintEvent 
&event 
); 
 158     void OnMouseEvent( wxMouseEvent
& event 
); 
 159     void OnMouseWheel( wxMouseEvent
& event 
); 
 160     void OnKeyDown( wxKeyEvent
& event 
); 
 161     void OnKeyUp( wxKeyEvent
& ); 
 163     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
) 
 164     DECLARE_EVENT_TABLE() 
 168 class WXDLLEXPORT wxGridCornerLabelWindow 
: public wxWindow
 
 171     wxGridCornerLabelWindow() { m_owner 
= (wxGrid 
*)NULL
; } 
 172     wxGridCornerLabelWindow( wxGrid 
*parent
, wxWindowID id
, 
 173                              const wxPoint 
&pos
, const wxSize 
&size 
); 
 178     void OnMouseEvent( wxMouseEvent
& event 
); 
 179     void OnMouseWheel( wxMouseEvent
& event 
); 
 180     void OnKeyDown( wxKeyEvent
& event 
); 
 181     void OnKeyUp( wxKeyEvent
& ); 
 182     void OnPaint( wxPaintEvent
& event 
); 
 184     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
) 
 185     DECLARE_EVENT_TABLE() 
 188 class WXDLLEXPORT wxGridWindow 
: public wxWindow
 
 193         m_owner 
= (wxGrid 
*)NULL
; 
 194         m_rowLabelWin 
= (wxGridRowLabelWindow 
*)NULL
; 
 195         m_colLabelWin 
= (wxGridColLabelWindow 
*)NULL
; 
 198     wxGridWindow( wxGrid 
*parent
, 
 199                   wxGridRowLabelWindow 
*rowLblWin
, 
 200                   wxGridColLabelWindow 
*colLblWin
, 
 201                   wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
); 
 204     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 208     wxGridRowLabelWindow     
*m_rowLabelWin
; 
 209     wxGridColLabelWindow     
*m_colLabelWin
; 
 211     void OnPaint( wxPaintEvent 
&event 
); 
 212     void OnMouseWheel( wxMouseEvent
& event 
); 
 213     void OnMouseEvent( wxMouseEvent
& event 
); 
 214     void OnKeyDown( wxKeyEvent
& ); 
 215     void OnKeyUp( wxKeyEvent
& ); 
 216     void OnEraseBackground( wxEraseEvent
& ); 
 219     DECLARE_DYNAMIC_CLASS(wxGridWindow
) 
 220     DECLARE_EVENT_TABLE() 
 225 class wxGridCellEditorEvtHandler 
: public wxEvtHandler
 
 228     wxGridCellEditorEvtHandler() 
 229         : m_grid(0), m_editor(0) 
 231     wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
) 
 232         : m_grid(grid
), m_editor(editor
) 
 235     void OnKeyDown(wxKeyEvent
& event
); 
 236     void OnChar(wxKeyEvent
& event
); 
 240     wxGridCellEditor
*   m_editor
; 
 241     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
) 
 242     DECLARE_EVENT_TABLE() 
 246 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 247 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler 
) 
 248     EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown 
) 
 249     EVT_CHAR( wxGridCellEditorEvtHandler::OnChar 
) 
 254 // ---------------------------------------------------------------------------- 
 255 // the internal data representation used by wxGridCellAttrProvider 
 256 // ---------------------------------------------------------------------------- 
 258 // this class stores attributes set for cells 
 259 class WXDLLEXPORT wxGridCellAttrData
 
 262     void SetAttr(wxGridCellAttr 
*attr
, int row
, int col
); 
 263     wxGridCellAttr 
*GetAttr(int row
, int col
) const; 
 264     void UpdateAttrRows( size_t pos
, int numRows 
); 
 265     void UpdateAttrCols( size_t pos
, int numCols 
); 
 268     // searches for the attr for given cell, returns wxNOT_FOUND if not found 
 269     int FindIndex(int row
, int col
) const; 
 271     wxGridCellWithAttrArray m_attrs
; 
 274 // this class stores attributes set for rows or columns 
 275 class WXDLLEXPORT wxGridRowOrColAttrData
 
 278     // empty ctor to suppress warnings 
 279     wxGridRowOrColAttrData() { } 
 280     ~wxGridRowOrColAttrData(); 
 282     void SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
); 
 283     wxGridCellAttr 
*GetAttr(int rowOrCol
) const; 
 284     void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
); 
 287     wxArrayInt m_rowsOrCols
; 
 288     wxArrayAttrs m_attrs
; 
 291 // NB: this is just a wrapper around 3 objects: one which stores cell 
 292 //     attributes, and 2 others for row/col ones 
 293 class WXDLLEXPORT wxGridCellAttrProviderData
 
 296     wxGridCellAttrData m_cellAttrs
; 
 297     wxGridRowOrColAttrData m_rowAttrs
, 
 302 // ---------------------------------------------------------------------------- 
 303 // data structures used for the data type registry 
 304 // ---------------------------------------------------------------------------- 
 306 struct wxGridDataTypeInfo
 
 308     wxGridDataTypeInfo(const wxString
& typeName
, 
 309                        wxGridCellRenderer
* renderer
, 
 310                        wxGridCellEditor
* editor
) 
 311         : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
) 
 314     ~wxGridDataTypeInfo() 
 316         wxSafeDecRef(m_renderer
); 
 317         wxSafeDecRef(m_editor
); 
 321     wxGridCellRenderer
* m_renderer
; 
 322     wxGridCellEditor
*   m_editor
; 
 326 WX_DEFINE_EXPORTED_ARRAY(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
); 
 329 class WXDLLEXPORT wxGridTypeRegistry
 
 332   wxGridTypeRegistry() {} 
 333     ~wxGridTypeRegistry(); 
 335     void RegisterDataType(const wxString
& typeName
, 
 336                      wxGridCellRenderer
* renderer
, 
 337                      wxGridCellEditor
* editor
); 
 339     // find one of already registered data types 
 340     int FindRegisteredDataType(const wxString
& typeName
); 
 342     // try to FindRegisteredDataType(), if this fails and typeName is one of 
 343     // standard typenames, register it and return its index 
 344     int FindDataType(const wxString
& typeName
); 
 346     // try to FindDataType(), if it fails see if it is not one of already 
 347     // registered data types with some params in which case clone the 
 348     // registered data type and set params for it 
 349     int FindOrCloneDataType(const wxString
& typeName
); 
 351     wxGridCellRenderer
* GetRenderer(int index
); 
 352     wxGridCellEditor
*   GetEditor(int index
); 
 355     wxGridDataTypeInfoArray m_typeinfo
; 
 358 // ---------------------------------------------------------------------------- 
 359 // conditional compilation 
 360 // ---------------------------------------------------------------------------- 
 362 #ifndef WXGRID_DRAW_LINES 
 363 #define WXGRID_DRAW_LINES 1 
 366 // ---------------------------------------------------------------------------- 
 368 // ---------------------------------------------------------------------------- 
 370 //#define DEBUG_ATTR_CACHE 
 371 #ifdef DEBUG_ATTR_CACHE 
 372     static size_t gs_nAttrCacheHits 
= 0; 
 373     static size_t gs_nAttrCacheMisses 
= 0; 
 374 #endif // DEBUG_ATTR_CACHE 
 376 // ---------------------------------------------------------------------------- 
 378 // ---------------------------------------------------------------------------- 
 380 wxGridCellCoords 
wxGridNoCellCoords( -1, -1 ); 
 381 wxRect           
wxGridNoCellRect( -1, -1, -1, -1 ); 
 384 // TODO: this doesn't work at all, grid cells have different sizes and approx 
 385 //       calculations don't work as because of the size mismatch scrollbars 
 386 //       sometimes fail to be shown when they should be or vice versa 
 388 //       The scroll bars may be a little flakey once in a while, but that is 
 389 //       surely much less horrible than having scroll lines of only 1!!! 
 392 //       Well, it's still seriously broken so it might be better but needs 
 395 static const size_t GRID_SCROLL_LINE_X 
= 15;  // 1; 
 396 static const size_t GRID_SCROLL_LINE_Y 
= GRID_SCROLL_LINE_X
; 
 398 // the size of hash tables used a bit everywhere (the max number of elements 
 399 // in these hash tables is the number of rows/columns) 
 400 static const int GRID_HASH_SIZE 
= 100; 
 402 // ---------------------------------------------------------------------------- 
 404 // ---------------------------------------------------------------------------- 
 406 static inline int GetScrollX(int x
) 
 408     return (x 
+ GRID_SCROLL_LINE_X 
- 1) / GRID_SCROLL_LINE_X
; 
 411 static inline int GetScrollY(int y
) 
 413     return (y 
+ GRID_SCROLL_LINE_Y 
- 1) / GRID_SCROLL_LINE_Y
; 
 416 // ============================================================================ 
 418 // ============================================================================ 
 420 // ---------------------------------------------------------------------------- 
 422 // ---------------------------------------------------------------------------- 
 424 wxGridCellEditor::wxGridCellEditor() 
 430 wxGridCellEditor::~wxGridCellEditor() 
 435 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
), 
 436                               wxWindowID 
WXUNUSED(id
), 
 437                               wxEvtHandler
* evtHandler
) 
 440         m_control
->PushEventHandler(evtHandler
); 
 443 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
, 
 444                                        wxGridCellAttr 
*attr
) 
 446     // erase the background because we might not fill the cell 
 447     wxClientDC 
dc(m_control
->GetParent()); 
 448     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 449     dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 450     dc
.DrawRectangle(rectCell
); 
 452     // redraw the control we just painted over 
 453     m_control
->Refresh(); 
 456 void wxGridCellEditor::Destroy() 
 460         m_control
->PopEventHandler(TRUE 
/* delete it*/); 
 462         m_control
->Destroy(); 
 467 void wxGridCellEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
 469     wxASSERT_MSG(m_control
, 
 470                  wxT("The wxGridCellEditor must be Created first!")); 
 471     m_control
->Show(show
); 
 475         // set the colours/fonts if we have any 
 478             m_colFgOld 
= m_control
->GetForegroundColour(); 
 479             m_control
->SetForegroundColour(attr
->GetTextColour()); 
 481             m_colBgOld 
= m_control
->GetBackgroundColour(); 
 482             m_control
->SetBackgroundColour(attr
->GetBackgroundColour()); 
 484             m_fontOld 
= m_control
->GetFont(); 
 485             m_control
->SetFont(attr
->GetFont()); 
 487             // can't do anything more in the base class version, the other 
 488             // attributes may only be used by the derived classes 
 493         // restore the standard colours fonts 
 494         if ( m_colFgOld
.Ok() ) 
 496             m_control
->SetForegroundColour(m_colFgOld
); 
 497             m_colFgOld 
= wxNullColour
; 
 500         if ( m_colBgOld
.Ok() ) 
 502             m_control
->SetBackgroundColour(m_colBgOld
); 
 503             m_colBgOld 
= wxNullColour
; 
 506         if ( m_fontOld
.Ok() ) 
 508             m_control
->SetFont(m_fontOld
); 
 509             m_fontOld 
= wxNullFont
; 
 514 void wxGridCellEditor::SetSize(const wxRect
& rect
) 
 516     wxASSERT_MSG(m_control
, 
 517                  wxT("The wxGridCellEditor must be Created first!")); 
 518     m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
); 
 521 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
) 
 526 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 528     // accept the simple key presses, not anything with Ctrl/Alt/Meta 
 529     return !(event
.ControlDown() || event
.AltDown()); 
 532 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
) 
 537 void wxGridCellEditor::StartingClick() 
 543 // ---------------------------------------------------------------------------- 
 544 // wxGridCellTextEditor 
 545 // ---------------------------------------------------------------------------- 
 547 wxGridCellTextEditor::wxGridCellTextEditor() 
 552 void wxGridCellTextEditor::Create(wxWindow
* parent
, 
 554                                   wxEvtHandler
* evtHandler
) 
 556     m_control 
= new wxTextCtrl(parent
, id
, wxEmptyString
, 
 557                                wxDefaultPosition
, wxDefaultSize
 
 558 #if defined(__WXMSW__) 
 559                                , wxTE_PROCESS_TAB 
| wxTE_MULTILINE 
| 
 560                                  wxTE_NO_VSCROLL 
| wxTE_AUTO_SCROLL
 
 564     // TODO: use m_maxChars 
 566     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 569 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
), 
 570                                            wxGridCellAttr 
* WXUNUSED(attr
)) 
 572     // as we fill the entire client area, don't do anything here to minimize 
 576 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
) 
 578     wxRect 
rect(rectOrig
); 
 580     // Make the edit control large enough to allow for internal 
 583     // TODO: remove this if the text ctrl sizing is improved esp. for 
 586 #if defined(__WXGTK__) 
 595     int extra_x 
= ( rect
.x 
> 2 )? 2 : 1; 
 597 // MB: treat MSW separately here otherwise the caret doesn't show 
 598 // when the editor is in the first row. 
 599 #if defined(__WXMSW__) 
 602     int extra_y 
= ( rect
.y 
> 2 )? 2 : 1; 
 605 #if defined(__WXMOTIF__) 
 609     rect
.SetLeft( wxMax(0, rect
.x 
- extra_x
) ); 
 610     rect
.SetTop( wxMax(0, rect
.y 
- extra_y
) ); 
 611     rect
.SetRight( rect
.GetRight() + 2*extra_x 
); 
 612     rect
.SetBottom( rect
.GetBottom() + 2*extra_y 
); 
 615     wxGridCellEditor::SetSize(rect
); 
 618 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 620     wxASSERT_MSG(m_control
, 
 621                  wxT("The wxGridCellEditor must be Created first!")); 
 623     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
 625     DoBeginEdit(m_startValue
); 
 628 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
) 
 630     Text()->SetValue(startValue
); 
 631     Text()->SetInsertionPointEnd(); 
 632     Text()->SetSelection(-1,-1); 
 636 bool wxGridCellTextEditor::EndEdit(int row
, int col
, 
 639     wxASSERT_MSG(m_control
, 
 640                  wxT("The wxGridCellEditor must be Created first!")); 
 642     bool changed 
= FALSE
; 
 643     wxString value 
= Text()->GetValue(); 
 644     if (value 
!= m_startValue
) 
 648         grid
->GetTable()->SetValue(row
, col
, value
); 
 650     m_startValue 
= wxEmptyString
; 
 651     Text()->SetValue(m_startValue
); 
 657 void wxGridCellTextEditor::Reset() 
 659     wxASSERT_MSG(m_control
, 
 660                  wxT("The wxGridCellEditor must be Created first!")); 
 662     DoReset(m_startValue
); 
 665 void wxGridCellTextEditor::DoReset(const wxString
& startValue
) 
 667     Text()->SetValue(startValue
); 
 668     Text()->SetInsertionPointEnd(); 
 671 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 673     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 675         int keycode 
= event
.GetKeyCode(); 
 689             case WXK_NUMPAD_MULTIPLY
: 
 693             case WXK_NUMPAD_SUBTRACT
: 
 695             case WXK_NUMPAD_DECIMAL
: 
 697             case WXK_NUMPAD_DIVIDE
: 
 701                 // accept 8 bit chars too if isprint() agrees 
 702                 if ( (keycode 
< 255) && (isprint(keycode
)) ) 
 710 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
) 
 712     if ( !Text()->EmulateKeyPress(event
) ) 
 718 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
& 
 719                                          WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) ) 
 721 #if defined(__WXMOTIF__) || defined(__WXGTK__) 
 722     // wxMotif needs a little extra help... 
 723     size_t pos 
= (size_t)( Text()->GetInsertionPoint() ); 
 724     wxString 
s( Text()->GetValue() ); 
 725     s 
= s
.Left(pos
) + "\n" + s
.Mid(pos
); 
 727     Text()->SetInsertionPoint( pos 
); 
 729     // the other ports can handle a Return key press 
 735 void wxGridCellTextEditor::SetParameters(const wxString
& params
) 
 745         if ( !params
.ToLong(&tmp
) ) 
 747             wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str()); 
 751             m_maxChars 
= (size_t)tmp
; 
 756 // ---------------------------------------------------------------------------- 
 757 // wxGridCellNumberEditor 
 758 // ---------------------------------------------------------------------------- 
 760 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 766 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 768                                     wxEvtHandler
* evtHandler
) 
 772         // create a spin ctrl 
 773         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 774                                    wxDefaultPosition
, wxDefaultSize
, 
 778         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 782         // just a text control 
 783         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 786         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 787 #endif // wxUSE_VALIDATORS 
 791 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 793     // first get the value 
 794     wxGridTableBase 
*table 
= grid
->GetTable(); 
 795     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 797         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 802         wxString sValue 
= table
->GetValue(row
, col
); 
 803         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.IsEmpty()) 
 805             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 812         Spin()->SetValue((int)m_valueOld
); 
 817         DoBeginEdit(GetString()); 
 821 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 830         value 
= Spin()->GetValue(); 
 831         changed 
= value 
!= m_valueOld
; 
 833             text 
= wxString::Format(wxT("%ld"), value
); 
 837         text 
= Text()->GetValue(); 
 838         changed 
= (text
.IsEmpty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 843         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 844             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 846             grid
->GetTable()->SetValue(row
, col
, text
); 
 852 void wxGridCellNumberEditor::Reset() 
 856         Spin()->SetValue((int)m_valueOld
); 
 860         DoReset(GetString()); 
 864 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 866     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 868         int keycode 
= event
.GetKeyCode(); 
 884             case WXK_NUMPAD_SUBTRACT
: 
 890                 if ( (keycode 
< 128) && isdigit(keycode
) ) 
 898 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 902         int keycode 
= (int) event
.KeyCode(); 
 903         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
 904             || keycode 
==  WXK_NUMPAD0
 
 905             || keycode 
==  WXK_NUMPAD1
 
 906             || keycode 
==  WXK_NUMPAD2
 
 907             || keycode 
==  WXK_NUMPAD3
 
 908             || keycode 
==  WXK_NUMPAD4
 
 909             || keycode 
==  WXK_NUMPAD5
 
 910             || keycode 
==  WXK_NUMPAD6
 
 911             || keycode 
==  WXK_NUMPAD7
 
 912             || keycode 
==  WXK_NUMPAD8
 
 913             || keycode 
==  WXK_NUMPAD9
 
 914             || keycode 
==  WXK_ADD
 
 915             || keycode 
==  WXK_NUMPAD_ADD
 
 916             || keycode 
==  WXK_SUBTRACT
 
 917             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
 919             wxGridCellTextEditor::StartingKey(event
); 
 929 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 940         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 944             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 948                 // skip the error message below 
 953         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 957 // ---------------------------------------------------------------------------- 
 958 // wxGridCellFloatEditor 
 959 // ---------------------------------------------------------------------------- 
 961 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
 964     m_precision 
= precision
; 
 967 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 969                                    wxEvtHandler
* evtHandler
) 
 971     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 974     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 975 #endif // wxUSE_VALIDATORS 
 978 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 980     // first get the value 
 981     wxGridTableBase 
*table 
= grid
->GetTable(); 
 982     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
 984         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
 989         wxString sValue 
= table
->GetValue(row
, col
); 
 990         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.IsEmpty()) 
 992             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
 997     DoBeginEdit(GetString()); 
1000 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1004     wxString 
text(Text()->GetValue()); 
1006     if ( (text
.IsEmpty() || text
.ToDouble(&value
)) && (value 
!= m_valueOld
) ) 
1008         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1009             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1011             grid
->GetTable()->SetValue(row
, col
, text
); 
1021 void wxGridCellFloatEditor::Reset() 
1023     DoReset(GetString()); 
1026 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1028     int keycode 
= (int)event
.KeyCode(); 
1029         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' || keycode 
== '.' 
1030             || keycode 
==  WXK_NUMPAD0
 
1031             || keycode 
==  WXK_NUMPAD1
 
1032             || keycode 
==  WXK_NUMPAD2
 
1033             || keycode 
==  WXK_NUMPAD3
 
1034             || keycode 
==  WXK_NUMPAD4
 
1035             || keycode 
==  WXK_NUMPAD5
 
1036             || keycode 
==  WXK_NUMPAD6
 
1037             || keycode 
==  WXK_NUMPAD7
 
1038             || keycode 
==  WXK_NUMPAD8
 
1039             || keycode 
==  WXK_NUMPAD9
 
1040             || keycode 
==  WXK_ADD
 
1041             || keycode 
==  WXK_NUMPAD_ADD
 
1042             || keycode 
==  WXK_SUBTRACT
 
1043             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
1045         wxGridCellTextEditor::StartingKey(event
); 
1047         // skip Skip() below 
1054 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1065         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1069             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1071                 m_precision 
= (int)tmp
; 
1073                 // skip the error message below 
1078         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1082 wxString 
wxGridCellFloatEditor::GetString() const 
1085     if ( m_width 
== -1 ) 
1087         // default width/precision 
1090     else if ( m_precision 
== -1 ) 
1092         // default precision 
1093         fmt
.Printf(_T("%%%d.f"), m_width
); 
1097         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1100     return wxString::Format(fmt
, m_valueOld
); 
1103 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1105     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1107         int keycode 
= event
.GetKeyCode(); 
1121             case WXK_NUMPAD_ADD
: 
1123             case WXK_NUMPAD_SUBTRACT
: 
1125             case WXK_NUMPAD_DECIMAL
: 
1129                 // additionally accept 'e' as in '1e+6' 
1130                 if ( (keycode 
< 128) && 
1131                      (isdigit(keycode
) || tolower(keycode
) == 'e') ) 
1139 #endif // wxUSE_TEXTCTRL 
1143 // ---------------------------------------------------------------------------- 
1144 // wxGridCellBoolEditor 
1145 // ---------------------------------------------------------------------------- 
1147 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1149                                   wxEvtHandler
* evtHandler
) 
1151     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1152                                wxDefaultPosition
, wxDefaultSize
, 
1155     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1158 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1160     bool resize 
= FALSE
; 
1161     wxSize size 
= m_control
->GetSize(); 
1162     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1164     // check if the checkbox is not too big/small for this cell 
1165     wxSize sizeBest 
= m_control
->GetBestSize(); 
1166     if ( !(size 
== sizeBest
) ) 
1168         // reset to default size if it had been made smaller 
1174     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1176         // leave 1 pixel margin 
1177         size
.x 
= size
.y 
= minSize 
- 2; 
1184         m_control
->SetSize(size
); 
1187     // position it in the centre of the rectangle (TODO: support alignment?) 
1189 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1190     // the checkbox without label still has some space to the right in wxGTK, 
1191     // so shift it to the right 
1193 #elif defined(__WXMSW__) 
1194     // here too, but in other way 
1199     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
1202 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1204     m_control
->Show(show
); 
1208         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1209         CBox()->SetBackgroundColour(colBg
); 
1213 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1215     wxASSERT_MSG(m_control
, 
1216                  wxT("The wxGridCellEditor must be Created first!")); 
1218     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1219         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1222         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1223         m_startValue 
= !( !cellval 
|| (cellval 
== "0") ); 
1225     CBox()->SetValue(m_startValue
); 
1229 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1232     wxASSERT_MSG(m_control
, 
1233                  wxT("The wxGridCellEditor must be Created first!")); 
1235     bool changed 
= FALSE
; 
1236     bool value 
= CBox()->GetValue(); 
1237     if ( value 
!= m_startValue 
) 
1242         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1243             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1245             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1251 void wxGridCellBoolEditor::Reset() 
1253     wxASSERT_MSG(m_control
, 
1254                  wxT("The wxGridCellEditor must be Created first!")); 
1256     CBox()->SetValue(m_startValue
); 
1259 void wxGridCellBoolEditor::StartingClick() 
1261     CBox()->SetValue(!CBox()->GetValue()); 
1264 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1266     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1268         int keycode 
= event
.GetKeyCode(); 
1272             case WXK_NUMPAD_MULTIPLY
: 
1274             case WXK_NUMPAD_ADD
: 
1276             case WXK_NUMPAD_SUBTRACT
: 
1287 #endif // wxUSE_CHECKBOX 
1291 // ---------------------------------------------------------------------------- 
1292 // wxGridCellChoiceEditor 
1293 // ---------------------------------------------------------------------------- 
1295 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1296                                                const wxString choices
[], 
1298                       : m_allowOthers(allowOthers
) 
1302         m_choices
.Alloc(count
); 
1303         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1305             m_choices
.Add(choices
[n
]); 
1310 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1312     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1313     editor
->m_allowOthers 
= m_allowOthers
; 
1314     editor
->m_choices 
= m_choices
; 
1319 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1321                                     wxEvtHandler
* evtHandler
) 
1323     size_t count 
= m_choices
.GetCount(); 
1324     wxString 
*choices 
= new wxString
[count
]; 
1325     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1327         choices
[n
] = m_choices
[n
]; 
1330     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1331                                wxDefaultPosition
, wxDefaultSize
, 
1333                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1337     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1340 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1341                                              wxGridCellAttr 
* attr
) 
1343     // as we fill the entire client area, don't do anything here to minimize 
1346     // TODO: It doesn't actually fill the client area since the height of a 
1347     // combo always defaults to the standard...  Until someone has time to 
1348     // figure out the right rectangle to paint, just do it the normal way... 
1349     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1352 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1354     wxASSERT_MSG(m_control
, 
1355                  wxT("The wxGridCellEditor must be Created first!")); 
1357     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1359     Combo()->SetValue(m_startValue
); 
1360     size_t count 
= m_choices
.GetCount(); 
1361     for (size_t i
=0; i
<count
; i
++) 
1363         if (m_startValue 
== m_choices
[i
]) 
1365             Combo()->SetSelection(i
); 
1369     Combo()->SetInsertionPointEnd(); 
1370     Combo()->SetFocus(); 
1373 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1376     wxString value 
= Combo()->GetValue(); 
1377     bool changed 
= value 
!= m_startValue
; 
1380         grid
->GetTable()->SetValue(row
, col
, value
); 
1382     m_startValue 
= wxEmptyString
; 
1383     Combo()->SetValue(m_startValue
); 
1388 void wxGridCellChoiceEditor::Reset() 
1390     Combo()->SetValue(m_startValue
); 
1391     Combo()->SetInsertionPointEnd(); 
1394 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1404     wxStringTokenizer 
tk(params
, _T(',')); 
1405     while ( tk
.HasMoreTokens() ) 
1407         m_choices
.Add(tk
.GetNextToken()); 
1411 #endif // wxUSE_COMBOBOX 
1413 // ---------------------------------------------------------------------------- 
1414 // wxGridCellEditorEvtHandler 
1415 // ---------------------------------------------------------------------------- 
1417 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1419     switch ( event
.KeyCode() ) 
1423             m_grid
->DisableCellEditControl(); 
1427             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1431         case WXK_NUMPAD_ENTER
: 
1432             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1433                 m_editor
->HandleReturn(event
); 
1442 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1444     switch ( event
.KeyCode() ) 
1449         case WXK_NUMPAD_ENTER
: 
1457 // ---------------------------------------------------------------------------- 
1458 // wxGridCellWorker is an (almost) empty common base class for 
1459 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1460 // ---------------------------------------------------------------------------- 
1462 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1467 wxGridCellWorker::~wxGridCellWorker() 
1471 // ============================================================================ 
1473 // ============================================================================ 
1475 // ---------------------------------------------------------------------------- 
1476 // wxGridCellRenderer 
1477 // ---------------------------------------------------------------------------- 
1479 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1480                               wxGridCellAttr
& attr
, 
1483                               int WXUNUSED(row
), int WXUNUSED(col
), 
1486     dc
.SetBackgroundMode( wxSOLID 
); 
1490         dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1494         dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1497     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1498     dc
.DrawRectangle(rect
); 
1501 // ---------------------------------------------------------------------------- 
1502 // wxGridCellStringRenderer 
1503 // ---------------------------------------------------------------------------- 
1505 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1506                                                      wxGridCellAttr
& attr
, 
1510     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1512     // TODO some special colours for attr.IsReadOnly() case? 
1516         dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1517         dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1521         dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1522         dc
.SetTextForeground( attr
.GetTextColour() ); 
1525     dc
.SetFont( attr
.GetFont() ); 
1528 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1530                                                const wxString
& text
) 
1532     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1533     dc
.SetFont(attr
.GetFont()); 
1534     wxStringTokenizer 
tk(text
, _T('\n')); 
1535     while ( tk
.HasMoreTokens() ) 
1537         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1538         max_x 
= wxMax(max_x
, x
); 
1541     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1543     return wxSize(max_x
, y
); 
1546 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1547                                              wxGridCellAttr
& attr
, 
1551     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1554 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1555                                     wxGridCellAttr
& attr
, 
1557                                     const wxRect
& rectCell
, 
1561     wxRect rect 
= rectCell
; 
1563     if (attr
.GetOverflow()) 
1565         int cols 
= grid
.GetNumberCols(); 
1566         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1567         int cell_rows
, cell_cols
; 
1568         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <=0 
1569         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1571             int i
, c_cols
, c_rows
; 
1572             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1574                 // check w/ anchor cell for multicell block 
1575                 grid
.GetCellSize(row
, i
, &c_rows
, &c_cols
); 
1576                 if (c_rows 
> 0) c_rows 
= 0; 
1577                 if (grid
.GetTable()->IsEmptyCell(row
+c_rows
, i
)) 
1579                     rect
.width 
+= grid
.GetColSize(i
); 
1580                     if (rect
.width 
>= best_width
) break; 
1587     // erase only this cells background, overflow cells should have been erased 
1588     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1590     // now we only have to draw the text 
1591     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1594     attr
.GetAlignment(&hAlign
, &vAlign
); 
1598     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1599                            rect
, hAlign
, vAlign
); 
1602 // ---------------------------------------------------------------------------- 
1603 // wxGridCellNumberRenderer 
1604 // ---------------------------------------------------------------------------- 
1606 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1608     wxGridTableBase 
*table 
= grid
.GetTable(); 
1610     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1612         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1616         text 
= table
->GetValue(row
, col
); 
1622 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1623                                     wxGridCellAttr
& attr
, 
1625                                     const wxRect
& rectCell
, 
1629     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1631     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1633     // draw the text right aligned by default 
1635     attr
.GetAlignment(&hAlign
, &vAlign
); 
1636     hAlign 
= wxALIGN_RIGHT
; 
1638     wxRect rect 
= rectCell
; 
1641     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1644 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1645                                              wxGridCellAttr
& attr
, 
1649     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1652 // ---------------------------------------------------------------------------- 
1653 // wxGridCellFloatRenderer 
1654 // ---------------------------------------------------------------------------- 
1656 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1659     SetPrecision(precision
); 
1662 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1664     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1665     renderer
->m_width 
= m_width
; 
1666     renderer
->m_precision 
= m_precision
; 
1667     renderer
->m_format 
= m_format
; 
1672 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1674     wxGridTableBase 
*table 
= grid
.GetTable(); 
1679     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1681         val 
= table
->GetValueAsDouble(row
, col
); 
1686         text 
= table
->GetValue(row
, col
); 
1687         hasDouble 
= text
.ToDouble(&val
); 
1694             if ( m_width 
== -1 ) 
1696                 if ( m_precision 
== -1 ) 
1698                 // default width/precision 
1699                 m_format 
= _T("%f"); 
1703                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1706             else if ( m_precision 
== -1 ) 
1708                 // default precision 
1709                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1713                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1717         text
.Printf(m_format
, val
); 
1720     //else: text already contains the string 
1725 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1726                                    wxGridCellAttr
& attr
, 
1728                                    const wxRect
& rectCell
, 
1732     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1734     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1736     // draw the text right aligned by default 
1738     attr
.GetAlignment(&hAlign
, &vAlign
); 
1739     hAlign 
= wxALIGN_RIGHT
; 
1741     wxRect rect 
= rectCell
; 
1744     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1747 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1748                                             wxGridCellAttr
& attr
, 
1752     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1755 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1759         // reset to defaults 
1765         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1769             if ( tmp
.ToLong(&width
) ) 
1771                 SetWidth((int)width
); 
1775                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1779                 tmp 
= params
.AfterFirst(_T(',')); 
1783             if ( tmp
.ToLong(&precision
) ) 
1785                 SetPrecision((int)precision
); 
1789                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1797 // ---------------------------------------------------------------------------- 
1798 // wxGridCellBoolRenderer 
1799 // ---------------------------------------------------------------------------- 
1801 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1803 // FIXME these checkbox size calculations are really ugly... 
1805 // between checkmark and box 
1806 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1808 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1809                                            wxGridCellAttr
& WXUNUSED(attr
), 
1814     // compute it only once (no locks for MT safeness in GUI thread...) 
1815     if ( !ms_sizeCheckMark
.x 
) 
1817         // get checkbox size 
1818         wxCoord checkSize 
= 0; 
1819         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1820         wxSize size 
= checkbox
->GetBestSize(); 
1821         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1823         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1824 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1825         checkSize 
-= size
.y 
/ 2; 
1830         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1833     return ms_sizeCheckMark
; 
1836 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1837                                   wxGridCellAttr
& attr
, 
1843     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1845     // draw a check mark in the centre (ignoring alignment - TODO) 
1846     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1848     // don't draw outside the cell 
1849     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1850     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1852         // and even leave (at least) 1 pixel margin 
1853         size
.x 
= size
.y 
= minSize 
- 2; 
1856     // draw a border around checkmark 
1858     rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1859     rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1860     rectBorder
.width 
= size
.x
; 
1861     rectBorder
.height 
= size
.y
; 
1864     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1865         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1868         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
1869         value 
= !( !cellval 
|| (cellval 
== "0") ); 
1874         wxRect rectMark 
= rectBorder
; 
1876         // MSW DrawCheckMark() is weird (and should probably be changed...) 
1877         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
1881         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1884         dc
.SetTextForeground(attr
.GetTextColour()); 
1885         dc
.DrawCheckMark(rectMark
); 
1888     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1889     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1890     dc
.DrawRectangle(rectBorder
); 
1893 // ---------------------------------------------------------------------------- 
1895 // ---------------------------------------------------------------------------- 
1897 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
1901     m_isReadOnly 
= Unset
; 
1906     m_attrkind 
= wxGridCellAttr::Cell
; 
1908     m_sizeRows 
= m_sizeCols 
= 1; 
1911     SetDefAttr(attrDefault
); 
1914 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
1916     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
1918     if ( HasTextColour() ) 
1919         attr
->SetTextColour(GetTextColour()); 
1920     if ( HasBackgroundColour() ) 
1921         attr
->SetBackgroundColour(GetBackgroundColour()); 
1923         attr
->SetFont(GetFont()); 
1924     if ( HasAlignment() ) 
1925         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
1927     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
1931         attr
->SetRenderer(m_renderer
); 
1932         m_renderer
->IncRef(); 
1936         attr
->SetEditor(m_editor
); 
1941         attr
->SetReadOnly(); 
1943     attr
->SetKind( m_attrkind 
); 
1948 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
1950     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
1951         SetTextColour(mergefrom
->GetTextColour()); 
1952     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
1953         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
1954     if ( !HasFont() && mergefrom
->HasFont() ) 
1955         SetFont(mergefrom
->GetFont()); 
1956     if ( !!HasAlignment() && mergefrom
->HasAlignment() ){ 
1958         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
1959         SetAlignment(hAlign
, vAlign
); 
1962     mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
1964     // Directly access member functions as GetRender/Editor don't just return 
1965     // m_renderer/m_editor 
1967     // Maybe add support for merge of Render and Editor? 
1968     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
1970         m_renderer 
= mergefrom
->m_renderer
; 
1971         m_renderer
->IncRef(); 
1973     if ( !HasEditor() && mergefrom
->HasEditor() ) 
1975         m_editor 
=  mergefrom
->m_editor
; 
1978     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
1979         SetReadOnly(mergefrom
->IsReadOnly()); 
1981     SetDefAttr(mergefrom
->m_defGridAttr
); 
1984 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
1986     // The size of a cell is normally 1,1 
1988     // If this cell is larger (2,2) then this is the top left cell 
1989     // the other cells that will be covered (lower right cells) must be 
1990     // set to negative or zero values such that 
1991     // row + num_rows of the covered cell points to the larger cell (this cell) 
1992     // same goes for the col + num_cols. 
1994     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
1996     wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) || 
1997                   !((num_rows
<=0)&&(num_cols
>0)) || 
1998                   !((num_rows
==0)&&(num_cols
==0))), 
1999                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2001     m_sizeRows 
= num_rows
; 
2002     m_sizeCols 
= num_cols
; 
2005 const wxColour
& wxGridCellAttr::GetTextColour() const 
2007     if (HasTextColour()) 
2011     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2013         return m_defGridAttr
->GetTextColour(); 
2017         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2018         return wxNullColour
; 
2023 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2025     if (HasBackgroundColour()) 
2027     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2028         return m_defGridAttr
->GetBackgroundColour(); 
2031         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2032         return wxNullColour
; 
2037 const wxFont
& wxGridCellAttr::GetFont() const 
2041     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2042         return m_defGridAttr
->GetFont(); 
2045         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2051 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2055         if ( hAlign 
) *hAlign 
= m_hAlign
; 
2056         if ( vAlign 
) *vAlign 
= m_vAlign
; 
2058     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2059         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2062         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2066 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2068     if ( num_rows 
) *num_rows 
= m_sizeRows
; 
2069     if ( num_cols 
) *num_cols 
= m_sizeCols
; 
2072 // GetRenderer and GetEditor use a slightly different decision path about 
2073 // which attribute to use.  If a non-default attr object has one then it is 
2074 // used, otherwise the default editor or renderer is fetched from the grid and 
2075 // used.  It should be the default for the data type of the cell.  If it is 
2076 // NULL (because the table has a type that the grid does not have in its 
2077 // registry,) then the grid's default editor or renderer is used. 
2079 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2081     wxGridCellRenderer 
*renderer
; 
2083     if ( m_renderer 
&& this != m_defGridAttr 
) 
2085         // use the cells renderer if it has one 
2086         renderer 
= m_renderer
; 
2089     else // no non default cell renderer 
2091         // get default renderer for the data type 
2094             // GetDefaultRendererForCell() will do IncRef() for us 
2095             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2104             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2106                 // if we still don't have one then use the grid default 
2107                 // (no need for IncRef() here neither) 
2108                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2110             else // default grid attr 
2112                 // use m_renderer which we had decided not to use initially 
2113                 renderer 
= m_renderer
; 
2120     // we're supposed to always find something 
2121     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2126 // same as above, except for s/renderer/editor/g 
2127 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2129     wxGridCellEditor 
*editor
; 
2131     if ( m_editor 
&& this != m_defGridAttr 
) 
2133         // use the cells editor if it has one 
2137     else // no non default cell editor 
2139         // get default editor for the data type 
2142             // GetDefaultEditorForCell() will do IncRef() for us 
2143             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2152             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2154                 // if we still don't have one then use the grid default 
2155                 // (no need for IncRef() here neither) 
2156                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2158             else // default grid attr 
2160                 // use m_editor which we had decided not to use initially 
2168     // we're supposed to always find something 
2169     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2174 // ---------------------------------------------------------------------------- 
2175 // wxGridCellAttrData 
2176 // ---------------------------------------------------------------------------- 
2178 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2180     int n 
= FindIndex(row
, col
); 
2181     if ( n 
== wxNOT_FOUND 
) 
2183         // add the attribute 
2184         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2188         // free the old attribute 
2189         m_attrs
[(size_t)n
].attr
->DecRef(); 
2193             // change the attribute 
2194             m_attrs
[(size_t)n
].attr 
= attr
; 
2198             // remove this attribute 
2199             m_attrs
.RemoveAt((size_t)n
); 
2204 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2206     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2208     int n 
= FindIndex(row
, col
); 
2209     if ( n 
!= wxNOT_FOUND 
) 
2211         attr 
= m_attrs
[(size_t)n
].attr
; 
2218 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2220     size_t count 
= m_attrs
.GetCount(); 
2221     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2223         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2224         wxCoord row 
= coords
.GetRow(); 
2225         if ((size_t)row 
>= pos
) 
2229                 // If rows inserted, include row counter where necessary 
2230                 coords
.SetRow(row 
+ numRows
); 
2232             else if (numRows 
< 0) 
2234                 // If rows deleted ... 
2235                 if ((size_t)row 
>= pos 
- numRows
) 
2237                     // ...either decrement row counter (if row still exists)... 
2238                     coords
.SetRow(row 
+ numRows
); 
2242                     // ...or remove the attribute 
2243                     m_attrs
.RemoveAt((size_t)n
); 
2251 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2253     size_t count 
= m_attrs
.GetCount(); 
2254     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2256         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2257         wxCoord col 
= coords
.GetCol(); 
2258         if ( (size_t)col 
>= pos 
) 
2262                 // If rows inserted, include row counter where necessary 
2263                 coords
.SetCol(col 
+ numCols
); 
2265             else if (numCols 
< 0) 
2267                 // If rows deleted ... 
2268                 if ((size_t)col 
>= pos 
- numCols
) 
2270                     // ...either decrement row counter (if row still exists)... 
2271                     coords
.SetCol(col 
+ numCols
); 
2275                     // ...or remove the attribute 
2276                     m_attrs
.RemoveAt((size_t)n
); 
2284 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2286     size_t count 
= m_attrs
.GetCount(); 
2287     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2289         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2290         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2299 // ---------------------------------------------------------------------------- 
2300 // wxGridRowOrColAttrData 
2301 // ---------------------------------------------------------------------------- 
2303 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2305     size_t count 
= m_attrs
.Count(); 
2306     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2308         m_attrs
[n
]->DecRef(); 
2312 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2314     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2316     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2317     if ( n 
!= wxNOT_FOUND 
) 
2319         attr 
= m_attrs
[(size_t)n
]; 
2326 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2328     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2329     if ( i 
== wxNOT_FOUND 
) 
2331         // add the attribute 
2332         m_rowsOrCols
.Add(rowOrCol
); 
2337         size_t n 
= (size_t)i
; 
2340             // change the attribute 
2341             m_attrs
[n
]->DecRef(); 
2346             // remove this attribute 
2347             m_attrs
[n
]->DecRef(); 
2348             m_rowsOrCols
.RemoveAt(n
); 
2349             m_attrs
.RemoveAt(n
); 
2354 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2356     size_t count 
= m_attrs
.GetCount(); 
2357     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2359         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2360         if ( (size_t)rowOrCol 
>= pos 
) 
2362             if ( numRowsOrCols 
> 0 ) 
2364                 // If rows inserted, include row counter where necessary 
2365                 rowOrCol 
+= numRowsOrCols
; 
2367             else if ( numRowsOrCols 
< 0) 
2369                 // If rows deleted, either decrement row counter (if row still exists) 
2370                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2371                     rowOrCol 
+= numRowsOrCols
; 
2374                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2375                     m_attrs
.RemoveAt((size_t)n
); 
2383 // ---------------------------------------------------------------------------- 
2384 // wxGridCellAttrProvider 
2385 // ---------------------------------------------------------------------------- 
2387 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2389     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2392 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2397 void wxGridCellAttrProvider::InitData() 
2399     m_data 
= new wxGridCellAttrProviderData
; 
2402 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2403                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2405     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2410             case (wxGridCellAttr::Any
): 
2411                 //Get cached merge attributes. 
2412                 // Currenlty not used as no cache implemented as not mutiable 
2413                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2416                     //Basicaly implement old version. 
2417                     //Also check merge cache, so we don't have to re-merge every time.. 
2418                     wxGridCellAttr 
*attrcell 
= (wxGridCellAttr 
*)NULL
, 
2419                                    *attrrow 
= (wxGridCellAttr 
*)NULL
, 
2420                                    *attrcol 
= (wxGridCellAttr 
*)NULL
; 
2422                     attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2423                     attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2424                     attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2426                     if((attrcell 
!= attrrow
) && (attrrow 
!=attrcol
) && (attrcell 
!= attrcol
)){ 
2427                         // Two or move are non NULL 
2428                         attr 
= new wxGridCellAttr
; 
2429                         attr
->SetKind(wxGridCellAttr::Merged
); 
2433                             attr
->MergeWith(attrcell
); 
2437                             attr
->MergeWith(attrcol
); 
2441                             attr
->MergeWith(attrrow
); 
2444                         //store merge attr if cache implemented 
2446                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2450                         // one or none is non null return it or null. 
2451                         if(attrrow
) attr 
= attrrow
; 
2452                         if(attrcol
) attr 
= attrcol
; 
2453                         if(attrcell
) attr 
= attrcell
; 
2457             case (wxGridCellAttr::Cell
): 
2458                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2460             case (wxGridCellAttr::Col
): 
2461                  attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2463             case (wxGridCellAttr::Row
): 
2464             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2468                 // (wxGridCellAttr::Default): 
2469                 // (wxGridCellAttr::Merged): 
2476 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2482     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2485 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2490     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2493 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2498     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2501 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2505         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2507         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2511 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2515         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2517         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2521 // ---------------------------------------------------------------------------- 
2522 // wxGridTypeRegistry 
2523 // ---------------------------------------------------------------------------- 
2525 wxGridTypeRegistry::~wxGridTypeRegistry() 
2527     size_t count 
= m_typeinfo
.Count(); 
2528     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2529         delete m_typeinfo
[i
]; 
2533 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2534                                           wxGridCellRenderer
* renderer
, 
2535                                           wxGridCellEditor
* editor
) 
2537     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2539     // is it already registered? 
2540     int loc 
= FindRegisteredDataType(typeName
); 
2541     if ( loc 
!= wxNOT_FOUND 
) 
2543         delete m_typeinfo
[loc
]; 
2544         m_typeinfo
[loc
] = info
; 
2548         m_typeinfo
.Add(info
); 
2552 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2554     size_t count 
= m_typeinfo
.GetCount(); 
2555     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2557         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2566 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2568     int index 
= FindRegisteredDataType(typeName
); 
2569     if ( index 
== wxNOT_FOUND 
) 
2571         // check whether this is one of the standard ones, in which case 
2572         // register it "on the fly" 
2574         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2576             RegisterDataType(wxGRID_VALUE_STRING
, 
2577                              new wxGridCellStringRenderer
, 
2578                              new wxGridCellTextEditor
); 
2580 #endif // wxUSE_TEXTCTRL 
2582         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2584             RegisterDataType(wxGRID_VALUE_BOOL
, 
2585                              new wxGridCellBoolRenderer
, 
2586                              new wxGridCellBoolEditor
); 
2588 #endif // wxUSE_CHECKBOX 
2590         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2592             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2593                              new wxGridCellNumberRenderer
, 
2594                              new wxGridCellNumberEditor
); 
2596         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2598             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2599                              new wxGridCellFloatRenderer
, 
2600                              new wxGridCellFloatEditor
); 
2602 #endif // wxUSE_TEXTCTRL 
2604         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2606             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2607                              new wxGridCellStringRenderer
, 
2608                              new wxGridCellChoiceEditor
); 
2610 #endif // wxUSE_COMBOBOX 
2615         // we get here only if just added the entry for this type, so return 
2617         index 
= m_typeinfo
.GetCount() - 1; 
2623 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2625     int index 
= FindDataType(typeName
); 
2626     if ( index 
== wxNOT_FOUND 
) 
2628         // the first part of the typename is the "real" type, anything after ':' 
2629         // are the parameters for the renderer 
2630         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2631         if ( index 
== wxNOT_FOUND 
) 
2636         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2637         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2638         renderer 
= renderer
->Clone(); 
2639         rendererOld
->DecRef(); 
2641         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2642         wxGridCellEditor 
*editorOld 
= editor
; 
2643         editor 
= editor
->Clone(); 
2644         editorOld
->DecRef(); 
2646         // do it even if there are no parameters to reset them to defaults 
2647         wxString params 
= typeName
.AfterFirst(_T(':')); 
2648         renderer
->SetParameters(params
); 
2649         editor
->SetParameters(params
); 
2651         // register the new typename 
2652         RegisterDataType(typeName
, renderer
, editor
); 
2654         // we just registered it, it's the last one 
2655         index 
= m_typeinfo
.GetCount() - 1; 
2661 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2663     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2669 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2671     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2677 // ---------------------------------------------------------------------------- 
2679 // ---------------------------------------------------------------------------- 
2681 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2684 wxGridTableBase::wxGridTableBase() 
2686     m_view 
= (wxGrid 
*) NULL
; 
2687     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2690 wxGridTableBase::~wxGridTableBase() 
2692     delete m_attrProvider
; 
2695 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2697     delete m_attrProvider
; 
2698     m_attrProvider 
= attrProvider
; 
2701 bool wxGridTableBase::CanHaveAttributes() 
2703     if ( ! GetAttrProvider() ) 
2705         // use the default attr provider by default 
2706         SetAttrProvider(new wxGridCellAttrProvider
); 
2711 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2713     if ( m_attrProvider 
) 
2714         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2716         return (wxGridCellAttr 
*)NULL
; 
2719 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2721     if ( m_attrProvider 
) 
2723         attr
->SetKind(wxGridCellAttr::Cell
); 
2724         m_attrProvider
->SetAttr(attr
, row
, col
); 
2728         // as we take ownership of the pointer and don't store it, we must 
2734 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2736     if ( m_attrProvider 
) 
2738         attr
->SetKind(wxGridCellAttr::Row
); 
2739         m_attrProvider
->SetRowAttr(attr
, row
); 
2743         // as we take ownership of the pointer and don't store it, we must 
2749 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2751     if ( m_attrProvider 
) 
2753         attr
->SetKind(wxGridCellAttr::Col
); 
2754         m_attrProvider
->SetColAttr(attr
, col
); 
2758         // as we take ownership of the pointer and don't store it, we must 
2764 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2765                                   size_t WXUNUSED(numRows
) ) 
2767     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2772 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2774     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2779 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2780                                   size_t WXUNUSED(numRows
) ) 
2782     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2787 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2788                                   size_t WXUNUSED(numCols
) ) 
2790     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2795 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2797     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2802 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2803                                   size_t WXUNUSED(numCols
) ) 
2805     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2811 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2814     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2815                   //     how much it makes sense to us geeks. 
2819 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2821     // default col labels are: 
2822     //   cols 0 to 25   : A-Z 
2823     //   cols 26 to 675 : AA-ZZ 
2828     for ( n 
= 1; ; n
++ ) 
2830         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2832         if ( col 
< 0 ) break; 
2835     // reverse the string... 
2837     for ( i 
= 0;  i 
< n
;  i
++ ) 
2846 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2848     return wxGRID_VALUE_STRING
; 
2851 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2852                                      const wxString
& typeName 
) 
2854     return typeName 
== wxGRID_VALUE_STRING
; 
2857 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2859     return CanGetValueAs(row
, col
, typeName
); 
2862 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2867 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2872 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2877 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2878                                       long WXUNUSED(value
) ) 
2882 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2883                                         double WXUNUSED(value
) ) 
2887 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2888                                       bool WXUNUSED(value
) ) 
2893 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2894                                          const wxString
& WXUNUSED(typeName
) ) 
2899 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2900                                          const wxString
& WXUNUSED(typeName
), 
2901                                          void* WXUNUSED(value
) ) 
2905 ////////////////////////////////////////////////////////////////////// 
2907 // Message class for the grid table to send requests and notifications 
2911 wxGridTableMessage::wxGridTableMessage() 
2913     m_table 
= (wxGridTableBase 
*) NULL
; 
2919 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
2920                                         int commandInt1
, int commandInt2 
) 
2924     m_comInt1 
= commandInt1
; 
2925     m_comInt2 
= commandInt2
; 
2930 ////////////////////////////////////////////////////////////////////// 
2932 // A basic grid table for string data. An object of this class will 
2933 // created by wxGrid if you don't specify an alternative table class. 
2936 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
2938 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
2940 wxGridStringTable::wxGridStringTable() 
2945 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
2948     m_data
.Alloc( numRows 
); 
2951     sa
.Alloc( numCols 
); 
2952     sa
.Add( wxEmptyString
, numCols 
); 
2954     m_data
.Add( sa
, numRows 
); 
2957 wxGridStringTable::~wxGridStringTable() 
2961 int wxGridStringTable::GetNumberRows() 
2963     return m_data
.GetCount(); 
2966 int wxGridStringTable::GetNumberCols() 
2968     if ( m_data
.GetCount() > 0 ) 
2969         return m_data
[0].GetCount(); 
2974 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
2976     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2977                   _T("invalid row or column index in wxGridStringTable") ); 
2979     return m_data
[row
][col
]; 
2982 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
2984     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2985                   _T("invalid row or column index in wxGridStringTable") ); 
2987     m_data
[row
][col
] = value
; 
2990 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
2992     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
2993                   _T("invalid row or column index in wxGridStringTable") ); 
2995     return (m_data
[row
][col
] == wxEmptyString
); 
2998 void wxGridStringTable::Clear() 
3001     int numRows
, numCols
; 
3003     numRows 
= m_data
.GetCount(); 
3006         numCols 
= m_data
[0].GetCount(); 
3008         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
3010             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
3012                 m_data
[row
][col
] = wxEmptyString
; 
3019 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3021     size_t curNumRows 
= m_data
.GetCount(); 
3022     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3023                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3025     if ( pos 
>= curNumRows 
) 
3027         return AppendRows( numRows 
); 
3031     sa
.Alloc( curNumCols 
); 
3032     sa
.Add( wxEmptyString
, curNumCols 
); 
3033     m_data
.Insert( sa
, pos
, numRows 
); 
3036         wxGridTableMessage 
msg( this, 
3037                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3041         GetView()->ProcessTableMessage( msg 
); 
3047 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3049     size_t curNumRows 
= m_data
.GetCount(); 
3050     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3051                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3054     if ( curNumCols 
> 0 ) 
3056         sa
.Alloc( curNumCols 
); 
3057         sa
.Add( wxEmptyString
, curNumCols 
); 
3060     m_data
.Add( sa
, numRows 
); 
3064         wxGridTableMessage 
msg( this, 
3065                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3068         GetView()->ProcessTableMessage( msg 
); 
3074 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3076     size_t curNumRows 
= m_data
.GetCount(); 
3078     if ( pos 
>= curNumRows 
) 
3081         errmsg
.Printf(wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"), 
3082                       pos
, numRows
, curNumRows 
); 
3083         wxFAIL_MSG( errmsg 
); 
3087     if ( numRows 
> curNumRows 
- pos 
) 
3089         numRows 
= curNumRows 
- pos
; 
3092     if ( numRows 
>= curNumRows 
) 
3094         m_data
.Empty();  // don't release memory just yet 
3098         m_data
.RemoveAt( pos
, numRows 
); 
3102         wxGridTableMessage 
msg( this, 
3103                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3107         GetView()->ProcessTableMessage( msg 
); 
3113 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3117     size_t curNumRows 
= m_data
.GetCount(); 
3118     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3119                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3121     if ( pos 
>= curNumCols 
) 
3123         return AppendCols( numCols 
); 
3126     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3128         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3130             m_data
[row
].Insert( wxEmptyString
, col 
); 
3135         wxGridTableMessage 
msg( this, 
3136                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3140         GetView()->ProcessTableMessage( msg 
); 
3146 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3150     size_t curNumRows 
= m_data
.GetCount(); 
3154         // TODO: something better than this ? 
3156         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3161     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3163         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3168         wxGridTableMessage 
msg( this, 
3169                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3172         GetView()->ProcessTableMessage( msg 
); 
3178 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3182     size_t curNumRows 
= m_data
.GetCount(); 
3183     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3184                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3186     if ( pos 
>= curNumCols 
) 
3189         errmsg
.Printf( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"), 
3190                         pos
, numCols
, curNumCols 
); 
3191         wxFAIL_MSG( errmsg 
); 
3195     if ( numCols 
> curNumCols 
- pos 
) 
3197         numCols 
= curNumCols 
- pos
; 
3200     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3202         if ( numCols 
>= curNumCols 
) 
3204             m_data
[row
].Clear(); 
3208             m_data
[row
].RemoveAt( pos
, numCols 
); 
3213         wxGridTableMessage 
msg( this, 
3214                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3218         GetView()->ProcessTableMessage( msg 
); 
3224 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3226     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3228         // using default label 
3230         return wxGridTableBase::GetRowLabelValue( row 
); 
3234         return m_rowLabels
[ row 
]; 
3238 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3240     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3242         // using default label 
3244         return wxGridTableBase::GetColLabelValue( col 
); 
3248         return m_colLabels
[ col 
]; 
3252 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3254     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3256         int n 
= m_rowLabels
.GetCount(); 
3258         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3260             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3264     m_rowLabels
[row
] = value
; 
3267 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3269     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3271         int n 
= m_colLabels
.GetCount(); 
3273         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3275             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3279     m_colLabels
[col
] = value
; 
3284 ////////////////////////////////////////////////////////////////////// 
3285 ////////////////////////////////////////////////////////////////////// 
3287 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3289 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3290     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3291     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3292     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3293     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3294     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3297 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3299                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3300   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3305 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3309     // NO - don't do this because it will set both the x and y origin 
3310     // coords to match the parent scrolled window and we just want to 
3311     // set the y coord  - MB 
3313     // m_owner->PrepareDC( dc ); 
3316     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3317     dc
.SetDeviceOrigin( 0, -y 
); 
3319     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3320     m_owner
->DrawRowLabels( dc 
, rows 
); 
3324 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3326     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3330 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3332     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3336 // This seems to be required for wxMotif otherwise the mouse 
3337 // cursor must be in the cell edit control to get key events 
3339 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3341     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3344 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3346     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3351 ////////////////////////////////////////////////////////////////////// 
3353 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3355 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3356     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3357     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3358     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3359     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3360     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3363 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3365                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3366   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3371 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3375     // NO - don't do this because it will set both the x and y origin 
3376     // coords to match the parent scrolled window and we just want to 
3377     // set the x coord  - MB 
3379     // m_owner->PrepareDC( dc ); 
3382     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3383     dc
.SetDeviceOrigin( -x
, 0 ); 
3385     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3386     m_owner
->DrawColLabels( dc 
, cols 
); 
3390 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3392     m_owner
->ProcessColLabelMouseEvent( event 
); 
3395 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3397     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3401 // This seems to be required for wxMotif otherwise the mouse 
3402 // cursor must be in the cell edit control to get key events 
3404 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3406     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3409 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3411     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3416 ////////////////////////////////////////////////////////////////////// 
3418 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3420 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3421     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3422     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3423     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3424     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3425     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3428 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3430                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3431   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3436 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3440     int client_height 
= 0; 
3441     int client_width 
= 0; 
3442     GetClientSize( &client_width
, &client_height 
); 
3444     dc
.SetPen( *wxBLACK_PEN 
); 
3445     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3446     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3448     dc
.SetPen( *wxWHITE_PEN 
); 
3449     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3450     dc
.DrawLine( 0, 0, 0, client_height 
); 
3454 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3456     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3460 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3462     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3465 // This seems to be required for wxMotif otherwise the mouse 
3466 // cursor must be in the cell edit control to get key events 
3468 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3470     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3473 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3475     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3480 ////////////////////////////////////////////////////////////////////// 
3482 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3484 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3485     EVT_PAINT( wxGridWindow::OnPaint 
) 
3486     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3487     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3488     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3489     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3490     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3493 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3494                             wxGridRowLabelWindow 
*rowLblWin
, 
3495                             wxGridColLabelWindow 
*colLblWin
, 
3496                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
3497         : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
, "grid window" ) 
3500     m_rowLabelWin 
= rowLblWin
; 
3501     m_colLabelWin 
= colLblWin
; 
3502     SetBackgroundColour(_T("WHITE")); 
3506 wxGridWindow::~wxGridWindow() 
3511 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3513     wxPaintDC 
dc( this ); 
3514     m_owner
->PrepareDC( dc 
); 
3515     wxRegion reg 
= GetUpdateRegion(); 
3516     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3517     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3518 #if WXGRID_DRAW_LINES 
3519     m_owner
->DrawAllGridLines( dc
, reg 
); 
3521     m_owner
->DrawGridSpace( dc 
); 
3522     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3526 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3528     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3529     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3530     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3534 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3536     m_owner
->ProcessGridCellMouseEvent( event 
); 
3539 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3541     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3544 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3545 // cursor must be in the cell edit control to get key events 
3547 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3549     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3552 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3554     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3557 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3562 ////////////////////////////////////////////////////////////////////// 
3564 // Internal Helper function for computing row or column from some 
3565 // (unscrolled) coordinate value, using either 
3566 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
3567 // of m_rowBottoms/m_ColRights to speed up the search! 
3569 // Internal helper macros for simpler use of that function 
3571 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
3572                            const wxArrayInt
& BorderArray
, bool maxOnOverflow
); 
3574 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ 
3575                                           WXGRID_MIN_COL_WIDTH, \ 
3577 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
3578                                           WXGRID_MIN_ROW_HEIGHT, \ 
3580 ///////////////////////////////////////////////////////////////////// 
3582 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3584 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3585     EVT_PAINT( wxGrid::OnPaint 
) 
3586     EVT_SIZE( wxGrid::OnSize 
) 
3587     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3588     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3589     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3592 wxGrid::wxGrid( wxWindow 
*parent
, 
3597                  const wxString
& name 
) 
3598   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3599     m_colMinWidths(GRID_HASH_SIZE
), 
3600     m_rowMinHeights(GRID_HASH_SIZE
) 
3608     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3609     SetTargetWindow(this); 
3611     wxSafeDecRef(m_defaultCellAttr
); 
3613 #ifdef DEBUG_ATTR_CACHE 
3614     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3615     wxPrintf(_T("wxGrid attribute cache statistics: " 
3616                 "total: %u, hits: %u (%u%%)\n"), 
3617              total
, gs_nAttrCacheHits
, 
3618              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3624     delete m_typeRegistry
; 
3630 // ----- internal init and update functions 
3633 void wxGrid::Create() 
3635     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3637     m_table        
= (wxGridTableBase 
*) NULL
; 
3640     m_cellEditCtrlEnabled 
= FALSE
; 
3642     m_defaultCellAttr 
= new wxGridCellAttr(); 
3644     // Set default cell attributes 
3645     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3646     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3647     m_defaultCellAttr
->SetFont(GetFont()); 
3648     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3649     m_defaultCellAttr
->SetTextColour( 
3650         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3651     m_defaultCellAttr
->SetBackgroundColour( 
3652         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
3653     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3654     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3659     m_currentCellCoords 
= wxGridNoCellCoords
; 
3661     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3662     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3664     // create the type registry 
3665     m_typeRegistry 
= new wxGridTypeRegistry
; 
3668     // subwindow components that make up the wxGrid 
3669     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3674     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3679     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3684     m_gridWin 
= new wxGridWindow( this, 
3691     SetTargetWindow( m_gridWin 
); 
3697 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3698                          wxGrid::wxGridSelectionModes selmode 
) 
3700     wxCHECK_MSG( !m_created
, 
3702                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3704     m_numRows 
= numRows
; 
3705     m_numCols 
= numCols
; 
3707     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3708     m_table
->SetView( this ); 
3710     m_selection 
= new wxGridSelection( this, selmode 
); 
3719 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3721     wxCHECK_RET( m_created
, 
3722                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3724     m_selection
->SetSelectionMode( selmode 
); 
3727 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3728                        wxGrid::wxGridSelectionModes selmode 
) 
3732         // RD: Actually, this should probably be allowed.  I think it would be 
3733         //     nice to be able to switch multiple Tables in and out of a single 
3734         //     View at runtime.  Is there anything in the implementation that 
3735         //     would prevent this? 
3737         // At least, you now have to cope with m_selection 
3738         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3743         m_numRows 
= table
->GetNumberRows(); 
3744         m_numCols 
= table
->GetNumberCols(); 
3747         m_table
->SetView( this ); 
3750         m_selection 
= new wxGridSelection( this, selmode 
); 
3763     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3764     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3766     if ( m_rowLabelWin 
) 
3768         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3772         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3775     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3778     m_attrCache
.row 
= -1; 
3780     // TODO: something better than this ? 
3782     m_labelFont 
= this->GetFont(); 
3783     m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 ); 
3785     m_rowLabelHorizAlign 
= wxALIGN_LEFT
; 
3786     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3788     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3789     m_colLabelVertAlign  
= wxALIGN_TOP
; 
3791     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3792     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3794 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3795     m_defaultRowHeight 
+= 8; 
3797     m_defaultRowHeight 
+= 4; 
3800     m_gridLineColour 
= wxColour( 128, 128, 255 ); 
3801     m_gridLinesEnabled 
= TRUE
; 
3802     m_cellHighlightColour 
= m_gridLineColour
; 
3803     m_cellHighlightPenWidth 
= 2; 
3804     m_cellHighlightROPenWidth 
= 1; 
3806     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3807     m_winCapture 
= (wxWindow 
*)NULL
; 
3808     m_canDragRowSize 
= TRUE
; 
3809     m_canDragColSize 
= TRUE
; 
3810     m_canDragGridSize 
= TRUE
; 
3812     m_dragRowOrCol 
= -1; 
3813     m_isDragging 
= FALSE
; 
3814     m_startDragPos 
= wxDefaultPosition
; 
3816     m_waitForSlowClick 
= FALSE
; 
3818     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3819     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3821     m_currentCellCoords 
= wxGridNoCellCoords
; 
3823     m_selectingTopLeft 
= wxGridNoCellCoords
; 
3824     m_selectingBottomRight 
= wxGridNoCellCoords
; 
3825     m_selectionBackground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
3826     m_selectionForeground 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3828     m_editable 
= TRUE
;  // default for whole grid 
3830     m_inOnKeyDown 
= FALSE
; 
3837 // ---------------------------------------------------------------------------- 
3838 // the idea is to call these functions only when necessary because they create 
3839 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3840 // default widths/heights are used for all rows/columns, we may not use these 
3843 // with some extra code, it should be possible to only store the 
3844 // widths/heights different from default ones but this will be done later... 
3845 // ---------------------------------------------------------------------------- 
3847 void wxGrid::InitRowHeights() 
3849     m_rowHeights
.Empty(); 
3850     m_rowBottoms
.Empty(); 
3852     m_rowHeights
.Alloc( m_numRows 
); 
3853     m_rowBottoms
.Alloc( m_numRows 
); 
3857     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
3859     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3861         rowBottom 
+= m_defaultRowHeight
; 
3862         m_rowBottoms
.Add( rowBottom 
); 
3866 void wxGrid::InitColWidths() 
3868     m_colWidths
.Empty(); 
3869     m_colRights
.Empty(); 
3871     m_colWidths
.Alloc( m_numCols 
); 
3872     m_colRights
.Alloc( m_numCols 
); 
3875     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
3877     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
3879         colRight 
+= m_defaultColWidth
; 
3880         m_colRights
.Add( colRight 
); 
3884 int wxGrid::GetColWidth(int col
) const 
3886     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
3889 int wxGrid::GetColLeft(int col
) const 
3891     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
3892                                  : m_colRights
[col
] - m_colWidths
[col
]; 
3895 int wxGrid::GetColRight(int col
) const 
3897     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
3901 int wxGrid::GetRowHeight(int row
) const 
3903     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
3906 int wxGrid::GetRowTop(int row
) const 
3908     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
3909                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
3912 int wxGrid::GetRowBottom(int row
) const 
3914     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
3915                                   : m_rowBottoms
[row
]; 
3918 void wxGrid::CalcDimensions() 
3921     GetClientSize( &cw
, &ch 
); 
3923     if ( m_rowLabelWin
->IsShown() ) 
3924         cw 
-= m_rowLabelWidth
; 
3925     if ( m_colLabelWin
->IsShown() ) 
3926         ch 
-= m_colLabelHeight
; 
3929     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
3930     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
3932     // preserve (more or less) the previous position 
3934     GetViewStart( &x
, &y 
); 
3936     // maybe we don't need scrollbars at all? 
3938     // also adjust the position to be valid for the new scroll rangs 
3959     // do set scrollbar parameters 
3960     SetScrollbars( GRID_SCROLL_LINE_X
, GRID_SCROLL_LINE_Y
, 
3961                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
3962                    GetBatchCount() != 0); 
3964     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
3965     // still must reposition the children 
3970 void wxGrid::CalcWindowSizes() 
3973     GetClientSize( &cw
, &ch 
); 
3975     if ( m_cornerLabelWin
->IsShown() ) 
3976         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
3978     if ( m_colLabelWin
->IsShown() ) 
3979         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
3981     if ( m_rowLabelWin
->IsShown() ) 
3982         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3984     if ( m_gridWin
->IsShown() ) 
3985         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
3989 // this is called when the grid table sends a message to say that it 
3990 // has been redimensioned 
3992 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
3995     bool result 
= FALSE
; 
3998     // if we were using the default widths/heights so far, we must change them 
4000     if ( m_colWidths
.IsEmpty() ) 
4005     if ( m_rowHeights
.IsEmpty() ) 
4011     switch ( msg
.GetId() ) 
4013         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4015             size_t pos 
= msg
.GetCommandInt(); 
4016             int numRows 
= msg
.GetCommandInt2(); 
4018             m_numRows 
+= numRows
; 
4020             if ( !m_rowHeights
.IsEmpty() ) 
4022                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4023                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4026                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
4028                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
4030                     bottom 
+= m_rowHeights
[i
]; 
4031                     m_rowBottoms
[i
] = bottom
; 
4034             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4036                 // if we have just inserted cols into an empty grid the current 
4037                 // cell will be undefined... 
4039                 SetCurrentCell( 0, 0 ); 
4043                 m_selection
->UpdateRows( pos
, numRows 
); 
4044             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4046                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4048             if ( !GetBatchCount() ) 
4051                 m_rowLabelWin
->Refresh(); 
4057         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4059             int numRows 
= msg
.GetCommandInt(); 
4060             int oldNumRows 
= m_numRows
; 
4061             m_numRows 
+= numRows
; 
4063             if ( !m_rowHeights
.IsEmpty() ) 
4065                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4066                 m_rowBottoms
.Add( 0, numRows 
); 
4069                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
4071                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
4073                     bottom 
+= m_rowHeights
[i
]; 
4074                     m_rowBottoms
[i
] = bottom
; 
4077             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4079                 // if we have just inserted cols into an empty grid the current 
4080                 // cell will be undefined... 
4082                 SetCurrentCell( 0, 0 ); 
4084             if ( !GetBatchCount() ) 
4087                 m_rowLabelWin
->Refresh(); 
4093         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4095             size_t pos 
= msg
.GetCommandInt(); 
4096             int numRows 
= msg
.GetCommandInt2(); 
4097             m_numRows 
-= numRows
; 
4099             if ( !m_rowHeights
.IsEmpty() ) 
4101                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4102                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4105                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4107                     h 
+= m_rowHeights
[i
]; 
4108                     m_rowBottoms
[i
] = h
; 
4113                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4117                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4118                     m_currentCellCoords
.Set( 0, 0 ); 
4122                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4123             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4125                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4126 // ifdef'd out following patch from Paul Gammans 
4128                 // No need to touch column attributes, unless we 
4129                 // removed _all_ rows, in this case, we remove 
4130                 // all column attributes. 
4131                 // I hate to do this here, but the 
4132                 // needed data is not available inside UpdateAttrRows. 
4133                 if ( !GetNumberRows() ) 
4134                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4137             if ( !GetBatchCount() ) 
4140                 m_rowLabelWin
->Refresh(); 
4146         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4148             size_t pos 
= msg
.GetCommandInt(); 
4149             int numCols 
= msg
.GetCommandInt2(); 
4150             m_numCols 
+= numCols
; 
4152             if ( !m_colWidths
.IsEmpty() ) 
4154                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4155                 m_colRights
.Insert( 0, pos
, numCols 
); 
4158                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4160                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4162                     right 
+= m_colWidths
[i
]; 
4163                     m_colRights
[i
] = right
; 
4166             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4168                 // if we have just inserted cols into an empty grid the current 
4169                 // cell will be undefined... 
4171                 SetCurrentCell( 0, 0 ); 
4175                 m_selection
->UpdateCols( pos
, numCols 
); 
4176             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4178                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4179             if ( !GetBatchCount() ) 
4182                 m_colLabelWin
->Refresh(); 
4189         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4191             int numCols 
= msg
.GetCommandInt(); 
4192             int oldNumCols 
= m_numCols
; 
4193             m_numCols 
+= numCols
; 
4194             if ( !m_colWidths
.IsEmpty() ) 
4196                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4197                 m_colRights
.Add( 0, numCols 
); 
4200                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4202                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4204                     right 
+= m_colWidths
[i
]; 
4205                     m_colRights
[i
] = right
; 
4208             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4210                 // if we have just inserted cols into an empty grid the current 
4211                 // cell will be undefined... 
4213                 SetCurrentCell( 0, 0 ); 
4215             if ( !GetBatchCount() ) 
4218                 m_colLabelWin
->Refresh(); 
4224         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4226             size_t pos 
= msg
.GetCommandInt(); 
4227             int numCols 
= msg
.GetCommandInt2(); 
4228             m_numCols 
-= numCols
; 
4230             if ( !m_colWidths
.IsEmpty() ) 
4232                 m_colWidths
.RemoveAt( pos
, numCols 
); 
4233                 m_colRights
.RemoveAt( pos
, numCols 
); 
4236                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4238                     w 
+= m_colWidths
[i
]; 
4244                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4248                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4249                   m_currentCellCoords
.Set( 0, 0 ); 
4253                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4254             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4256                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4257 // ifdef'd out following patch from Paul Gammans 
4259                 // No need to touch row attributes, unless we 
4260                 // removed _all_ columns, in this case, we remove 
4261                 // all row attributes. 
4262                 // I hate to do this here, but the 
4263                 // needed data is not available inside UpdateAttrCols. 
4264                 if ( !GetNumberCols() ) 
4265                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4268             if ( !GetBatchCount() ) 
4271                 m_colLabelWin
->Refresh(); 
4278     if (result 
&& !GetBatchCount() ) 
4279         m_gridWin
->Refresh(); 
4284 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4286     wxRegionIterator 
iter( reg 
); 
4289     wxArrayInt  rowlabels
; 
4296         // TODO: remove this when we can... 
4297         // There is a bug in wxMotif that gives garbage update 
4298         // rectangles if you jump-scroll a long way by clicking the 
4299         // scrollbar with middle button.  This is a work-around 
4301 #if defined(__WXMOTIF__) 
4303         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4304         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4305         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4308         // logical bounds of update region 
4311         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4312         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4314         // find the row labels within these bounds 
4317         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4319             if ( GetRowBottom(row
) < top 
) 
4322             if ( GetRowTop(row
) > bottom 
) 
4325             rowlabels
.Add( row 
); 
4335 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4337     wxRegionIterator 
iter( reg 
); 
4340     wxArrayInt colLabels
; 
4347         // TODO: remove this when we can... 
4348         // There is a bug in wxMotif that gives garbage update 
4349         // rectangles if you jump-scroll a long way by clicking the 
4350         // scrollbar with middle button.  This is a work-around 
4352 #if defined(__WXMOTIF__) 
4354         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4355         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4356         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4359         // logical bounds of update region 
4362         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4363         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4365         // find the cells within these bounds 
4368         for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4370             if ( GetColRight(col
) < left 
) 
4373             if ( GetColLeft(col
) > right 
) 
4376             colLabels
.Add( col 
); 
4385 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4387     wxRegionIterator 
iter( reg 
); 
4390     wxGridCellCoordsArray  cellsExposed
; 
4392     int left
, top
, right
, bottom
; 
4397         // TODO: remove this when we can... 
4398         // There is a bug in wxMotif that gives garbage update 
4399         // rectangles if you jump-scroll a long way by clicking the 
4400         // scrollbar with middle button.  This is a work-around 
4402 #if defined(__WXMOTIF__) 
4404         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4405         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4406         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4407         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4408         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4411         // logical bounds of update region 
4413         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4414         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4416         // find the cells within these bounds 
4419         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4421             if ( GetRowBottom(row
) <= top 
) 
4424             if ( GetRowTop(row
) > bottom 
) 
4427             for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4429                 if ( GetColRight(col
) <= left 
) 
4432                 if ( GetColLeft(col
) > right 
) 
4435                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4442     return cellsExposed
; 
4446 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4449     wxPoint 
pos( event
.GetPosition() ); 
4450     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4452     if ( event
.Dragging() ) 
4456             m_isDragging 
= TRUE
; 
4457             m_rowLabelWin
->CaptureMouse(); 
4460         if ( event
.LeftIsDown() ) 
4462             switch( m_cursorMode 
) 
4464                 case WXGRID_CURSOR_RESIZE_ROW
: 
4466                     int cw
, ch
, left
, dummy
; 
4467                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4468                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4470                     wxClientDC 
dc( m_gridWin 
); 
4473                                GetRowTop(m_dragRowOrCol
) + 
4474                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4475                     dc
.SetLogicalFunction(wxINVERT
); 
4476                     if ( m_dragLastPos 
>= 0 ) 
4478                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4480                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4485                 case WXGRID_CURSOR_SELECT_ROW
: 
4486                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4490                             m_selection
->SelectRow( row
, 
4491                                                     event
.ControlDown(), 
4498                 // default label to suppress warnings about "enumeration value 
4499                 // 'xxx' not handled in switch 
4507     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4512         if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse(); 
4513         m_isDragging 
= FALSE
; 
4516     // ------------ Entering or leaving the window 
4518     if ( event
.Entering() || event
.Leaving() ) 
4520         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4524     // ------------ Left button pressed 
4526     else if ( event
.LeftDown() ) 
4528         // don't send a label click event for a hit on the 
4529         // edge of the row label - this is probably the user 
4530         // wanting to resize the row 
4532         if ( YToEdgeOfRow(y
) < 0 ) 
4536                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4538                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4540                 else if ( m_selection 
) 
4542                     if ( event
.ShiftDown() ) 
4544                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4547                                                   GetNumberCols() - 1, 
4548                                                   event
.ControlDown(), 
4555                         m_selection
->SelectRow( row
, 
4556                                                 event
.ControlDown(), 
4563                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4568             // starting to drag-resize a row 
4570             if ( CanDragRowSize() ) 
4571                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4576     // ------------ Left double click 
4578     else if (event
.LeftDClick() ) 
4580         if ( YToEdgeOfRow(y
) < 0 ) 
4583             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
4588     // ------------ Left button released 
4590     else if ( event
.LeftUp() ) 
4592         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4594             DoEndDragResizeRow(); 
4596             // Note: we are ending the event *after* doing 
4597             // default processing in this case 
4599             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4602         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4607     // ------------ Right button down 
4609     else if ( event
.RightDown() ) 
4612         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4614             // no default action at the moment 
4619     // ------------ Right double click 
4621     else if ( event
.RightDClick() ) 
4624         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4626             // no default action at the moment 
4631     // ------------ No buttons down and mouse moving 
4633     else if ( event
.Moving() ) 
4635         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4636         if ( m_dragRowOrCol 
>= 0 ) 
4638             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4640                 // don't capture the mouse yet 
4641                 if ( CanDragRowSize() ) 
4642                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4645         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4647             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4653 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4656     wxPoint 
pos( event
.GetPosition() ); 
4657     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4659     if ( event
.Dragging() ) 
4663             m_isDragging 
= TRUE
; 
4664             m_colLabelWin
->CaptureMouse(); 
4667         if ( event
.LeftIsDown() ) 
4669             switch( m_cursorMode 
) 
4671                 case WXGRID_CURSOR_RESIZE_COL
: 
4673                     int cw
, ch
, dummy
, top
; 
4674                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4675                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4677                     wxClientDC 
dc( m_gridWin 
); 
4680                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4681                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4682                     dc
.SetLogicalFunction(wxINVERT
); 
4683                     if ( m_dragLastPos 
>= 0 ) 
4685                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4687                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4692                 case WXGRID_CURSOR_SELECT_COL
: 
4693                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4697                             m_selection
->SelectCol( col
, 
4698                                                     event
.ControlDown(), 
4705                 // default label to suppress warnings about "enumeration value 
4706                 // 'xxx' not handled in switch 
4714     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4719         if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse(); 
4720         m_isDragging 
= FALSE
; 
4723     // ------------ Entering or leaving the window 
4725     if ( event
.Entering() || event
.Leaving() ) 
4727         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4731     // ------------ Left button pressed 
4733     else if ( event
.LeftDown() ) 
4735         // don't send a label click event for a hit on the 
4736         // edge of the col label - this is probably the user 
4737         // wanting to resize the col 
4739         if ( XToEdgeOfCol(x
) < 0 ) 
4743                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4745                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4749                     if ( event
.ShiftDown() ) 
4751                         m_selection
->SelectBlock( 0, 
4752                                                   m_currentCellCoords
.GetCol(), 
4753                                                   GetNumberRows() - 1, col
, 
4754                                                   event
.ControlDown(), 
4761                         m_selection
->SelectCol( col
, 
4762                                                 event
.ControlDown(), 
4769                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
4774             // starting to drag-resize a col 
4776             if ( CanDragColSize() ) 
4777                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
4782     // ------------ Left double click 
4784     if ( event
.LeftDClick() ) 
4786         if ( XToEdgeOfCol(x
) < 0 ) 
4789             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
4794     // ------------ Left button released 
4796     else if ( event
.LeftUp() ) 
4798         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4800             DoEndDragResizeCol(); 
4802             // Note: we are ending the event *after* doing 
4803             // default processing in this case 
4805             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4808         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4813     // ------------ Right button down 
4815     else if ( event
.RightDown() ) 
4818         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
4820             // no default action at the moment 
4825     // ------------ Right double click 
4827     else if ( event
.RightDClick() ) 
4830         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
4832             // no default action at the moment 
4837     // ------------ No buttons down and mouse moving 
4839     else if ( event
.Moving() ) 
4841         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
4842         if ( m_dragRowOrCol 
>= 0 ) 
4844             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4846                 // don't capture the cursor yet 
4847                 if ( CanDragColSize() ) 
4848                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
4851         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4853             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
4859 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
4861     if ( event
.LeftDown() ) 
4863         // indicate corner label by having both row and 
4866         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
4872     else if ( event
.LeftDClick() ) 
4874         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
4877     else if ( event
.RightDown() ) 
4879         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
4881             // no default action at the moment 
4885     else if ( event
.RightDClick() ) 
4887         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
4889             // no default action at the moment 
4894 void wxGrid::ChangeCursorMode(CursorMode mode
, 
4899     static const wxChar 
*cursorModes
[] = 
4908     wxLogTrace(_T("grid"), 
4909                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
4910                win 
== m_colLabelWin 
? _T("colLabelWin") 
4911                                     : win 
? _T("rowLabelWin") 
4913                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
4914 #endif // __WXDEBUG__ 
4916     if ( mode 
== m_cursorMode 
&& 
4917          win 
== m_winCapture 
&& 
4918          captureMouse 
== (m_winCapture 
!= NULL
)) 
4923         // by default use the grid itself 
4929         if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
4930         m_winCapture 
= (wxWindow 
*)NULL
; 
4933     m_cursorMode 
= mode
; 
4935     switch ( m_cursorMode 
) 
4937         case WXGRID_CURSOR_RESIZE_ROW
: 
4938             win
->SetCursor( m_rowResizeCursor 
); 
4941         case WXGRID_CURSOR_RESIZE_COL
: 
4942             win
->SetCursor( m_colResizeCursor 
); 
4946             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
4949     // we need to capture mouse when resizing 
4950     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
4951                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
4953     if ( captureMouse 
&& resize 
) 
4955         win
->CaptureMouse(); 
4960 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
4963     wxPoint 
pos( event
.GetPosition() ); 
4964     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4966     wxGridCellCoords coords
; 
4967     XYToCell( x
, y
, coords 
); 
4969     int cell_rows
, cell_cols
; 
4970     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
4971     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
4973         coords
.SetRow(coords
.GetRow() + cell_rows
); 
4974         coords
.SetCol(coords
.GetCol() + cell_cols
); 
4977     if ( event
.Dragging() ) 
4979         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
4981         // Don't start doing anything until the mouse has been drug at 
4982         // least 3 pixels in any direction... 
4985             if (m_startDragPos 
== wxDefaultPosition
) 
4987                 m_startDragPos 
= pos
; 
4990             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
4994         m_isDragging 
= TRUE
; 
4995         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4997             // Hide the edit control, so it 
4998             // won't interfer with drag-shrinking. 
4999             if ( IsCellEditControlShown() ) 
5001                 HideCellEditControl(); 
5002                 SaveEditControlValue(); 
5005             // Have we captured the mouse yet? 
5008                 m_winCapture 
= m_gridWin
; 
5009                 m_winCapture
->CaptureMouse(); 
5012             if ( coords 
!= wxGridNoCellCoords 
) 
5014                 if ( event
.ControlDown() ) 
5016                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5017                         m_selectingKeyboard 
= coords
; 
5018                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
5022                     if ( !IsSelection() ) 
5024                         HighlightBlock( coords
, coords 
); 
5028                         HighlightBlock( m_currentCellCoords
, coords 
); 
5032                 if (! IsVisible(coords
)) 
5034                     MakeCellVisible(coords
); 
5035                     // TODO: need to introduce a delay or something here.  The 
5036                     // scrolling is way to fast, at least on MSW - also on GTK. 
5040         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5042             int cw
, ch
, left
, dummy
; 
5043             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5044             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5046             wxClientDC 
dc( m_gridWin 
); 
5048             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
5049                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
5050             dc
.SetLogicalFunction(wxINVERT
); 
5051             if ( m_dragLastPos 
>= 0 ) 
5053                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5055             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5058         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5060             int cw
, ch
, dummy
, top
; 
5061             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5062             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5064             wxClientDC 
dc( m_gridWin 
); 
5066             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5067                           GetColMinimalWidth(m_dragRowOrCol
) ); 
5068             dc
.SetLogicalFunction(wxINVERT
); 
5069             if ( m_dragLastPos 
>= 0 ) 
5071                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5073             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5080     m_isDragging 
= FALSE
; 
5081     m_startDragPos 
= wxDefaultPosition
; 
5083     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
5084     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
5087     if ( event
.Entering() || event
.Leaving() ) 
5089         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5090         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
5095     // ------------ Left button pressed 
5097     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
5099         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
5104             if ( !event
.ControlDown() ) 
5106             if ( event
.ShiftDown() ) 
5110                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5111                                               m_currentCellCoords
.GetCol(), 
5114                                               event
.ControlDown(), 
5120             else if ( XToEdgeOfCol(x
) < 0  && 
5121                       YToEdgeOfRow(y
) < 0 ) 
5123                 DisableCellEditControl(); 
5124                 MakeCellVisible( coords 
); 
5126                 // if this is the second click on this cell then start 
5128                 if ( m_waitForSlowClick 
&& 
5129                      (coords 
== m_currentCellCoords
) && 
5130                      CanEnableCellControl()) 
5132                     EnableCellEditControl(); 
5134                     wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
5135                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, 
5138                     editor
->StartingClick(); 
5142                     m_waitForSlowClick 
= FALSE
; 
5146                     if ( event
.ControlDown() ) 
5150                             m_selection
->ToggleCellSelection( coords
.GetRow(), 
5152                                                               event
.ControlDown(), 
5157                         m_selectingTopLeft 
= wxGridNoCellCoords
; 
5158                         m_selectingBottomRight 
= wxGridNoCellCoords
; 
5159                         m_selectingKeyboard 
= coords
; 
5163                         SetCurrentCell( coords 
); 
5166                             if ( m_selection
->GetSelectionMode() != 
5167                                     wxGrid::wxGridSelectCells 
) 
5169                                 HighlightBlock( coords
, coords 
); 
5173                     m_waitForSlowClick 
= TRUE
; 
5180     // ------------ Left double click 
5182     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5184         DisableCellEditControl(); 
5186         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5188             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5196     // ------------ Left button released 
5198     else if ( event
.LeftUp() ) 
5200         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5202             if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5203                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5207                     if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5208                     m_winCapture 
= NULL
; 
5213                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5214                                               m_selectingTopLeft
.GetCol(), 
5215                                               m_selectingBottomRight
.GetRow(), 
5216                                               m_selectingBottomRight
.GetCol(), 
5217                                               event
.ControlDown(), 
5223                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5224                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5227             // Show the edit control, if it has been hidden for 
5229             ShowCellEditControl(); 
5231         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5233             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5234             DoEndDragResizeRow(); 
5236             // Note: we are ending the event *after* doing 
5237             // default processing in this case 
5239             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5241         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5243             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5244             DoEndDragResizeCol(); 
5246             // Note: we are ending the event *after* doing 
5247             // default processing in this case 
5249             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5256     // ------------ Right button down 
5258     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5260         DisableCellEditControl(); 
5261         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5266             // no default action at the moment 
5271     // ------------ Right double click 
5273     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5275         DisableCellEditControl(); 
5276         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5281             // no default action at the moment 
5285     // ------------ Moving and no button action 
5287     else if ( event
.Moving() && !event
.IsButton() ) 
5289         int dragRow 
= YToEdgeOfRow( y 
); 
5290         int dragCol 
= XToEdgeOfCol( x 
); 
5292         // Dragging on the corner of a cell to resize in both 
5293         // directions is not implemented yet... 
5295         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5297             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5303             m_dragRowOrCol 
= dragRow
; 
5305             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5307                 if ( CanDragRowSize() && CanDragGridSize() ) 
5308                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5313                 m_dragRowOrCol 
= dragCol
; 
5321             m_dragRowOrCol 
= dragCol
; 
5323             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5325                 if ( CanDragColSize() && CanDragGridSize() ) 
5326                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5332         // Neither on a row or col edge 
5334         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5336             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5342 void wxGrid::DoEndDragResizeRow() 
5344     if ( m_dragLastPos 
>= 0 ) 
5346         // erase the last line and resize the row 
5348         int cw
, ch
, left
, dummy
; 
5349         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5350         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5352         wxClientDC 
dc( m_gridWin 
); 
5354         dc
.SetLogicalFunction( wxINVERT 
); 
5355         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5356         HideCellEditControl(); 
5357         SaveEditControlValue(); 
5359         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5360         SetRowSize( m_dragRowOrCol
, 
5361                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
5363         if ( !GetBatchCount() ) 
5365             // Only needed to get the correct rect.y: 
5366             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5368             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5369             rect
.width 
= m_rowLabelWidth
; 
5370             rect
.height 
= ch 
- rect
.y
; 
5371             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5373             // if there is a multicell block, paint all of it 
5376                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
5377                 int leftCol 
= XToCol(left
); 
5378                 int rightCol 
= XToCol(left
+cw
); 
5381                     if (rightCol 
< 0) rightCol 
= m_numCols
; 
5382                     for (i
=leftCol
; i
<rightCol
; i
++) 
5384                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
5385                         if (cell_rows 
< subtract_rows
) 
5386                             subtract_rows 
= cell_rows
; 
5388                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
5389                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5390                     rect
.height 
= ch 
- rect
.y
; 
5393             m_gridWin
->Refresh( FALSE
, &rect 
); 
5396         ShowCellEditControl(); 
5401 void wxGrid::DoEndDragResizeCol() 
5403     if ( m_dragLastPos 
>= 0 ) 
5405         // erase the last line and resize the col 
5407         int cw
, ch
, dummy
, top
; 
5408         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5409         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5411         wxClientDC 
dc( m_gridWin 
); 
5413         dc
.SetLogicalFunction( wxINVERT 
); 
5414         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5415         HideCellEditControl(); 
5416         SaveEditControlValue(); 
5418         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5419         SetColSize( m_dragRowOrCol
, 
5420                     wxMax( m_dragLastPos 
- colLeft
, 
5421                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5423         if ( !GetBatchCount() ) 
5425             // Only needed to get the correct rect.x: 
5426             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5428             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5429             rect
.width 
= cw 
- rect
.x
; 
5430             rect
.height 
= m_colLabelHeight
; 
5431             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5433             // if there is a multicell block, paint all of it 
5436                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
5437                 int topRow 
= YToRow(top
); 
5438                 int bottomRow 
= YToRow(top
+cw
); 
5441                     if (bottomRow 
< 0) bottomRow 
= m_numRows
; 
5442                     for (i
=topRow
; i
<bottomRow
; i
++) 
5444                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
5445                         if (cell_cols 
< subtract_cols
) 
5446                             subtract_cols 
= cell_cols
; 
5448                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
5449                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5450                     rect
.width 
= cw 
- rect
.x
; 
5453             m_gridWin
->Refresh( FALSE
, &rect 
); 
5456         ShowCellEditControl(); 
5463 // ------ interaction with data model 
5465 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5467     switch ( msg
.GetId() ) 
5469         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5470             return GetModelValues(); 
5472         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5473             return SetModelValues(); 
5475         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5476         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5477         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5478         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5479         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5480         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5481             return Redimension( msg 
); 
5490 // The behaviour of this function depends on the grid table class 
5491 // Clear() function.  For the default wxGridStringTable class the 
5492 // behavious is to replace all cell contents with wxEmptyString but 
5493 // not to change the number of rows or cols. 
5495 void wxGrid::ClearGrid() 
5499         if (IsCellEditControlEnabled()) 
5500             DisableCellEditControl(); 
5503         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5508 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5510     // TODO: something with updateLabels flag 
5514         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5520         if (IsCellEditControlEnabled()) 
5521             DisableCellEditControl(); 
5523         return m_table
->InsertRows( pos
, numRows 
); 
5525         // the table will have sent the results of the insert row 
5526         // operation to this view object as a grid table message 
5532 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5534     // TODO: something with updateLabels flag 
5538         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5542     return ( m_table 
&& m_table
->AppendRows( numRows 
) ); 
5543     // the table will have sent the results of the append row 
5544     // operation to this view object as a grid table message 
5548 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5550     // TODO: something with updateLabels flag 
5554         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5560         if (IsCellEditControlEnabled()) 
5561             DisableCellEditControl(); 
5563         return (m_table
->DeleteRows( pos
, numRows 
)); 
5564         // the table will have sent the results of the delete row 
5565         // operation to this view object as a grid table message 
5571 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5573     // TODO: something with updateLabels flag 
5577         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5583         if (IsCellEditControlEnabled()) 
5584             DisableCellEditControl(); 
5586         return m_table
->InsertCols( pos
, numCols 
); 
5587         // the table will have sent the results of the insert col 
5588         // operation to this view object as a grid table message 
5594 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5596     // TODO: something with updateLabels flag 
5600         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5604     return ( m_table 
&& m_table
->AppendCols( numCols 
) ); 
5605     // the table will have sent the results of the append col 
5606     // operation to this view object as a grid table message 
5610 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5612     // TODO: something with updateLabels flag 
5616         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5622         if (IsCellEditControlEnabled()) 
5623             DisableCellEditControl(); 
5625         return ( m_table
->DeleteCols( pos
, numCols 
) ); 
5626         // the table will have sent the results of the delete col 
5627         // operation to this view object as a grid table message 
5635 // ----- event handlers 
5638 // Generate a grid event based on a mouse event and 
5639 // return the result of ProcessEvent() 
5641 int wxGrid::SendEvent( const wxEventType type
, 
5643                         wxMouseEvent
& mouseEv 
) 
5648    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5650        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5652        wxGridSizeEvent 
gridEvt( GetId(), 
5656                mouseEv
.GetX() + GetRowLabelSize(), 
5657                mouseEv
.GetY() + GetColLabelSize(), 
5658                mouseEv
.ControlDown(), 
5659                mouseEv
.ShiftDown(), 
5661                mouseEv
.MetaDown() ); 
5663        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5664        vetoed 
= !gridEvt
.IsAllowed(); 
5666    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5668        // Right now, it should _never_ end up here! 
5669        wxGridRangeSelectEvent 
gridEvt( GetId(), 
5673                m_selectingBottomRight
, 
5675                mouseEv
.ControlDown(), 
5676                mouseEv
.ShiftDown(), 
5678                mouseEv
.MetaDown() ); 
5680        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5681        vetoed 
= !gridEvt
.IsAllowed(); 
5685        wxGridEvent 
gridEvt( GetId(), 
5689                mouseEv
.GetX() + GetRowLabelSize(), 
5690                mouseEv
.GetY() + GetColLabelSize(), 
5692                mouseEv
.ControlDown(), 
5693                mouseEv
.ShiftDown(), 
5695                mouseEv
.MetaDown() ); 
5696        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5697        vetoed 
= !gridEvt
.IsAllowed(); 
5700    // A Veto'd event may not be `claimed' so test this first 
5701    if (vetoed
) return -1; 
5702    return claimed 
? 1 : 0; 
5706 // Generate a grid event of specified type and return the result 
5707 // of ProcessEvent(). 
5709 int wxGrid::SendEvent( const wxEventType type
, 
5715     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5717         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5719         wxGridSizeEvent 
gridEvt( GetId(), 
5724         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5725         vetoed  
= !gridEvt
.IsAllowed(); 
5729         wxGridEvent 
gridEvt( GetId(), 
5734         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5735         vetoed  
= !gridEvt
.IsAllowed(); 
5738     // A Veto'd event may not be `claimed' so test this first 
5739     if (vetoed
) return -1; 
5740     return claimed 
? 1 : 0; 
5744 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
5746     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
5749 void wxGrid::Refresh(bool eraseb
, wxRect
* rect
) 
5751     // Don't do anything if between Begin/EndBatch... 
5752     // EndBatch() will do all this on the last nested one anyway. 
5753     if (! GetBatchCount()) 
5755         wxScrolledWindow::Refresh(eraseb
,rect
); 
5757         int off_x
=0 ,off_y
=0; 
5758         wxRect 
* anotherrect 
= NULL 
; 
5762             //Copy rectangle can get scroll offsets.. 
5763             anotherrect 
= new wxRect(*rect
); 
5764             CalcScrolledPosition( 0, 0, &off_x
, &off_y 
); 
5766         //Corner label Doesn't move from the origin. 
5767         m_cornerLabelWin
->Refresh(eraseb
,rect
); 
5769         //Move Rect down for row labels... 
5771             rect
->Offset(0,off_y
); 
5772         m_rowLabelWin
->Refresh(eraseb
,rect
); 
5774         //Move rect copy along for col labels... 
5776             anotherrect
->Offset(off_x
,0); 
5777         m_colLabelWin
->Refresh(eraseb
,anotherrect
);      
5779         //Move main rect along (so it's down and across!) 
5782             rect
->Offset(off_x
,0); 
5783         m_gridWin
->Refresh(eraseb
,rect
); 
5787 void wxGrid::OnSize( wxSizeEvent
& event 
) 
5789     // position the child windows 
5792     // don't call CalcDimensions() from here, the base class handles the size 
5798 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
5800     if ( m_inOnKeyDown 
) 
5802         // shouldn't be here - we are going round in circles... 
5804         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
5807     m_inOnKeyDown 
= TRUE
; 
5809     // propagate the event up and see if it gets processed 
5811     wxWindow 
*parent 
= GetParent(); 
5812     wxKeyEvent 
keyEvt( event 
); 
5813     keyEvt
.SetEventObject( parent 
); 
5815     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
5818         // try local handlers 
5820         switch ( event
.KeyCode() ) 
5823                 if ( event
.ControlDown() ) 
5825                     MoveCursorUpBlock( event
.ShiftDown() ); 
5829                     MoveCursorUp( event
.ShiftDown() ); 
5834                 if ( event
.ControlDown() ) 
5836                     MoveCursorDownBlock( event
.ShiftDown() ); 
5840                     MoveCursorDown( event
.ShiftDown() ); 
5845                 if ( event
.ControlDown() ) 
5847                     MoveCursorLeftBlock( event
.ShiftDown() ); 
5851                     MoveCursorLeft( event
.ShiftDown() ); 
5856                 if ( event
.ControlDown() ) 
5858                     MoveCursorRightBlock( event
.ShiftDown() ); 
5862                     MoveCursorRight( event
.ShiftDown() ); 
5867             case WXK_NUMPAD_ENTER
: 
5868                 if ( event
.ControlDown() ) 
5870                     event
.Skip();  // to let the edit control have the return 
5874                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
5876                         MoveCursorDown( event
.ShiftDown() ); 
5880                         // at the bottom of a column 
5881                         HideCellEditControl(); 
5882                         SaveEditControlValue(); 
5892                 if (event
.ShiftDown()) 
5894                     if ( GetGridCursorCol() > 0 ) 
5896                         MoveCursorLeft( FALSE 
); 
5901                         HideCellEditControl(); 
5902                         SaveEditControlValue(); 
5907                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
5909                         MoveCursorRight( FALSE 
); 
5914                         HideCellEditControl(); 
5915                         SaveEditControlValue(); 
5921                 if ( event
.ControlDown() ) 
5923                     MakeCellVisible( 0, 0 ); 
5924                     SetCurrentCell( 0, 0 ); 
5933                 if ( event
.ControlDown() ) 
5935                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
5936                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
5953                 if ( event
.ControlDown() ) 
5957                         m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
5958                                                           m_currentCellCoords
.GetCol(), 
5959                                                           event
.ControlDown(), 
5966                 if ( !IsEditable() ) 
5968                     MoveCursorRight( FALSE 
); 
5971                 // Otherwise fall through to default 
5974                 // is it possible to edit the current cell at all? 
5975                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
5977                     // yes, now check whether the cells editor accepts the key 
5978                     int row 
= m_currentCellCoords
.GetRow(); 
5979                     int col 
= m_currentCellCoords
.GetCol(); 
5980                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
5981                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
5983                     // <F2> is special and will always start editing, for 
5984                     // other keys - ask the editor itself 
5985                     if ( (event
.KeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
5986                          || editor
->IsAcceptedKey(event
) ) 
5988                         EnableCellEditControl(); 
5990                         // the editor could be not shown for a variety of 
5991                         // reasons (i.e. blocked by the app or whatever), so 
5992                         // check if it really was created 
5993                         if ( m_cellEditCtrlEnabled 
) 
5995                             editor
->StartingKey(event
); 
6008                     // let others process char events with modifiers or all 
6009                     // char events for readonly cells 
6016     m_inOnKeyDown 
= FALSE
; 
6019 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
6021     // try local handlers 
6023     if ( event
.KeyCode() == WXK_SHIFT 
) 
6025         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6026              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6030                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6031                                           m_selectingTopLeft
.GetCol(), 
6032                                           m_selectingBottomRight
.GetRow(), 
6033                                           m_selectingBottomRight
.GetCol(), 
6034                                           event
.ControlDown(), 
6041         m_selectingTopLeft 
= wxGridNoCellCoords
; 
6042         m_selectingBottomRight 
= wxGridNoCellCoords
; 
6043         m_selectingKeyboard 
= wxGridNoCellCoords
; 
6047 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
6051 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
6053     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
6055         // the event has been intercepted - do nothing 
6059     wxClientDC 
dc(m_gridWin
); 
6062     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
6064         HideCellEditControl(); 
6065         DisableCellEditControl(); 
6067         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
6070             r 
= BlockToDeviceRect(m_currentCellCoords
, coords
); 
6071             if ( !m_gridLinesEnabled 
) 
6079              wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
6081             // Otherwise refresh redraws the highlight! 
6082             m_currentCellCoords 
= coords
; 
6084             DrawGridCellArea(dc
,cells
); 
6085             DrawAllGridLines( dc
, r 
); 
6089     m_currentCellCoords 
= coords
; 
6091     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
6092     DrawCellHighlight(dc
, attr
); 
6097 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6100     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6104         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
6107             rightCol 
= GetNumberCols() - 1; 
6109         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
6112             bottomRow 
= GetNumberRows() - 1; 
6116     if ( topRow 
> bottomRow 
) 
6123     if ( leftCol 
> rightCol 
) 
6130     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6131     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6133     if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
6134          m_selectingBottomRight 
!= updateBottomRight 
) 
6136         // Compute two optimal update rectangles: 
6137         // Either one rectangle is a real subset of the 
6138         // other, or they are (almost) disjoint! 
6140         bool    need_refresh
[4]; 
6144         need_refresh
[3] = FALSE
; 
6147         // Store intermediate values 
6148         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
6149         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
6150         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
6151         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
6153         // Determine the outer/inner coordinates. 
6154         if (oldLeft 
> leftCol
) 
6160         if (oldTop 
> topRow 
) 
6166         if (oldRight 
< rightCol 
) 
6169             oldRight 
= rightCol
; 
6172         if (oldBottom 
< bottomRow
) 
6175             oldBottom 
= bottomRow
; 
6179         // Now, either the stuff marked old is the outer 
6180         // rectangle or we don't have a situation where one 
6181         // is contained in the other. 
6183         if ( oldLeft 
< leftCol 
) 
6185             need_refresh
[0] = TRUE
; 
6186             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6188                                          wxGridCellCoords ( oldBottom
, 
6192         if ( oldTop  
< topRow 
) 
6194             need_refresh
[1] = TRUE
; 
6195             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6197                                          wxGridCellCoords ( topRow 
- 1, 
6201         if ( oldRight 
> rightCol 
) 
6203             need_refresh
[2] = TRUE
; 
6204             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6206                                          wxGridCellCoords ( oldBottom
, 
6210         if ( oldBottom 
> bottomRow 
) 
6212             need_refresh
[3] = TRUE
; 
6213             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6215                                          wxGridCellCoords ( oldBottom
, 
6221         m_selectingTopLeft 
= updateTopLeft
; 
6222         m_selectingBottomRight 
= updateBottomRight
; 
6224         // various Refresh() calls 
6225         for (i 
= 0; i 
< 4; i
++ ) 
6226             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6227                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6230     // never generate an event as it will be generated from 
6231     // wxGridSelection::SelectBlock! 
6232     // (old comment from when this was the body of SelectBlock) 
6236 // ------ functions to get/send data (see also public functions) 
6239 bool wxGrid::GetModelValues() 
6243         // all we need to do is repaint the grid 
6245         m_gridWin
->Refresh(); 
6253 bool wxGrid::SetModelValues() 
6259         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6261             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6263                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6275 // Note - this function only draws cells that are in the list of 
6276 // exposed cells (usually set from the update region by 
6277 // CalcExposedCells) 
6279 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6281     if ( !m_numRows 
|| !m_numCols 
) return; 
6283     int i
, j
, k
, l
, numCells 
= cells
.GetCount(); 
6284     int row
, col
, cell_rows
, cell_cols
; 
6285     wxGridCellCoordsArray redrawCells
; 
6287     for ( i 
= numCells
-1; i 
>= 0;  i
-- ) 
6289         row 
= cells
[i
].GetRow(); 
6290         col 
= cells
[i
].GetCol(); 
6291         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
6293         // If this cell is part of a multicell block, find owner for repaint 
6294         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
6296             wxGridCellCoords 
cell(row
+cell_rows
, col
+cell_cols
); 
6297             bool marked 
= FALSE
; 
6298             for ( j 
= 0;  j 
< numCells
;  j
++ ) 
6300                 if ( cell 
== cells
[j
] ) 
6308                 int count 
= redrawCells
.GetCount(); 
6309                 for (j 
= 0; j 
< count
; j
++) 
6311                     if ( cell 
== redrawCells
[j
] ) 
6317                 if (!marked
) redrawCells
.Add( cell 
); 
6319             continue; // don't bother drawing this cell 
6322         // If this cell is empty, find cell to left that might want to overflow 
6323         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
6325             for ( l 
= 0; l 
< cell_rows
; l
++ ) 
6327                 for (j 
= col
-1; j 
>= 0; j
--) 
6329                     if (!m_table
->IsEmptyCell(row
+l
, j
)) 
6331                         if (GetCellOverflow(row
+l
, j
)) 
6333                             wxGridCellCoords 
cell(row
+l
, j
); 
6334                             bool marked 
= FALSE
; 
6336                             for (k 
= 0; k 
< numCells
; k
++) 
6338                                 if ( cell 
== cells
[k
] ) 
6346                                 int count 
= redrawCells
.GetCount(); 
6347                                 for (k 
= 0; k 
< count
; k
++) 
6349                                     if ( cell 
== redrawCells
[k
] ) 
6355                                 if (!marked
) redrawCells
.Add( cell 
); 
6363         DrawCell( dc
, cells
[i
] ); 
6366     numCells 
= redrawCells
.GetCount(); 
6368     for ( i 
= numCells 
- 1; i 
>= 0;  i
-- ) 
6370         DrawCell( dc
, redrawCells
[i
] ); 
6375 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6378   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6381   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6383   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6384   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6386   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6389       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6391       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6392       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6394       if ( right 
> rightCol 
) 
6396           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6399       if ( bottom 
> bottomRow 
) 
6401           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6407 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6409     int row 
= coords
.GetRow(); 
6410     int col 
= coords
.GetCol(); 
6412     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6415     // we draw the cell border ourselves 
6416 #if !WXGRID_DRAW_LINES 
6417     if ( m_gridLinesEnabled 
) 
6418         DrawCellBorder( dc
, coords 
); 
6421     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6423     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6425     wxRect rect 
= CellToRect( row
, col 
); 
6427     // if the editor is shown, we should use it and not the renderer 
6428     // Note: However, only if it is really _shown_, i.e. not hidden! 
6429     if ( isCurrent 
&& IsCellEditControlShown() ) 
6431         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6432         editor
->PaintBackground(rect
, attr
); 
6437         // but all the rest is drawn by the cell renderer and hence may be 
6439         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
6440         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
6447 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
6449     int row 
= m_currentCellCoords
.GetRow(); 
6450     int col 
= m_currentCellCoords
.GetCol(); 
6452     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6455     wxRect rect 
= CellToRect(row
, col
); 
6457     // hmmm... what could we do here to show that the cell is disabled? 
6458     // for now, I just draw a thinner border than for the other ones, but 
6459     // it doesn't look really good 
6461     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
6465         // The center of th drawn line is where the position/width/height of 
6466         // the rectangle is actually at, (on wxMSW atr least,) so we will 
6467         // reduce the size of the rectangle to compensate for the thickness of 
6468         // the line.  If this is too strange on non wxMSW platforms then 
6469         // please #ifdef this appropriately. 
6470         rect
.x 
+= penWidth
/2; 
6471         rect
.y 
+= penWidth
/2; 
6472         rect
.width 
-= penWidth
-1; 
6473         rect
.height 
-= penWidth
-1; 
6476         // Now draw the rectangle 
6477         dc
.SetPen(wxPen(m_cellHighlightColour
, penWidth
, wxSOLID
)); 
6478         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
6479         dc
.DrawRectangle(rect
); 
6483         // VZ: my experiments with 3d borders... 
6485         // how to properly set colours for arbitrary bg? 
6486         wxCoord x1 
= rect
.x
, 
6488                 x2 
= rect
.x 
+ rect
.width 
-1, 
6489                 y2 
= rect
.y 
+ rect
.height 
-1; 
6491         dc
.SetPen(*wxWHITE_PEN
); 
6492         dc
.DrawLine(x1
, y1
, x2
, y1
); 
6493         dc
.DrawLine(x1
, y1
, x1
, y2
); 
6495         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
6496         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
6498         dc
.SetPen(*wxBLACK_PEN
); 
6499         dc
.DrawLine(x1
, y2
, x2
, y2
); 
6500         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
6505 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6507     int row 
= coords
.GetRow(); 
6508     int col 
= coords
.GetCol(); 
6509     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6512     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6514     wxRect rect 
= CellToRect( row
, col 
); 
6516     // right hand border 
6518     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
6519                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
6523     dc
.DrawLine( rect
.x
,              rect
.y 
+ rect
.height
, 
6524                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
6527 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
6529     // This if block was previously in wxGrid::OnPaint but that doesn't 
6530     // seem to get called under wxGTK - MB 
6532     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
6533          m_numRows 
&& m_numCols 
) 
6535         m_currentCellCoords
.Set(0, 0); 
6538     if ( IsCellEditControlShown() ) 
6540         // don't show highlight when the edit control is shown 
6544     // if the active cell was repainted, repaint its highlight too because it 
6545     // might have been damaged by the grid lines 
6546     size_t count 
= cells
.GetCount(); 
6547     for ( size_t n 
= 0; n 
< count
; n
++ ) 
6549         if ( cells
[n
] == m_currentCellCoords 
) 
6551             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
6552             DrawCellHighlight(dc
, attr
); 
6560 // TODO: remove this ??? 
6561 // This is used to redraw all grid lines e.g. when the grid line colour 
6564 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
6566 #if !WXGRID_DRAW_LINES 
6570     if ( !m_gridLinesEnabled 
|| 
6572          !m_numCols 
) return; 
6574     int top
, bottom
, left
, right
; 
6576 #if 0  //#ifndef __WXGTK__ 
6580       m_gridWin
->GetClientSize(&cw
, &ch
); 
6582       // virtual coords of visible area 
6584       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6585       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6590       reg
.GetBox(x
, y
, w
, h
); 
6591       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6592       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6596       m_gridWin
->GetClientSize(&cw
, &ch
); 
6597       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6598       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6601     // avoid drawing grid lines past the last row and col 
6603     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6604     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6606     // no gridlines inside multicells, clip them out 
6607     int leftCol   
= XToCol(left
); 
6608     int topRow    
= YToRow(top
); 
6609     int rightCol  
= XToCol(right
); 
6610     int bottomRow 
= YToRow(bottom
); 
6611     wxRegion 
clippedcells(0, 0, cw
, ch
); 
6613     if ((leftCol 
>= 0) && (topRow 
>= 0)) 
6615         if (rightCol  
< 0) rightCol  
= m_numCols
; 
6616         if (bottomRow 
< 0) bottomRow 
= m_numRows
; 
6618         int i
, j
, cell_rows
, cell_cols
; 
6621         for (j
=topRow
; j
<bottomRow
; j
++) 
6623             for (i
=leftCol
; i
<rightCol
; i
++) 
6625                 GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
6626                 if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
6628                     rect 
= CellToRect(j
,i
); 
6629                     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6630                     clippedcells
.Subtract(rect
); 
6632                 else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
6634                     rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
6635                     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6636                     clippedcells
.Subtract(rect
); 
6641     dc
.SetClippingRegion( clippedcells 
); 
6643     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6645     // horizontal grid lines 
6648     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
6650         int bot 
= GetRowBottom(i
) - 1; 
6659             dc
.DrawLine( left
, bot
, right
, bot 
); 
6664     // vertical grid lines 
6666     for ( i 
= internalXToCol(left
); i 
< m_numCols
; i
++ ) 
6668         int colRight 
= GetColRight(i
) - 1; 
6669         if ( colRight 
> right 
) 
6674         if ( colRight 
>= left 
) 
6676             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
6679     dc
.DestroyClippingRegion(); 
6683 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
6685     if ( !m_numRows 
) return; 
6688     size_t numLabels 
= rows
.GetCount(); 
6690     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6692         DrawRowLabel( dc
, rows
[i
] ); 
6697 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
6699     if ( GetRowHeight(row
) <= 0 ) 
6702     int rowTop 
= GetRowTop(row
), 
6703         rowBottom 
= GetRowBottom(row
) - 1; 
6705     dc
.SetPen( *wxBLACK_PEN 
); 
6706     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
6707                  m_rowLabelWidth
-1, rowBottom 
); 
6709     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
-1, rowBottom 
); 
6711     dc
.SetPen( *wxWHITE_PEN 
); 
6712     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
6713     dc
.DrawLine( 0, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
6715     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6716     dc
.SetTextForeground( GetLabelTextColour() ); 
6717     dc
.SetFont( GetLabelFont() ); 
6720     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
6724     rect
.SetY( GetRowTop(row
) + 2 ); 
6725     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
6726     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
6727     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
6731 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
6733     if ( !m_numCols 
) return; 
6736     size_t numLabels 
= cols
.GetCount(); 
6738     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6740         DrawColLabel( dc
, cols
[i
] ); 
6745 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
6747     if ( GetColWidth(col
) <= 0 ) 
6750     int colLeft 
= GetColLeft(col
), 
6751         colRight 
= GetColRight(col
) - 1; 
6753     dc
.SetPen( *wxBLACK_PEN 
); 
6754     dc
.DrawLine( colRight
, 0, 
6755                  colRight
, m_colLabelHeight
-1 ); 
6757     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
6758                  colRight
, m_colLabelHeight
-1 ); 
6760     dc
.SetPen( *wxWHITE_PEN 
); 
6761     dc
.DrawLine( colLeft
, 0, colLeft
, m_colLabelHeight
-1 ); 
6762     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
6764     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6765     dc
.SetTextForeground( GetLabelTextColour() ); 
6766     dc
.SetFont( GetLabelFont() ); 
6768     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6769     dc
.SetTextForeground( GetLabelTextColour() ); 
6770     dc
.SetFont( GetLabelFont() ); 
6773     GetColLabelAlignment( &hAlign
, &vAlign 
); 
6776     rect
.SetX( colLeft 
+ 2 ); 
6778     rect
.SetWidth( GetColWidth(col
) - 4 ); 
6779     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
6780     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
6783 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6784                                 const wxString
& value
, 
6789     wxArrayString lines
; 
6791     StringToLines( value
, lines 
); 
6794     //Forward to new API. 
6795     DrawTextRectangle(  dc
, 
6803 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
6804                                 const wxArrayString
& lines
, 
6809     long textWidth
, textHeight
; 
6810     long lineWidth
, lineHeight
; 
6812     dc
.SetClippingRegion( rect 
); 
6813     if ( lines
.GetCount() ) 
6815         GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight 
); 
6816         dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight 
); 
6819         switch ( horizAlign 
) 
6822                 x 
= rect
.x 
+ (rect
.width 
- textWidth 
- 1); 
6825             case wxALIGN_CENTRE
: 
6826                 x 
= rect
.x 
+ ((rect
.width 
- textWidth
)/2); 
6835         switch ( vertAlign 
) 
6837             case wxALIGN_BOTTOM
: 
6838                 y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
6841             case wxALIGN_CENTRE
: 
6842                 y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
6851         for ( size_t i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6853             dc
.DrawText( lines
[i
], (int)x
, (int)y 
); 
6858     dc
.DestroyClippingRegion(); 
6862 // Split multi line text up into an array of strings.  Any existing 
6863 // contents of the string array are preserved. 
6865 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
6869     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
6870     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
6872     while ( startPos 
< (int)tVal
.Length() ) 
6874         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
6879         else if ( pos 
== 0 ) 
6881             lines
.Add( wxEmptyString 
); 
6885             lines
.Add( value
.Mid(startPos
, pos
) ); 
6889     if ( startPos 
< (int)value
.Length() ) 
6891         lines
.Add( value
.Mid( startPos 
) ); 
6896 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
6897                              const wxArrayString
& lines
, 
6898                              long *width
, long *height 
) 
6905     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
6907         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
6908         w 
= wxMax( w
, lineW 
); 
6917 // ------ Batch processing. 
6919 void wxGrid::EndBatch() 
6921     if ( m_batchCount 
> 0 ) 
6924         if ( !m_batchCount 
) 
6927             m_rowLabelWin
->Refresh(); 
6928             m_colLabelWin
->Refresh(); 
6929             m_cornerLabelWin
->Refresh(); 
6930             m_gridWin
->Refresh(); 
6935 // Use this, rather than wxWindow::Refresh(), to force an immediate 
6936 // repainting of the grid. Has no effect if you are already inside a 
6937 // BeginBatch / EndBatch block. 
6939 void wxGrid::ForceRefresh() 
6947 // ------ Edit control functions 
6951 void wxGrid::EnableEditing( bool edit 
) 
6953     // TODO: improve this ? 
6955     if ( edit 
!= m_editable 
) 
6957         if(!edit
) EnableCellEditControl(edit
); 
6963 void wxGrid::EnableCellEditControl( bool enable 
) 
6968     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
6969         SetCurrentCell( 0, 0 ); 
6971     if ( enable 
!= m_cellEditCtrlEnabled 
) 
6975             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
6978             // this should be checked by the caller! 
6979             wxASSERT_MSG( CanEnableCellControl(), 
6980                           _T("can't enable editing for this cell!") ); 
6982             // do it before ShowCellEditControl() 
6983             m_cellEditCtrlEnabled 
= enable
; 
6985             ShowCellEditControl(); 
6989             //FIXME:add veto support 
6990             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
6992             HideCellEditControl(); 
6993             SaveEditControlValue(); 
6995             // do it after HideCellEditControl() 
6996             m_cellEditCtrlEnabled 
= enable
; 
7001 bool wxGrid::IsCurrentCellReadOnly() const 
7004     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
7005     bool readonly 
= attr
->IsReadOnly(); 
7011 bool wxGrid::CanEnableCellControl() const 
7013     return m_editable 
&& !IsCurrentCellReadOnly(); 
7016 bool wxGrid::IsCellEditControlEnabled() const 
7018     // the cell edit control might be disable for all cells or just for the 
7019     // current one if it's read only 
7020     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
7023 bool wxGrid::IsCellEditControlShown() const 
7025     bool isShown 
= FALSE
; 
7027     if ( m_cellEditCtrlEnabled 
) 
7029         int row 
= m_currentCellCoords
.GetRow(); 
7030         int col 
= m_currentCellCoords
.GetCol(); 
7031         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7032         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
7037             if ( editor
->IsCreated() ) 
7039                 isShown 
= editor
->GetControl()->IsShown(); 
7049 void wxGrid::ShowCellEditControl() 
7051     if ( IsCellEditControlEnabled() ) 
7053         if ( !IsVisible( m_currentCellCoords 
) ) 
7055             m_cellEditCtrlEnabled 
= FALSE
; 
7060             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
7061             int row 
= m_currentCellCoords
.GetRow(); 
7062             int col 
= m_currentCellCoords
.GetCol(); 
7064             // if this is part of a multicell, find owner (topleft) 
7065             int cell_rows
, cell_cols
; 
7066             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7067             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7071                 m_currentCellCoords
.SetRow( row 
); 
7072                 m_currentCellCoords
.SetCol( col 
); 
7075             // convert to scrolled coords 
7077             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7079             // done in PaintBackground() 
7081             // erase the highlight and the cell contents because the editor 
7082             // might not cover the entire cell 
7083             wxClientDC 
dc( m_gridWin 
); 
7085             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
7086             dc
.SetPen(*wxTRANSPARENT_PEN
); 
7087             dc
.DrawRectangle(rect
); 
7090             // cell is shifted by one pixel 
7091             // However, don't allow x or y to become negative 
7092             // since the SetSize() method interprets that as 
7099             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7100             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7101             if ( !editor
->IsCreated() ) 
7103                 editor
->Create(m_gridWin
, -1, 
7104                                new wxGridCellEditorEvtHandler(this, editor
)); 
7106                 wxGridEditorCreatedEvent 
evt(GetId(), 
7107                                              wxEVT_GRID_EDITOR_CREATED
, 
7111                                              editor
->GetControl()); 
7112                 GetEventHandler()->ProcessEvent(evt
); 
7115             editor
->Show( TRUE
, attr 
); 
7117             // resize editor to overflow into righthand cells if allowed 
7118             wxString value 
= GetCellValue(row
, col
); 
7119             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
7121                 wxClientDC 
dc(m_gridWin
); 
7122                 wxCoord y 
= 0, best_width 
= 0; 
7123                 dc
.SetFont(attr
->GetFont()); 
7124                 dc
.GetTextExtent(value
, &best_width
, &y
); 
7126                 int cell_rows
, cell_cols
; 
7127                 attr
->GetSize( &cell_rows
, &cell_cols 
); 
7129                 if ((best_width 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
7132                     for (i 
= col
+cell_cols
; i 
< m_numCols
; i
++) 
7134                         if (m_table
->IsEmptyCell(row
,i
)) 
7136                             rect
.width 
+= GetColWidth(i
); 
7137                             if (rect
.width 
>= best_width
) break; 
7144             editor
->SetSize( rect 
); 
7146             editor
->BeginEdit(row
, col
, this); 
7155 void wxGrid::HideCellEditControl() 
7157     if ( IsCellEditControlEnabled() ) 
7159         int row 
= m_currentCellCoords
.GetRow(); 
7160         int col 
= m_currentCellCoords
.GetCol(); 
7162         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7163         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7164         editor
->Show( FALSE 
); 
7167         m_gridWin
->SetFocus(); 
7168         // refresh whole row to the right 
7169         wxRect 
rect( CellToRect(row
, col
) ); 
7170         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7171         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
7172         m_gridWin
->Refresh( FALSE
, &rect 
); 
7177 void wxGrid::SaveEditControlValue() 
7179     if ( IsCellEditControlEnabled() ) 
7181         int row 
= m_currentCellCoords
.GetRow(); 
7182         int col 
= m_currentCellCoords
.GetCol(); 
7184         wxString oldval 
= GetCellValue(row
,col
); 
7186         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7187         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7188         bool changed 
= editor
->EndEdit(row
, col
, this); 
7195             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
7196                        m_currentCellCoords
.GetRow(), 
7197                        m_currentCellCoords
.GetCol() ) < 0 ) { 
7199                 // Event has been vetoed, set the data back. 
7200                 SetCellValue(row
,col
,oldval
); 
7208 // ------ Grid location functions 
7209 //  Note that all of these functions work with the logical coordinates of 
7210 //  grid cells and labels so you will need to convert from device 
7211 //  coordinates for mouse events etc. 
7214 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
7216     int row 
= YToRow(y
); 
7217     int col 
= XToCol(x
); 
7219     if ( row 
== -1  ||  col 
== -1 ) 
7221         coords 
= wxGridNoCellCoords
; 
7225         coords
.Set( row
, col 
); 
7230 // Internal Helper function for computing row or column from some 
7231 // (unscrolled) coordinate value, using either 
7232 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
7233 // of m_rowBottoms/m_ColRights to speed up the search! 
7235 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
7236                            const wxArrayInt
& BorderArray
, bool maxOnOverflow
) 
7240     size_t i_max 
= coord 
/ defaultDist
, 
7242     if (BorderArray
.IsEmpty()) 
7247     if ( i_max 
>= BorderArray
.GetCount()) 
7248         i_max 
= BorderArray
.GetCount() - 1; 
7251         if ( coord 
>= BorderArray
[i_max
]) 
7254             i_max 
= coord 
/ minDist
; 
7256         if ( i_max 
>= BorderArray
.GetCount()) 
7257             i_max 
= BorderArray
.GetCount() - 1; 
7259     if ( coord 
>= BorderArray
[i_max
]) 
7260         return maxOnOverflow 
? (int)i_max 
: -1; 
7261     if ( coord 
< BorderArray
[0] ) 
7264     while ( i_max 
- i_min 
> 0 ) 
7266         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
7267                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
7268         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
7272         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
7273         if (coord 
< BorderArray
[median
]) 
7281 int wxGrid::YToRow( int y 
) 
7283     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
7284                            WXGRID_MIN_ROW_HEIGHT
, m_rowBottoms
, FALSE
); 
7288 int wxGrid::XToCol( int x 
) 
7290     return CoordToRowOrCol(x
, m_defaultColWidth
, 
7291                            WXGRID_MIN_COL_WIDTH
, m_colRights
, FALSE
); 
7295 // return the row number that that the y coord is near the edge of, or 
7296 // -1 if not near an edge 
7298 int wxGrid::YToEdgeOfRow( int y 
) 
7301     i 
= internalYToRow(y
); 
7303     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7305         // We know that we are in row i, test whether we are 
7306         // close enough to lower or upper border, respectively. 
7307         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
7309         else if( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7317 // return the col number that that the x coord is near the edge of, or 
7318 // -1 if not near an edge 
7320 int wxGrid::XToEdgeOfCol( int x 
) 
7323     i 
= internalXToCol(x
); 
7325     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7327         // We know that we are in column i,  test whether we are 
7328         // close enough to right or left border, respectively. 
7329         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
7331         else if( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7339 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
7341     wxRect 
rect( -1, -1, -1, -1 ); 
7343     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7344          col 
>= 0  &&  col 
< m_numCols 
) 
7346         int i
, cell_rows
, cell_cols
; 
7347         rect
.width 
= rect
.height 
= 0; 
7348         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7349         // if negative then find multicell owner 
7350         if (cell_rows 
< 0) row 
+= cell_rows
; 
7351         if (cell_cols 
< 0) col 
+= cell_cols
; 
7352         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7354         rect
.x 
= GetColLeft(col
); 
7355         rect
.y 
= GetRowTop(row
); 
7356         for (i
=col
; i
<col
+cell_cols
; i
++) 
7357             rect
.width  
+= GetColWidth(i
); 
7358         for (i
=row
; i
<row
+cell_rows
; i
++) 
7359             rect
.height 
+= GetRowHeight(i
); 
7362     // if grid lines are enabled, then the area of the cell is a bit smaller 
7363     if (m_gridLinesEnabled
) { 
7371 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
7373     // get the cell rectangle in logical coords 
7375     wxRect 
r( CellToRect( row
, col 
) ); 
7377     // convert to device coords 
7379     int left
, top
, right
, bottom
; 
7380     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7381     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7383     // check against the client area of the grid window 
7386     m_gridWin
->GetClientSize( &cw
, &ch 
); 
7388     if ( wholeCellVisible 
) 
7390         // is the cell wholly visible ? 
7392         return ( left 
>= 0  &&  right 
<= cw  
&& 
7393                  top 
>= 0  &&  bottom 
<= ch 
); 
7397         // is the cell partly visible ? 
7399         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
7400                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
7405 // make the specified cell location visible by doing a minimal amount 
7408 void wxGrid::MakeCellVisible( int row
, int col 
) 
7412     int xpos 
= -1, ypos 
= -1; 
7414     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7415          col 
>= 0  &&  col 
< m_numCols 
) 
7417         // get the cell rectangle in logical coords 
7419         wxRect 
r( CellToRect( row
, col 
) ); 
7421         // convert to device coords 
7423         int left
, top
, right
, bottom
; 
7424         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7425         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7428         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7434         else if ( bottom 
> ch 
) 
7436             int h 
= r
.GetHeight(); 
7438             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
7440                 int rowHeight 
= GetRowHeight(i
); 
7441                 if ( h 
+ rowHeight 
> ch 
) 
7448             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
7449             // have rounding errors (this is important, because if we do, we 
7450             // might not scroll at all and some cells won't be redrawn) 
7452             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
7454             ypos 
+= GRID_SCROLL_LINE_Y
; 
7461         else if ( right 
> cw 
) 
7463             int w 
= r
.GetWidth(); 
7465             for ( i 
= col
-1;  i 
>= 0;  i
-- ) 
7467                 int colWidth 
= GetColWidth(i
); 
7468                 if ( w 
+ colWidth 
> cw 
) 
7475             // see comment for ypos above 
7476             xpos 
+= GRID_SCROLL_LINE_X
; 
7479         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
7482                 xpos 
/= GRID_SCROLL_LINE_X
; 
7484                 ypos 
/= GRID_SCROLL_LINE_Y
; 
7485             Scroll( xpos
, ypos 
); 
7493 // ------ Grid cursor movement functions 
7496 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
7498     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7499          m_currentCellCoords
.GetRow() >= 0 ) 
7501         if ( expandSelection
) 
7503             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7504                 m_selectingKeyboard 
= m_currentCellCoords
; 
7505             if ( m_selectingKeyboard
.GetRow() > 0 ) 
7507                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
7508                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7509                                  m_selectingKeyboard
.GetCol() ); 
7510                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7513         else if ( m_currentCellCoords
.GetRow() > 0 ) 
7516             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
7517                              m_currentCellCoords
.GetCol() ); 
7518             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
7519                             m_currentCellCoords
.GetCol() ); 
7530 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
7532     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7533          m_currentCellCoords
.GetRow() < m_numRows 
) 
7535         if ( expandSelection 
) 
7537             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7538                 m_selectingKeyboard 
= m_currentCellCoords
; 
7539             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
7541                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
7542                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7543                         m_selectingKeyboard
.GetCol() ); 
7544                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7547         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
7550             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
7551                              m_currentCellCoords
.GetCol() ); 
7552             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
7553                             m_currentCellCoords
.GetCol() ); 
7564 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
7566     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7567          m_currentCellCoords
.GetCol() >= 0 ) 
7569         if ( expandSelection 
) 
7571             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7572                 m_selectingKeyboard 
= m_currentCellCoords
; 
7573             if ( m_selectingKeyboard
.GetCol() > 0 ) 
7575                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
7576                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7577                         m_selectingKeyboard
.GetCol() ); 
7578                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7581         else if ( m_currentCellCoords
.GetCol() > 0 ) 
7584             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7585                              m_currentCellCoords
.GetCol() - 1 ); 
7586             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7587                             m_currentCellCoords
.GetCol() - 1 ); 
7598 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
7600     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7601          m_currentCellCoords
.GetCol() < m_numCols 
) 
7603         if ( expandSelection 
) 
7605             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7606                 m_selectingKeyboard 
= m_currentCellCoords
; 
7607             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
7609                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
7610                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7611                         m_selectingKeyboard
.GetCol() ); 
7612                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7615         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
7618             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7619                              m_currentCellCoords
.GetCol() + 1 ); 
7620             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7621                             m_currentCellCoords
.GetCol() + 1 ); 
7632 bool wxGrid::MovePageUp() 
7634     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7636     int row 
= m_currentCellCoords
.GetRow(); 
7640         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7642         int y 
= GetRowTop(row
); 
7643         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
7648         else if ( newRow 
== row 
) 
7653         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7654         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7662 bool wxGrid::MovePageDown() 
7664     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7666     int row 
= m_currentCellCoords
.GetRow(); 
7667     if ( row 
< m_numRows 
) 
7670         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7672         int y 
= GetRowTop(row
); 
7673         int newRow 
= YToRow( y 
+ ch 
); 
7676             newRow 
= m_numRows 
- 1; 
7678         else if ( newRow 
== row 
) 
7683         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7684         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7692 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
7695          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7696          m_currentCellCoords
.GetRow() > 0 ) 
7698         int row 
= m_currentCellCoords
.GetRow(); 
7699         int col 
= m_currentCellCoords
.GetCol(); 
7701         if ( m_table
->IsEmptyCell(row
, col
) ) 
7703             // starting in an empty cell: find the next block of 
7709                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7712         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
7714             // starting at the top of a block: find the next block 
7720                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7725             // starting within a block: find the top of the block 
7730                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7738         MakeCellVisible( row
, col 
); 
7739         if ( expandSelection 
) 
7741             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7742             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7747             SetCurrentCell( row
, col 
); 
7755 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
7758          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7759          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
7761         int row 
= m_currentCellCoords
.GetRow(); 
7762         int col 
= m_currentCellCoords
.GetCol(); 
7764         if ( m_table
->IsEmptyCell(row
, col
) ) 
7766             // starting in an empty cell: find the next block of 
7769             while ( row 
< m_numRows
-1 ) 
7772                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7775         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
7777             // starting at the bottom of a block: find the next block 
7780             while ( row 
< m_numRows
-1 ) 
7783                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7788             // starting within a block: find the bottom of the block 
7790             while ( row 
< m_numRows
-1 ) 
7793                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7801         MakeCellVisible( row
, col 
); 
7802         if ( expandSelection 
) 
7804             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7805             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7810             SetCurrentCell( row
, col 
); 
7819 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
7822          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7823          m_currentCellCoords
.GetCol() > 0 ) 
7825         int row 
= m_currentCellCoords
.GetRow(); 
7826         int col 
= m_currentCellCoords
.GetCol(); 
7828         if ( m_table
->IsEmptyCell(row
, col
) ) 
7830             // starting in an empty cell: find the next block of 
7836                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7839         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
7841             // starting at the left of a block: find the next block 
7847                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7852             // starting within a block: find the left of the block 
7857                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7865         MakeCellVisible( row
, col 
); 
7866         if ( expandSelection 
) 
7868             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7869             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7874             SetCurrentCell( row
, col 
); 
7883 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
7886          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7887          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
7889         int row 
= m_currentCellCoords
.GetRow(); 
7890         int col 
= m_currentCellCoords
.GetCol(); 
7892         if ( m_table
->IsEmptyCell(row
, col
) ) 
7894             // starting in an empty cell: find the next block of 
7897             while ( col 
< m_numCols
-1 ) 
7900                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7903         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
7905             // starting at the right of a block: find the next block 
7908             while ( col 
< m_numCols
-1 ) 
7911                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7916             // starting within a block: find the right of the block 
7918             while ( col 
< m_numCols
-1 ) 
7921                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7929         MakeCellVisible( row
, col 
); 
7930         if ( expandSelection 
) 
7932             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7933             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7938             SetCurrentCell( row
, col 
); 
7950 // ------ Label values and formatting 
7953 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
7955     *horiz 
= m_rowLabelHorizAlign
; 
7956     *vert  
= m_rowLabelVertAlign
; 
7959 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
7961     *horiz 
= m_colLabelHorizAlign
; 
7962     *vert  
= m_colLabelVertAlign
; 
7965 wxString 
wxGrid::GetRowLabelValue( int row 
) 
7969         return m_table
->GetRowLabelValue( row 
); 
7979 wxString 
wxGrid::GetColLabelValue( int col 
) 
7983         return m_table
->GetColLabelValue( col 
); 
7994 void wxGrid::SetRowLabelSize( int width 
) 
7996     width 
= wxMax( width
, 0 ); 
7997     if ( width 
!= m_rowLabelWidth 
) 
8001             m_rowLabelWin
->Show( FALSE 
); 
8002             m_cornerLabelWin
->Show( FALSE 
); 
8004         else if ( m_rowLabelWidth 
== 0 ) 
8006             m_rowLabelWin
->Show( TRUE 
); 
8007             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8010         m_rowLabelWidth 
= width
; 
8012         wxScrolledWindow::Refresh( TRUE 
); 
8017 void wxGrid::SetColLabelSize( int height 
) 
8019     height 
= wxMax( height
, 0 ); 
8020     if ( height 
!= m_colLabelHeight 
) 
8024             m_colLabelWin
->Show( FALSE 
); 
8025             m_cornerLabelWin
->Show( FALSE 
); 
8027         else if ( m_colLabelHeight 
== 0 ) 
8029             m_colLabelWin
->Show( TRUE 
); 
8030             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8033         m_colLabelHeight 
= height
; 
8035         wxScrolledWindow::Refresh( TRUE 
); 
8040 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
8042     if ( m_labelBackgroundColour 
!= colour 
) 
8044         m_labelBackgroundColour 
= colour
; 
8045         m_rowLabelWin
->SetBackgroundColour( colour 
); 
8046         m_colLabelWin
->SetBackgroundColour( colour 
); 
8047         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
8049         if ( !GetBatchCount() ) 
8051             m_rowLabelWin
->Refresh(); 
8052             m_colLabelWin
->Refresh(); 
8053             m_cornerLabelWin
->Refresh(); 
8058 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
8060     if ( m_labelTextColour 
!= colour 
) 
8062         m_labelTextColour 
= colour
; 
8063         if ( !GetBatchCount() ) 
8065             m_rowLabelWin
->Refresh(); 
8066             m_colLabelWin
->Refresh(); 
8071 void wxGrid::SetLabelFont( const wxFont
& font 
) 
8074     if ( !GetBatchCount() ) 
8076         m_rowLabelWin
->Refresh(); 
8077         m_colLabelWin
->Refresh(); 
8081 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
8083     // allow old (incorrect) defs to be used 
8086         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8087         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8088         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8093         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8094         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8095         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8098     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8100         m_rowLabelHorizAlign 
= horiz
; 
8103     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8105         m_rowLabelVertAlign 
= vert
; 
8108     if ( !GetBatchCount() ) 
8110         m_rowLabelWin
->Refresh(); 
8114 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
8116     // allow old (incorrect) defs to be used 
8119         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8120         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8121         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8126         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8127         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8128         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8131     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8133         m_colLabelHorizAlign 
= horiz
; 
8136     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8138         m_colLabelVertAlign 
= vert
; 
8141     if ( !GetBatchCount() ) 
8143         m_colLabelWin
->Refresh(); 
8147 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
8151         m_table
->SetRowLabelValue( row
, s 
); 
8152         if ( !GetBatchCount() ) 
8154             wxRect rect 
= CellToRect( row
, 0); 
8155             if ( rect
.height 
> 0 ) 
8157                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
8159                 rect
.width 
= m_rowLabelWidth
; 
8160                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
8166 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
8170         m_table
->SetColLabelValue( col
, s 
); 
8171         if ( !GetBatchCount() ) 
8173             wxRect rect 
= CellToRect( 0, col 
); 
8174             if ( rect
.width 
> 0 ) 
8176                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
8178                 rect
.height 
= m_colLabelHeight
; 
8179                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
8185 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
8187     if ( m_gridLineColour 
!= colour 
) 
8189         m_gridLineColour 
= colour
; 
8191         wxClientDC 
dc( m_gridWin 
); 
8193         DrawAllGridLines( dc
, wxRegion() ); 
8198 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
8200     if ( m_cellHighlightColour 
!= colour 
) 
8202         m_cellHighlightColour 
= colour
; 
8204         wxClientDC 
dc( m_gridWin 
); 
8206         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
8207         DrawCellHighlight(dc
, attr
); 
8212 void wxGrid::SetCellHighlightPenWidth(int width
) 
8214     if (m_cellHighlightPenWidth 
!= width
) { 
8215         m_cellHighlightPenWidth 
= width
; 
8217         // Just redrawing the cell highlight is not enough since that won't 
8218         // make any visible change if the the thickness is getting smaller. 
8219         int row 
= m_currentCellCoords
.GetRow(); 
8220         int col 
= m_currentCellCoords
.GetCol(); 
8221         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8223         wxRect rect 
= CellToRect(row
, col
); 
8224         m_gridWin
->Refresh(TRUE
, &rect
); 
8228 void wxGrid::SetCellHighlightROPenWidth(int width
) 
8230     if (m_cellHighlightROPenWidth 
!= width
) { 
8231         m_cellHighlightROPenWidth 
= width
; 
8233         // Just redrawing the cell highlight is not enough since that won't 
8234         // make any visible change if the the thickness is getting smaller. 
8235         int row 
= m_currentCellCoords
.GetRow(); 
8236         int col 
= m_currentCellCoords
.GetCol(); 
8237         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8239         wxRect rect 
= CellToRect(row
, col
); 
8240         m_gridWin
->Refresh(TRUE
, &rect
); 
8244 void wxGrid::EnableGridLines( bool enable 
) 
8246     if ( enable 
!= m_gridLinesEnabled 
) 
8248         m_gridLinesEnabled 
= enable
; 
8250         if ( !GetBatchCount() ) 
8254                 wxClientDC 
dc( m_gridWin 
); 
8256                 DrawAllGridLines( dc
, wxRegion() ); 
8260                 m_gridWin
->Refresh(); 
8267 int wxGrid::GetDefaultRowSize() 
8269     return m_defaultRowHeight
; 
8272 int wxGrid::GetRowSize( int row 
) 
8274     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
8276     return GetRowHeight(row
); 
8279 int wxGrid::GetDefaultColSize() 
8281     return m_defaultColWidth
; 
8284 int wxGrid::GetColSize( int col 
) 
8286     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
8288     return GetColWidth(col
); 
8291 // ============================================================================ 
8292 // access to the grid attributes: each of them has a default value in the grid 
8293 // itself and may be overidden on a per-cell basis 
8294 // ============================================================================ 
8296 // ---------------------------------------------------------------------------- 
8297 // setting default attributes 
8298 // ---------------------------------------------------------------------------- 
8300 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
8302     m_defaultCellAttr
->SetBackgroundColour(col
); 
8304     m_gridWin
->SetBackgroundColour(col
); 
8308 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
8310     m_defaultCellAttr
->SetTextColour(col
); 
8313 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
8315     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
8318 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
8320     m_defaultCellAttr
->SetOverflow(allow
); 
8323 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
8325     m_defaultCellAttr
->SetFont(font
); 
8328 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
8330     m_defaultCellAttr
->SetRenderer(renderer
); 
8333 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
8335     m_defaultCellAttr
->SetEditor(editor
); 
8338 // ---------------------------------------------------------------------------- 
8339 // access to the default attrbiutes 
8340 // ---------------------------------------------------------------------------- 
8342 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
8344     return m_defaultCellAttr
->GetBackgroundColour(); 
8347 wxColour 
wxGrid::GetDefaultCellTextColour() 
8349     return m_defaultCellAttr
->GetTextColour(); 
8352 wxFont 
wxGrid::GetDefaultCellFont() 
8354     return m_defaultCellAttr
->GetFont(); 
8357 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
8359     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
8362 bool wxGrid::GetDefaultCellOverflow() 
8364     return m_defaultCellAttr
->GetOverflow(); 
8367 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
8369     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
8372 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
8374     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
8377 // ---------------------------------------------------------------------------- 
8378 // access to cell attributes 
8379 // ---------------------------------------------------------------------------- 
8381 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
8383     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8384     wxColour colour 
= attr
->GetBackgroundColour(); 
8389 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
8391     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8392     wxColour colour 
= attr
->GetTextColour(); 
8397 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
8399     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8400     wxFont font 
= attr
->GetFont(); 
8405 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
8407     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8408     attr
->GetAlignment(horiz
, vert
); 
8412 bool wxGrid::GetCellOverflow( int row
, int col 
) 
8414     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8415     bool allow 
= attr
->GetOverflow(); 
8420 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) 
8422     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8423     attr
->GetSize( num_rows
, num_cols 
); 
8427 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
8429     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8430     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8436 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
8438     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8439     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8445 bool wxGrid::IsReadOnly(int row
, int col
) const 
8447     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8448     bool isReadOnly 
= attr
->IsReadOnly(); 
8453 // ---------------------------------------------------------------------------- 
8454 // attribute support: cache, automatic provider creation, ... 
8455 // ---------------------------------------------------------------------------- 
8457 bool wxGrid::CanHaveAttributes() 
8464     return m_table
->CanHaveAttributes(); 
8467 void wxGrid::ClearAttrCache() 
8469     if ( m_attrCache
.row 
!= -1 ) 
8471         wxSafeDecRef(m_attrCache
.attr
); 
8472         m_attrCache
.attr 
= NULL
; 
8473         m_attrCache
.row 
= -1; 
8477 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
8479     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8481     self
->ClearAttrCache(); 
8482     self
->m_attrCache
.row 
= row
; 
8483     self
->m_attrCache
.col 
= col
; 
8484     self
->m_attrCache
.attr 
= attr
; 
8488 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
8490     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
8492         *attr 
= m_attrCache
.attr
; 
8493         wxSafeIncRef(m_attrCache
.attr
); 
8495 #ifdef DEBUG_ATTR_CACHE 
8496         gs_nAttrCacheHits
++; 
8503 #ifdef DEBUG_ATTR_CACHE 
8504         gs_nAttrCacheMisses
++; 
8510 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
8512     wxGridCellAttr 
*attr 
= NULL
; 
8513     // Additional test to avoid looking at the cache e.g. for 
8514     // wxNoCellCoords, as this will confuse memory management. 
8517         if ( !LookupAttr(row
, col
, &attr
) ) 
8519             attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) 
8520                            : (wxGridCellAttr 
*)NULL
; 
8521             CacheAttr(row
, col
, attr
); 
8526         attr
->SetDefAttr(m_defaultCellAttr
); 
8530         attr 
= m_defaultCellAttr
; 
8537 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
8539     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8541     wxCHECK_MSG( m_table
, attr
, 
8542                   _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
8544     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
8547         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
8549         // artificially inc the ref count to match DecRef() in caller 
8551         m_table
->SetAttr(attr
, row
, col
); 
8557 // ---------------------------------------------------------------------------- 
8558 // setting column attributes (wrappers around SetColAttr) 
8559 // ---------------------------------------------------------------------------- 
8561 void wxGrid::SetColFormatBool(int col
) 
8563     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
8566 void wxGrid::SetColFormatNumber(int col
) 
8568     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
8571 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
8573     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
8574     if ( (width 
!= -1) || (precision 
!= -1) ) 
8576         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
8579     SetColFormatCustom(col
, typeName
); 
8582 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
8584     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8586     attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
8588         attr 
= new wxGridCellAttr
; 
8589     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
8590     attr
->SetRenderer(renderer
); 
8592     SetColAttr(col
, attr
); 
8596 // ---------------------------------------------------------------------------- 
8597 // setting cell attributes: this is forwarded to the table 
8598 // ---------------------------------------------------------------------------- 
8600 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
8602     if ( CanHaveAttributes() ) 
8604         m_table
->SetAttr(attr
, row
, col
); 
8613 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
8615     if ( CanHaveAttributes() ) 
8617         m_table
->SetRowAttr(attr
, row
); 
8626 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
8628     if ( CanHaveAttributes() ) 
8630         m_table
->SetColAttr(attr
, col
); 
8639 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
8641     if ( CanHaveAttributes() ) 
8643         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8644         attr
->SetBackgroundColour(colour
); 
8649 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
8651     if ( CanHaveAttributes() ) 
8653         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8654         attr
->SetTextColour(colour
); 
8659 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
8661     if ( CanHaveAttributes() ) 
8663         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8664         attr
->SetFont(font
); 
8669 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
8671     if ( CanHaveAttributes() ) 
8673         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8674         attr
->SetAlignment(horiz
, vert
); 
8679 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
8681     if ( CanHaveAttributes() ) 
8683         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8684         attr
->SetOverflow(allow
); 
8689 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
8691     if ( CanHaveAttributes() ) 
8693         int cell_rows
, cell_cols
; 
8695         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8696         attr
->GetSize(&cell_rows
, &cell_cols
); 
8697         attr
->SetSize(num_rows
, num_cols
); 
8700         // Cannot set the size of a cell to 0 or negative values 
8701         // While it is perfectly legal to do that, this function cannot 
8702         // handle all the possibilies, do it by hand by getting the CellAttr. 
8703         // You can only set the size of a cell to 1,1 or greater with this fn 
8704         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
8705                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
8706         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
8707                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
8709         // if this was already a multicell then "turn off" the other cells first 
8710         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
8713             for (j
=row
; j
<row
+cell_rows
; j
++) 
8715                 for (i
=col
; i
<col
+cell_cols
; i
++) 
8717                     if ((i 
!= col
) || (j 
!= row
)) 
8719                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
8720                         attr_stub
->SetSize( 1, 1 ); 
8721                         attr_stub
->DecRef(); 
8727         // mark the cells that will be covered by this cell to 
8728         // negative or zero values to point back at this cell 
8729         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
8732             for (j
=row
; j
<row
+num_rows
; j
++) 
8734                 for (i
=col
; i
<col
+num_cols
; i
++) 
8736                     if ((i 
!= col
) || (j 
!= row
)) 
8738                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
8739                         attr_stub
->SetSize( row
-j
, col
-i 
); 
8740                         attr_stub
->DecRef(); 
8748 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
8750     if ( CanHaveAttributes() ) 
8752         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8753         attr
->SetRenderer(renderer
); 
8758 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
8760     if ( CanHaveAttributes() ) 
8762         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8763         attr
->SetEditor(editor
); 
8768 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
8770     if ( CanHaveAttributes() ) 
8772         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8773         attr
->SetReadOnly(isReadOnly
); 
8778 // ---------------------------------------------------------------------------- 
8779 // Data type registration 
8780 // ---------------------------------------------------------------------------- 
8782 void wxGrid::RegisterDataType(const wxString
& typeName
, 
8783                               wxGridCellRenderer
* renderer
, 
8784                               wxGridCellEditor
* editor
) 
8786     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
8790 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
8792     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8793     return GetDefaultEditorForType(typeName
); 
8796 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
8798     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
8799     return GetDefaultRendererForType(typeName
); 
8803 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
8805     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8806     if ( index 
== wxNOT_FOUND 
) 
8808         wxFAIL_MSG(wxT("Unknown data type name")); 
8813     return m_typeRegistry
->GetEditor(index
); 
8817 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
8819     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
8820     if ( index 
== wxNOT_FOUND 
) 
8822         wxFAIL_MSG(wxT("Unknown data type name")); 
8827     return m_typeRegistry
->GetRenderer(index
); 
8831 // ---------------------------------------------------------------------------- 
8833 // ---------------------------------------------------------------------------- 
8835 void wxGrid::EnableDragRowSize( bool enable 
) 
8837     m_canDragRowSize 
= enable
; 
8841 void wxGrid::EnableDragColSize( bool enable 
) 
8843     m_canDragColSize 
= enable
; 
8846 void wxGrid::EnableDragGridSize( bool enable 
) 
8848     m_canDragGridSize 
= enable
; 
8852 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
8854     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
8856     if ( resizeExistingRows 
) 
8858         // since we are resizing all rows to the default row size, 
8859         // we can simply clear the row heights and row bottoms 
8860         // arrays (which also allows us to take advantage of 
8861         // some speed optimisations) 
8862         m_rowHeights
.Empty(); 
8863         m_rowBottoms
.Empty(); 
8864         if ( !GetBatchCount() ) 
8869 void wxGrid::SetRowSize( int row
, int height 
) 
8871     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
8873     if ( m_rowHeights
.IsEmpty() ) 
8875         // need to really create the array 
8879     int h 
= wxMax( 0, height 
); 
8880     int diff 
= h 
- m_rowHeights
[row
]; 
8882     m_rowHeights
[row
] = h
; 
8884     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
8886         m_rowBottoms
[i
] += diff
; 
8888     if ( !GetBatchCount() ) 
8892 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
8894     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
8896     if ( resizeExistingCols 
) 
8898         // since we are resizing all columns to the default column size, 
8899         // we can simply clear the col widths and col rights 
8900         // arrays (which also allows us to take advantage of 
8901         // some speed optimisations) 
8902         m_colWidths
.Empty(); 
8903         m_colRights
.Empty(); 
8904         if ( !GetBatchCount() ) 
8909 void wxGrid::SetColSize( int col
, int width 
) 
8911     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
8913     // should we check that it's bigger than GetColMinimalWidth(col) here? 
8915     if ( m_colWidths
.IsEmpty() ) 
8917         // need to really create the array 
8921     int w 
= wxMax( 0, width 
); 
8922     int diff 
= w 
- m_colWidths
[col
]; 
8923     m_colWidths
[col
] = w
; 
8926     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
8928         m_colRights
[i
] += diff
; 
8930     if ( !GetBatchCount() ) 
8935 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
8937     m_colMinWidths
.Put(col
, width
); 
8940 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
8942     m_rowMinHeights
.Put(row
, width
); 
8945 int wxGrid::GetColMinimalWidth(int col
) const 
8947     long value 
= m_colMinWidths
.Get(col
); 
8948     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
8951 int wxGrid::GetRowMinimalHeight(int row
) const 
8953     long value 
= m_rowMinHeights
.Get(row
); 
8954     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
8957 // ---------------------------------------------------------------------------- 
8959 // ---------------------------------------------------------------------------- 
8961 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
8963     wxClientDC 
dc(m_gridWin
); 
8965     // init both of them to avoid compiler warnings, even if weo nly need one 
8973     wxCoord extent
, extentMax 
= 0; 
8974     int max 
= column 
? m_numRows 
: m_numCols
; 
8975     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
8982         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8983         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8986             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
8987             extent 
= column 
? size
.x 
: size
.y
; 
8988             if ( extent 
> extentMax 
) 
8999     // now also compare with the column label extent 
9001     dc
.SetFont( GetLabelFont() ); 
9004         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
9006         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
9008     extent 
= column 
? w 
: h
; 
9009     if ( extent 
> extentMax 
) 
9016         // empty column - give default extent (notice that if extentMax is less 
9017         // than default extent but != 0, it's ok) 
9018         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
9024             // leave some space around text 
9035         SetColSize(col
, extentMax
); 
9036         if ( !GetBatchCount() ) 
9039             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9040             wxRect 
rect ( CellToRect( 0, col 
) ); 
9042             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
9043             rect
.width 
= cw 
- rect
.x
; 
9044             rect
.height 
= m_colLabelHeight
; 
9045             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
9050         SetRowSize(row
, extentMax
); 
9051         if ( !GetBatchCount() ) 
9054             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9055             wxRect 
rect ( CellToRect( row
, 0 ) ); 
9057             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9058             rect
.width 
= m_rowLabelWidth
; 
9059             rect
.height 
= ch 
- rect
.y
; 
9060             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
9066             SetColMinimalWidth(col
, extentMax
); 
9068             SetRowMinimalHeight(row
, extentMax
); 
9072 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
9074     int width 
= m_rowLabelWidth
; 
9079     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9083             AutoSizeColumn(col
, setAsMin
); 
9086         width 
+= GetColWidth(col
); 
9095 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
9097     int height 
= m_colLabelHeight
; 
9102     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9106             AutoSizeRow(row
, setAsMin
); 
9109         height 
+= GetRowHeight(row
); 
9118 void wxGrid::AutoSize() 
9122     wxSize 
size(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
9124     // round up the size to a multiple of scroll step - this ensures that we 
9125     // won't get the scrollbars if we're sized exactly to this width 
9126     wxSize 
sizeFit(GetScrollX(size
.x
) * GRID_SCROLL_LINE_X
, 
9127                    GetScrollY(size
.y
) * GRID_SCROLL_LINE_Y
); 
9129     // distribute the extra space between teh columns/rows to avoid having 
9130     // extra white space 
9131     wxCoord diff 
= sizeFit
.x 
- size
.x
; 
9134         // try to resize the columns uniformly 
9135         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
9138             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9140                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
9144         // add remaining amount to the last columns 
9145         diff 
-= diffPerCol 
* m_numCols
; 
9148             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
9150                 SetColSize(col
, GetColWidth(col
) + 1); 
9156     diff 
= sizeFit
.y 
- size
.y
; 
9159         // try to resize the columns uniformly 
9160         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
9163             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9165                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
9169         // add remaining amount to the last rows 
9170         diff 
-= diffPerRow 
* m_numRows
; 
9173             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
9175                 SetRowSize(row
, GetRowHeight(row
) + 1); 
9182     SetClientSize(sizeFit
); 
9185 wxSize 
wxGrid::DoGetBestSize() const 
9187     // don't set sizes, only calculate them 
9188     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9190     return wxSize(self
->SetOrCalcColumnSizes(TRUE
), 
9191                   self
->SetOrCalcRowSizes(TRUE
)); 
9200 wxPen
& wxGrid::GetDividerPen() const 
9205 // ---------------------------------------------------------------------------- 
9206 // cell value accessor functions 
9207 // ---------------------------------------------------------------------------- 
9209 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
9213         m_table
->SetValue( row
, col
, s 
); 
9214         if ( !GetBatchCount() ) 
9217             wxRect 
rect( CellToRect( row
, col 
) ); 
9219             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
9220             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9221             m_gridWin
->Refresh( FALSE
, &rect 
); 
9224         if ( m_currentCellCoords
.GetRow() == row 
&& 
9225              m_currentCellCoords
.GetCol() == col 
&& 
9226              IsCellEditControlShown()) 
9227              // Note: If we are using IsCellEditControlEnabled, 
9228              // this interacts badly with calling SetCellValue from 
9229              // an EVT_GRID_CELL_CHANGE handler. 
9231             HideCellEditControl(); 
9232             ShowCellEditControl(); // will reread data from table 
9239 // ------ Block, row and col selection 
9242 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
9244     if ( IsSelection() && !addToSelected 
) 
9248         m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
9252 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
9254     if ( IsSelection() && !addToSelected 
) 
9258         m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
9262 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
9263                           bool addToSelected 
) 
9265     if ( IsSelection() && !addToSelected 
) 
9269         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
9270                                   FALSE
, addToSelected 
); 
9274 void wxGrid::SelectAll() 
9276     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
9279             m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
9284 // ------ Cell, row and col deselection 
9287 void wxGrid::DeselectRow( int row 
) 
9292     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
9294         if ( m_selection
->IsInSelection(row
, 0 ) ) 
9295             m_selection
->ToggleCellSelection( row
, 0); 
9299         int nCols 
= GetNumberCols(); 
9300         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
9302             if ( m_selection
->IsInSelection(row
, i 
) ) 
9303                 m_selection
->ToggleCellSelection( row
, i
); 
9308 void wxGrid::DeselectCol( int col 
) 
9313     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
9315         if ( m_selection
->IsInSelection(0, col 
) ) 
9316             m_selection
->ToggleCellSelection( 0, col
); 
9320         int nRows 
= GetNumberRows(); 
9321         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
9323             if ( m_selection
->IsInSelection(i
, col 
) ) 
9324                 m_selection
->ToggleCellSelection(i
, col
); 
9329 void wxGrid::DeselectCell( int row
, int col 
) 
9331     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
9332         m_selection
->ToggleCellSelection(row
, col
); 
9335 bool wxGrid::IsSelection() 
9337     return ( m_selection 
&& (m_selection
->IsSelection() || 
9338              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
9339                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
9342 bool wxGrid::IsInSelection( int row
, int col 
) 
9344     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
9345              ( row 
>= m_selectingTopLeft
.GetRow() && 
9346                col 
>= m_selectingTopLeft
.GetCol() && 
9347                row 
<= m_selectingBottomRight
.GetRow() && 
9348                col 
<= m_selectingBottomRight
.GetCol() )) ); 
9351 void wxGrid::ClearSelection() 
9353     m_selectingTopLeft 
= wxGridNoCellCoords
; 
9354     m_selectingBottomRight 
= wxGridNoCellCoords
; 
9356         m_selection
->ClearSelection(); 
9360 // This function returns the rectangle that encloses the given block 
9361 // in device coords clipped to the client size of the grid window. 
9363 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
9364                                   const wxGridCellCoords 
&bottomRight 
) 
9366     wxRect 
rect( wxGridNoCellRect 
); 
9369     cellRect 
= CellToRect( topLeft 
); 
9370     if ( cellRect 
!= wxGridNoCellRect 
) 
9376         rect 
= wxRect( 0, 0, 0, 0 ); 
9379     cellRect 
= CellToRect( bottomRight 
); 
9380     if ( cellRect 
!= wxGridNoCellRect 
) 
9386         return wxGridNoCellRect
; 
9390     int left 
= rect
.GetLeft(); 
9391     int top 
= rect
.GetTop(); 
9392     int right 
= rect
.GetRight(); 
9393     int bottom 
= rect
.GetBottom(); 
9395     int leftCol 
= topLeft
.GetCol(); 
9396     int topRow 
= topLeft
.GetRow(); 
9397     int rightCol 
= bottomRight
.GetCol(); 
9398     int bottomRow 
= bottomRight
.GetRow(); 
9400     for ( j 
= topRow
; j 
<= bottomRow
; j
++ ) 
9402         for ( i 
= leftCol
; i 
<= rightCol
; i
++ ) 
9404             if ((j
==topRow
) || (j
==bottomRow
) || (i
==leftCol
) || (i
==rightCol
)) 
9406                 cellRect 
= CellToRect( j
, i 
); 
9408                 if (cellRect
.x 
< left
) 
9410                 if (cellRect
.y 
< top
) 
9412                 if (cellRect
.x 
+ cellRect
.width 
> right
) 
9413                     right 
= cellRect
.x 
+ cellRect
.width
; 
9414                 if (cellRect
.y 
+ cellRect
.height 
> bottom
) 
9415                     bottom 
= cellRect
.y 
+ cellRect
.height
; 
9420     // convert to scrolled coords 
9422     CalcScrolledPosition( left
, top
, &left
, &top 
); 
9423     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
9426     m_gridWin
->GetClientSize( &cw
, &ch 
); 
9428     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
9429         return wxRect( 0, 0, 0, 0); 
9431     rect
.SetLeft( wxMax(0, left
) ); 
9432     rect
.SetTop( wxMax(0, top
) ); 
9433     rect
.SetRight( wxMin(cw
, right
) ); 
9434     rect
.SetBottom( wxMin(ch
, bottom
) ); 
9442 // ------ Grid event classes 
9445 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
9447 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
9448                           int row
, int col
, int x
, int y
, bool sel
, 
9449                           bool control
, bool shift
, bool alt
, bool meta 
) 
9450         : wxNotifyEvent( type
, id 
) 
9457     m_control 
= control
; 
9462     SetEventObject(obj
); 
9466 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
9468 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
9469                                   int rowOrCol
, int x
, int y
, 
9470                                   bool control
, bool shift
, bool alt
, bool meta 
) 
9471         : wxNotifyEvent( type
, id 
) 
9473     m_rowOrCol 
= rowOrCol
; 
9476     m_control 
= control
; 
9481     SetEventObject(obj
); 
9485 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
9487 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
9488                                                const wxGridCellCoords
& topLeft
, 
9489                                                const wxGridCellCoords
& bottomRight
, 
9490                                                bool sel
, bool control
, 
9491                                                bool shift
, bool alt
, bool meta 
) 
9492         : wxNotifyEvent( type
, id 
) 
9494     m_topLeft     
= topLeft
; 
9495     m_bottomRight 
= bottomRight
; 
9497     m_control     
= control
; 
9502     SetEventObject(obj
); 
9506 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
9508 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
9509                                                    wxObject
* obj
, int row
, 
9510                                                    int col
, wxControl
* ctrl
) 
9511     : wxCommandEvent(type
, id
) 
9513     SetEventObject(obj
); 
9520 #endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID 
9522 #endif // wxUSE_GRID