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
) + wxT("\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
; 
 757 // return the value in the text control 
 758 wxString 
wxGridCellTextEditor::GetValue() const 
 760   return Text()->GetValue(); 
 763 // ---------------------------------------------------------------------------- 
 764 // wxGridCellNumberEditor 
 765 // ---------------------------------------------------------------------------- 
 767 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
) 
 773 void wxGridCellNumberEditor::Create(wxWindow
* parent
, 
 775                                     wxEvtHandler
* evtHandler
) 
 779         // create a spin ctrl 
 780         m_control 
= new wxSpinCtrl(parent
, -1, wxEmptyString
, 
 781                                    wxDefaultPosition
, wxDefaultSize
, 
 785         wxGridCellEditor::Create(parent
, id
, evtHandler
); 
 789         // just a text control 
 790         wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 793         Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
 794 #endif // wxUSE_VALIDATORS 
 798 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
 800     // first get the value 
 801     wxGridTableBase 
*table 
= grid
->GetTable(); 
 802     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
 804         m_valueOld 
= table
->GetValueAsLong(row
, col
); 
 809         wxString sValue 
= table
->GetValue(row
, col
); 
 810         if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.IsEmpty()) 
 812             wxFAIL_MSG( _T("this cell doesn't have numeric value") ); 
 819         Spin()->SetValue((int)m_valueOld
); 
 824         DoBeginEdit(GetString()); 
 828 bool wxGridCellNumberEditor::EndEdit(int row
, int col
, 
 837         value 
= Spin()->GetValue(); 
 838         changed 
= value 
!= m_valueOld
; 
 840             text 
= wxString::Format(wxT("%ld"), value
); 
 844         text 
= Text()->GetValue(); 
 845         changed 
= (text
.IsEmpty() || text
.ToLong(&value
)) && (value 
!= m_valueOld
); 
 850         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
)) 
 851             grid
->GetTable()->SetValueAsLong(row
, col
, value
); 
 853             grid
->GetTable()->SetValue(row
, col
, text
); 
 859 void wxGridCellNumberEditor::Reset() 
 863         Spin()->SetValue((int)m_valueOld
); 
 867         DoReset(GetString()); 
 871 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
) 
 873     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
 875         int keycode 
= event
.GetKeyCode(); 
 891             case WXK_NUMPAD_SUBTRACT
: 
 897                 if ( (keycode 
< 128) && isdigit(keycode
) ) 
 905 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
) 
 909         int keycode 
= (int) event
.KeyCode(); 
 910         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' 
 911             || keycode 
==  WXK_NUMPAD0
 
 912             || keycode 
==  WXK_NUMPAD1
 
 913             || keycode 
==  WXK_NUMPAD2
 
 914             || keycode 
==  WXK_NUMPAD3
 
 915             || keycode 
==  WXK_NUMPAD4
 
 916             || keycode 
==  WXK_NUMPAD5
 
 917             || keycode 
==  WXK_NUMPAD6
 
 918             || keycode 
==  WXK_NUMPAD7
 
 919             || keycode 
==  WXK_NUMPAD8
 
 920             || keycode 
==  WXK_NUMPAD9
 
 921             || keycode 
==  WXK_ADD
 
 922             || keycode 
==  WXK_NUMPAD_ADD
 
 923             || keycode 
==  WXK_SUBTRACT
 
 924             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
 926             wxGridCellTextEditor::StartingKey(event
); 
 936 void wxGridCellNumberEditor::SetParameters(const wxString
& params
) 
 947         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
 951             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
 955                 // skip the error message below 
 960         wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str()); 
 965 // return the value in the spin control if it is there (the text control otherwise) 
 966 wxString 
wxGridCellNumberEditor::GetValue() const 
 972     int value 
= Spin()->GetValue(); 
 973     s
.Printf(wxT("%ld"), value
); 
 977     s 
= Text()->GetValue(); 
 982 // ---------------------------------------------------------------------------- 
 983 // wxGridCellFloatEditor 
 984 // ---------------------------------------------------------------------------- 
 986 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
) 
 989     m_precision 
= precision
; 
 992 void wxGridCellFloatEditor::Create(wxWindow
* parent
, 
 994                                    wxEvtHandler
* evtHandler
) 
 996     wxGridCellTextEditor::Create(parent
, id
, evtHandler
); 
 999     Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
)); 
1000 #endif // wxUSE_VALIDATORS 
1003 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1005     // first get the value 
1006     wxGridTableBase 
*table 
= grid
->GetTable(); 
1007     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1009         m_valueOld 
= table
->GetValueAsDouble(row
, col
); 
1014         wxString sValue 
= table
->GetValue(row
, col
); 
1015         if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.IsEmpty()) 
1017             wxFAIL_MSG( _T("this cell doesn't have float value") ); 
1022     DoBeginEdit(GetString()); 
1025 bool wxGridCellFloatEditor::EndEdit(int row
, int col
, 
1029     wxString 
text(Text()->GetValue()); 
1031     if ( (text
.IsEmpty() || text
.ToDouble(&value
)) && (value 
!= m_valueOld
) ) 
1033         if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
)) 
1034             grid
->GetTable()->SetValueAsDouble(row
, col
, value
); 
1036             grid
->GetTable()->SetValue(row
, col
, text
); 
1043 void wxGridCellFloatEditor::Reset() 
1045     DoReset(GetString()); 
1048 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
) 
1050     int keycode 
= (int)event
.KeyCode(); 
1051         if ( isdigit(keycode
) || keycode 
== '+' || keycode 
== '-' || keycode 
== '.' 
1052             || keycode 
==  WXK_NUMPAD0
 
1053             || keycode 
==  WXK_NUMPAD1
 
1054             || keycode 
==  WXK_NUMPAD2
 
1055             || keycode 
==  WXK_NUMPAD3
 
1056             || keycode 
==  WXK_NUMPAD4
 
1057             || keycode 
==  WXK_NUMPAD5
 
1058             || keycode 
==  WXK_NUMPAD6
 
1059             || keycode 
==  WXK_NUMPAD7
 
1060             || keycode 
==  WXK_NUMPAD8
 
1061             || keycode 
==  WXK_NUMPAD9
 
1062             || keycode 
==  WXK_ADD
 
1063             || keycode 
==  WXK_NUMPAD_ADD
 
1064             || keycode 
==  WXK_SUBTRACT
 
1065             || keycode 
==  WXK_NUMPAD_SUBTRACT
) 
1067         wxGridCellTextEditor::StartingKey(event
); 
1069         // skip Skip() below 
1076 void wxGridCellFloatEditor::SetParameters(const wxString
& params
) 
1087         if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) ) 
1091             if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) ) 
1093                 m_precision 
= (int)tmp
; 
1095                 // skip the error message below 
1100         wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str()); 
1104 wxString 
wxGridCellFloatEditor::GetString() const 
1107     if ( m_width 
== -1 ) 
1109         // default width/precision 
1112     else if ( m_precision 
== -1 ) 
1114         // default precision 
1115         fmt
.Printf(_T("%%%d.f"), m_width
); 
1119         fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1122     return wxString::Format(fmt
, m_valueOld
); 
1125 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1127     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1129         int keycode 
= event
.GetKeyCode(); 
1143             case WXK_NUMPAD_ADD
: 
1145             case WXK_NUMPAD_SUBTRACT
: 
1147             case WXK_NUMPAD_DECIMAL
: 
1151                 // additionally accept 'e' as in '1e+6' 
1152                 if ( (keycode 
< 128) && 
1153                      (isdigit(keycode
) || tolower(keycode
) == 'e') ) 
1161 #endif // wxUSE_TEXTCTRL 
1165 // ---------------------------------------------------------------------------- 
1166 // wxGridCellBoolEditor 
1167 // ---------------------------------------------------------------------------- 
1169 void wxGridCellBoolEditor::Create(wxWindow
* parent
, 
1171                                   wxEvtHandler
* evtHandler
) 
1173     m_control 
= new wxCheckBox(parent
, id
, wxEmptyString
, 
1174                                wxDefaultPosition
, wxDefaultSize
, 
1177     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1180 void wxGridCellBoolEditor::SetSize(const wxRect
& r
) 
1182     bool resize 
= FALSE
; 
1183     wxSize size 
= m_control
->GetSize(); 
1184     wxCoord minSize 
= wxMin(r
.width
, r
.height
); 
1186     // check if the checkbox is not too big/small for this cell 
1187     wxSize sizeBest 
= m_control
->GetBestSize(); 
1188     if ( !(size 
== sizeBest
) ) 
1190         // reset to default size if it had been made smaller 
1196     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1198         // leave 1 pixel margin 
1199         size
.x 
= size
.y 
= minSize 
- 2; 
1206         m_control
->SetSize(size
); 
1209     // position it in the centre of the rectangle (TODO: support alignment?) 
1211 #if defined(__WXGTK__) || defined (__WXMOTIF__) 
1212     // the checkbox without label still has some space to the right in wxGTK, 
1213     // so shift it to the right 
1215 #elif defined(__WXMSW__) 
1216     // here too, but in other way 
1221     m_control
->Move(r
.x 
+ r
.width
/2 - size
.x
/2, r
.y 
+ r
.height
/2 - size
.y
/2); 
1224 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr 
*attr
) 
1226     m_control
->Show(show
); 
1230         wxColour colBg 
= attr 
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
; 
1231         CBox()->SetBackgroundColour(colBg
); 
1235 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1237     wxASSERT_MSG(m_control
, 
1238                  wxT("The wxGridCellEditor must be Created first!")); 
1240     if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1241         m_startValue 
= grid
->GetTable()->GetValueAsBool(row
, col
); 
1244         wxString 
cellval( grid
->GetTable()->GetValue(row
, col
) ); 
1245         m_startValue 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
1247     CBox()->SetValue(m_startValue
); 
1251 bool wxGridCellBoolEditor::EndEdit(int row
, int col
, 
1254     wxASSERT_MSG(m_control
, 
1255                  wxT("The wxGridCellEditor must be Created first!")); 
1257     bool changed 
= FALSE
; 
1258     bool value 
= CBox()->GetValue(); 
1259     if ( value 
!= m_startValue 
) 
1264         if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
)) 
1265             grid
->GetTable()->SetValueAsBool(row
, col
, value
); 
1267             grid
->GetTable()->SetValue(row
, col
, value 
? _T("1") : wxEmptyString
); 
1273 void wxGridCellBoolEditor::Reset() 
1275     wxASSERT_MSG(m_control
, 
1276                  wxT("The wxGridCellEditor must be Created first!")); 
1278     CBox()->SetValue(m_startValue
); 
1281 void wxGridCellBoolEditor::StartingClick() 
1283     CBox()->SetValue(!CBox()->GetValue()); 
1286 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
) 
1288     if ( wxGridCellEditor::IsAcceptedKey(event
) ) 
1290         int keycode 
= event
.GetKeyCode(); 
1294             case WXK_NUMPAD_MULTIPLY
: 
1296             case WXK_NUMPAD_ADD
: 
1298             case WXK_NUMPAD_SUBTRACT
: 
1309 // return the value as "1" for true and the empty string for false 
1310 wxString 
wxGridCellBoolEditor::GetValue() const 
1312   bool bSet 
= CBox()->GetValue(); 
1313   return bSet 
? "1" : wxEmptyString
; 
1316 #endif // wxUSE_CHECKBOX 
1320 // ---------------------------------------------------------------------------- 
1321 // wxGridCellChoiceEditor 
1322 // ---------------------------------------------------------------------------- 
1324 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
, 
1325                                                const wxString choices
[], 
1327                       : m_allowOthers(allowOthers
) 
1331         m_choices
.Alloc(count
); 
1332         for ( size_t n 
= 0; n 
< count
; n
++ ) 
1334             m_choices
.Add(choices
[n
]); 
1339 wxGridCellEditor 
*wxGridCellChoiceEditor::Clone() const 
1341     wxGridCellChoiceEditor 
*editor 
= new wxGridCellChoiceEditor
; 
1342     editor
->m_allowOthers 
= m_allowOthers
; 
1343     editor
->m_choices 
= m_choices
; 
1348 void wxGridCellChoiceEditor::Create(wxWindow
* parent
, 
1350                                     wxEvtHandler
* evtHandler
) 
1352     size_t count 
= m_choices
.GetCount(); 
1353     wxString 
*choices 
= new wxString
[count
]; 
1354     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1356         choices
[n
] = m_choices
[n
]; 
1359     m_control 
= new wxComboBox(parent
, id
, wxEmptyString
, 
1360                                wxDefaultPosition
, wxDefaultSize
, 
1362                                m_allowOthers 
? 0 : wxCB_READONLY
); 
1366     wxGridCellEditor::Create(parent
, id
, evtHandler
); 
1369 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
, 
1370                                              wxGridCellAttr 
* attr
) 
1372     // as we fill the entire client area, don't do anything here to minimize 
1375     // TODO: It doesn't actually fill the client area since the height of a 
1376     // combo always defaults to the standard...  Until someone has time to 
1377     // figure out the right rectangle to paint, just do it the normal way... 
1378     wxGridCellEditor::PaintBackground(rectCell
, attr
); 
1381 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
) 
1383     wxASSERT_MSG(m_control
, 
1384                  wxT("The wxGridCellEditor must be Created first!")); 
1386     m_startValue 
= grid
->GetTable()->GetValue(row
, col
); 
1389         Combo()->SetValue(m_startValue
); 
1392         // find the right position, or default to the first if not found 
1393         int pos 
= Combo()->FindString(m_startValue
); 
1396         Combo()->SetSelection(pos
); 
1398     Combo()->SetInsertionPointEnd(); 
1399     Combo()->SetFocus(); 
1402 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
, 
1405     wxString value 
= Combo()->GetValue(); 
1406     bool changed 
= value 
!= m_startValue
; 
1409         grid
->GetTable()->SetValue(row
, col
, value
); 
1411     m_startValue 
= wxEmptyString
; 
1413         Combo()->SetValue(m_startValue
); 
1415         Combo()->SetSelection(0); 
1420 void wxGridCellChoiceEditor::Reset() 
1422     Combo()->SetValue(m_startValue
); 
1423     Combo()->SetInsertionPointEnd(); 
1426 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
) 
1436     wxStringTokenizer 
tk(params
, _T(',')); 
1437     while ( tk
.HasMoreTokens() ) 
1439         m_choices
.Add(tk
.GetNextToken()); 
1444 // return the value in the text control 
1445 wxString 
wxGridCellChoiceEditor::GetValue() const 
1447   return Combo()->GetValue(); 
1449 #endif // wxUSE_COMBOBOX 
1451 // ---------------------------------------------------------------------------- 
1452 // wxGridCellEditorEvtHandler 
1453 // ---------------------------------------------------------------------------- 
1455 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
) 
1457     switch ( event
.KeyCode() ) 
1461             m_grid
->DisableCellEditControl(); 
1465             m_grid
->GetEventHandler()->ProcessEvent( event 
); 
1469         case WXK_NUMPAD_ENTER
: 
1470             if (!m_grid
->GetEventHandler()->ProcessEvent(event
)) 
1471                 m_editor
->HandleReturn(event
); 
1480 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
) 
1482     switch ( event
.KeyCode() ) 
1487         case WXK_NUMPAD_ENTER
: 
1495 // ---------------------------------------------------------------------------- 
1496 // wxGridCellWorker is an (almost) empty common base class for 
1497 // wxGridCellRenderer and wxGridCellEditor managing ref counting 
1498 // ---------------------------------------------------------------------------- 
1500 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
)) 
1505 wxGridCellWorker::~wxGridCellWorker() 
1509 // ============================================================================ 
1511 // ============================================================================ 
1513 // ---------------------------------------------------------------------------- 
1514 // wxGridCellRenderer 
1515 // ---------------------------------------------------------------------------- 
1517 void wxGridCellRenderer::Draw(wxGrid
& grid
, 
1518                               wxGridCellAttr
& attr
, 
1521                               int WXUNUSED(row
), int WXUNUSED(col
), 
1524     dc
.SetBackgroundMode( wxSOLID 
); 
1526 // DJC (MAPTEK) grey out fields if the grid is disabled 
1527     if( grid
.IsEnabled() ) 
1531           dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) ); 
1535           dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) ); 
1540       dc
.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
), wxSOLID
)); 
1543     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1544     dc
.DrawRectangle(rect
); 
1547 // ---------------------------------------------------------------------------- 
1548 // wxGridCellStringRenderer 
1549 // ---------------------------------------------------------------------------- 
1551 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
, 
1552                                                      wxGridCellAttr
& attr
, 
1556     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
1558     // TODO some special colours for attr.IsReadOnly() case? 
1560     // DJC (MAPTEK) different coloured text when the grid is disabled 
1561     if( grid
.IsEnabled() ) 
1565           dc
.SetTextBackground( grid
.GetSelectionBackground() ); 
1566           dc
.SetTextForeground( grid
.GetSelectionForeground() ); 
1570           dc
.SetTextBackground( attr
.GetBackgroundColour() ); 
1571           dc
.SetTextForeground( attr
.GetTextColour() ); 
1576       dc
.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)); 
1577       dc
.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT
)); 
1580     dc
.SetFont( attr
.GetFont() ); 
1583 wxSize 
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
, 
1585                                                const wxString
& text
) 
1587     wxCoord x 
= 0, y 
= 0, max_x 
= 0; 
1588     dc
.SetFont(attr
.GetFont()); 
1589     wxStringTokenizer 
tk(text
, _T('\n')); 
1590     while ( tk
.HasMoreTokens() ) 
1592         dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
); 
1593         max_x 
= wxMax(max_x
, x
); 
1596     y 
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines. 
1598     return wxSize(max_x
, y
); 
1601 wxSize 
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
, 
1602                                              wxGridCellAttr
& attr
, 
1606     return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
)); 
1609 void wxGridCellStringRenderer::Draw(wxGrid
& grid
, 
1610                                     wxGridCellAttr
& attr
, 
1612                                     const wxRect
& rectCell
, 
1616     wxRect rect 
= rectCell
; 
1619     // erase only this cells background, overflow cells should have been erased 
1620     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1623     attr
.GetAlignment(&hAlign
, &vAlign
); 
1625     int overflowCols 
= 0; 
1627     if (attr
.GetOverflow()) 
1629         int cols 
= grid
.GetNumberCols(); 
1630         int best_width 
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth(); 
1631         int cell_rows
, cell_cols
; 
1632         attr
.GetSize( &cell_rows
, &cell_cols 
); // shouldn't get here if <=0 
1633         if ((best_width 
> rectCell
.width
) && (col 
< cols
) && grid
.GetTable()) 
1635             int i
, c_cols
, c_rows
; 
1636             for (i 
= col
+cell_cols
; i 
< cols
; i
++) 
1638                 bool is_empty 
= TRUE
; 
1639                 for (int j
=row
; j
<row
+cell_rows
; j
++) 
1641                     // check w/ anchor cell for multicell block 
1642                     grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
); 
1643                     if (c_rows 
> 0) c_rows 
= 0; 
1644                     if (!grid
.GetTable()->IsEmptyCell(j
+c_rows
, i
)) 
1651                     rect
.width 
+= grid
.GetColSize(i
); 
1657                 if (rect
.width 
>= best_width
) break; 
1659             overflowCols 
= i 
- col 
- cell_cols 
+ 1; 
1660             if (overflowCols 
>= cols
) overflowCols 
= cols 
- 1; 
1663         if (overflowCols 
> 0) // redraw overflow cells w/ proper hilight 
1665             hAlign 
= wxALIGN_LEFT
; // if oveflowed then it's left aligned 
1667             clip
.x 
+= rectCell
.width
; 
1668             // draw each overflow cell individually 
1669             int col_end 
= col
+cell_cols
+overflowCols
; 
1670             if (col_end 
>= grid
.GetNumberCols()) 
1671                 col_end 
= grid
.GetNumberCols() - 1; 
1672             for (int i 
= col
+cell_cols
; i 
<= col_end
; i
++) 
1674                 clip
.width 
= grid
.GetColSize(i
) - 1; 
1675                 dc
.DestroyClippingRegion(); 
1676                 dc
.SetClippingRegion(clip
); 
1678                 SetTextColoursAndFont(grid
, attr
, dc
, 
1679                         grid
.IsInSelection(row
,i
)); 
1681                 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1682                         rect
, hAlign
, vAlign
); 
1683                 clip
.x 
+= grid
.GetColSize(i
) - 1; 
1689             dc
.DestroyClippingRegion(); 
1693     // now we only have to draw the text 
1694     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1696     grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
), 
1697                            rect
, hAlign
, vAlign
); 
1700 // ---------------------------------------------------------------------------- 
1701 // wxGridCellNumberRenderer 
1702 // ---------------------------------------------------------------------------- 
1704 wxString 
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1706     wxGridTableBase 
*table 
= grid
.GetTable(); 
1708     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) ) 
1710         text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
)); 
1714         text 
= table
->GetValue(row
, col
); 
1720 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
, 
1721                                     wxGridCellAttr
& attr
, 
1723                                     const wxRect
& rectCell
, 
1727     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1729     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1731     // draw the text right aligned by default 
1733     attr
.GetAlignment(&hAlign
, &vAlign
); 
1734     hAlign 
= wxALIGN_RIGHT
; 
1736     wxRect rect 
= rectCell
; 
1739     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1742 wxSize 
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
, 
1743                                              wxGridCellAttr
& attr
, 
1747     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1750 // ---------------------------------------------------------------------------- 
1751 // wxGridCellFloatRenderer 
1752 // ---------------------------------------------------------------------------- 
1754 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
) 
1757     SetPrecision(precision
); 
1760 wxGridCellRenderer 
*wxGridCellFloatRenderer::Clone() const 
1762     wxGridCellFloatRenderer 
*renderer 
= new wxGridCellFloatRenderer
; 
1763     renderer
->m_width 
= m_width
; 
1764     renderer
->m_precision 
= m_precision
; 
1765     renderer
->m_format 
= m_format
; 
1770 wxString 
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
) 
1772     wxGridTableBase 
*table 
= grid
.GetTable(); 
1777     if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) ) 
1779         val 
= table
->GetValueAsDouble(row
, col
); 
1784         text 
= table
->GetValue(row
, col
); 
1785         hasDouble 
= text
.ToDouble(&val
); 
1792             if ( m_width 
== -1 ) 
1794                 if ( m_precision 
== -1 ) 
1796                     // default width/precision 
1797                     m_format 
= _T("%f"); 
1801                     m_format
.Printf(_T("%%.%df"), m_precision
); 
1804             else if ( m_precision 
== -1 ) 
1806                 // default precision 
1807                 m_format
.Printf(_T("%%%d.f"), m_width
); 
1811                 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
); 
1815         text
.Printf(m_format
, val
); 
1818     //else: text already contains the string 
1823 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
, 
1824                                    wxGridCellAttr
& attr
, 
1826                                    const wxRect
& rectCell
, 
1830     wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
); 
1832     SetTextColoursAndFont(grid
, attr
, dc
, isSelected
); 
1834     // draw the text right aligned by default 
1836     attr
.GetAlignment(&hAlign
, &vAlign
); 
1837     hAlign 
= wxALIGN_RIGHT
; 
1839     wxRect rect 
= rectCell
; 
1842     grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
); 
1845 wxSize 
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
, 
1846                                             wxGridCellAttr
& attr
, 
1850     return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
)); 
1853 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
) 
1857         // reset to defaults 
1863         wxString tmp 
= params
.BeforeFirst(_T(',')); 
1867             if ( tmp
.ToLong(&width
) ) 
1869                 SetWidth((int)width
); 
1873                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str()); 
1877                 tmp 
= params
.AfterFirst(_T(',')); 
1881             if ( tmp
.ToLong(&precision
) ) 
1883                 SetPrecision((int)precision
); 
1887                 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str()); 
1895 // ---------------------------------------------------------------------------- 
1896 // wxGridCellBoolRenderer 
1897 // ---------------------------------------------------------------------------- 
1899 wxSize 
wxGridCellBoolRenderer::ms_sizeCheckMark
; 
1901 // FIXME these checkbox size calculations are really ugly... 
1903 // between checkmark and box 
1904 static const wxCoord wxGRID_CHECKMARK_MARGIN 
= 2; 
1906 wxSize 
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
, 
1907                                            wxGridCellAttr
& WXUNUSED(attr
), 
1912     // compute it only once (no locks for MT safeness in GUI thread...) 
1913     if ( !ms_sizeCheckMark
.x 
) 
1915         // get checkbox size 
1916         wxCoord checkSize 
= 0; 
1917         wxCheckBox 
*checkbox 
= new wxCheckBox(&grid
, -1, wxEmptyString
); 
1918         wxSize size 
= checkbox
->GetBestSize(); 
1919         checkSize 
= size
.y 
+ 2*wxGRID_CHECKMARK_MARGIN
; 
1921         // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result 
1922 #if defined(__WXGTK__) || defined(__WXMOTIF__) 
1923         checkSize 
-= size
.y 
/ 2; 
1928         ms_sizeCheckMark
.x 
= ms_sizeCheckMark
.y 
= checkSize
; 
1931     return ms_sizeCheckMark
; 
1934 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
, 
1935                                   wxGridCellAttr
& attr
, 
1941     wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
); 
1943     // draw a check mark in the centre (ignoring alignment - TODO) 
1944     wxSize size 
= GetBestSize(grid
, attr
, dc
, row
, col
); 
1946     // don't draw outside the cell 
1947     wxCoord minSize 
= wxMin(rect
.width
, rect
.height
); 
1948     if ( size
.x 
>= minSize 
|| size
.y 
>= minSize 
) 
1950         // and even leave (at least) 1 pixel margin 
1951         size
.x 
= size
.y 
= minSize 
- 2; 
1954     // draw a border around checkmark 
1956     rectBorder
.x 
= rect
.x 
+ rect
.width
/2 - size
.x
/2; 
1957     rectBorder
.y 
= rect
.y 
+ rect
.height
/2 - size
.y
/2; 
1958     rectBorder
.width 
= size
.x
; 
1959     rectBorder
.height 
= size
.y
; 
1962     if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) ) 
1963         value 
= grid
.GetTable()->GetValueAsBool(row
, col
); 
1966         wxString 
cellval( grid
.GetTable()->GetValue(row
, col
) ); 
1967         value 
= !( !cellval 
|| (cellval 
== wxT("0")) ); 
1972         wxRect rectMark 
= rectBorder
; 
1974         // MSW DrawCheckMark() is weird (and should probably be changed...) 
1975         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2); 
1979         rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
); 
1982         dc
.SetTextForeground(attr
.GetTextColour()); 
1983         dc
.DrawCheckMark(rectMark
); 
1986     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1987     dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
)); 
1988     dc
.DrawRectangle(rectBorder
); 
1991 // ---------------------------------------------------------------------------- 
1993 // ---------------------------------------------------------------------------- 
1995 void wxGridCellAttr::Init(wxGridCellAttr 
*attrDefault
) 
1999     m_isReadOnly 
= Unset
; 
2004     m_attrkind 
= wxGridCellAttr::Cell
; 
2006     m_sizeRows 
= m_sizeCols 
= 1; 
2009     SetDefAttr(attrDefault
); 
2012 wxGridCellAttr 
*wxGridCellAttr::Clone() const 
2014     wxGridCellAttr 
*attr 
= new wxGridCellAttr(m_defGridAttr
); 
2016     if ( HasTextColour() ) 
2017         attr
->SetTextColour(GetTextColour()); 
2018     if ( HasBackgroundColour() ) 
2019         attr
->SetBackgroundColour(GetBackgroundColour()); 
2021         attr
->SetFont(GetFont()); 
2022     if ( HasAlignment() ) 
2023         attr
->SetAlignment(m_hAlign
, m_vAlign
); 
2025     attr
->SetSize( m_sizeRows
, m_sizeCols 
); 
2029         attr
->SetRenderer(m_renderer
); 
2030         m_renderer
->IncRef(); 
2034         attr
->SetEditor(m_editor
); 
2039         attr
->SetReadOnly(); 
2041     attr
->SetKind( m_attrkind 
); 
2046 void wxGridCellAttr::MergeWith(wxGridCellAttr 
*mergefrom
) 
2048     if ( !HasTextColour() && mergefrom
->HasTextColour() ) 
2049         SetTextColour(mergefrom
->GetTextColour()); 
2050     if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() ) 
2051         SetBackgroundColour(mergefrom
->GetBackgroundColour()); 
2052     if ( !HasFont() && mergefrom
->HasFont() ) 
2053         SetFont(mergefrom
->GetFont()); 
2054     if ( !HasAlignment() && mergefrom
->HasAlignment() ){ 
2056         mergefrom
->GetAlignment( &hAlign
, &vAlign
); 
2057         SetAlignment(hAlign
, vAlign
); 
2060     mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols 
); 
2062     // Directly access member functions as GetRender/Editor don't just return 
2063     // m_renderer/m_editor 
2065     // Maybe add support for merge of Render and Editor? 
2066     if (!HasRenderer() && mergefrom
->HasRenderer() ) 
2068         m_renderer 
= mergefrom
->m_renderer
; 
2069         m_renderer
->IncRef(); 
2071     if ( !HasEditor() && mergefrom
->HasEditor() ) 
2073         m_editor 
=  mergefrom
->m_editor
; 
2076     if ( !HasReadWriteMode()  && mergefrom
->HasReadWriteMode() ) 
2077         SetReadOnly(mergefrom
->IsReadOnly()); 
2079     SetDefAttr(mergefrom
->m_defGridAttr
); 
2082 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
) 
2084     // The size of a cell is normally 1,1 
2086     // If this cell is larger (2,2) then this is the top left cell 
2087     // the other cells that will be covered (lower right cells) must be 
2088     // set to negative or zero values such that 
2089     // row + num_rows of the covered cell points to the larger cell (this cell) 
2090     // same goes for the col + num_cols. 
2092     // Size of 0,0 is NOT valid, neither is <=0 and any positive value 
2094     wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) || 
2095                   !((num_rows
<=0)&&(num_cols
>0)) || 
2096                   !((num_rows
==0)&&(num_cols
==0))), 
2097                   wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values")); 
2099     m_sizeRows 
= num_rows
; 
2100     m_sizeCols 
= num_cols
; 
2103 const wxColour
& wxGridCellAttr::GetTextColour() const 
2105     if (HasTextColour()) 
2109     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2111         return m_defGridAttr
->GetTextColour(); 
2115         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2116         return wxNullColour
; 
2121 const wxColour
& wxGridCellAttr::GetBackgroundColour() const 
2123     if (HasBackgroundColour()) 
2125     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2126         return m_defGridAttr
->GetBackgroundColour(); 
2129         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2130         return wxNullColour
; 
2135 const wxFont
& wxGridCellAttr::GetFont() const 
2139     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2140         return m_defGridAttr
->GetFont(); 
2143         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2149 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const 
2153         if ( hAlign 
) *hAlign 
= m_hAlign
; 
2154         if ( vAlign 
) *vAlign 
= m_vAlign
; 
2156     else if (m_defGridAttr 
&& m_defGridAttr 
!= this) 
2157         m_defGridAttr
->GetAlignment(hAlign
, vAlign
); 
2160         wxFAIL_MSG(wxT("Missing default cell attribute")); 
2164 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols 
) const 
2166     if ( num_rows 
) *num_rows 
= m_sizeRows
; 
2167     if ( num_cols 
) *num_cols 
= m_sizeCols
; 
2170 // GetRenderer and GetEditor use a slightly different decision path about 
2171 // which attribute to use.  If a non-default attr object has one then it is 
2172 // used, otherwise the default editor or renderer is fetched from the grid and 
2173 // used.  It should be the default for the data type of the cell.  If it is 
2174 // NULL (because the table has a type that the grid does not have in its 
2175 // registry,) then the grid's default editor or renderer is used. 
2177 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const 
2179     wxGridCellRenderer 
*renderer
; 
2181     if ( m_renderer 
&& this != m_defGridAttr 
) 
2183         // use the cells renderer if it has one 
2184         renderer 
= m_renderer
; 
2187     else // no non default cell renderer 
2189         // get default renderer for the data type 
2192             // GetDefaultRendererForCell() will do IncRef() for us 
2193             renderer 
= grid
->GetDefaultRendererForCell(row
, col
); 
2202             if (m_defGridAttr 
&&  this != m_defGridAttr 
) 
2204                 // if we still don't have one then use the grid default 
2205                 // (no need for IncRef() here neither) 
2206                 renderer 
= m_defGridAttr
->GetRenderer(NULL
, 0, 0); 
2208             else // default grid attr 
2210                 // use m_renderer which we had decided not to use initially 
2211                 renderer 
= m_renderer
; 
2218     // we're supposed to always find something 
2219     wxASSERT_MSG(renderer
, wxT("Missing default cell renderer")); 
2224 // same as above, except for s/renderer/editor/g 
2225 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const 
2227     wxGridCellEditor 
*editor
; 
2229     if ( m_editor 
&& this != m_defGridAttr 
) 
2231         // use the cells editor if it has one 
2235     else // no non default cell editor 
2237         // get default editor for the data type 
2240             // GetDefaultEditorForCell() will do IncRef() for us 
2241             editor 
= grid
->GetDefaultEditorForCell(row
, col
); 
2250             if ( m_defGridAttr 
&& this != m_defGridAttr 
) 
2252                 // if we still don't have one then use the grid default 
2253                 // (no need for IncRef() here neither) 
2254                 editor 
= m_defGridAttr
->GetEditor(NULL
, 0, 0); 
2256             else // default grid attr 
2258                 // use m_editor which we had decided not to use initially 
2266     // we're supposed to always find something 
2267     wxASSERT_MSG(editor
, wxT("Missing default cell editor")); 
2272 // ---------------------------------------------------------------------------- 
2273 // wxGridCellAttrData 
2274 // ---------------------------------------------------------------------------- 
2276 void wxGridCellAttrData::SetAttr(wxGridCellAttr 
*attr
, int row
, int col
) 
2278     int n 
= FindIndex(row
, col
); 
2279     if ( n 
== wxNOT_FOUND 
) 
2281         // add the attribute 
2282         m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
)); 
2286         // free the old attribute 
2287         m_attrs
[(size_t)n
].attr
->DecRef(); 
2291             // change the attribute 
2292             m_attrs
[(size_t)n
].attr 
= attr
; 
2296             // remove this attribute 
2297             m_attrs
.RemoveAt((size_t)n
); 
2302 wxGridCellAttr 
*wxGridCellAttrData::GetAttr(int row
, int col
) const 
2304     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2306     int n 
= FindIndex(row
, col
); 
2307     if ( n 
!= wxNOT_FOUND 
) 
2309         attr 
= m_attrs
[(size_t)n
].attr
; 
2316 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows 
) 
2318     size_t count 
= m_attrs
.GetCount(); 
2319     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2321         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2322         wxCoord row 
= coords
.GetRow(); 
2323         if ((size_t)row 
>= pos
) 
2327                 // If rows inserted, include row counter where necessary 
2328                 coords
.SetRow(row 
+ numRows
); 
2330             else if (numRows 
< 0) 
2332                 // If rows deleted ... 
2333                 if ((size_t)row 
>= pos 
- numRows
) 
2335                     // ...either decrement row counter (if row still exists)... 
2336                     coords
.SetRow(row 
+ numRows
); 
2340                     // ...or remove the attribute 
2341                     m_attrs
.RemoveAt((size_t)n
); 
2349 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols 
) 
2351     size_t count 
= m_attrs
.GetCount(); 
2352     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2354         wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2355         wxCoord col 
= coords
.GetCol(); 
2356         if ( (size_t)col 
>= pos 
) 
2360                 // If rows inserted, include row counter where necessary 
2361                 coords
.SetCol(col 
+ numCols
); 
2363             else if (numCols 
< 0) 
2365                 // If rows deleted ... 
2366                 if ((size_t)col 
>= pos 
- numCols
) 
2368                     // ...either decrement row counter (if row still exists)... 
2369                     coords
.SetCol(col 
+ numCols
); 
2373                     // ...or remove the attribute 
2374                     m_attrs
.RemoveAt((size_t)n
); 
2382 int wxGridCellAttrData::FindIndex(int row
, int col
) const 
2384     size_t count 
= m_attrs
.GetCount(); 
2385     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2387         const wxGridCellCoords
& coords 
= m_attrs
[n
].coords
; 
2388         if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) ) 
2397 // ---------------------------------------------------------------------------- 
2398 // wxGridRowOrColAttrData 
2399 // ---------------------------------------------------------------------------- 
2401 wxGridRowOrColAttrData::~wxGridRowOrColAttrData() 
2403     size_t count 
= m_attrs
.Count(); 
2404     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2406         m_attrs
[n
]->DecRef(); 
2410 wxGridCellAttr 
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const 
2412     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2414     int n 
= m_rowsOrCols
.Index(rowOrCol
); 
2415     if ( n 
!= wxNOT_FOUND 
) 
2417         attr 
= m_attrs
[(size_t)n
]; 
2424 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr 
*attr
, int rowOrCol
) 
2426     int i 
= m_rowsOrCols
.Index(rowOrCol
); 
2427     if ( i 
== wxNOT_FOUND 
) 
2429         // add the attribute 
2430         m_rowsOrCols
.Add(rowOrCol
); 
2435         size_t n 
= (size_t)i
; 
2438             // change the attribute 
2439             m_attrs
[n
]->DecRef(); 
2444             // remove this attribute 
2445             m_attrs
[n
]->DecRef(); 
2446             m_rowsOrCols
.RemoveAt(n
); 
2447             m_attrs
.RemoveAt(n
); 
2452 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols 
) 
2454     size_t count 
= m_attrs
.GetCount(); 
2455     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2457         int & rowOrCol 
= m_rowsOrCols
[n
]; 
2458         if ( (size_t)rowOrCol 
>= pos 
) 
2460             if ( numRowsOrCols 
> 0 ) 
2462                 // If rows inserted, include row counter where necessary 
2463                 rowOrCol 
+= numRowsOrCols
; 
2465             else if ( numRowsOrCols 
< 0) 
2467                 // If rows deleted, either decrement row counter (if row still exists) 
2468                 if ((size_t)rowOrCol 
>= pos 
- numRowsOrCols
) 
2469                     rowOrCol 
+= numRowsOrCols
; 
2472                     m_rowsOrCols
.RemoveAt((size_t)n
); 
2473                     m_attrs
.RemoveAt((size_t)n
); 
2481 // ---------------------------------------------------------------------------- 
2482 // wxGridCellAttrProvider 
2483 // ---------------------------------------------------------------------------- 
2485 wxGridCellAttrProvider::wxGridCellAttrProvider() 
2487     m_data 
= (wxGridCellAttrProviderData 
*)NULL
; 
2490 wxGridCellAttrProvider::~wxGridCellAttrProvider() 
2495 void wxGridCellAttrProvider::InitData() 
2497     m_data 
= new wxGridCellAttrProviderData
; 
2500 wxGridCellAttr 
*wxGridCellAttrProvider::GetAttr(int row
, int col
, 
2501                                                 wxGridCellAttr::wxAttrKind  kind 
) const 
2503     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
2508             case (wxGridCellAttr::Any
): 
2509                 //Get cached merge attributes. 
2510                 // Currenlty not used as no cache implemented as not mutiable 
2511                 // attr = m_data->m_mergeAttr.GetAttr(row, col); 
2514                     //Basicaly implement old version. 
2515                     //Also check merge cache, so we don't have to re-merge every time.. 
2516                     wxGridCellAttr 
*attrcell 
= (wxGridCellAttr 
*)NULL
, 
2517                                    *attrrow 
= (wxGridCellAttr 
*)NULL
, 
2518                                    *attrcol 
= (wxGridCellAttr 
*)NULL
; 
2520                     attrcell 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2521                     attrcol 
= m_data
->m_colAttrs
.GetAttr(col
); 
2522                     attrrow 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2524                     if((attrcell 
!= attrrow
) && (attrrow 
!=attrcol
) && (attrcell 
!= attrcol
)){ 
2525                         // Two or move are non NULL 
2526                         attr 
= new wxGridCellAttr
; 
2527                         attr
->SetKind(wxGridCellAttr::Merged
); 
2531                             attr
->MergeWith(attrcell
); 
2535                             attr
->MergeWith(attrcol
); 
2539                             attr
->MergeWith(attrrow
); 
2542                         //store merge attr if cache implemented 
2544                         //m_data->m_mergeAttr.SetAttr(attr, row, col); 
2548                         // one or none is non null return it or null. 
2549                         if(attrrow
) attr 
= attrrow
; 
2550                         if(attrcol
) attr 
= attrcol
; 
2551                         if(attrcell
) attr 
= attrcell
; 
2555             case (wxGridCellAttr::Cell
): 
2556                 attr 
= m_data
->m_cellAttrs
.GetAttr(row
, col
); 
2558             case (wxGridCellAttr::Col
): 
2559                  attr 
= m_data
->m_colAttrs
.GetAttr(col
); 
2561             case (wxGridCellAttr::Row
): 
2562             attr 
= m_data
->m_rowAttrs
.GetAttr(row
); 
2566                 // (wxGridCellAttr::Default): 
2567                 // (wxGridCellAttr::Merged): 
2574 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr 
*attr
, 
2580     m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
); 
2583 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2588     m_data
->m_rowAttrs
.SetAttr(attr
, row
); 
2591 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2596     m_data
->m_colAttrs
.SetAttr(attr
, col
); 
2599 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows 
) 
2603         m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows 
); 
2605         m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows 
); 
2609 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols 
) 
2613         m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols 
); 
2615         m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols 
); 
2619 // ---------------------------------------------------------------------------- 
2620 // wxGridTypeRegistry 
2621 // ---------------------------------------------------------------------------- 
2623 wxGridTypeRegistry::~wxGridTypeRegistry() 
2625     size_t count 
= m_typeinfo
.Count(); 
2626     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2627         delete m_typeinfo
[i
]; 
2631 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
, 
2632                                           wxGridCellRenderer
* renderer
, 
2633                                           wxGridCellEditor
* editor
) 
2635     wxGridDataTypeInfo
* info 
= new wxGridDataTypeInfo(typeName
, renderer
, editor
); 
2637     // is it already registered? 
2638     int loc 
= FindRegisteredDataType(typeName
); 
2639     if ( loc 
!= wxNOT_FOUND 
) 
2641         delete m_typeinfo
[loc
]; 
2642         m_typeinfo
[loc
] = info
; 
2646         m_typeinfo
.Add(info
); 
2650 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
) 
2652     size_t count 
= m_typeinfo
.GetCount(); 
2653     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2655         if ( typeName 
== m_typeinfo
[i
]->m_typeName 
) 
2664 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
) 
2666     int index 
= FindRegisteredDataType(typeName
); 
2667     if ( index 
== wxNOT_FOUND 
) 
2669         // check whether this is one of the standard ones, in which case 
2670         // register it "on the fly" 
2672         if ( typeName 
== wxGRID_VALUE_STRING 
) 
2674             RegisterDataType(wxGRID_VALUE_STRING
, 
2675                              new wxGridCellStringRenderer
, 
2676                              new wxGridCellTextEditor
); 
2678 #endif // wxUSE_TEXTCTRL 
2680         if ( typeName 
== wxGRID_VALUE_BOOL 
) 
2682             RegisterDataType(wxGRID_VALUE_BOOL
, 
2683                              new wxGridCellBoolRenderer
, 
2684                              new wxGridCellBoolEditor
); 
2686 #endif // wxUSE_CHECKBOX 
2688         if ( typeName 
== wxGRID_VALUE_NUMBER 
) 
2690             RegisterDataType(wxGRID_VALUE_NUMBER
, 
2691                              new wxGridCellNumberRenderer
, 
2692                              new wxGridCellNumberEditor
); 
2694         else if ( typeName 
== wxGRID_VALUE_FLOAT 
) 
2696             RegisterDataType(wxGRID_VALUE_FLOAT
, 
2697                              new wxGridCellFloatRenderer
, 
2698                              new wxGridCellFloatEditor
); 
2700 #endif // wxUSE_TEXTCTRL 
2702         if ( typeName 
== wxGRID_VALUE_CHOICE 
) 
2704             RegisterDataType(wxGRID_VALUE_CHOICE
, 
2705                              new wxGridCellStringRenderer
, 
2706                              new wxGridCellChoiceEditor
); 
2708 #endif // wxUSE_COMBOBOX 
2713         // we get here only if just added the entry for this type, so return 
2715         index 
= m_typeinfo
.GetCount() - 1; 
2721 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
) 
2723     int index 
= FindDataType(typeName
); 
2724     if ( index 
== wxNOT_FOUND 
) 
2726         // the first part of the typename is the "real" type, anything after ':' 
2727         // are the parameters for the renderer 
2728         index 
= FindDataType(typeName
.BeforeFirst(_T(':'))); 
2729         if ( index 
== wxNOT_FOUND 
) 
2734         wxGridCellRenderer 
*renderer 
= GetRenderer(index
); 
2735         wxGridCellRenderer 
*rendererOld 
= renderer
; 
2736         renderer 
= renderer
->Clone(); 
2737         rendererOld
->DecRef(); 
2739         wxGridCellEditor 
*editor 
= GetEditor(index
); 
2740         wxGridCellEditor 
*editorOld 
= editor
; 
2741         editor 
= editor
->Clone(); 
2742         editorOld
->DecRef(); 
2744         // do it even if there are no parameters to reset them to defaults 
2745         wxString params 
= typeName
.AfterFirst(_T(':')); 
2746         renderer
->SetParameters(params
); 
2747         editor
->SetParameters(params
); 
2749         // register the new typename 
2750         RegisterDataType(typeName
, renderer
, editor
); 
2752         // we just registered it, it's the last one 
2753         index 
= m_typeinfo
.GetCount() - 1; 
2759 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
) 
2761     wxGridCellRenderer
* renderer 
= m_typeinfo
[index
]->m_renderer
; 
2767 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
) 
2769     wxGridCellEditor
* editor 
= m_typeinfo
[index
]->m_editor
; 
2775 // ---------------------------------------------------------------------------- 
2777 // ---------------------------------------------------------------------------- 
2779 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject 
) 
2782 wxGridTableBase::wxGridTableBase() 
2784     m_view 
= (wxGrid 
*) NULL
; 
2785     m_attrProvider 
= (wxGridCellAttrProvider 
*) NULL
; 
2788 wxGridTableBase::~wxGridTableBase() 
2790     delete m_attrProvider
; 
2793 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider 
*attrProvider
) 
2795     delete m_attrProvider
; 
2796     m_attrProvider 
= attrProvider
; 
2799 bool wxGridTableBase::CanHaveAttributes() 
2801     if ( ! GetAttrProvider() ) 
2803         // use the default attr provider by default 
2804         SetAttrProvider(new wxGridCellAttrProvider
); 
2809 wxGridCellAttr 
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind  kind
) 
2811     if ( m_attrProvider 
) 
2812         return m_attrProvider
->GetAttr(row
, col
, kind
); 
2814         return (wxGridCellAttr 
*)NULL
; 
2817 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
) 
2819     if ( m_attrProvider 
) 
2821         attr
->SetKind(wxGridCellAttr::Cell
); 
2822         m_attrProvider
->SetAttr(attr
, row
, col
); 
2826         // as we take ownership of the pointer and don't store it, we must 
2832 void wxGridTableBase::SetRowAttr(wxGridCellAttr 
*attr
, int row
) 
2834     if ( m_attrProvider 
) 
2836         attr
->SetKind(wxGridCellAttr::Row
); 
2837         m_attrProvider
->SetRowAttr(attr
, row
); 
2841         // as we take ownership of the pointer and don't store it, we must 
2847 void wxGridTableBase::SetColAttr(wxGridCellAttr 
*attr
, int col
) 
2849     if ( m_attrProvider 
) 
2851         attr
->SetKind(wxGridCellAttr::Col
); 
2852         m_attrProvider
->SetColAttr(attr
, col
); 
2856         // as we take ownership of the pointer and don't store it, we must 
2862 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
), 
2863                                   size_t WXUNUSED(numRows
) ) 
2865     wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") ); 
2870 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) ) 
2872     wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function")); 
2877 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
), 
2878                                   size_t WXUNUSED(numRows
) ) 
2880     wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function")); 
2885 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
), 
2886                                   size_t WXUNUSED(numCols
) ) 
2888     wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function")); 
2893 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) ) 
2895     wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function")); 
2900 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
), 
2901                                   size_t WXUNUSED(numCols
) ) 
2903     wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function")); 
2909 wxString 
wxGridTableBase::GetRowLabelValue( int row 
) 
2912     s 
<< row 
+ 1; // RD: Starting the rows at zero confuses users, no matter 
2913                   //     how much it makes sense to us geeks. 
2917 wxString 
wxGridTableBase::GetColLabelValue( int col 
) 
2919     // default col labels are: 
2920     //   cols 0 to 25   : A-Z 
2921     //   cols 26 to 675 : AA-ZZ 
2926     for ( n 
= 1; ; n
++ ) 
2928         s 
+= (_T('A') + (wxChar
)( col%26 
)); 
2930         if ( col 
< 0 ) break; 
2933     // reverse the string... 
2935     for ( i 
= 0;  i 
< n
;  i
++ ) 
2944 wxString 
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2946     return wxGRID_VALUE_STRING
; 
2949 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
), 
2950                                      const wxString
& typeName 
) 
2952     return typeName 
== wxGRID_VALUE_STRING
; 
2955 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName 
) 
2957     return CanGetValueAs(row
, col
, typeName
); 
2960 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2965 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2970 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) ) 
2975 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
), 
2976                                       long WXUNUSED(value
) ) 
2980 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
), 
2981                                         double WXUNUSED(value
) ) 
2985 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
), 
2986                                       bool WXUNUSED(value
) ) 
2991 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2992                                          const wxString
& WXUNUSED(typeName
) ) 
2997 void  wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
), 
2998                                          const wxString
& WXUNUSED(typeName
), 
2999                                          void* WXUNUSED(value
) ) 
3003 ////////////////////////////////////////////////////////////////////// 
3005 // Message class for the grid table to send requests and notifications 
3009 wxGridTableMessage::wxGridTableMessage() 
3011     m_table 
= (wxGridTableBase 
*) NULL
; 
3017 wxGridTableMessage::wxGridTableMessage( wxGridTableBase 
*table
, int id
, 
3018                                         int commandInt1
, int commandInt2 
) 
3022     m_comInt1 
= commandInt1
; 
3023     m_comInt2 
= commandInt2
; 
3028 ////////////////////////////////////////////////////////////////////// 
3030 // A basic grid table for string data. An object of this class will 
3031 // created by wxGrid if you don't specify an alternative table class. 
3034 WX_DEFINE_OBJARRAY(wxGridStringArray
) 
3036 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase 
) 
3038 wxGridStringTable::wxGridStringTable() 
3043 wxGridStringTable::wxGridStringTable( int numRows
, int numCols 
) 
3046     m_data
.Alloc( numRows 
); 
3049     sa
.Alloc( numCols 
); 
3050     sa
.Add( wxEmptyString
, numCols 
); 
3052     m_data
.Add( sa
, numRows 
); 
3055 wxGridStringTable::~wxGridStringTable() 
3059 int wxGridStringTable::GetNumberRows() 
3061     return m_data
.GetCount(); 
3064 int wxGridStringTable::GetNumberCols() 
3066     if ( m_data
.GetCount() > 0 ) 
3067         return m_data
[0].GetCount(); 
3072 wxString 
wxGridStringTable::GetValue( int row
, int col 
) 
3074     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3075                   _T("invalid row or column index in wxGridStringTable") ); 
3077     return m_data
[row
][col
]; 
3080 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value 
) 
3082     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3083                   _T("invalid row or column index in wxGridStringTable") ); 
3085     m_data
[row
][col
] = value
; 
3088 bool wxGridStringTable::IsEmptyCell( int row
, int col 
) 
3090     wxASSERT_MSG( (row 
< GetNumberRows()) && (col 
< GetNumberCols()), 
3091                   _T("invalid row or column index in wxGridStringTable") ); 
3093     return (m_data
[row
][col
] == wxEmptyString
); 
3096 void wxGridStringTable::Clear() 
3099     int numRows
, numCols
; 
3101     numRows 
= m_data
.GetCount(); 
3104         numCols 
= m_data
[0].GetCount(); 
3106         for ( row 
= 0;  row 
< numRows
;  row
++ ) 
3108             for ( col 
= 0;  col 
< numCols
;  col
++ ) 
3110                 m_data
[row
][col
] = wxEmptyString
; 
3117 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows 
) 
3119     size_t curNumRows 
= m_data
.GetCount(); 
3120     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3121                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3123     if ( pos 
>= curNumRows 
) 
3125         return AppendRows( numRows 
); 
3129     sa
.Alloc( curNumCols 
); 
3130     sa
.Add( wxEmptyString
, curNumCols 
); 
3131     m_data
.Insert( sa
, pos
, numRows 
); 
3134         wxGridTableMessage 
msg( this, 
3135                                 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
, 
3139         GetView()->ProcessTableMessage( msg 
); 
3145 bool wxGridStringTable::AppendRows( size_t numRows 
) 
3147     size_t curNumRows 
= m_data
.GetCount(); 
3148     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3149                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3152     if ( curNumCols 
> 0 ) 
3154         sa
.Alloc( curNumCols 
); 
3155         sa
.Add( wxEmptyString
, curNumCols 
); 
3158     m_data
.Add( sa
, numRows 
); 
3162         wxGridTableMessage 
msg( this, 
3163                                 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
, 
3166         GetView()->ProcessTableMessage( msg 
); 
3172 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows 
) 
3174     size_t curNumRows 
= m_data
.GetCount(); 
3176     if ( pos 
>= curNumRows 
) 
3178         wxFAIL_MSG( wxString::Format
 
3180                         wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"), 
3182                         (unsigned long)numRows
, 
3183                         (unsigned long)curNumRows
 
3189     if ( numRows 
> curNumRows 
- pos 
) 
3191         numRows 
= curNumRows 
- pos
; 
3194     if ( numRows 
>= curNumRows 
) 
3200         m_data
.RemoveAt( pos
, numRows 
); 
3204         wxGridTableMessage 
msg( this, 
3205                                 wxGRIDTABLE_NOTIFY_ROWS_DELETED
, 
3209         GetView()->ProcessTableMessage( msg 
); 
3215 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols 
) 
3219     size_t curNumRows 
= m_data
.GetCount(); 
3220     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3221                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3223     if ( pos 
>= curNumCols 
) 
3225         return AppendCols( numCols 
); 
3228     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3230         for ( col 
= pos
;  col 
< pos 
+ numCols
;  col
++ ) 
3232             m_data
[row
].Insert( wxEmptyString
, col 
); 
3237         wxGridTableMessage 
msg( this, 
3238                                 wxGRIDTABLE_NOTIFY_COLS_INSERTED
, 
3242         GetView()->ProcessTableMessage( msg 
); 
3248 bool wxGridStringTable::AppendCols( size_t numCols 
) 
3252     size_t curNumRows 
= m_data
.GetCount(); 
3256         // TODO: something better than this ? 
3258         wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") ); 
3263     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3265         m_data
[row
].Add( wxEmptyString
, numCols 
); 
3270         wxGridTableMessage 
msg( this, 
3271                                 wxGRIDTABLE_NOTIFY_COLS_APPENDED
, 
3274         GetView()->ProcessTableMessage( msg 
); 
3280 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols 
) 
3284     size_t curNumRows 
= m_data
.GetCount(); 
3285     size_t curNumCols 
= ( curNumRows 
> 0 ? m_data
[0].GetCount() : 
3286                           ( GetView() ? GetView()->GetNumberCols() : 0 ) ); 
3288     if ( pos 
>= curNumCols 
) 
3290         wxFAIL_MSG( wxString::Format
 
3292                         wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"), 
3294                         (unsigned long)numCols
, 
3295                         (unsigned long)curNumCols
 
3300     if ( numCols 
> curNumCols 
- pos 
) 
3302         numCols 
= curNumCols 
- pos
; 
3305     for ( row 
= 0;  row 
< curNumRows
;  row
++ ) 
3307         if ( numCols 
>= curNumCols 
) 
3309             m_data
[row
].Clear(); 
3313             m_data
[row
].RemoveAt( pos
, numCols 
); 
3318         wxGridTableMessage 
msg( this, 
3319                                 wxGRIDTABLE_NOTIFY_COLS_DELETED
, 
3323         GetView()->ProcessTableMessage( msg 
); 
3329 wxString 
wxGridStringTable::GetRowLabelValue( int row 
) 
3331     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3333         // using default label 
3335         return wxGridTableBase::GetRowLabelValue( row 
); 
3339         return m_rowLabels
[ row 
]; 
3343 wxString 
wxGridStringTable::GetColLabelValue( int col 
) 
3345     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3347         // using default label 
3349         return wxGridTableBase::GetColLabelValue( col 
); 
3353         return m_colLabels
[ col 
]; 
3357 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value 
) 
3359     if ( row 
> (int)(m_rowLabels
.GetCount()) - 1 ) 
3361         int n 
= m_rowLabels
.GetCount(); 
3363         for ( i 
= n
;  i 
<= row
;  i
++ ) 
3365             m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) ); 
3369     m_rowLabels
[row
] = value
; 
3372 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value 
) 
3374     if ( col 
> (int)(m_colLabels
.GetCount()) - 1 ) 
3376         int n 
= m_colLabels
.GetCount(); 
3378         for ( i 
= n
;  i 
<= col
;  i
++ ) 
3380             m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) ); 
3384     m_colLabels
[col
] = value
; 
3389 ////////////////////////////////////////////////////////////////////// 
3390 ////////////////////////////////////////////////////////////////////// 
3392 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow 
) 
3394 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow 
) 
3395     EVT_PAINT( wxGridRowLabelWindow::OnPaint 
) 
3396     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
) 
3397     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent 
) 
3398     EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown 
) 
3399     EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp 
) 
3402 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid 
*parent
, 
3404                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3405   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3410 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3414     // NO - don't do this because it will set both the x and y origin 
3415     // coords to match the parent scrolled window and we just want to 
3416     // set the y coord  - MB 
3418     // m_owner->PrepareDC( dc ); 
3421     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3422     dc
.SetDeviceOrigin( 0, -y 
); 
3424     wxArrayInt rows 
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() ); 
3425     m_owner
->DrawRowLabels( dc 
, rows 
); 
3429 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3431     m_owner
->ProcessRowLabelMouseEvent( event 
); 
3435 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3437     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3441 // This seems to be required for wxMotif otherwise the mouse 
3442 // cursor must be in the cell edit control to get key events 
3444 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3446     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3449 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3451     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3456 ////////////////////////////////////////////////////////////////////// 
3458 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow 
) 
3460 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow 
) 
3461     EVT_PAINT( wxGridColLabelWindow::OnPaint 
) 
3462     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
) 
3463     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent 
) 
3464     EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown 
) 
3465     EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp 
) 
3468 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid 
*parent
, 
3470                                             const wxPoint 
&pos
, const wxSize 
&size 
) 
3471   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3476 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3480     // NO - don't do this because it will set both the x and y origin 
3481     // coords to match the parent scrolled window and we just want to 
3482     // set the x coord  - MB 
3484     // m_owner->PrepareDC( dc ); 
3487     m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y 
); 
3488     dc
.SetDeviceOrigin( -x
, 0 ); 
3490     wxArrayInt cols 
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() ); 
3491     m_owner
->DrawColLabels( dc 
, cols 
); 
3495 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3497     m_owner
->ProcessColLabelMouseEvent( event 
); 
3500 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3502     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3506 // This seems to be required for wxMotif otherwise the mouse 
3507 // cursor must be in the cell edit control to get key events 
3509 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3511     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3514 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3516     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3521 ////////////////////////////////////////////////////////////////////// 
3523 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow 
) 
3525 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow 
) 
3526     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
) 
3527     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent 
) 
3528     EVT_PAINT( wxGridCornerLabelWindow::OnPaint
) 
3529     EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown 
) 
3530     EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp 
) 
3533 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid 
*parent
, 
3535                                                   const wxPoint 
&pos
, const wxSize 
&size 
) 
3536   : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS 
) 
3541 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
3545     int client_height 
= 0; 
3546     int client_width 
= 0; 
3547     GetClientSize( &client_width
, &client_height 
); 
3549     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
3550     dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 ); 
3551     dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 ); 
3552     dc
.DrawLine( 0, 0, client_width
, 0 ); 
3553     dc
.DrawLine( 0, 0, 0, client_height 
); 
3555     dc
.SetPen( *wxWHITE_PEN 
); 
3556     dc
.DrawLine( 1, 1, client_width
-1, 1 ); 
3557     dc
.DrawLine( 1, 1, 1, client_height
-1 ); 
3561 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3563     m_owner
->ProcessCornerLabelMouseEvent( event 
); 
3567 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3569     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3572 // This seems to be required for wxMotif otherwise the mouse 
3573 // cursor must be in the cell edit control to get key events 
3575 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event 
) 
3577     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3580 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event 
) 
3582     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3587 ////////////////////////////////////////////////////////////////////// 
3589 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow 
) 
3591 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow 
) 
3592     EVT_PAINT( wxGridWindow::OnPaint 
) 
3593     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
) 
3594     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent 
) 
3595     EVT_KEY_DOWN( wxGridWindow::OnKeyDown 
) 
3596     EVT_KEY_UP( wxGridWindow::OnKeyUp 
) 
3597     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground 
) 
3600 // DJC (MAPTEK) 19-Jun-2001 use wxCLIP_CHILDREN as well 
3601 wxGridWindow::wxGridWindow( wxGrid 
*parent
, 
3602                             wxGridRowLabelWindow 
*rowLblWin
, 
3603                             wxGridColLabelWindow 
*colLblWin
, 
3604                             wxWindowID id
, const wxPoint 
&pos
, const wxSize 
&size 
) 
3605         : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxCLIP_CHILDREN
, wxT("grid window") ) 
3609     m_rowLabelWin 
= rowLblWin
; 
3610     m_colLabelWin 
= colLblWin
; 
3611     SetBackgroundColour(_T("WHITE")); 
3615 wxGridWindow::~wxGridWindow() 
3620 void wxGridWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3622     wxPaintDC 
dc( this ); 
3623     m_owner
->PrepareDC( dc 
); 
3624     wxRegion reg 
= GetUpdateRegion(); 
3625     wxGridCellCoordsArray DirtyCells 
= m_owner
->CalcCellsExposed( reg 
); 
3626     m_owner
->DrawGridCellArea( dc 
, DirtyCells
); 
3627 #if WXGRID_DRAW_LINES 
3628     m_owner
->DrawAllGridLines( dc
, reg 
); 
3630     m_owner
->DrawGridSpace( dc 
); 
3631     m_owner
->DrawHighlight( dc 
, DirtyCells 
); 
3635 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
3637     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
3638     m_rowLabelWin
->ScrollWindow( 0, dy
, rect 
); 
3639     m_colLabelWin
->ScrollWindow( dx
, 0, rect 
); 
3643 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event 
) 
3645     m_owner
->ProcessGridCellMouseEvent( event 
); 
3648 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event 
) 
3650     m_owner
->GetEventHandler()->ProcessEvent(event
); 
3653 // This seems to be required for wxMotif/wxGTK otherwise the mouse 
3654 // cursor must be in the cell edit control to get key events 
3656 void wxGridWindow::OnKeyDown( wxKeyEvent
& event 
) 
3658     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3661 void wxGridWindow::OnKeyUp( wxKeyEvent
& event 
) 
3663     if ( !m_owner
->GetEventHandler()->ProcessEvent( event 
) ) event
.Skip(); 
3666 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) ) 
3671 ////////////////////////////////////////////////////////////////////// 
3673 // Internal Helper function for computing row or column from some 
3674 // (unscrolled) coordinate value, using either 
3675 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
3676 // of m_rowBottoms/m_ColRights to speed up the search! 
3678 // Internal helper macros for simpler use of that function 
3680 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
3681                            const wxArrayInt
& BorderArray
, int nMax
, 
3682                            bool maxOnOverflow
); 
3684 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ 
3685                                           WXGRID_MIN_COL_WIDTH, \ 
3686                                           m_colRights, m_numCols, TRUE) 
3687 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ 
3688                                           WXGRID_MIN_ROW_HEIGHT, \ 
3689                                           m_rowBottoms, m_numRows, TRUE) 
3690 ///////////////////////////////////////////////////////////////////// 
3692 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow 
) 
3694 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow 
) 
3695     EVT_PAINT( wxGrid::OnPaint 
) 
3696     EVT_SIZE( wxGrid::OnSize 
) 
3697     EVT_KEY_DOWN( wxGrid::OnKeyDown 
) 
3698     EVT_KEY_UP( wxGrid::OnKeyUp 
) 
3699     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground 
) 
3702 wxGrid::wxGrid( wxWindow 
*parent
, 
3707                  const wxString
& name 
) 
3708   : wxScrolledWindow( parent
, id
, pos
, size
, (style 
| wxWANTS_CHARS
), name 
), 
3709     m_colMinWidths(GRID_HASH_SIZE
), 
3710     m_rowMinHeights(GRID_HASH_SIZE
) 
3718     // Must do this or ~wxScrollHelper will pop the wrong event handler 
3719     SetTargetWindow(this); 
3721     wxSafeDecRef(m_defaultCellAttr
); 
3723 #ifdef DEBUG_ATTR_CACHE 
3724     size_t total 
= gs_nAttrCacheHits 
+ gs_nAttrCacheMisses
; 
3725     wxPrintf(_T("wxGrid attribute cache statistics: " 
3726                 "total: %u, hits: %u (%u%%)\n"), 
3727              total
, gs_nAttrCacheHits
, 
3728              total 
? (gs_nAttrCacheHits
*100) / total 
: 0); 
3734     delete m_typeRegistry
; 
3740 // ----- internal init and update functions 
3743 void wxGrid::Create() 
3745     m_created 
= FALSE
;    // set to TRUE by CreateGrid 
3747     m_table        
= (wxGridTableBase 
*) NULL
; 
3750     m_cellEditCtrlEnabled 
= FALSE
; 
3752     m_defaultCellAttr 
= new wxGridCellAttr(); 
3754     // Set default cell attributes 
3755     m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
); 
3756     m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
); 
3757     m_defaultCellAttr
->SetFont(GetFont()); 
3758     m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
); 
3759     m_defaultCellAttr
->SetTextColour( 
3760         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
3761     m_defaultCellAttr
->SetBackgroundColour( 
3762         wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
3763     m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
); 
3764     m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
); 
3769     m_currentCellCoords 
= wxGridNoCellCoords
; 
3771     m_rowLabelWidth 
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3772     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3774     // create the type registry 
3775     m_typeRegistry 
= new wxGridTypeRegistry
; 
3778     // subwindow components that make up the wxGrid 
3779     m_cornerLabelWin 
= new wxGridCornerLabelWindow( this, 
3784     m_rowLabelWin 
= new wxGridRowLabelWindow( this, 
3789     m_colLabelWin 
= new wxGridColLabelWindow( this, 
3794     m_gridWin 
= new wxGridWindow( this, 
3801     SetTargetWindow( m_gridWin 
); 
3807 bool wxGrid::CreateGrid( int numRows
, int numCols
, 
3808                          wxGrid::wxGridSelectionModes selmode 
) 
3810     wxCHECK_MSG( !m_created
, 
3812                  wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3814     m_numRows 
= numRows
; 
3815     m_numCols 
= numCols
; 
3817     m_table 
= new wxGridStringTable( m_numRows
, m_numCols 
); 
3818     m_table
->SetView( this ); 
3820     m_selection 
= new wxGridSelection( this, selmode 
); 
3829 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
) 
3831     wxCHECK_RET( m_created
, 
3832                  wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") ); 
3834     m_selection
->SetSelectionMode( selmode 
); 
3837 wxGrid::wxGridSelectionModes 
wxGrid::GetSelectionMode() const 
3839     wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
, 
3840                  wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") ); 
3842     return m_selection
->GetSelectionMode(); 
3845 bool wxGrid::SetTable( wxGridTableBase 
*table
, bool takeOwnership
, 
3846                        wxGrid::wxGridSelectionModes selmode 
) 
3850         // RD: Actually, this should probably be allowed.  I think it would be 
3851         //     nice to be able to switch multiple Tables in and out of a single 
3852         //     View at runtime.  Is there anything in the implementation that 
3853         //     would prevent this? 
3855         // At least, you now have to cope with m_selection 
3856         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); 
3861         m_numRows 
= table
->GetNumberRows(); 
3862         m_numCols 
= table
->GetNumberCols(); 
3865         m_table
->SetView( this ); 
3868         m_selection 
= new wxGridSelection( this, selmode 
); 
3881     m_rowLabelWidth  
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
; 
3882     m_colLabelHeight 
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
; 
3884     if ( m_rowLabelWin 
) 
3886         m_labelBackgroundColour 
= m_rowLabelWin
->GetBackgroundColour(); 
3890         m_labelBackgroundColour 
= wxColour( _T("WHITE") ); 
3893     m_labelTextColour 
= wxColour( _T("BLACK") ); 
3896     m_attrCache
.row 
= -1; 
3897     m_attrCache
.col 
= -1; 
3898     m_attrCache
.attr 
= NULL
; 
3900     // TODO: something better than this ? 
3902     m_labelFont 
= this->GetFont(); 
3903 //    m_labelFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); 
3904 //    m_labelFont.SetWeight( m_labelFont.GetWeight() + 2 ); 
3906     m_rowLabelHorizAlign 
= wxALIGN_CENTRE
; 
3907     m_rowLabelVertAlign  
= wxALIGN_CENTRE
; 
3909     m_colLabelHorizAlign 
= wxALIGN_CENTRE
; 
3910     m_colLabelVertAlign  
= wxALIGN_CENTRE
; 
3912     m_defaultColWidth  
= WXGRID_DEFAULT_COL_WIDTH
; 
3913     m_defaultRowHeight 
= m_gridWin
->GetCharHeight(); 
3915 #if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl() 
3916     m_defaultRowHeight 
+= 8; 
3918     m_defaultRowHeight 
+= 4; 
3921     m_gridLineColour 
= wxColour( 192,192,192 ); 
3922     m_gridLinesEnabled 
= TRUE
; 
3923     m_cellHighlightColour 
= *wxBLACK
; 
3924     m_cellHighlightPenWidth 
= 2; 
3925     m_cellHighlightROPenWidth 
= 1; 
3927     m_cursorMode  
= WXGRID_CURSOR_SELECT_CELL
; 
3928     m_winCapture 
= (wxWindow 
*)NULL
; 
3929     m_canDragRowSize 
= TRUE
; 
3930     m_canDragColSize 
= TRUE
; 
3931     m_canDragGridSize 
= TRUE
; 
3933     m_dragRowOrCol 
= -1; 
3934     m_isDragging 
= FALSE
; 
3935     m_startDragPos 
= wxDefaultPosition
; 
3937     m_waitForSlowClick 
= FALSE
; 
3939     m_rowResizeCursor 
= wxCursor( wxCURSOR_SIZENS 
); 
3940     m_colResizeCursor 
= wxCursor( wxCURSOR_SIZEWE 
); 
3942     m_currentCellCoords 
= wxGridNoCellCoords
; 
3944     m_selectingTopLeft 
= wxGridNoCellCoords
; 
3945     m_selectingBottomRight 
= wxGridNoCellCoords
; 
3946 //  m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); 
3947 //  m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); 
3948     m_selectionBackground 
= *wxBLACK
;  
3949     m_selectionForeground 
= *wxWHITE
;  
3951     m_editable 
= TRUE
;  // default for whole grid 
3953     m_inOnKeyDown 
= FALSE
; 
3960 // ---------------------------------------------------------------------------- 
3961 // the idea is to call these functions only when necessary because they create 
3962 // quite big arrays which eat memory mostly unnecessary - in particular, if 
3963 // default widths/heights are used for all rows/columns, we may not use these 
3966 // with some extra code, it should be possible to only store the 
3967 // widths/heights different from default ones but this will be done later... 
3968 // ---------------------------------------------------------------------------- 
3970 void wxGrid::InitRowHeights() 
3972     m_rowHeights
.Empty(); 
3973     m_rowBottoms
.Empty(); 
3975     m_rowHeights
.Alloc( m_numRows 
); 
3976     m_rowBottoms
.Alloc( m_numRows 
); 
3980     m_rowHeights
.Add( m_defaultRowHeight
, m_numRows 
); 
3982     for ( int i 
= 0;  i 
< m_numRows
;  i
++ ) 
3984         rowBottom 
+= m_defaultRowHeight
; 
3985         m_rowBottoms
.Add( rowBottom 
); 
3989 void wxGrid::InitColWidths() 
3991     m_colWidths
.Empty(); 
3992     m_colRights
.Empty(); 
3994     m_colWidths
.Alloc( m_numCols 
); 
3995     m_colRights
.Alloc( m_numCols 
); 
3998     m_colWidths
.Add( m_defaultColWidth
, m_numCols 
); 
4000     for ( int i 
= 0;  i 
< m_numCols
;  i
++ ) 
4002         colRight 
+= m_defaultColWidth
; 
4003         m_colRights
.Add( colRight 
); 
4007 int wxGrid::GetColWidth(int col
) const 
4009     return m_colWidths
.IsEmpty() ? m_defaultColWidth 
: m_colWidths
[col
]; 
4012 int wxGrid::GetColLeft(int col
) const 
4014     return m_colRights
.IsEmpty() ? col 
* m_defaultColWidth
 
4015                                  : m_colRights
[col
] - m_colWidths
[col
]; 
4018 int wxGrid::GetColRight(int col
) const 
4020     return m_colRights
.IsEmpty() ? (col 
+ 1) * m_defaultColWidth
 
4024 int wxGrid::GetRowHeight(int row
) const 
4026     return m_rowHeights
.IsEmpty() ? m_defaultRowHeight 
: m_rowHeights
[row
]; 
4029 int wxGrid::GetRowTop(int row
) const 
4031     return m_rowBottoms
.IsEmpty() ? row 
* m_defaultRowHeight
 
4032                                   : m_rowBottoms
[row
] - m_rowHeights
[row
]; 
4035 int wxGrid::GetRowBottom(int row
) const 
4037     return m_rowBottoms
.IsEmpty() ? (row 
+ 1) * m_defaultRowHeight
 
4038                                   : m_rowBottoms
[row
]; 
4041 void wxGrid::CalcDimensions() 
4044     GetClientSize( &cw
, &ch 
); 
4046     if ( m_rowLabelWin
->IsShown() ) 
4047         cw 
-= m_rowLabelWidth
; 
4048     if ( m_colLabelWin
->IsShown() ) 
4049         ch 
-= m_colLabelHeight
; 
4052     int w 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) + m_extraWidth 
+ 1 : 0; 
4053     int h 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) + m_extraHeight 
+ 1 : 0; 
4055 // DJC (MAPTEK) 19-Jun-2001 account for editor since it could possibly 
4056 // be larger than the cell 
4057     // take into account editor if shown 
4058     if( IsCellEditControlShown() ) 
4061       int r 
= m_currentCellCoords
.GetRow(); 
4062       int c 
= m_currentCellCoords
.GetCol(); 
4063       int x 
= GetColLeft(c
); 
4064       int y 
= GetRowTop(r
); 
4066       // how big is the editor 
4067       wxGridCellAttr
* attr 
= GetCellAttr(r
, c
); 
4068       wxGridCellEditor
* editor 
= attr
->GetEditor(this, r
, c
); 
4069       editor
->GetControl()->GetSize(&w2
, &h2
); 
4072       if( w2 
> w 
) w 
= w2
; 
4073       if( h2 
> h 
) h 
= h2
; 
4078     // preserve (more or less) the previous position 
4080     GetViewStart( &x
, &y 
); 
4082     // maybe we don't need scrollbars at all? 
4084     // also adjust the position to be valid for the new scroll rangs 
4105     // do set scrollbar parameters 
4106     SetScrollbars( GRID_SCROLL_LINE_X
, GRID_SCROLL_LINE_Y
, 
4107                    GetScrollX(w
), GetScrollY(h
), x
, y
, 
4108                    GetBatchCount() != 0); 
4110     // if our OnSize() hadn't been called (it would if we have scrollbars), we 
4111     // still must reposition the children 
4116 void wxGrid::CalcWindowSizes() 
4119     GetClientSize( &cw
, &ch 
); 
4121     if ( m_cornerLabelWin
->IsShown() ) 
4122         m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight 
); 
4124     if ( m_colLabelWin
->IsShown() ) 
4125         m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
); 
4127     if ( m_rowLabelWin
->IsShown() ) 
4128         m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4130     if ( m_gridWin
->IsShown() ) 
4131         m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
); 
4135 // this is called when the grid table sends a message to say that it 
4136 // has been redimensioned 
4138 bool wxGrid::Redimension( wxGridTableMessage
& msg 
) 
4141     bool result 
= FALSE
; 
4143     // Clear the attribute cache as the attribute might refer to a different 
4144     // cell than stored in the cache after adding/removing rows/columns. 
4146     // By the same reasoning, the editor should be dismissed if columns are 
4147     // added or removed. And for consistency, it should IMHO always be 
4148     // removed, not only if the cell "underneath" it actually changes. 
4149     // For now, I intentionally do not save the editor's content as the 
4150     // cell it might want to save that stuff to might no longer exist. 
4151     HideCellEditControl(); 
4153     // if we were using the default widths/heights so far, we must change them 
4155     if ( m_colWidths
.IsEmpty() ) 
4160     if ( m_rowHeights
.IsEmpty() ) 
4166     switch ( msg
.GetId() ) 
4168         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
4170             size_t pos 
= msg
.GetCommandInt(); 
4171             int numRows 
= msg
.GetCommandInt2(); 
4173             m_numRows 
+= numRows
; 
4175             if ( !m_rowHeights
.IsEmpty() ) 
4177                 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows 
); 
4178                 m_rowBottoms
.Insert( 0, pos
, numRows 
); 
4181                 if ( pos 
> 0 ) bottom 
= m_rowBottoms
[pos
-1]; 
4183                 for ( i 
= pos
;  i 
< m_numRows
;  i
++ ) 
4185                     bottom 
+= m_rowHeights
[i
]; 
4186                     m_rowBottoms
[i
] = bottom
; 
4189             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4191                 // if we have just inserted cols into an empty grid the current 
4192                 // cell will be undefined... 
4194                 SetCurrentCell( 0, 0 ); 
4198                 m_selection
->UpdateRows( pos
, numRows 
); 
4199             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4201                 attrProvider
->UpdateAttrRows( pos
, numRows 
); 
4203             if ( !GetBatchCount() ) 
4206                 m_rowLabelWin
->Refresh(); 
4212         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
4214             int numRows 
= msg
.GetCommandInt(); 
4215             int oldNumRows 
= m_numRows
; 
4216             m_numRows 
+= numRows
; 
4218             if ( !m_rowHeights
.IsEmpty() ) 
4220                 m_rowHeights
.Add( m_defaultRowHeight
, numRows 
); 
4221                 m_rowBottoms
.Add( 0, numRows 
); 
4224                 if ( oldNumRows 
> 0 ) bottom 
= m_rowBottoms
[oldNumRows
-1]; 
4226                 for ( i 
= oldNumRows
;  i 
< m_numRows
;  i
++ ) 
4228                     bottom 
+= m_rowHeights
[i
]; 
4229                     m_rowBottoms
[i
] = bottom
; 
4232             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4234                 // if we have just inserted cols into an empty grid the current 
4235                 // cell will be undefined... 
4237                 SetCurrentCell( 0, 0 ); 
4239             if ( !GetBatchCount() ) 
4242                 m_rowLabelWin
->Refresh(); 
4248         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
4250             size_t pos 
= msg
.GetCommandInt(); 
4251             int numRows 
= msg
.GetCommandInt2(); 
4252             m_numRows 
-= numRows
; 
4254             if ( !m_rowHeights
.IsEmpty() ) 
4256                 m_rowHeights
.RemoveAt( pos
, numRows 
); 
4257                 m_rowBottoms
.RemoveAt( pos
, numRows 
); 
4260                 for ( i 
= 0;  i 
< m_numRows
;  i
++ ) 
4262                     h 
+= m_rowHeights
[i
]; 
4263                     m_rowBottoms
[i
] = h
; 
4268                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4272                 if ( m_currentCellCoords
.GetRow() >= m_numRows 
) 
4273                     m_currentCellCoords
.Set( 0, 0 ); 
4277                 m_selection
->UpdateRows( pos
, -((int)numRows
) ); 
4278             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4280                 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) ); 
4281 // ifdef'd out following patch from Paul Gammans 
4283                 // No need to touch column attributes, unless we 
4284                 // removed _all_ rows, in this case, we remove 
4285                 // all column attributes. 
4286                 // I hate to do this here, but the 
4287                 // needed data is not available inside UpdateAttrRows. 
4288                 if ( !GetNumberRows() ) 
4289                     attrProvider
->UpdateAttrCols( 0, -GetNumberCols() ); 
4292             if ( !GetBatchCount() ) 
4295                 m_rowLabelWin
->Refresh(); 
4301         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
4303             size_t pos 
= msg
.GetCommandInt(); 
4304             int numCols 
= msg
.GetCommandInt2(); 
4305             m_numCols 
+= numCols
; 
4307             if ( !m_colWidths
.IsEmpty() ) 
4309                 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols 
); 
4310                 m_colRights
.Insert( 0, pos
, numCols 
); 
4313                 if ( pos 
> 0 ) right 
= m_colRights
[pos
-1]; 
4315                 for ( i 
= pos
;  i 
< m_numCols
;  i
++ ) 
4317                     right 
+= m_colWidths
[i
]; 
4318                     m_colRights
[i
] = right
; 
4321             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4323                 // if we have just inserted cols into an empty grid the current 
4324                 // cell will be undefined... 
4326                 SetCurrentCell( 0, 0 ); 
4330                 m_selection
->UpdateCols( pos
, numCols 
); 
4331             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4333                 attrProvider
->UpdateAttrCols( pos
, numCols 
); 
4334             if ( !GetBatchCount() ) 
4337                 m_colLabelWin
->Refresh(); 
4344         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
4346             int numCols 
= msg
.GetCommandInt(); 
4347             int oldNumCols 
= m_numCols
; 
4348             m_numCols 
+= numCols
; 
4349             if ( !m_colWidths
.IsEmpty() ) 
4351                 m_colWidths
.Add( m_defaultColWidth
, numCols 
); 
4352                 m_colRights
.Add( 0, numCols 
); 
4355                 if ( oldNumCols 
> 0 ) right 
= m_colRights
[oldNumCols
-1]; 
4357                 for ( i 
= oldNumCols
;  i 
< m_numCols
;  i
++ ) 
4359                     right 
+= m_colWidths
[i
]; 
4360                     m_colRights
[i
] = right
; 
4363             if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
4365                 // if we have just inserted cols into an empty grid the current 
4366                 // cell will be undefined... 
4368                 SetCurrentCell( 0, 0 ); 
4370             if ( !GetBatchCount() ) 
4373                 m_colLabelWin
->Refresh(); 
4379         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
4381             size_t pos 
= msg
.GetCommandInt(); 
4382             int numCols 
= msg
.GetCommandInt2(); 
4383             m_numCols 
-= numCols
; 
4385             if ( !m_colWidths
.IsEmpty() ) 
4387                 m_colWidths
.RemoveAt( pos
, numCols 
); 
4388                 m_colRights
.RemoveAt( pos
, numCols 
); 
4391                 for ( i 
= 0;  i 
< m_numCols
;  i
++ ) 
4393                     w 
+= m_colWidths
[i
]; 
4399                 m_currentCellCoords 
= wxGridNoCellCoords
; 
4403                 if ( m_currentCellCoords
.GetCol() >= m_numCols 
) 
4404                   m_currentCellCoords
.Set( 0, 0 ); 
4408                 m_selection
->UpdateCols( pos
, -((int)numCols
) ); 
4409             wxGridCellAttrProvider 
* attrProvider 
= m_table
->GetAttrProvider(); 
4411                 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) ); 
4412 // ifdef'd out following patch from Paul Gammans 
4414                 // No need to touch row attributes, unless we 
4415                 // removed _all_ columns, in this case, we remove 
4416                 // all row attributes. 
4417                 // I hate to do this here, but the 
4418                 // needed data is not available inside UpdateAttrCols. 
4419                 if ( !GetNumberCols() ) 
4420                     attrProvider
->UpdateAttrRows( 0, -GetNumberRows() ); 
4423             if ( !GetBatchCount() ) 
4426                 m_colLabelWin
->Refresh(); 
4433     if (result 
&& !GetBatchCount() ) 
4434         m_gridWin
->Refresh(); 
4439 wxArrayInt 
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg 
) 
4441     wxRegionIterator 
iter( reg 
); 
4444     wxArrayInt  rowlabels
; 
4451         // TODO: remove this when we can... 
4452         // There is a bug in wxMotif that gives garbage update 
4453         // rectangles if you jump-scroll a long way by clicking the 
4454         // scrollbar with middle button.  This is a work-around 
4456 #if defined(__WXMOTIF__) 
4458         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4459         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4460         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4463         // logical bounds of update region 
4466         CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top 
); 
4467         CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom 
); 
4469         // find the row labels within these bounds 
4472         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4474             if ( GetRowBottom(row
) < top 
) 
4477             if ( GetRowTop(row
) > bottom 
) 
4480             rowlabels
.Add( row 
); 
4490 wxArrayInt 
wxGrid::CalcColLabelsExposed( const wxRegion
& reg 
) 
4492     wxRegionIterator 
iter( reg 
); 
4495     wxArrayInt colLabels
; 
4502         // TODO: remove this when we can... 
4503         // There is a bug in wxMotif that gives garbage update 
4504         // rectangles if you jump-scroll a long way by clicking the 
4505         // scrollbar with middle button.  This is a work-around 
4507 #if defined(__WXMOTIF__) 
4509         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4510         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4511         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4514         // logical bounds of update region 
4517         CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy 
); 
4518         CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy 
); 
4520         // find the cells within these bounds 
4523         for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4525             if ( GetColRight(col
) < left 
) 
4528             if ( GetColLeft(col
) > right 
) 
4531             colLabels
.Add( col 
); 
4540 wxGridCellCoordsArray 
wxGrid::CalcCellsExposed( const wxRegion
& reg 
) 
4542     wxRegionIterator 
iter( reg 
); 
4545     wxGridCellCoordsArray  cellsExposed
; 
4547     int left
, top
, right
, bottom
; 
4552         // TODO: remove this when we can... 
4553         // There is a bug in wxMotif that gives garbage update 
4554         // rectangles if you jump-scroll a long way by clicking the 
4555         // scrollbar with middle button.  This is a work-around 
4557 #if defined(__WXMOTIF__) 
4559         m_gridWin
->GetClientSize( &cw
, &ch 
); 
4560         if ( r
.GetTop() > ch 
) r
.SetTop( 0 ); 
4561         if ( r
.GetLeft() > cw 
) r
.SetLeft( 0 ); 
4562         r
.SetRight( wxMin( r
.GetRight(), cw 
) ); 
4563         r
.SetBottom( wxMin( r
.GetBottom(), ch 
) ); 
4566         // logical bounds of update region 
4568         CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
4569         CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
4571         // find the cells within these bounds 
4574         for ( row 
= internalYToRow(top
);  row 
< m_numRows
;  row
++ ) 
4576             if ( GetRowBottom(row
) <= top 
) 
4579             if ( GetRowTop(row
) > bottom 
) 
4582             for ( col 
= internalXToCol(left
);  col 
< m_numCols
;  col
++ ) 
4584                 if ( GetColRight(col
) <= left 
) 
4587                 if ( GetColLeft(col
) > right 
) 
4590                 cellsExposed
.Add( wxGridCellCoords( row
, col 
) ); 
4597     return cellsExposed
; 
4601 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event 
) 
4604     wxPoint 
pos( event
.GetPosition() ); 
4605     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4607     if ( event
.Dragging() ) 
4611             m_isDragging 
= TRUE
; 
4612             m_rowLabelWin
->CaptureMouse(); 
4615         if ( event
.LeftIsDown() ) 
4617             switch( m_cursorMode 
) 
4619                 case WXGRID_CURSOR_RESIZE_ROW
: 
4621                     int cw
, ch
, left
, dummy
; 
4622                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4623                     CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
4625                     wxClientDC 
dc( m_gridWin 
); 
4628                                GetRowTop(m_dragRowOrCol
) + 
4629                                GetRowMinimalHeight(m_dragRowOrCol
) ); 
4630                     dc
.SetLogicalFunction(wxINVERT
); 
4631                     if ( m_dragLastPos 
>= 0 ) 
4633                         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
4635                     dc
.DrawLine( left
, y
, left
+cw
, y 
); 
4640                 case WXGRID_CURSOR_SELECT_ROW
: 
4641                     if ( (row 
= YToRow( y 
)) >= 0 ) 
4645                             m_selection
->SelectRow( row
, 
4646                                                     event
.ControlDown(), 
4653                 // default label to suppress warnings about "enumeration value 
4654                 // 'xxx' not handled in switch 
4662     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4667         if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse(); 
4668         m_isDragging 
= FALSE
; 
4671     // ------------ Entering or leaving the window 
4673     if ( event
.Entering() || event
.Leaving() ) 
4675         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4679     // ------------ Left button pressed 
4681     else if ( event
.LeftDown() ) 
4683         // don't send a label click event for a hit on the 
4684         // edge of the row label - this is probably the user 
4685         // wanting to resize the row 
4687         if ( YToEdgeOfRow(y
) < 0 ) 
4691                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event 
) ) 
4693                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4697                     if ( event
.ShiftDown() ) 
4699                         m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
4702                                                   GetNumberCols() - 1, 
4703                                                   event
.ControlDown(), 
4710                         m_selection
->SelectRow( row
, 
4711                                                 event
.ControlDown(), 
4718                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
); 
4723             // starting to drag-resize a row 
4725             if ( CanDragRowSize() ) 
4726                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
); 
4731     // ------------ Left double click 
4733     else if (event
.LeftDClick() ) 
4735         if ( YToEdgeOfRow(y
) < 0 ) 
4738             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event 
); 
4743     // ------------ Left button released 
4745     else if ( event
.LeftUp() ) 
4747         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
4749             DoEndDragResizeRow(); 
4751             // Note: we are ending the event *after* doing 
4752             // default processing in this case 
4754             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
4757         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
); 
4762     // ------------ Right button down 
4764     else if ( event
.RightDown() ) 
4767         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event 
) ) 
4769             // no default action at the moment 
4774     // ------------ Right double click 
4776     else if ( event
.RightDClick() ) 
4779         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event 
) ) 
4781             // no default action at the moment 
4786     // ------------ No buttons down and mouse moving 
4788     else if ( event
.Moving() ) 
4790         m_dragRowOrCol 
= YToEdgeOfRow( y 
); 
4791         if ( m_dragRowOrCol 
>= 0 ) 
4793             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
4795                 // don't capture the mouse yet 
4796                 if ( CanDragRowSize() ) 
4797                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, FALSE
); 
4800         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
4802             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, FALSE
); 
4808 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event 
) 
4811     wxPoint 
pos( event
.GetPosition() ); 
4812     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
4814     if ( event
.Dragging() ) 
4818             m_isDragging 
= TRUE
; 
4819             m_colLabelWin
->CaptureMouse(); 
4822         if ( event
.LeftIsDown() ) 
4824             switch( m_cursorMode 
) 
4826                 case WXGRID_CURSOR_RESIZE_COL
: 
4828                     int cw
, ch
, dummy
, top
; 
4829                     m_gridWin
->GetClientSize( &cw
, &ch 
); 
4830                     CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
4832                     wxClientDC 
dc( m_gridWin 
); 
4835                     x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
4836                                   GetColMinimalWidth(m_dragRowOrCol
)); 
4837                     dc
.SetLogicalFunction(wxINVERT
); 
4838                     if ( m_dragLastPos 
>= 0 ) 
4840                         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
4842                     dc
.DrawLine( x
, top
, x
, top
+ch 
); 
4847                 case WXGRID_CURSOR_SELECT_COL
: 
4848                     if ( (col 
= XToCol( x 
)) >= 0 ) 
4852                             m_selection
->SelectCol( col
, 
4853                                                     event
.ControlDown(), 
4860                 // default label to suppress warnings about "enumeration value 
4861                 // 'xxx' not handled in switch 
4869     if ( m_isDragging 
&& (event
.Entering() || event
.Leaving()) ) 
4874         if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse(); 
4875         m_isDragging 
= FALSE
; 
4878     // ------------ Entering or leaving the window 
4880     if ( event
.Entering() || event
.Leaving() ) 
4882         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4886     // ------------ Left button pressed 
4888     else if ( event
.LeftDown() ) 
4890         // don't send a label click event for a hit on the 
4891         // edge of the col label - this is probably the user 
4892         // wanting to resize the col 
4894         if ( XToEdgeOfCol(x
) < 0 ) 
4898                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event 
) ) 
4900                 if ( !event
.ShiftDown() && !event
.ControlDown() ) 
4904                     if ( event
.ShiftDown() ) 
4906                         m_selection
->SelectBlock( 0, 
4907                                                   m_currentCellCoords
.GetCol(), 
4908                                                   GetNumberRows() - 1, col
, 
4909                                                   event
.ControlDown(), 
4916                         m_selection
->SelectCol( col
, 
4917                                                 event
.ControlDown(), 
4924                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
); 
4929             // starting to drag-resize a col 
4931             if ( CanDragColSize() ) 
4932                 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
); 
4937     // ------------ Left double click 
4939     if ( event
.LeftDClick() ) 
4941         if ( XToEdgeOfCol(x
) < 0 ) 
4944             SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event 
); 
4949     // ------------ Left button released 
4951     else if ( event
.LeftUp() ) 
4953         if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
4955             DoEndDragResizeCol(); 
4957             // Note: we are ending the event *after* doing 
4958             // default processing in this case 
4960             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
4963         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
); 
4968     // ------------ Right button down 
4970     else if ( event
.RightDown() ) 
4973         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event 
) ) 
4975             // no default action at the moment 
4980     // ------------ Right double click 
4982     else if ( event
.RightDClick() ) 
4985         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event 
) ) 
4987             // no default action at the moment 
4992     // ------------ No buttons down and mouse moving 
4994     else if ( event
.Moving() ) 
4996         m_dragRowOrCol 
= XToEdgeOfCol( x 
); 
4997         if ( m_dragRowOrCol 
>= 0 ) 
4999             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5001                 // don't capture the cursor yet 
5002                 if ( CanDragColSize() ) 
5003                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, FALSE
); 
5006         else if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5008             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, FALSE
); 
5014 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event 
) 
5016     if ( event
.LeftDown() ) 
5018         // indicate corner label by having both row and 
5021         if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event 
) ) 
5027     else if ( event
.LeftDClick() ) 
5029         SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event 
); 
5032     else if ( event
.RightDown() ) 
5034         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event 
) ) 
5036             // no default action at the moment 
5040     else if ( event
.RightDClick() ) 
5042         if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event 
) ) 
5044             // no default action at the moment 
5049 void wxGrid::ChangeCursorMode(CursorMode mode
, 
5054     static const wxChar 
*cursorModes
[] = 
5063     wxLogTrace(_T("grid"), 
5064                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"), 
5065                win 
== m_colLabelWin 
? _T("colLabelWin") 
5066                                     : win 
? _T("rowLabelWin") 
5068                cursorModes
[m_cursorMode
], cursorModes
[mode
]); 
5069 #endif // __WXDEBUG__ 
5071     if ( mode 
== m_cursorMode 
&& 
5072          win 
== m_winCapture 
&& 
5073          captureMouse 
== (m_winCapture 
!= NULL
)) 
5078         // by default use the grid itself 
5084         if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5085         m_winCapture 
= (wxWindow 
*)NULL
; 
5088     m_cursorMode 
= mode
; 
5090     switch ( m_cursorMode 
) 
5092         case WXGRID_CURSOR_RESIZE_ROW
: 
5093             win
->SetCursor( m_rowResizeCursor 
); 
5096         case WXGRID_CURSOR_RESIZE_COL
: 
5097             win
->SetCursor( m_colResizeCursor 
); 
5101             win
->SetCursor( *wxSTANDARD_CURSOR 
); 
5104     // we need to capture mouse when resizing 
5105     bool resize 
= m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
|| 
5106                   m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL
; 
5108     if ( captureMouse 
&& resize 
) 
5110         win
->CaptureMouse(); 
5115 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event 
) 
5118     wxPoint 
pos( event
.GetPosition() ); 
5119     CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y 
); 
5121     wxGridCellCoords coords
; 
5122     XYToCell( x
, y
, coords 
); 
5124     int cell_rows
, cell_cols
; 
5125     GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols 
); 
5126     if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
5128         coords
.SetRow(coords
.GetRow() + cell_rows
); 
5129         coords
.SetCol(coords
.GetCol() + cell_cols
); 
5132     if ( event
.Dragging() ) 
5134         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol()); 
5136         // Don't start doing anything until the mouse has been drug at 
5137         // least 3 pixels in any direction... 
5140             if (m_startDragPos 
== wxDefaultPosition
) 
5142                 m_startDragPos 
= pos
; 
5145             if (abs(m_startDragPos
.x 
- pos
.x
) < 4 && abs(m_startDragPos
.y 
- pos
.y
) < 4) 
5149         m_isDragging 
= TRUE
; 
5150         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5152             // Hide the edit control, so it 
5153             // won't interfer with drag-shrinking. 
5154             if ( IsCellEditControlShown() ) 
5156                 HideCellEditControl(); 
5157                 SaveEditControlValue(); 
5160             // Have we captured the mouse yet? 
5163                 m_winCapture 
= m_gridWin
; 
5164                 m_winCapture
->CaptureMouse(); 
5167             if ( coords 
!= wxGridNoCellCoords 
) 
5169                 if ( event
.ControlDown() ) 
5171                     if ( m_selectingKeyboard 
== wxGridNoCellCoords
) 
5172                         m_selectingKeyboard 
= coords
; 
5173                     HighlightBlock ( m_selectingKeyboard
, coords 
); 
5177                     if ( !IsSelection() ) 
5179                         HighlightBlock( coords
, coords 
); 
5183                         HighlightBlock( m_currentCellCoords
, coords 
); 
5187                 if (! IsVisible(coords
)) 
5189                     MakeCellVisible(coords
); 
5190                     // TODO: need to introduce a delay or something here.  The 
5191                     // scrolling is way to fast, at least on MSW - also on GTK. 
5195         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5197             int cw
, ch
, left
, dummy
; 
5198             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5199             CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5201             wxClientDC 
dc( m_gridWin 
); 
5203             y 
= wxMax( y
, GetRowTop(m_dragRowOrCol
) + 
5204                           GetRowMinimalHeight(m_dragRowOrCol
) ); 
5205             dc
.SetLogicalFunction(wxINVERT
); 
5206             if ( m_dragLastPos 
>= 0 ) 
5208                 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5210             dc
.DrawLine( left
, y
, left
+cw
, y 
); 
5213         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5215             int cw
, ch
, dummy
, top
; 
5216             m_gridWin
->GetClientSize( &cw
, &ch 
); 
5217             CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5219             wxClientDC 
dc( m_gridWin 
); 
5221             x 
= wxMax( x
, GetColLeft(m_dragRowOrCol
) + 
5222                           GetColMinimalWidth(m_dragRowOrCol
) ); 
5223             dc
.SetLogicalFunction(wxINVERT
); 
5224             if ( m_dragLastPos 
>= 0 ) 
5226                 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5228             dc
.DrawLine( x
, top
, x
, top
+ch 
); 
5235     m_isDragging 
= FALSE
; 
5236     m_startDragPos 
= wxDefaultPosition
; 
5238     // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL 
5239     //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under 
5242     if ( event
.Entering() || event
.Leaving() ) 
5244         ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5245         m_gridWin
->SetCursor( *wxSTANDARD_CURSOR 
); 
5250     // ------------ Left button pressed 
5252     if ( event
.LeftDown() && coords 
!= wxGridNoCellCoords 
) 
5254         if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
, 
5259             if ( !event
.ControlDown() ) 
5261             if ( event
.ShiftDown() ) 
5265                     m_selection
->SelectBlock( m_currentCellCoords
.GetRow(), 
5266                                               m_currentCellCoords
.GetCol(), 
5269                                               event
.ControlDown(), 
5275             else if ( XToEdgeOfCol(x
) < 0  && 
5276                       YToEdgeOfRow(y
) < 0 ) 
5278                 DisableCellEditControl(); 
5279                 MakeCellVisible( coords 
); 
5281                 if ( event
.ControlDown() ) 
5285                         m_selection
->ToggleCellSelection( coords
.GetRow(), 
5287                                                           event
.ControlDown(), 
5292                     m_selectingTopLeft 
= wxGridNoCellCoords
; 
5293                     m_selectingBottomRight 
= wxGridNoCellCoords
; 
5294                     m_selectingKeyboard 
= coords
; 
5298                     m_waitForSlowClick 
= m_currentCellCoords 
== coords 
&& coords 
!= wxGridNoCellCoords
; 
5299                     SetCurrentCell( coords 
); 
5302                         if ( m_selection
->GetSelectionMode() != 
5303                                 wxGrid::wxGridSelectCells 
) 
5305                             HighlightBlock( coords
, coords 
); 
5314     // ------------ Left double click 
5316     else if ( event
.LeftDClick() && coords 
!= wxGridNoCellCoords 
) 
5318         DisableCellEditControl(); 
5320         if ( XToEdgeOfCol(x
) < 0  &&  YToEdgeOfRow(y
) < 0 ) 
5322             SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
, 
5330     // ------------ Left button released 
5332     else if ( event
.LeftUp() ) 
5334         if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5336             if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
5337                  m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
5341                     if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse(); 
5342                     m_winCapture 
= NULL
; 
5347                     m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
5348                                               m_selectingTopLeft
.GetCol(), 
5349                                               m_selectingBottomRight
.GetRow(), 
5350                                               m_selectingBottomRight
.GetCol(), 
5351                                               event
.ControlDown(), 
5357                 m_selectingTopLeft 
= wxGridNoCellCoords
; 
5358                 m_selectingBottomRight 
= wxGridNoCellCoords
; 
5360                 // Show the edit control, if it has been hidden for 
5362                 ShowCellEditControl(); 
5366               if( m_waitForSlowClick 
&& CanEnableCellControl()) 
5368                 EnableCellEditControl(); 
5370                 wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
5371                 wxGridCellEditor 
*editor 
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol()); 
5372                 editor
->StartingClick(); 
5376                 m_waitForSlowClick 
= FALSE
; 
5380         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_ROW 
) 
5382             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5383             DoEndDragResizeRow(); 
5385             // Note: we are ending the event *after* doing 
5386             // default processing in this case 
5388             SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event 
); 
5390         else if ( m_cursorMode 
== WXGRID_CURSOR_RESIZE_COL 
) 
5392             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5393             DoEndDragResizeCol(); 
5395             // Note: we are ending the event *after* doing 
5396             // default processing in this case 
5398             SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event 
); 
5405     // ------------ Right button down 
5407     else if ( event
.RightDown() && coords 
!= wxGridNoCellCoords 
) 
5409         DisableCellEditControl(); 
5410         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
, 
5415             // no default action at the moment 
5420     // ------------ Right double click 
5422     else if ( event
.RightDClick() && coords 
!= wxGridNoCellCoords 
) 
5424         DisableCellEditControl(); 
5425         if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
, 
5430             // no default action at the moment 
5434     // ------------ Moving and no button action 
5436     else if ( event
.Moving() && !event
.IsButton() ) 
5438         if( coords
.GetRow() < 0 || coords
.GetCol() < 0 ) 
5440             // out of grid cell area 
5441             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5445         int dragRow 
= YToEdgeOfRow( y 
); 
5446         int dragCol 
= XToEdgeOfCol( x 
); 
5448         // Dragging on the corner of a cell to resize in both 
5449         // directions is not implemented yet... 
5451         if ( dragRow 
>= 0  &&  dragCol 
>= 0 ) 
5453             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5459             m_dragRowOrCol 
= dragRow
; 
5461             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5463                 if ( CanDragRowSize() && CanDragGridSize() ) 
5464                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
); 
5469                 m_dragRowOrCol 
= dragCol
; 
5477             m_dragRowOrCol 
= dragCol
; 
5479             if ( m_cursorMode 
== WXGRID_CURSOR_SELECT_CELL 
) 
5481                 if ( CanDragColSize() && CanDragGridSize() ) 
5482                     ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
); 
5488         // Neither on a row or col edge 
5490         if ( m_cursorMode 
!= WXGRID_CURSOR_SELECT_CELL 
) 
5492             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
); 
5498 void wxGrid::DoEndDragResizeRow() 
5500     if ( m_dragLastPos 
>= 0 ) 
5502         // erase the last line and resize the row 
5504         int cw
, ch
, left
, dummy
; 
5505         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5506         CalcUnscrolledPosition( 0, 0, &left
, &dummy 
); 
5508         wxClientDC 
dc( m_gridWin 
); 
5510         dc
.SetLogicalFunction( wxINVERT 
); 
5511         dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos 
); 
5512         HideCellEditControl(); 
5513         SaveEditControlValue(); 
5515         int rowTop 
= GetRowTop(m_dragRowOrCol
); 
5516         SetRowSize( m_dragRowOrCol
, 
5517                     wxMax( m_dragLastPos 
- rowTop
, WXGRID_MIN_ROW_HEIGHT 
) ); 
5519         if ( !GetBatchCount() ) 
5521             // Only needed to get the correct rect.y: 
5522             wxRect 
rect ( CellToRect( m_dragRowOrCol
, 0 ) ); 
5524             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5525             rect
.width 
= m_rowLabelWidth
; 
5526             rect
.height 
= ch 
- rect
.y
; 
5527             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
5529             // if there is a multicell block, paint all of it 
5532                 int i
, cell_rows
, cell_cols
, subtract_rows 
= 0; 
5533                 int leftCol 
= XToCol(left
); 
5534                 int rightCol 
= XToCol(left
+cw
); 
5537                     if (rightCol 
< 0) rightCol 
= m_numCols
; 
5538                     for (i
=leftCol
; i
<rightCol
; i
++) 
5540                         GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
); 
5541                         if (cell_rows 
< subtract_rows
) 
5542                             subtract_rows 
= cell_rows
; 
5544                     rect
.y 
= GetRowTop(m_dragRowOrCol 
+ subtract_rows
); 
5545                     CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
5546                     rect
.height 
= ch 
- rect
.y
; 
5549             m_gridWin
->Refresh( FALSE
, &rect 
); 
5552         ShowCellEditControl(); 
5557 void wxGrid::DoEndDragResizeCol() 
5559     if ( m_dragLastPos 
>= 0 ) 
5561         // erase the last line and resize the col 
5563         int cw
, ch
, dummy
, top
; 
5564         m_gridWin
->GetClientSize( &cw
, &ch 
); 
5565         CalcUnscrolledPosition( 0, 0, &dummy
, &top 
); 
5567         wxClientDC 
dc( m_gridWin 
); 
5569         dc
.SetLogicalFunction( wxINVERT 
); 
5570         dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch 
); 
5571         HideCellEditControl(); 
5572         SaveEditControlValue(); 
5574         int colLeft 
= GetColLeft(m_dragRowOrCol
); 
5575         SetColSize( m_dragRowOrCol
, 
5576                     wxMax( m_dragLastPos 
- colLeft
, 
5577                            GetColMinimalWidth(m_dragRowOrCol
) ) ); 
5579         if ( !GetBatchCount() ) 
5581             // Only needed to get the correct rect.x: 
5582             wxRect 
rect ( CellToRect( 0, m_dragRowOrCol 
) ); 
5584             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5585             rect
.width 
= cw 
- rect
.x
; 
5586             rect
.height 
= m_colLabelHeight
; 
5587             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
5589             // if there is a multicell block, paint all of it 
5592                 int i
, cell_rows
, cell_cols
, subtract_cols 
= 0; 
5593                 int topRow 
= YToRow(top
); 
5594                 int bottomRow 
= YToRow(top
+cw
); 
5597                     if (bottomRow 
< 0) bottomRow 
= m_numRows
; 
5598                     for (i
=topRow
; i
<bottomRow
; i
++) 
5600                         GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
); 
5601                         if (cell_cols 
< subtract_cols
) 
5602                             subtract_cols 
= cell_cols
; 
5604                     rect
.x 
= GetColLeft(m_dragRowOrCol 
+ subtract_cols
); 
5605                     CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
5606                     rect
.width 
= cw 
- rect
.x
; 
5609             m_gridWin
->Refresh( FALSE
, &rect 
); 
5612         ShowCellEditControl(); 
5619 // ------ interaction with data model 
5621 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg 
) 
5623     switch ( msg
.GetId() ) 
5625         case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
: 
5626             return GetModelValues(); 
5628         case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
: 
5629             return SetModelValues(); 
5631         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
: 
5632         case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
: 
5633         case wxGRIDTABLE_NOTIFY_ROWS_DELETED
: 
5634         case wxGRIDTABLE_NOTIFY_COLS_INSERTED
: 
5635         case wxGRIDTABLE_NOTIFY_COLS_APPENDED
: 
5636         case wxGRIDTABLE_NOTIFY_COLS_DELETED
: 
5637             return Redimension( msg 
); 
5646 // The behaviour of this function depends on the grid table class 
5647 // Clear() function.  For the default wxGridStringTable class the 
5648 // behavious is to replace all cell contents with wxEmptyString but 
5649 // not to change the number of rows or cols. 
5651 void wxGrid::ClearGrid() 
5655         if (IsCellEditControlEnabled()) 
5656             DisableCellEditControl(); 
5659         if ( !GetBatchCount() ) m_gridWin
->Refresh(); 
5664 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5666     // TODO: something with updateLabels flag 
5670         wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") ); 
5676         if (IsCellEditControlEnabled()) 
5677             DisableCellEditControl(); 
5679         return m_table
->InsertRows( pos
, numRows 
); 
5681         // the table will have sent the results of the insert row 
5682         // operation to this view object as a grid table message 
5688 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) ) 
5690     // TODO: something with updateLabels flag 
5694         wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") ); 
5698     return ( m_table 
&& m_table
->AppendRows( numRows 
) ); 
5699     // the table will have sent the results of the append row 
5700     // operation to this view object as a grid table message 
5704 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) ) 
5706     // TODO: something with updateLabels flag 
5710         wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") ); 
5716         if (IsCellEditControlEnabled()) 
5717             DisableCellEditControl(); 
5719         return (m_table
->DeleteRows( pos
, numRows 
)); 
5720         // the table will have sent the results of the delete row 
5721         // operation to this view object as a grid table message 
5727 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5729     // TODO: something with updateLabels flag 
5733         wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") ); 
5739         if (IsCellEditControlEnabled()) 
5740             DisableCellEditControl(); 
5742         return m_table
->InsertCols( pos
, numCols 
); 
5743         // the table will have sent the results of the insert col 
5744         // operation to this view object as a grid table message 
5750 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) ) 
5752     // TODO: something with updateLabels flag 
5756         wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") ); 
5760     return ( m_table 
&& m_table
->AppendCols( numCols 
) ); 
5761     // the table will have sent the results of the append col 
5762     // operation to this view object as a grid table message 
5766 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) ) 
5768     // TODO: something with updateLabels flag 
5772         wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") ); 
5778         if (IsCellEditControlEnabled()) 
5779             DisableCellEditControl(); 
5781         return ( m_table
->DeleteCols( pos
, numCols 
) ); 
5782         // the table will have sent the results of the delete col 
5783         // operation to this view object as a grid table message 
5791 // ----- event handlers 
5794 // Generate a grid event based on a mouse event and 
5795 // return the result of ProcessEvent() 
5797 int wxGrid::SendEvent( const wxEventType type
, 
5799                         wxMouseEvent
& mouseEv 
) 
5804    if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5806        int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5808        wxGridSizeEvent 
gridEvt( GetId(), 
5812                mouseEv
.GetX() + GetRowLabelSize(), 
5813                mouseEv
.GetY() + GetColLabelSize(), 
5814                mouseEv
.ControlDown(), 
5815                mouseEv
.ShiftDown(), 
5817                mouseEv
.MetaDown() ); 
5819        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5820        vetoed 
= !gridEvt
.IsAllowed(); 
5822    else if ( type 
== wxEVT_GRID_RANGE_SELECT 
) 
5824        // Right now, it should _never_ end up here! 
5825        wxGridRangeSelectEvent 
gridEvt( GetId(), 
5829                m_selectingBottomRight
, 
5831                mouseEv
.ControlDown(), 
5832                mouseEv
.ShiftDown(), 
5834                mouseEv
.MetaDown() ); 
5836        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5837        vetoed 
= !gridEvt
.IsAllowed(); 
5841        wxGridEvent 
gridEvt( GetId(), 
5845                mouseEv
.GetX() + GetRowLabelSize(), 
5846                mouseEv
.GetY() + GetColLabelSize(), 
5848                mouseEv
.ControlDown(), 
5849                mouseEv
.ShiftDown(), 
5851                mouseEv
.MetaDown() ); 
5852        claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5853        vetoed 
= !gridEvt
.IsAllowed(); 
5856    // A Veto'd event may not be `claimed' so test this first 
5857    if (vetoed
) return -1; 
5858    return claimed 
? 1 : 0; 
5862 // Generate a grid event of specified type and return the result 
5863 // of ProcessEvent(). 
5865 int wxGrid::SendEvent( const wxEventType type
, 
5871     if ( type 
== wxEVT_GRID_ROW_SIZE 
|| type 
== wxEVT_GRID_COL_SIZE 
) 
5873         int rowOrCol 
= (row 
== -1 ? col 
: row
); 
5875         wxGridSizeEvent 
gridEvt( GetId(), 
5880         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5881         vetoed  
= !gridEvt
.IsAllowed(); 
5885         wxGridEvent 
gridEvt( GetId(), 
5890         claimed 
= GetEventHandler()->ProcessEvent(gridEvt
); 
5891         vetoed  
= !gridEvt
.IsAllowed(); 
5894     // A Veto'd event may not be `claimed' so test this first 
5895     if (vetoed
) return -1; 
5896     return claimed 
? 1 : 0; 
5900 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) ) 
5902     wxPaintDC 
dc(this);  // needed to prevent zillions of paint events on MSW 
5905 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
) 
5907     // Don't do anything if between Begin/EndBatch... 
5908     // EndBatch() will do all this on the last nested one anyway. 
5909     if (! GetBatchCount()) 
5911         // Refresh to get correct scrolled position: 
5912         wxScrolledWindow::Refresh(eraseb
,rect
); 
5916             int rect_x
, rect_y
, rectWidth
, rectHeight
; 
5917             int width_label
, width_cell
, height_label
, height_cell
; 
5920             //Copy rectangle can get scroll offsets.. 
5921             rect_x 
= rect
->GetX(); 
5922             rect_y 
= rect
->GetY(); 
5923             rectWidth 
= rect
->GetWidth(); 
5924             rectHeight 
= rect
->GetHeight(); 
5926             width_label 
= m_rowLabelWidth 
- rect_x
; 
5927             if (width_label 
> rectWidth
) width_label 
= rectWidth
; 
5929             height_label 
= m_colLabelHeight 
- rect_y
; 
5930             if (height_label 
> rectHeight
) height_label 
= rectHeight
; 
5932             if (rect_x 
> m_rowLabelWidth
) 
5934                 x 
= rect_x 
- m_rowLabelWidth
; 
5935                 width_cell 
= rectWidth
; 
5940                 width_cell 
= rectWidth 
- (m_rowLabelWidth 
- rect_x
); 
5943             if (rect_y 
> m_colLabelHeight
) 
5945                 y 
= rect_y 
- m_colLabelHeight
; 
5946                 height_cell 
= rectHeight
; 
5951                 height_cell 
= rectHeight 
- (m_colLabelHeight 
- rect_y
); 
5954             // Paint corner label part intersecting rect. 
5955             if ( width_label 
> 0 && height_label 
> 0 ) 
5957                 wxRect 
anotherrect(rect_x
, rect_y
, width_label
, height_label
); 
5958                 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
); 
5961             // Paint col labels part intersecting rect. 
5962             if ( width_cell 
> 0 && height_label 
> 0 ) 
5964                 wxRect 
anotherrect(x
, rect_y
, width_cell
, height_label
); 
5965                 m_colLabelWin
->Refresh(eraseb
, &anotherrect
); 
5968             // Paint row labels part intersecting rect. 
5969             if ( width_label 
> 0 && height_cell 
> 0 ) 
5971                 wxRect 
anotherrect(rect_x
, y
, width_label
, height_cell
); 
5972                 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
); 
5975             // Paint cell area part intersecting rect. 
5976             if ( width_cell 
> 0 && height_cell 
> 0 ) 
5978                 wxRect 
anotherrect(x
, y
, width_cell
, height_cell
); 
5979                 m_gridWin
->Refresh(eraseb
, &anotherrect
); 
5984             m_cornerLabelWin
->Refresh(eraseb
, NULL
); 
5985             m_colLabelWin
->Refresh(eraseb
, NULL
); 
5986             m_rowLabelWin
->Refresh(eraseb
, NULL
); 
5987             m_gridWin
->Refresh(eraseb
, NULL
); 
5992 void wxGrid::OnSize( wxSizeEvent
& event 
) 
5994     // position the child windows 
5997     // don't call CalcDimensions() from here, the base class handles the size 
6003 void wxGrid::OnKeyDown( wxKeyEvent
& event 
) 
6005     if ( m_inOnKeyDown 
) 
6007         // shouldn't be here - we are going round in circles... 
6009         wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") ); 
6012     m_inOnKeyDown 
= TRUE
; 
6014     // propagate the event up and see if it gets processed 
6016     wxWindow 
*parent 
= GetParent(); 
6017     wxKeyEvent 
keyEvt( event 
); 
6018     keyEvt
.SetEventObject( parent 
); 
6020     if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt 
) ) 
6023         // try local handlers 
6025         switch ( event
.KeyCode() ) 
6028                 if ( event
.ControlDown() ) 
6030                     MoveCursorUpBlock( event
.ShiftDown() ); 
6034                     MoveCursorUp( event
.ShiftDown() ); 
6039                 if ( event
.ControlDown() ) 
6041                     MoveCursorDownBlock( event
.ShiftDown() ); 
6045                     MoveCursorDown( event
.ShiftDown() ); 
6050                 if ( event
.ControlDown() ) 
6052                     MoveCursorLeftBlock( event
.ShiftDown() ); 
6056                     MoveCursorLeft( event
.ShiftDown() ); 
6061                 if ( event
.ControlDown() ) 
6063                     MoveCursorRightBlock( event
.ShiftDown() ); 
6067                     MoveCursorRight( event
.ShiftDown() ); 
6072             case WXK_NUMPAD_ENTER
: 
6073                 if ( event
.ControlDown() ) 
6075                     event
.Skip();  // to let the edit control have the return 
6079                     if ( GetGridCursorRow() < GetNumberRows()-1 ) 
6081                         MoveCursorDown( event
.ShiftDown() ); 
6085                         // at the bottom of a column 
6086                         HideCellEditControl(); 
6087                         SaveEditControlValue(); 
6097                 if (event
.ShiftDown()) 
6099                     if ( GetGridCursorCol() > 0 ) 
6101                         MoveCursorLeft( FALSE 
); 
6106                         HideCellEditControl(); 
6107                         SaveEditControlValue(); 
6112                     if ( GetGridCursorCol() < GetNumberCols()-1 ) 
6114                         MoveCursorRight( FALSE 
); 
6119                         HideCellEditControl(); 
6120                         SaveEditControlValue(); 
6126                 if ( event
.ControlDown() ) 
6128                     MakeCellVisible( 0, 0 ); 
6129                     SetCurrentCell( 0, 0 ); 
6138                 if ( event
.ControlDown() ) 
6140                     MakeCellVisible( m_numRows
-1, m_numCols
-1 ); 
6141                     SetCurrentCell( m_numRows
-1, m_numCols
-1 ); 
6158                 if ( event
.ControlDown() ) 
6162                         m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(), 
6163                                                           m_currentCellCoords
.GetCol(), 
6164                                                           event
.ControlDown(), 
6171                 if ( !IsEditable() ) 
6173                     MoveCursorRight( FALSE 
); 
6176                 // Otherwise fall through to default 
6179                 // is it possible to edit the current cell at all? 
6180                 if ( !IsCellEditControlEnabled() && CanEnableCellControl() ) 
6182                     // yes, now check whether the cells editor accepts the key 
6183                     int row 
= m_currentCellCoords
.GetRow(); 
6184                     int col 
= m_currentCellCoords
.GetCol(); 
6185                     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6186                     wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6188                     // <F2> is special and will always start editing, for 
6189                     // other keys - ask the editor itself 
6190                     if ( (event
.KeyCode() == WXK_F2 
&& !event
.HasModifiers()) 
6191                          || editor
->IsAcceptedKey(event
) ) 
6193                         // DJC MAPTEK - ensure cell is visble 
6194                         MakeCellVisible(row
, col
); 
6195                         EnableCellEditControl(); 
6196                         // DJC MAPTEK - a problem can arise if the cell is not 
6197                         // completely visible (even after calling MakeCellVisible 
6198                         // the control is not created and calling StartingKey will 
6200                         if( editor
->IsCreated() && m_cellEditCtrlEnabled 
) editor
->StartingKey(event
); 
6212                     // let others process char events with modifiers or all 
6213                     // char events for readonly cells 
6220     m_inOnKeyDown 
= FALSE
; 
6223 void wxGrid::OnKeyUp( wxKeyEvent
& event 
) 
6225     // try local handlers 
6227     if ( event
.KeyCode() == WXK_SHIFT 
) 
6229         if ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
6230              m_selectingBottomRight 
!= wxGridNoCellCoords 
) 
6234                 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(), 
6235                                           m_selectingTopLeft
.GetCol(), 
6236                                           m_selectingBottomRight
.GetRow(), 
6237                                           m_selectingBottomRight
.GetCol(), 
6238                                           event
.ControlDown(), 
6245         m_selectingTopLeft 
= wxGridNoCellCoords
; 
6246         m_selectingBottomRight 
= wxGridNoCellCoords
; 
6247         m_selectingKeyboard 
= wxGridNoCellCoords
; 
6251 void wxGrid::OnEraseBackground(wxEraseEvent
&) 
6255 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords 
) 
6257     if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) ) 
6259         // the event has been intercepted - do nothing 
6263     wxClientDC 
dc(m_gridWin
); 
6266     if ( m_currentCellCoords 
!= wxGridNoCellCoords 
) 
6268         HideCellEditControl(); 
6269         DisableCellEditControl(); 
6271         if ( IsVisible( m_currentCellCoords
, FALSE 
) ) 
6274             r 
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
); 
6275             if ( !m_gridLinesEnabled 
) 
6283             wxGridCellCoordsArray cells 
= CalcCellsExposed( r 
); 
6285             // Otherwise refresh redraws the highlight! 
6286             m_currentCellCoords 
= coords
; 
6288             DrawGridCellArea(dc
,cells
); 
6289             DrawAllGridLines( dc
, r 
); 
6293     m_currentCellCoords 
= coords
; 
6295     wxGridCellAttr
* attr 
= GetCellAttr(coords
); 
6296     DrawCellHighlight(dc
, attr
); 
6301 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol 
) 
6304     wxGridCellCoords updateTopLeft
, updateBottomRight
; 
6308         if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
6311             rightCol 
= GetNumberCols() - 1; 
6313         else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
6316             bottomRow 
= GetNumberRows() - 1; 
6320     if ( topRow 
> bottomRow 
) 
6327     if ( leftCol 
> rightCol 
) 
6334     updateTopLeft 
= wxGridCellCoords( topRow
, leftCol 
); 
6335     updateBottomRight 
= wxGridCellCoords( bottomRow
, rightCol 
); 
6337     // First the case that we selected a completely new area 
6338     if ( m_selectingTopLeft 
== wxGridNoCellCoords 
|| 
6339          m_selectingBottomRight 
== wxGridNoCellCoords 
) 
6342         rect 
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol 
), 
6343                                   wxGridCellCoords ( bottomRow
, rightCol 
) ); 
6344         m_gridWin
->Refresh( FALSE
, &rect 
); 
6346     // Now handle changing an existing selection area. 
6347     else if ( m_selectingTopLeft 
!= updateTopLeft 
|| 
6348               m_selectingBottomRight 
!= updateBottomRight 
) 
6350         // Compute two optimal update rectangles: 
6351         // Either one rectangle is a real subset of the 
6352         // other, or they are (almost) disjoint! 
6354         bool    need_refresh
[4]; 
6358         need_refresh
[3] = FALSE
; 
6361         // Store intermediate values 
6362         wxCoord oldLeft   
= m_selectingTopLeft
.GetCol(); 
6363         wxCoord oldTop    
= m_selectingTopLeft
.GetRow(); 
6364         wxCoord oldRight  
= m_selectingBottomRight
.GetCol(); 
6365         wxCoord oldBottom 
= m_selectingBottomRight
.GetRow(); 
6367         // Determine the outer/inner coordinates. 
6368         if (oldLeft 
> leftCol
) 
6374         if (oldTop 
> topRow 
) 
6380         if (oldRight 
< rightCol 
) 
6383             oldRight 
= rightCol
; 
6386         if (oldBottom 
< bottomRow
) 
6389             oldBottom 
= bottomRow
; 
6393         // Now, either the stuff marked old is the outer 
6394         // rectangle or we don't have a situation where one 
6395         // is contained in the other. 
6397         if ( oldLeft 
< leftCol 
) 
6399             // Refresh the newly selected or deselected 
6400             // area to the left of the old or new selection. 
6401             need_refresh
[0] = TRUE
; 
6402             rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6404                                          wxGridCellCoords ( oldBottom
, 
6408         if ( oldTop  
< topRow 
) 
6410             // Refresh the newly selected or deselected 
6411             // area above the old or new selection. 
6412             need_refresh
[1] = TRUE
; 
6413             rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6415                                          wxGridCellCoords ( topRow 
- 1, 
6419         if ( oldRight 
> rightCol 
) 
6421             // Refresh the newly selected or deselected 
6422             // area to the right of the old or new selection. 
6423             need_refresh
[2] = TRUE
; 
6424             rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
, 
6426                                          wxGridCellCoords ( oldBottom
, 
6430         if ( oldBottom 
> bottomRow 
) 
6432             // Refresh the newly selected or deselected 
6433             // area below the old or new selection. 
6434             need_refresh
[3] = TRUE
; 
6435             rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow 
+ 1, 
6437                                          wxGridCellCoords ( oldBottom
, 
6441         // various Refresh() calls 
6442         for (i 
= 0; i 
< 4; i
++ ) 
6443             if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect 
) 
6444                 m_gridWin
->Refresh( FALSE
, &(rect
[i
]) ); 
6447     m_selectingTopLeft 
= updateTopLeft
; 
6448     m_selectingBottomRight 
= updateBottomRight
; 
6452 // ------ functions to get/send data (see also public functions) 
6455 bool wxGrid::GetModelValues() 
6457     // Hide the editor, so it won't hide a changed value. 
6458     HideCellEditControl(); 
6462         // all we need to do is repaint the grid 
6464         m_gridWin
->Refresh(); 
6472 bool wxGrid::SetModelValues() 
6476     // Disable the editor, so it won't hide a changed value. 
6477     // Do we also want to save the current value of the editor first? 
6479     DisableCellEditControl(); 
6483         for ( row 
= 0;  row 
< m_numRows
;  row
++ ) 
6485             for ( col 
= 0;  col 
< m_numCols
;  col
++ ) 
6487                 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) ); 
6499 // Note - this function only draws cells that are in the list of 
6500 // exposed cells (usually set from the update region by 
6501 // CalcExposedCells) 
6503 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells 
) 
6505     if ( !m_numRows 
|| !m_numCols 
) return; 
6507     int i
, numCells 
= cells
.GetCount(); 
6508     int row
, col
, cell_rows
, cell_cols
; 
6509     wxGridCellCoordsArray redrawCells
; 
6511     for ( i 
= numCells
-1; i 
>= 0;  i
-- ) 
6513         row 
= cells
[i
].GetRow(); 
6514         col 
= cells
[i
].GetCol(); 
6515         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
6517         // If this cell is part of a multicell block, find owner for repaint 
6518         if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
6520             wxGridCellCoords 
cell(row
+cell_rows
, col
+cell_cols
); 
6521             bool marked 
= FALSE
; 
6522             for ( int j 
= 0;  j 
< numCells
;  j
++ ) 
6524                 if ( cell 
== cells
[j
] ) 
6532                 int count 
= redrawCells
.GetCount(); 
6533                 for (int j 
= 0; j 
< count
; j
++) 
6535                     if ( cell 
== redrawCells
[j
] ) 
6541                 if (!marked
) redrawCells
.Add( cell 
); 
6543             continue; // don't bother drawing this cell 
6546         // If this cell is empty, find cell to left that might want to overflow 
6547         if (m_table 
&& m_table
->IsEmptyCell(row
, col
)) 
6549             for ( int l 
= 0; l 
< cell_rows
; l
++ ) 
6551                 // find a cell in this row to left alreay marked for repaint 
6553                 for (int k 
= 0; k 
< int(redrawCells
.GetCount()); k
++) 
6554                     if ((redrawCells
[k
].GetCol() < left
) && 
6555                         (redrawCells
[k
].GetRow() == row
)) 
6556                         left
=redrawCells
[k
].GetCol(); 
6558                 if (left 
== col
) left 
= 0; // oh well 
6560                 for (int j 
= col
-1; j 
>= left
; j
--) 
6562                     if (!m_table
->IsEmptyCell(row
+l
, j
)) 
6564                         if (GetCellOverflow(row
+l
, j
)) 
6566                             wxGridCellCoords 
cell(row
+l
, j
); 
6567                             bool marked 
= FALSE
; 
6569                             for (int k 
= 0; k 
< numCells
; k
++) 
6571                                 if ( cell 
== cells
[k
] ) 
6579                                 int count 
= redrawCells
.GetCount(); 
6580                                 for (int k 
= 0; k 
< count
; k
++) 
6582                                     if ( cell 
== redrawCells
[k
] ) 
6588                                 if (!marked
) redrawCells
.Add( cell 
); 
6596         DrawCell( dc
, cells
[i
] ); 
6599     numCells 
= redrawCells
.GetCount(); 
6601     for ( i 
= numCells 
- 1; i 
>= 0;  i
-- ) 
6603         DrawCell( dc
, redrawCells
[i
] ); 
6608 void wxGrid::DrawGridSpace( wxDC
& dc 
) 
6611   m_gridWin
->GetClientSize( &cw
, &ch 
); 
6614   CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6616   int rightCol 
= m_numCols 
> 0 ? GetColRight(m_numCols 
- 1) : 0; 
6617   int bottomRow 
= m_numRows 
> 0 ? GetRowBottom(m_numRows 
- 1) : 0 ; 
6619   if ( right 
> rightCol 
|| bottom 
> bottomRow 
) 
6622       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6624       dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) ); 
6625       dc
.SetPen( *wxTRANSPARENT_PEN 
); 
6627       if ( right 
> rightCol 
) 
6629           dc
.DrawRectangle( rightCol
, top
, right 
- rightCol
, ch
); 
6632       if ( bottom 
> bottomRow 
) 
6634           dc
.DrawRectangle( left
, bottomRow
, cw
, bottom 
- bottomRow
); 
6640 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6642     int row 
= coords
.GetRow(); 
6643     int col 
= coords
.GetCol(); 
6645     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6648     // we draw the cell border ourselves 
6649 #if !WXGRID_DRAW_LINES 
6650     if ( m_gridLinesEnabled 
) 
6651         DrawCellBorder( dc
, coords 
); 
6654     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
6656     bool isCurrent 
= coords 
== m_currentCellCoords
; 
6658     wxRect rect 
= CellToRect( row
, col 
); 
6660     // if the editor is shown, we should use it and not the renderer 
6661     // Note: However, only if it is really _shown_, i.e. not hidden! 
6662     if ( isCurrent 
&& IsCellEditControlShown() ) 
6664         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
6665         editor
->PaintBackground(rect
, attr
); 
6670         // but all the rest is drawn by the cell renderer and hence may be 
6672         wxGridCellRenderer 
*renderer 
= attr
->GetRenderer(this, row
, col
); 
6673         renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
)); 
6680 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr 
*attr 
) 
6682     int row 
= m_currentCellCoords
.GetRow(); 
6683     int col 
= m_currentCellCoords
.GetCol(); 
6685     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6688     wxRect rect 
= CellToRect(row
, col
); 
6690     // hmmm... what could we do here to show that the cell is disabled? 
6691     // for now, I just draw a thinner border than for the other ones, but 
6692     // it doesn't look really good 
6694     int penWidth 
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth 
: m_cellHighlightPenWidth
; 
6698         // The center of th drawn line is where the position/width/height of 
6699         // the rectangle is actually at, (on wxMSW atr least,) so we will 
6700         // reduce the size of the rectangle to compensate for the thickness of 
6701         // the line.  If this is too strange on non wxMSW platforms then 
6702         // please #ifdef this appropriately. 
6703         rect
.x 
+= penWidth
/2; 
6704         rect
.y 
+= penWidth
/2; 
6705         rect
.width 
-= penWidth
-1; 
6706         rect
.height 
-= penWidth
-1; 
6709         // Now draw the rectangle 
6710         // use the cellHighlightColour if the cell is inside a selection, this 
6711         // will ensure the cell is always visible. 
6712         dc
.SetPen(wxPen(IsInSelection(row
,col
)?m_selectionForeground
:m_cellHighlightColour
, penWidth
, wxSOLID
)); 
6713         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
6714         dc
.DrawRectangle(rect
); 
6718         // VZ: my experiments with 3d borders... 
6720         // how to properly set colours for arbitrary bg? 
6721         wxCoord x1 
= rect
.x
, 
6723                 x2 
= rect
.x 
+ rect
.width 
-1, 
6724                 y2 
= rect
.y 
+ rect
.height 
-1; 
6726         dc
.SetPen(*wxWHITE_PEN
); 
6727         dc
.DrawLine(x1
, y1
, x2
, y1
); 
6728         dc
.DrawLine(x1
, y1
, x1
, y2
); 
6730         dc
.DrawLine(x1 
+ 1, y2 
- 1, x2 
- 1, y2 
- 1); 
6731         dc
.DrawLine(x2 
- 1, y1 
+ 1, x2 
- 1, y2 
); 
6733         dc
.SetPen(*wxBLACK_PEN
); 
6734         dc
.DrawLine(x1
, y2
, x2
, y2
); 
6735         dc
.DrawLine(x2
, y1
, x2
, y2
+1); 
6740 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords 
) 
6742     int row 
= coords
.GetRow(); 
6743     int col 
= coords
.GetCol(); 
6744     if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
6747     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6749     wxRect rect 
= CellToRect( row
, col 
); 
6751     // right hand border 
6753     dc
.DrawLine( rect
.x 
+ rect
.width
, rect
.y
, 
6754                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height 
+ 1 ); 
6758     dc
.DrawLine( rect
.x
,              rect
.y 
+ rect
.height
, 
6759                  rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
6762 void wxGrid::DrawHighlight(wxDC
& dc
,const  wxGridCellCoordsArray
& cells
) 
6764     // This if block was previously in wxGrid::OnPaint but that doesn't 
6765     // seem to get called under wxGTK - MB 
6767     if ( m_currentCellCoords 
== wxGridNoCellCoords  
&& 
6768          m_numRows 
&& m_numCols 
) 
6770         m_currentCellCoords
.Set(0, 0); 
6773     if ( IsCellEditControlShown() ) 
6775         // don't show highlight when the edit control is shown 
6779     // if the active cell was repainted, repaint its highlight too because it 
6780     // might have been damaged by the grid lines 
6781     size_t count 
= cells
.GetCount(); 
6782     for ( size_t n 
= 0; n 
< count
; n
++ ) 
6784         if ( cells
[n
] == m_currentCellCoords 
) 
6786             wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
6787             DrawCellHighlight(dc
, attr
); 
6795 // TODO: remove this ??? 
6796 // This is used to redraw all grid lines e.g. when the grid line colour 
6799 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion 
& WXUNUSED(reg
) ) 
6801 #if !WXGRID_DRAW_LINES 
6805     if ( !m_gridLinesEnabled 
|| 
6807          !m_numCols 
) return; 
6809     int top
, bottom
, left
, right
; 
6811 #if 0  //#ifndef __WXGTK__ 
6815       m_gridWin
->GetClientSize(&cw
, &ch
); 
6817       // virtual coords of visible area 
6819       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6820       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6825       reg
.GetBox(x
, y
, w
, h
); 
6826       CalcUnscrolledPosition( x
, y
, &left
, &top 
); 
6827       CalcUnscrolledPosition( x 
+ w
, y 
+ h
, &right
, &bottom 
); 
6831       m_gridWin
->GetClientSize(&cw
, &ch
); 
6832       CalcUnscrolledPosition( 0, 0, &left
, &top 
); 
6833       CalcUnscrolledPosition( cw
, ch
, &right
, &bottom 
); 
6836     // avoid drawing grid lines past the last row and col 
6838     right 
= wxMin( right
, GetColRight(m_numCols 
- 1) ); 
6839     bottom 
= wxMin( bottom
, GetRowBottom(m_numRows 
- 1) ); 
6841     // no gridlines inside multicells, clip them out 
6842     int leftCol   
= XToCol(left
); 
6843     int topRow    
= YToRow(top
); 
6844     int rightCol  
= XToCol(right
); 
6845     int bottomRow 
= YToRow(bottom
); 
6846     wxRegion 
clippedcells(0, 0, cw
, ch
); 
6848     if ((leftCol 
>= 0) && (topRow 
>= 0)) 
6850         if (rightCol  
< 0) rightCol  
= m_numCols
; 
6851         if (bottomRow 
< 0) bottomRow 
= m_numRows
; 
6853         int i
, j
, cell_rows
, cell_cols
; 
6856         for (j
=topRow
; j
<bottomRow
; j
++) 
6858             for (i
=leftCol
; i
<rightCol
; i
++) 
6860                 GetCellSize( j
, i
, &cell_rows
, &cell_cols 
); 
6861                 if ((cell_rows 
> 1) || (cell_cols 
> 1)) 
6863                     rect 
= CellToRect(j
,i
); 
6864                     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6865                     clippedcells
.Subtract(rect
); 
6867                 else if ((cell_rows 
< 0) || (cell_cols 
< 0)) 
6869                     rect 
= CellToRect(j
+cell_rows
, i
+cell_cols
); 
6870                     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
6871                     clippedcells
.Subtract(rect
); 
6876     dc
.SetClippingRegion( clippedcells 
); 
6878     dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) ); 
6880     // horizontal grid lines 
6883     for ( i 
= internalYToRow(top
); i 
< m_numRows
; i
++ ) 
6885         int bot 
= GetRowBottom(i
) - 1; 
6894             dc
.DrawLine( left
, bot
, right
, bot 
); 
6899     // vertical grid lines 
6901     for ( i 
= internalXToCol(left
); i 
< m_numCols
; i
++ ) 
6903         int colRight 
= GetColRight(i
) - 1; 
6904         if ( colRight 
> right 
) 
6909         if ( colRight 
>= left 
) 
6911             dc
.DrawLine( colRight
, top
, colRight
, bottom 
); 
6914     dc
.DestroyClippingRegion(); 
6918 void wxGrid::DrawRowLabels( wxDC
& dc 
,const wxArrayInt
& rows
) 
6920     if ( !m_numRows 
) return; 
6923     size_t numLabels 
= rows
.GetCount(); 
6925     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6927         DrawRowLabel( dc
, rows
[i
] ); 
6932 void wxGrid::DrawRowLabel( wxDC
& dc
, int row 
) 
6934     if ( GetRowHeight(row
) <= 0 ) 
6937     int rowTop 
= GetRowTop(row
), 
6938         rowBottom 
= GetRowBottom(row
) - 1; 
6940     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
6941     dc
.DrawLine( m_rowLabelWidth
-1, rowTop
, 
6942                  m_rowLabelWidth
-1, rowBottom 
); 
6944     dc
.DrawLine( 0, rowTop
, 0, rowBottom 
); 
6946     dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom 
); 
6948     dc
.SetPen( *wxWHITE_PEN 
); 
6949     dc
.DrawLine( 1, rowTop
, 1, rowBottom 
); 
6950     dc
.DrawLine( 1, rowTop
, m_rowLabelWidth
-1, rowTop 
); 
6952     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
6953     dc
.SetTextForeground( GetLabelTextColour() ); 
6954     dc
.SetFont( GetLabelFont() ); 
6957     GetRowLabelAlignment( &hAlign
, &vAlign 
); 
6961     rect
.SetY( GetRowTop(row
) + 2 ); 
6962     rect
.SetWidth( m_rowLabelWidth 
- 4 ); 
6963     rect
.SetHeight( GetRowHeight(row
) - 4 ); 
6964     DrawTextRectangle( dc
, GetRowLabelValue( row 
), rect
, hAlign
, vAlign 
); 
6968 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols 
) 
6970     if ( !m_numCols 
) return; 
6973     size_t numLabels 
= cols
.GetCount(); 
6975     for ( i 
= 0;  i 
< numLabels
;  i
++ ) 
6977         DrawColLabel( dc
, cols
[i
] ); 
6982 void wxGrid::DrawColLabel( wxDC
& dc
, int col 
) 
6984     if ( GetColWidth(col
) <= 0 ) 
6987     int colLeft 
= GetColLeft(col
), 
6988         colRight 
= GetColRight(col
) - 1; 
6990     dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) ); 
6991     dc
.DrawLine( colRight
, 0, 
6992                  colRight
, m_colLabelHeight
-1 ); 
6994     dc
.DrawLine( colLeft
, 0, colRight
, 0 ); 
6996     dc
.DrawLine( colLeft
, m_colLabelHeight
-1, 
6997                  colRight
+1, m_colLabelHeight
-1 ); 
6999     dc
.SetPen( *wxWHITE_PEN 
); 
7000     dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 ); 
7001     dc
.DrawLine( colLeft
, 1, colRight
, 1 ); 
7003     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7004     dc
.SetTextForeground( GetLabelTextColour() ); 
7005     dc
.SetFont( GetLabelFont() ); 
7007     dc
.SetBackgroundMode( wxTRANSPARENT 
); 
7008     dc
.SetTextForeground( GetLabelTextColour() ); 
7009     dc
.SetFont( GetLabelFont() ); 
7012     GetColLabelAlignment( &hAlign
, &vAlign 
); 
7015     rect
.SetX( colLeft 
+ 2 ); 
7017     rect
.SetWidth( GetColWidth(col
) - 4 ); 
7018     rect
.SetHeight( m_colLabelHeight 
- 4 ); 
7019     DrawTextRectangle( dc
, GetColLabelValue( col 
), rect
, hAlign
, vAlign 
); 
7022 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7023                                 const wxString
& value
, 
7028     wxArrayString lines
; 
7030     StringToLines( value
, lines 
); 
7033     //Forward to new API. 
7034     DrawTextRectangle(  dc
, 
7042 void wxGrid::DrawTextRectangle( wxDC
& dc
, 
7043                                 const wxArrayString
& lines
, 
7048     long textWidth
, textHeight
; 
7049     long lineWidth
, lineHeight
; 
7052     dc
.SetClippingRegion( rect 
); 
7054     nLines 
= lines
.GetCount(); 
7059       GetTextBoxSize(dc
, lines
, &textWidth
, &textHeight
); 
7062         case wxALIGN_BOTTOM
: 
7063           y 
= rect
.y 
+ (rect
.height 
- textHeight 
- 1); 
7066         case wxALIGN_CENTRE
: 
7067           y 
= rect
.y 
+ ((rect
.height 
- textHeight
)/2); 
7076       // Align each line of a multi-line label 
7077       for( l 
= 0; l 
< nLines
; l
++ ) 
7079         dc
.GetTextExtent(lines
[l
], &lineWidth
, &lineHeight
); 
7081         switch( horizAlign 
) 
7084             x 
= rect
.x 
+ (rect
.width 
- lineWidth 
- 1); 
7087           case wxALIGN_CENTRE
: 
7088             x 
= rect
.x 
+ ((rect
.width 
- lineWidth
)/2); 
7097         dc
.DrawText( lines
[l
], (int)x
, (int)y 
); 
7101     dc
.DestroyClippingRegion(); 
7105 // Split multi line text up into an array of strings.  Any existing 
7106 // contents of the string array are preserved. 
7108 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines 
) 
7112     wxString eol 
= wxTextFile::GetEOL( wxTextFileType_Unix 
); 
7113     wxString tVal 
= wxTextFile::Translate( value
, wxTextFileType_Unix 
); 
7115     while ( startPos 
< (int)tVal
.Length() ) 
7117         pos 
= tVal
.Mid(startPos
).Find( eol 
); 
7122         else if ( pos 
== 0 ) 
7124             lines
.Add( wxEmptyString 
); 
7128             lines
.Add( value
.Mid(startPos
, pos
) ); 
7132     if ( startPos 
< (int)value
.Length() ) 
7134         lines
.Add( value
.Mid( startPos 
) ); 
7139 void wxGrid::GetTextBoxSize( wxDC
& dc
, 
7140                              const wxArrayString
& lines
, 
7141                              long *width
, long *height 
) 
7148     for ( i 
= 0;  i 
< lines
.GetCount();  i
++ ) 
7150         dc
.GetTextExtent( lines
[i
], &lineW
, &lineH 
); 
7151         w 
= wxMax( w
, lineW 
); 
7160 // ------ Batch processing. 
7162 void wxGrid::EndBatch() 
7164     if ( m_batchCount 
> 0 ) 
7167         if ( !m_batchCount 
) 
7170             m_rowLabelWin
->Refresh(); 
7171             m_colLabelWin
->Refresh(); 
7172             m_cornerLabelWin
->Refresh(); 
7173             m_gridWin
->Refresh(); 
7178 // Use this, rather than wxWindow::Refresh(), to force an immediate 
7179 // repainting of the grid. Has no effect if you are already inside a 
7180 // BeginBatch / EndBatch block. 
7182 void wxGrid::ForceRefresh() 
7190 // ------ Edit control functions 
7194 void wxGrid::EnableEditing( bool edit 
) 
7196     // TODO: improve this ? 
7198     if ( edit 
!= m_editable 
) 
7200         if(!edit
) EnableCellEditControl(edit
); 
7206 void wxGrid::EnableCellEditControl( bool enable 
) 
7211     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) 
7212         SetCurrentCell( 0, 0 ); 
7214     if ( enable 
!= m_cellEditCtrlEnabled 
) 
7218             if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0) 
7221             // this should be checked by the caller! 
7222             wxASSERT_MSG( CanEnableCellControl(), 
7223                           _T("can't enable editing for this cell!") ); 
7225             // do it before ShowCellEditControl() 
7226             m_cellEditCtrlEnabled 
= enable
; 
7228             ShowCellEditControl(); 
7232             //FIXME:add veto support 
7233             SendEvent( wxEVT_GRID_EDITOR_HIDDEN
); 
7235             HideCellEditControl(); 
7236             SaveEditControlValue(); 
7238             // do it after HideCellEditControl() 
7239             m_cellEditCtrlEnabled 
= enable
; 
7244 bool wxGrid::IsCurrentCellReadOnly() const 
7247     wxGridCellAttr
* attr 
= ((wxGrid 
*)this)->GetCellAttr(m_currentCellCoords
); 
7248     bool readonly 
= attr
->IsReadOnly(); 
7254 bool wxGrid::CanEnableCellControl() const 
7256     return m_editable 
&& !IsCurrentCellReadOnly(); 
7259 bool wxGrid::IsCellEditControlEnabled() const 
7261     // the cell edit control might be disable for all cells or just for the 
7262     // current one if it's read only 
7263     return m_cellEditCtrlEnabled 
? !IsCurrentCellReadOnly() : FALSE
; 
7266 bool wxGrid::IsCellEditControlShown() const 
7268     bool isShown 
= FALSE
; 
7270     if ( m_cellEditCtrlEnabled 
) 
7272         int row 
= m_currentCellCoords
.GetRow(); 
7273         int col 
= m_currentCellCoords
.GetCol(); 
7274         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7275         wxGridCellEditor
* editor 
= attr
->GetEditor((wxGrid
*) this, row
, col
); 
7280             if ( editor
->IsCreated() ) 
7282                 isShown 
= editor
->GetControl()->IsShown(); 
7292 void wxGrid::ShowCellEditControl() 
7294     if ( IsCellEditControlEnabled() ) 
7296         if ( !IsVisible( m_currentCellCoords 
) ) 
7298             m_cellEditCtrlEnabled 
= FALSE
; 
7303             wxRect rect 
= CellToRect( m_currentCellCoords 
); 
7304             int row 
= m_currentCellCoords
.GetRow(); 
7305             int col 
= m_currentCellCoords
.GetCol(); 
7307             // if this is part of a multicell, find owner (topleft) 
7308             int cell_rows
, cell_cols
; 
7309             GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7310             if ( cell_rows 
<= 0 || cell_cols 
<= 0 ) 
7314                 m_currentCellCoords
.SetRow( row 
); 
7315                 m_currentCellCoords
.SetCol( col 
); 
7318             // convert to scrolled coords 
7320             CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7322             // done in PaintBackground() 
7324             // erase the highlight and the cell contents because the editor 
7325             // might not cover the entire cell 
7326             wxClientDC 
dc( m_gridWin 
); 
7328             dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID)); 
7329             dc
.SetPen(*wxTRANSPARENT_PEN
); 
7330             dc
.DrawRectangle(rect
); 
7333             // cell is shifted by one pixel 
7334             // However, don't allow x or y to become negative 
7335             // since the SetSize() method interprets that as 
7342             wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7343             wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7344             if ( !editor
->IsCreated() ) 
7346                 editor
->Create(m_gridWin
, -1, 
7347                                new wxGridCellEditorEvtHandler(this, editor
)); 
7349                 wxGridEditorCreatedEvent 
evt(GetId(), 
7350                                              wxEVT_GRID_EDITOR_CREATED
, 
7354                                              editor
->GetControl()); 
7355                 GetEventHandler()->ProcessEvent(evt
); 
7359             // resize editor to overflow into righthand cells if allowed 
7360             int maxWidth 
= rect
.width
; 
7361             wxString value 
= GetCellValue(row
, col
); 
7362             if ( (value 
!= wxEmptyString
) && (attr
->GetOverflow()) ) 
7365                 GetTextExtent(value
, &maxWidth
, &y
, 
7366                         NULL
, NULL
, &attr
->GetFont()); 
7367                 if (maxWidth 
< rect
.width
) maxWidth 
= rect
.width
; 
7369             int client_right 
= m_gridWin
->GetClientSize().GetWidth(); 
7370             if (rect
.x
+maxWidth 
> client_right
) 
7371                 maxWidth 
= client_right 
- rect
.x
; 
7373             if ((maxWidth 
> rect
.width
) && (col 
< m_numCols
) && m_table
) 
7375                 GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7376                 // may have changed earlier 
7377                 for (int i 
= col
+cell_cols
; i 
< m_numCols
; i
++) 
7380                     GetCellSize( row
, i
, &c_rows
, &c_cols 
); 
7381                     // looks weird going over a multicell 
7382                     if (m_table
->IsEmptyCell(row
,i
) && 
7383                             (rect
.width 
< maxWidth
) && (c_rows 
== 1)) 
7384                         rect
.width 
+= GetColWidth(i
); 
7388                 if (rect
.GetRight() > client_right
) 
7389                     rect
.SetRight(client_right
-1); 
7392 // DJC (MAPTEK) 19-Feb-2001 do set size prior to showing the control 
7393             editor
->SetSize( rect 
); 
7394             editor
->Show( TRUE
, attr 
); 
7395 // DJC (MAPTEK) 19-Jun-2001 recalc dimensions in case we need to 
7396 // expand the scrolled window to account for editor 
7399             editor
->BeginEdit(row
, col
, this); 
7408 void wxGrid::HideCellEditControl() 
7410     if ( IsCellEditControlEnabled() ) 
7412         int row 
= m_currentCellCoords
.GetRow(); 
7413         int col 
= m_currentCellCoords
.GetCol(); 
7415         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7416         wxGridCellEditor 
*editor 
= attr
->GetEditor(this, row
, col
); 
7417         editor
->Show( FALSE 
); 
7420         m_gridWin
->SetFocus(); 
7421         // refresh whole row to the right 
7422         wxRect 
rect( CellToRect(row
, col
) ); 
7423         CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
7424         rect
.width 
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
; 
7425         m_gridWin
->Refresh( FALSE
, &rect 
); 
7430 void wxGrid::SaveEditControlValue() 
7432     if ( IsCellEditControlEnabled() ) 
7434         int row 
= m_currentCellCoords
.GetRow(); 
7435         int col 
= m_currentCellCoords
.GetCol(); 
7437         wxString oldval 
= GetCellValue(row
,col
); 
7439         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
7440         wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
7441         bool changed 
= editor
->EndEdit(row
, col
, this); 
7448             if ( SendEvent( wxEVT_GRID_CELL_CHANGE
, 
7449                        m_currentCellCoords
.GetRow(), 
7450                        m_currentCellCoords
.GetCol() ) < 0 ) { 
7452                 // Event has been vetoed, set the data back. 
7453                 SetCellValue(row
,col
,oldval
); 
7461 // ------ Grid location functions 
7462 //  Note that all of these functions work with the logical coordinates of 
7463 //  grid cells and labels so you will need to convert from device 
7464 //  coordinates for mouse events etc. 
7467 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords 
) 
7469     int row 
= YToRow(y
); 
7470     int col 
= XToCol(x
); 
7472     if ( row 
== -1  ||  col 
== -1 ) 
7474         coords 
= wxGridNoCellCoords
; 
7478         coords
.Set( row
, col 
); 
7483 // Internal Helper function for computing row or column from some 
7484 // (unscrolled) coordinate value, using either 
7485 // m_defaultRowHeight/m_defaultColWidth or binary search on array 
7486 // of m_rowBottoms/m_ColRights to speed up the search! 
7488 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
, 
7489                            const wxArrayInt
& BorderArray
, int nMax
, 
7494     size_t i_max 
= coord 
/ defaultDist
, 
7497     if (BorderArray
.IsEmpty()) 
7499         if((int) i_max 
< nMax
) 
7501         return maxOnOverflow 
? nMax 
- 1 : -1; 
7504     if ( i_max 
>= BorderArray
.GetCount()) 
7505         i_max 
= BorderArray
.GetCount() - 1; 
7508         if ( coord 
>= BorderArray
[i_max
]) 
7511             i_max 
= coord 
/ minDist
; 
7513         if ( i_max 
>= BorderArray
.GetCount()) 
7514             i_max 
= BorderArray
.GetCount() - 1; 
7516     if ( coord 
>= BorderArray
[i_max
]) 
7517         return maxOnOverflow 
? (int)i_max 
: -1; 
7518     if ( coord 
< BorderArray
[0] ) 
7521     while ( i_max 
- i_min 
> 0 ) 
7523         wxCHECK_MSG(BorderArray
[i_min
] <= coord 
&& coord 
< BorderArray
[i_max
], 
7524                     0, _T("wxGrid: internal error in CoordToRowOrCol")); 
7525         if (coord 
>=  BorderArray
[ i_max 
- 1]) 
7529         int median 
= i_min 
+ (i_max 
- i_min 
+ 1) / 2; 
7530         if (coord 
< BorderArray
[median
]) 
7538 int wxGrid::YToRow( int y 
) 
7540     return CoordToRowOrCol(y
, m_defaultRowHeight
, 
7541                            WXGRID_MIN_ROW_HEIGHT
, m_rowBottoms
, m_numRows
, FALSE
); 
7545 int wxGrid::XToCol( int x 
) 
7547     return CoordToRowOrCol(x
, m_defaultColWidth
, 
7548                            WXGRID_MIN_COL_WIDTH
, m_colRights
, m_numCols
, FALSE
); 
7552 // return the row number that that the y coord is near the edge of, or 
7553 // -1 if not near an edge 
7555 int wxGrid::YToEdgeOfRow( int y 
) 
7558     i 
= internalYToRow(y
); 
7560     if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7562         // We know that we are in row i, test whether we are 
7563         // close enough to lower or upper border, respectively. 
7564         if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE 
) 
7566         else if( i 
> 0 && y 
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7574 // return the col number that that the x coord is near the edge of, or 
7575 // -1 if not near an edge 
7577 int wxGrid::XToEdgeOfCol( int x 
) 
7580     i 
= internalXToCol(x
); 
7582     if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE 
) 
7584         // We know that we are in column i,  test whether we are 
7585         // close enough to right or left border, respectively. 
7586         if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE 
) 
7588         else if( i 
> 0 && x 
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE 
) 
7596 wxRect 
wxGrid::CellToRect( int row
, int col 
) 
7598     wxRect 
rect( -1, -1, -1, -1 ); 
7600     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7601          col 
>= 0  &&  col 
< m_numCols 
) 
7603         int i
, cell_rows
, cell_cols
; 
7604         rect
.width 
= rect
.height 
= 0; 
7605         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7606         // if negative then find multicell owner 
7607         if (cell_rows 
< 0) row 
+= cell_rows
; 
7608         if (cell_cols 
< 0) col 
+= cell_cols
; 
7609         GetCellSize( row
, col
, &cell_rows
, &cell_cols 
); 
7611         rect
.x 
= GetColLeft(col
); 
7612         rect
.y 
= GetRowTop(row
); 
7613         for (i
=col
; i
<col
+cell_cols
; i
++) 
7614             rect
.width  
+= GetColWidth(i
); 
7615         for (i
=row
; i
<row
+cell_rows
; i
++) 
7616             rect
.height 
+= GetRowHeight(i
); 
7619     // if grid lines are enabled, then the area of the cell is a bit smaller 
7620     if (m_gridLinesEnabled
) { 
7628 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible 
) 
7630     // get the cell rectangle in logical coords 
7632     wxRect 
r( CellToRect( row
, col 
) ); 
7634     // convert to device coords 
7636     int left
, top
, right
, bottom
; 
7637     CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7638     CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7640     // check against the client area of the grid window 
7643     m_gridWin
->GetClientSize( &cw
, &ch 
); 
7645     if ( wholeCellVisible 
) 
7647         // is the cell wholly visible ? 
7649         return ( left 
>= 0  &&  right 
<= cw  
&& 
7650                  top 
>= 0  &&  bottom 
<= ch 
); 
7654         // is the cell partly visible ? 
7656         return ( ((left 
>=0 && left 
< cw
) || (right 
> 0 && right 
<= cw
))  && 
7657                  ((top 
>=0 && top 
< ch
) || (bottom 
> 0 && bottom 
<= ch
)) ); 
7662 // make the specified cell location visible by doing a minimal amount 
7665 void wxGrid::MakeCellVisible( int row
, int col 
) 
7669     int xpos 
= -1, ypos 
= -1; 
7671     if ( row 
>= 0  &&  row 
< m_numRows  
&& 
7672          col 
>= 0  &&  col 
< m_numCols 
) 
7674         // get the cell rectangle in logical coords 
7676         wxRect 
r( CellToRect( row
, col 
) ); 
7678         // convert to device coords 
7680         int left
, top
, right
, bottom
; 
7681         CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top 
); 
7682         CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom 
); 
7685         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7691         else if ( bottom 
> ch 
) 
7693             int h 
= r
.GetHeight(); 
7695             for ( i 
= row
-1;  i 
>= 0;  i
-- ) 
7697                 int rowHeight 
= GetRowHeight(i
); 
7698                 if ( h 
+ rowHeight 
> ch 
) 
7705             // we divide it later by GRID_SCROLL_LINE, make sure that we don't 
7706             // have rounding errors (this is important, because if we do, we 
7707             // might not scroll at all and some cells won't be redrawn) 
7709             // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full 
7711             ypos 
+= GRID_SCROLL_LINE_Y
; 
7718         else if ( right 
> cw 
) 
7721             // position the view so that the cell is on the right 
7723             CalcUnscrolledPosition(0, 0, &x0
, &y0
); 
7724             xpos 
= x0 
+ (right 
- cw
); 
7726             // see comment for ypos above 
7727             xpos 
+= GRID_SCROLL_LINE_X
; 
7730         if ( xpos 
!= -1  ||  ypos 
!= -1 ) 
7733                 xpos 
/= GRID_SCROLL_LINE_X
; 
7735                 ypos 
/= GRID_SCROLL_LINE_Y
; 
7736             Scroll( xpos
, ypos 
); 
7744 // ------ Grid cursor movement functions 
7747 bool wxGrid::MoveCursorUp( bool expandSelection 
) 
7749     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7750          m_currentCellCoords
.GetRow() >= 0 ) 
7752         if ( expandSelection
) 
7754             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7755                 m_selectingKeyboard 
= m_currentCellCoords
; 
7756             if ( m_selectingKeyboard
.GetRow() > 0 ) 
7758                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 ); 
7759                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7760                                  m_selectingKeyboard
.GetCol() ); 
7761                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7764         else if ( m_currentCellCoords
.GetRow() > 0 ) 
7767             MakeCellVisible( m_currentCellCoords
.GetRow() - 1, 
7768                              m_currentCellCoords
.GetCol() ); 
7769             SetCurrentCell( m_currentCellCoords
.GetRow() - 1, 
7770                             m_currentCellCoords
.GetCol() ); 
7781 bool wxGrid::MoveCursorDown( bool expandSelection 
) 
7783     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7784          m_currentCellCoords
.GetRow() < m_numRows 
) 
7786         if ( expandSelection 
) 
7788             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7789                 m_selectingKeyboard 
= m_currentCellCoords
; 
7790             if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 ) 
7792                 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 ); 
7793                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7794                         m_selectingKeyboard
.GetCol() ); 
7795                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7798         else if ( m_currentCellCoords
.GetRow() < m_numRows 
- 1 ) 
7801             MakeCellVisible( m_currentCellCoords
.GetRow() + 1, 
7802                              m_currentCellCoords
.GetCol() ); 
7803             SetCurrentCell( m_currentCellCoords
.GetRow() + 1, 
7804                             m_currentCellCoords
.GetCol() ); 
7815 bool wxGrid::MoveCursorLeft( bool expandSelection 
) 
7817     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7818          m_currentCellCoords
.GetCol() >= 0 ) 
7820         if ( expandSelection 
) 
7822             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7823                 m_selectingKeyboard 
= m_currentCellCoords
; 
7824             if ( m_selectingKeyboard
.GetCol() > 0 ) 
7826                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 ); 
7827                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7828                         m_selectingKeyboard
.GetCol() ); 
7829                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7832         else if ( m_currentCellCoords
.GetCol() > 0 ) 
7835             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7836                              m_currentCellCoords
.GetCol() - 1 ); 
7837             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7838                             m_currentCellCoords
.GetCol() - 1 ); 
7849 bool wxGrid::MoveCursorRight( bool expandSelection 
) 
7851     if ( m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7852          m_currentCellCoords
.GetCol() < m_numCols 
) 
7854         if ( expandSelection 
) 
7856             if ( m_selectingKeyboard 
== wxGridNoCellCoords 
) 
7857                 m_selectingKeyboard 
= m_currentCellCoords
; 
7858             if ( m_selectingKeyboard
.GetCol() < m_numCols 
- 1 ) 
7860                 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 ); 
7861                 MakeCellVisible( m_selectingKeyboard
.GetRow(), 
7862                         m_selectingKeyboard
.GetCol() ); 
7863                 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7866         else if ( m_currentCellCoords
.GetCol() < m_numCols 
- 1 ) 
7869             MakeCellVisible( m_currentCellCoords
.GetRow(), 
7870                              m_currentCellCoords
.GetCol() + 1 ); 
7871             SetCurrentCell( m_currentCellCoords
.GetRow(), 
7872                             m_currentCellCoords
.GetCol() + 1 ); 
7883 bool wxGrid::MovePageUp() 
7885     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7887     int row 
= m_currentCellCoords
.GetRow(); 
7891         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7893         int y 
= GetRowTop(row
); 
7894         int newRow 
= YToRow( y 
- ch 
+ 1 ); 
7899         else if ( newRow 
== row 
) 
7904         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7905         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7913 bool wxGrid::MovePageDown() 
7915     if ( m_currentCellCoords 
== wxGridNoCellCoords 
) return FALSE
; 
7917     int row 
= m_currentCellCoords
.GetRow(); 
7918     if ( row 
< m_numRows 
) 
7921         m_gridWin
->GetClientSize( &cw
, &ch 
); 
7923         int y 
= GetRowTop(row
); 
7924         int newRow 
= YToRow( y 
+ ch 
); 
7927             newRow 
= m_numRows 
- 1; 
7929         else if ( newRow 
== row 
) 
7934         MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() ); 
7935         SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() ); 
7943 bool wxGrid::MoveCursorUpBlock( bool expandSelection 
) 
7946          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
7947          m_currentCellCoords
.GetRow() > 0 ) 
7949         int row 
= m_currentCellCoords
.GetRow(); 
7950         int col 
= m_currentCellCoords
.GetCol(); 
7952         if ( m_table
->IsEmptyCell(row
, col
) ) 
7954             // starting in an empty cell: find the next block of 
7960                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7963         else if ( m_table
->IsEmptyCell(row
-1, col
) ) 
7965             // starting at the top of a block: find the next block 
7971                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
7976             // starting within a block: find the top of the block 
7981                 if ( m_table
->IsEmptyCell(row
, col
) ) 
7989         MakeCellVisible( row
, col 
); 
7990         if ( expandSelection 
) 
7992             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
7993             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
7998             SetCurrentCell( row
, col 
); 
8006 bool wxGrid::MoveCursorDownBlock( bool expandSelection 
) 
8009          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8010          m_currentCellCoords
.GetRow() < m_numRows
-1 ) 
8012         int row 
= m_currentCellCoords
.GetRow(); 
8013         int col 
= m_currentCellCoords
.GetCol(); 
8015         if ( m_table
->IsEmptyCell(row
, col
) ) 
8017             // starting in an empty cell: find the next block of 
8020             while ( row 
< m_numRows
-1 ) 
8023                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8026         else if ( m_table
->IsEmptyCell(row
+1, col
) ) 
8028             // starting at the bottom of a block: find the next block 
8031             while ( row 
< m_numRows
-1 ) 
8034                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8039             // starting within a block: find the bottom of the block 
8041             while ( row 
< m_numRows
-1 ) 
8044                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8052         MakeCellVisible( row
, col 
); 
8053         if ( expandSelection 
) 
8055             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8056             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8061             SetCurrentCell( row
, col 
); 
8070 bool wxGrid::MoveCursorLeftBlock( bool expandSelection 
) 
8073          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8074          m_currentCellCoords
.GetCol() > 0 ) 
8076         int row 
= m_currentCellCoords
.GetRow(); 
8077         int col 
= m_currentCellCoords
.GetCol(); 
8079         if ( m_table
->IsEmptyCell(row
, col
) ) 
8081             // starting in an empty cell: find the next block of 
8087                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8090         else if ( m_table
->IsEmptyCell(row
, col
-1) ) 
8092             // starting at the left of a block: find the next block 
8098                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8103             // starting within a block: find the left of the block 
8108                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8116         MakeCellVisible( row
, col 
); 
8117         if ( expandSelection 
) 
8119             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8120             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8125             SetCurrentCell( row
, col 
); 
8134 bool wxGrid::MoveCursorRightBlock( bool expandSelection 
) 
8137          m_currentCellCoords 
!= wxGridNoCellCoords  
&& 
8138          m_currentCellCoords
.GetCol() < m_numCols
-1 ) 
8140         int row 
= m_currentCellCoords
.GetRow(); 
8141         int col 
= m_currentCellCoords
.GetCol(); 
8143         if ( m_table
->IsEmptyCell(row
, col
) ) 
8145             // starting in an empty cell: find the next block of 
8148             while ( col 
< m_numCols
-1 ) 
8151                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8154         else if ( m_table
->IsEmptyCell(row
, col
+1) ) 
8156             // starting at the right of a block: find the next block 
8159             while ( col 
< m_numCols
-1 ) 
8162                 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break; 
8167             // starting within a block: find the right of the block 
8169             while ( col 
< m_numCols
-1 ) 
8172                 if ( m_table
->IsEmptyCell(row
, col
) ) 
8180         MakeCellVisible( row
, col 
); 
8181         if ( expandSelection 
) 
8183             m_selectingKeyboard 
= wxGridCellCoords( row
, col 
); 
8184             HighlightBlock( m_currentCellCoords
, m_selectingKeyboard 
); 
8189             SetCurrentCell( row
, col 
); 
8201 // ------ Label values and formatting 
8204 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert 
) 
8206     *horiz 
= m_rowLabelHorizAlign
; 
8207     *vert  
= m_rowLabelVertAlign
; 
8210 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert 
) 
8212     *horiz 
= m_colLabelHorizAlign
; 
8213     *vert  
= m_colLabelVertAlign
; 
8216 wxString 
wxGrid::GetRowLabelValue( int row 
) 
8220         return m_table
->GetRowLabelValue( row 
); 
8230 wxString 
wxGrid::GetColLabelValue( int col 
) 
8234         return m_table
->GetColLabelValue( col 
); 
8245 void wxGrid::SetRowLabelSize( int width 
) 
8247     width 
= wxMax( width
, 0 ); 
8248     if ( width 
!= m_rowLabelWidth 
) 
8252             m_rowLabelWin
->Show( FALSE 
); 
8253             m_cornerLabelWin
->Show( FALSE 
); 
8255         else if ( m_rowLabelWidth 
== 0 ) 
8257             m_rowLabelWin
->Show( TRUE 
); 
8258             if ( m_colLabelHeight 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8261         m_rowLabelWidth 
= width
; 
8263         wxScrolledWindow::Refresh( TRUE 
); 
8268 void wxGrid::SetColLabelSize( int height 
) 
8270     height 
= wxMax( height
, 0 ); 
8271     if ( height 
!= m_colLabelHeight 
) 
8275             m_colLabelWin
->Show( FALSE 
); 
8276             m_cornerLabelWin
->Show( FALSE 
); 
8278         else if ( m_colLabelHeight 
== 0 ) 
8280             m_colLabelWin
->Show( TRUE 
); 
8281             if ( m_rowLabelWidth 
> 0 ) m_cornerLabelWin
->Show( TRUE 
); 
8284         m_colLabelHeight 
= height
; 
8286         wxScrolledWindow::Refresh( TRUE 
); 
8291 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour 
) 
8293     if ( m_labelBackgroundColour 
!= colour 
) 
8295         m_labelBackgroundColour 
= colour
; 
8296         m_rowLabelWin
->SetBackgroundColour( colour 
); 
8297         m_colLabelWin
->SetBackgroundColour( colour 
); 
8298         m_cornerLabelWin
->SetBackgroundColour( colour 
); 
8300         if ( !GetBatchCount() ) 
8302             m_rowLabelWin
->Refresh(); 
8303             m_colLabelWin
->Refresh(); 
8304             m_cornerLabelWin
->Refresh(); 
8309 void wxGrid::SetLabelTextColour( const wxColour
& colour 
) 
8311     if ( m_labelTextColour 
!= colour 
) 
8313         m_labelTextColour 
= colour
; 
8314         if ( !GetBatchCount() ) 
8316             m_rowLabelWin
->Refresh(); 
8317             m_colLabelWin
->Refresh(); 
8322 void wxGrid::SetLabelFont( const wxFont
& font 
) 
8325     if ( !GetBatchCount() ) 
8327         m_rowLabelWin
->Refresh(); 
8328         m_colLabelWin
->Refresh(); 
8332 void wxGrid::SetRowLabelAlignment( int horiz
, int vert 
) 
8334     // allow old (incorrect) defs to be used 
8337         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8338         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8339         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8344         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8345         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8346         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8349     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8351         m_rowLabelHorizAlign 
= horiz
; 
8354     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8356         m_rowLabelVertAlign 
= vert
; 
8359     if ( !GetBatchCount() ) 
8361         m_rowLabelWin
->Refresh(); 
8365 void wxGrid::SetColLabelAlignment( int horiz
, int vert 
) 
8367     // allow old (incorrect) defs to be used 
8370         case wxLEFT
:   horiz 
= wxALIGN_LEFT
; break; 
8371         case wxRIGHT
:  horiz 
= wxALIGN_RIGHT
; break; 
8372         case wxCENTRE
: horiz 
= wxALIGN_CENTRE
; break; 
8377         case wxTOP
:    vert 
= wxALIGN_TOP
;    break; 
8378         case wxBOTTOM
: vert 
= wxALIGN_BOTTOM
; break; 
8379         case wxCENTRE
: vert 
= wxALIGN_CENTRE
; break; 
8382     if ( horiz 
== wxALIGN_LEFT 
|| horiz 
== wxALIGN_CENTRE 
|| horiz 
== wxALIGN_RIGHT 
) 
8384         m_colLabelHorizAlign 
= horiz
; 
8387     if ( vert 
== wxALIGN_TOP 
|| vert 
== wxALIGN_CENTRE 
|| vert 
== wxALIGN_BOTTOM 
) 
8389         m_colLabelVertAlign 
= vert
; 
8392     if ( !GetBatchCount() ) 
8394         m_colLabelWin
->Refresh(); 
8398 void wxGrid::SetRowLabelValue( int row
, const wxString
& s 
) 
8402         m_table
->SetRowLabelValue( row
, s 
); 
8403         if ( !GetBatchCount() ) 
8405             wxRect rect 
= CellToRect( row
, 0); 
8406             if ( rect
.height 
> 0 ) 
8408                 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
); 
8410                 rect
.width 
= m_rowLabelWidth
; 
8411                 m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
8417 void wxGrid::SetColLabelValue( int col
, const wxString
& s 
) 
8421         m_table
->SetColLabelValue( col
, s 
); 
8422         if ( !GetBatchCount() ) 
8424             wxRect rect 
= CellToRect( 0, col 
); 
8425             if ( rect
.width 
> 0 ) 
8427                 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
); 
8429                 rect
.height 
= m_colLabelHeight
; 
8430                 m_colLabelWin
->Refresh( TRUE
, &rect 
); 
8436 void wxGrid::SetGridLineColour( const wxColour
& colour 
) 
8438     if ( m_gridLineColour 
!= colour 
) 
8440         m_gridLineColour 
= colour
; 
8442         wxClientDC 
dc( m_gridWin 
); 
8444         DrawAllGridLines( dc
, wxRegion() ); 
8449 void wxGrid::SetCellHighlightColour( const wxColour
& colour 
) 
8451     if ( m_cellHighlightColour 
!= colour 
) 
8453         m_cellHighlightColour 
= colour
; 
8455         wxClientDC 
dc( m_gridWin 
); 
8457         wxGridCellAttr
* attr 
= GetCellAttr(m_currentCellCoords
); 
8458         DrawCellHighlight(dc
, attr
); 
8463 void wxGrid::SetCellHighlightPenWidth(int width
) 
8465     if (m_cellHighlightPenWidth 
!= width
) { 
8466         m_cellHighlightPenWidth 
= width
; 
8468         // Just redrawing the cell highlight is not enough since that won't 
8469         // make any visible change if the the thickness is getting smaller. 
8470         int row 
= m_currentCellCoords
.GetRow(); 
8471         int col 
= m_currentCellCoords
.GetCol(); 
8472         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8474         wxRect rect 
= CellToRect(row
, col
); 
8475         m_gridWin
->Refresh(TRUE
, &rect
); 
8479 void wxGrid::SetCellHighlightROPenWidth(int width
) 
8481     if (m_cellHighlightROPenWidth 
!= width
) { 
8482         m_cellHighlightROPenWidth 
= width
; 
8484         // Just redrawing the cell highlight is not enough since that won't 
8485         // make any visible change if the the thickness is getting smaller. 
8486         int row 
= m_currentCellCoords
.GetRow(); 
8487         int col 
= m_currentCellCoords
.GetCol(); 
8488         if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 ) 
8490         wxRect rect 
= CellToRect(row
, col
); 
8491         m_gridWin
->Refresh(TRUE
, &rect
); 
8495 void wxGrid::EnableGridLines( bool enable 
) 
8497     if ( enable 
!= m_gridLinesEnabled 
) 
8499         m_gridLinesEnabled 
= enable
; 
8501         if ( !GetBatchCount() ) 
8505                 wxClientDC 
dc( m_gridWin 
); 
8507                 DrawAllGridLines( dc
, wxRegion() ); 
8511                 m_gridWin
->Refresh(); 
8518 int wxGrid::GetDefaultRowSize() 
8520     return m_defaultRowHeight
; 
8523 int wxGrid::GetRowSize( int row 
) 
8525     wxCHECK_MSG( row 
>= 0 && row 
< m_numRows
, 0, _T("invalid row index") ); 
8527     return GetRowHeight(row
); 
8530 int wxGrid::GetDefaultColSize() 
8532     return m_defaultColWidth
; 
8535 int wxGrid::GetColSize( int col 
) 
8537     wxCHECK_MSG( col 
>= 0 && col 
< m_numCols
, 0, _T("invalid column index") ); 
8539     return GetColWidth(col
); 
8542 // ============================================================================ 
8543 // access to the grid attributes: each of them has a default value in the grid 
8544 // itself and may be overidden on a per-cell basis 
8545 // ============================================================================ 
8547 // ---------------------------------------------------------------------------- 
8548 // setting default attributes 
8549 // ---------------------------------------------------------------------------- 
8551 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col 
) 
8553     m_defaultCellAttr
->SetBackgroundColour(col
); 
8555     m_gridWin
->SetBackgroundColour(col
); 
8559 void wxGrid::SetDefaultCellTextColour( const wxColour
& col 
) 
8561     m_defaultCellAttr
->SetTextColour(col
); 
8564 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert 
) 
8566     m_defaultCellAttr
->SetAlignment(horiz
, vert
); 
8569 void wxGrid::SetDefaultCellOverflow( bool allow 
) 
8571     m_defaultCellAttr
->SetOverflow(allow
); 
8574 void wxGrid::SetDefaultCellFont( const wxFont
& font 
) 
8576     m_defaultCellAttr
->SetFont(font
); 
8579 void wxGrid::SetDefaultRenderer(wxGridCellRenderer 
*renderer
) 
8581     m_defaultCellAttr
->SetRenderer(renderer
); 
8584 void wxGrid::SetDefaultEditor(wxGridCellEditor 
*editor
) 
8586     m_defaultCellAttr
->SetEditor(editor
); 
8589 // ---------------------------------------------------------------------------- 
8590 // access to the default attrbiutes 
8591 // ---------------------------------------------------------------------------- 
8593 wxColour 
wxGrid::GetDefaultCellBackgroundColour() 
8595     return m_defaultCellAttr
->GetBackgroundColour(); 
8598 wxColour 
wxGrid::GetDefaultCellTextColour() 
8600     return m_defaultCellAttr
->GetTextColour(); 
8603 wxFont 
wxGrid::GetDefaultCellFont() 
8605     return m_defaultCellAttr
->GetFont(); 
8608 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert 
) 
8610     m_defaultCellAttr
->GetAlignment(horiz
, vert
); 
8613 bool wxGrid::GetDefaultCellOverflow() 
8615     return m_defaultCellAttr
->GetOverflow(); 
8618 wxGridCellRenderer 
*wxGrid::GetDefaultRenderer() const 
8620     return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0); 
8623 wxGridCellEditor 
*wxGrid::GetDefaultEditor() const 
8625     return m_defaultCellAttr
->GetEditor(NULL
,0,0); 
8628 // ---------------------------------------------------------------------------- 
8629 // access to cell attributes 
8630 // ---------------------------------------------------------------------------- 
8632 wxColour 
wxGrid::GetCellBackgroundColour(int row
, int col
) 
8634     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8635     wxColour colour 
= attr
->GetBackgroundColour(); 
8640 wxColour 
wxGrid::GetCellTextColour( int row
, int col 
) 
8642     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8643     wxColour colour 
= attr
->GetTextColour(); 
8648 wxFont 
wxGrid::GetCellFont( int row
, int col 
) 
8650     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8651     wxFont font 
= attr
->GetFont(); 
8656 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert 
) 
8658     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8659     attr
->GetAlignment(horiz
, vert
); 
8663 bool wxGrid::GetCellOverflow( int row
, int col 
) 
8665     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8666     bool allow 
= attr
->GetOverflow(); 
8671 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols 
) 
8673     wxGridCellAttr 
*attr 
= GetCellAttr(row
, col
); 
8674     attr
->GetSize( num_rows
, num_cols 
); 
8678 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
) 
8680     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8681     wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
8687 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
) 
8689     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8690     wxGridCellEditor
* editor 
= attr
->GetEditor(this, row
, col
); 
8696 bool wxGrid::IsReadOnly(int row
, int col
) const 
8698     wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
8699     bool isReadOnly 
= attr
->IsReadOnly(); 
8704 // ---------------------------------------------------------------------------- 
8705 // attribute support: cache, automatic provider creation, ... 
8706 // ---------------------------------------------------------------------------- 
8708 bool wxGrid::CanHaveAttributes() 
8715     return m_table
->CanHaveAttributes(); 
8718 void wxGrid::ClearAttrCache() 
8720     if ( m_attrCache
.row 
!= -1 ) 
8722         wxSafeDecRef(m_attrCache
.attr
); 
8723         m_attrCache
.attr 
= NULL
; 
8724         m_attrCache
.row 
= -1; 
8728 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr 
*attr
) const 
8732         wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
8734         self
->ClearAttrCache(); 
8735         self
->m_attrCache
.row 
= row
; 
8736         self
->m_attrCache
.col 
= col
; 
8737         self
->m_attrCache
.attr 
= attr
; 
8742 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr 
**attr
) const 
8744     if ( row 
== m_attrCache
.row 
&& col 
== m_attrCache
.col 
) 
8746         *attr 
= m_attrCache
.attr
; 
8747         wxSafeIncRef(m_attrCache
.attr
); 
8749 #ifdef DEBUG_ATTR_CACHE 
8750         gs_nAttrCacheHits
++; 
8757 #ifdef DEBUG_ATTR_CACHE 
8758         gs_nAttrCacheMisses
++; 
8764 wxGridCellAttr 
*wxGrid::GetCellAttr(int row
, int col
) const 
8766     wxGridCellAttr 
*attr 
= NULL
; 
8767     // Additional test to avoid looking at the cache e.g. for 
8768     // wxNoCellCoords, as this will confuse memory management. 
8771         if ( !LookupAttr(row
, col
, &attr
) ) 
8773             attr 
= m_table 
? m_table
->GetAttr(row
, col 
, wxGridCellAttr::Any
) 
8774                            : (wxGridCellAttr 
*)NULL
; 
8775             CacheAttr(row
, col
, attr
); 
8780         attr
->SetDefAttr(m_defaultCellAttr
); 
8784         attr 
= m_defaultCellAttr
; 
8791 wxGridCellAttr 
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const 
8793     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8795     wxCHECK_MSG( m_table
, attr
, 
8796                   _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") ); 
8798     attr 
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
); 
8801         attr 
= new wxGridCellAttr(m_defaultCellAttr
); 
8803         // artificially inc the ref count to match DecRef() in caller 
8805         m_table
->SetAttr(attr
, row
, col
); 
8811 // ---------------------------------------------------------------------------- 
8812 // setting column attributes (wrappers around SetColAttr) 
8813 // ---------------------------------------------------------------------------- 
8815 void wxGrid::SetColFormatBool(int col
) 
8817     SetColFormatCustom(col
, wxGRID_VALUE_BOOL
); 
8820 void wxGrid::SetColFormatNumber(int col
) 
8822     SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
); 
8825 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
) 
8827     wxString typeName 
= wxGRID_VALUE_FLOAT
; 
8828     if ( (width 
!= -1) || (precision 
!= -1) ) 
8830         typeName 
<< _T(':') << width 
<< _T(',') << precision
; 
8833     SetColFormatCustom(col
, typeName
); 
8836 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
) 
8838     wxGridCellAttr 
*attr 
= (wxGridCellAttr 
*)NULL
; 
8840     attr 
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col 
); 
8842         attr 
= new wxGridCellAttr
; 
8843     wxGridCellRenderer 
*renderer 
= GetDefaultRendererForType(typeName
); 
8844     attr
->SetRenderer(renderer
); 
8846     SetColAttr(col
, attr
); 
8850 // ---------------------------------------------------------------------------- 
8851 // setting cell attributes: this is forwarded to the table 
8852 // ---------------------------------------------------------------------------- 
8854 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr 
*attr
) 
8856     if ( CanHaveAttributes() ) 
8858         m_table
->SetAttr(attr
, row
, col
); 
8867 void wxGrid::SetRowAttr(int row
, wxGridCellAttr 
*attr
) 
8869     if ( CanHaveAttributes() ) 
8871         m_table
->SetRowAttr(attr
, row
); 
8880 void wxGrid::SetColAttr(int col
, wxGridCellAttr 
*attr
) 
8882     if ( CanHaveAttributes() ) 
8884         m_table
->SetColAttr(attr
, col
); 
8893 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour 
) 
8895     if ( CanHaveAttributes() ) 
8897         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8898         attr
->SetBackgroundColour(colour
); 
8903 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour 
) 
8905     if ( CanHaveAttributes() ) 
8907         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8908         attr
->SetTextColour(colour
); 
8913 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font 
) 
8915     if ( CanHaveAttributes() ) 
8917         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8918         attr
->SetFont(font
); 
8923 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert 
) 
8925     if ( CanHaveAttributes() ) 
8927         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8928         attr
->SetAlignment(horiz
, vert
); 
8933 void wxGrid::SetCellOverflow( int row
, int col
, bool allow 
) 
8935     if ( CanHaveAttributes() ) 
8937         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8938         attr
->SetOverflow(allow
); 
8943 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols 
) 
8945     if ( CanHaveAttributes() ) 
8947         int cell_rows
, cell_cols
; 
8949         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
8950         attr
->GetSize(&cell_rows
, &cell_cols
); 
8951         attr
->SetSize(num_rows
, num_cols
); 
8954         // Cannot set the size of a cell to 0 or negative values 
8955         // While it is perfectly legal to do that, this function cannot 
8956         // handle all the possibilies, do it by hand by getting the CellAttr. 
8957         // You can only set the size of a cell to 1,1 or greater with this fn 
8958         wxASSERT_MSG( !((cell_rows 
< 1) || (cell_cols 
< 1)), 
8959                       wxT("wxGrid::SetCellSize setting cell size that is already part of another cell")); 
8960         wxASSERT_MSG( !((num_rows 
< 1) || (num_cols 
< 1)), 
8961                       wxT("wxGrid::SetCellSize setting cell size to < 1")); 
8963         // if this was already a multicell then "turn off" the other cells first 
8964         if ((cell_rows 
> 1) || (cell_rows 
> 1)) 
8967             for (j
=row
; j
<row
+cell_rows
; j
++) 
8969                 for (i
=col
; i
<col
+cell_cols
; i
++) 
8971                     if ((i 
!= col
) || (j 
!= row
)) 
8973                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
8974                         attr_stub
->SetSize( 1, 1 ); 
8975                         attr_stub
->DecRef(); 
8981         // mark the cells that will be covered by this cell to 
8982         // negative or zero values to point back at this cell 
8983         if (((num_rows 
> 1) || (num_cols 
> 1)) && (num_rows 
>= 1) && (num_cols 
>= 1)) 
8986             for (j
=row
; j
<row
+num_rows
; j
++) 
8988                 for (i
=col
; i
<col
+num_cols
; i
++) 
8990                     if ((i 
!= col
) || (j 
!= row
)) 
8992                         wxGridCellAttr 
*attr_stub 
= GetOrCreateCellAttr(j
, i
); 
8993                         attr_stub
->SetSize( row
-j
, col
-i 
); 
8994                         attr_stub
->DecRef(); 
9002 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer 
*renderer
) 
9004     if ( CanHaveAttributes() ) 
9006         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9007         attr
->SetRenderer(renderer
); 
9012 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
) 
9014     if ( CanHaveAttributes() ) 
9016         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9017         attr
->SetEditor(editor
); 
9022 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
) 
9024     if ( CanHaveAttributes() ) 
9026         wxGridCellAttr 
*attr 
= GetOrCreateCellAttr(row
, col
); 
9027         attr
->SetReadOnly(isReadOnly
); 
9032 // ---------------------------------------------------------------------------- 
9033 // Data type registration 
9034 // ---------------------------------------------------------------------------- 
9036 void wxGrid::RegisterDataType(const wxString
& typeName
, 
9037                               wxGridCellRenderer
* renderer
, 
9038                               wxGridCellEditor
* editor
) 
9040     m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
); 
9044 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const 
9046     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9047     return GetDefaultEditorForType(typeName
); 
9050 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const 
9052     wxString typeName 
= m_table
->GetTypeName(row
, col
); 
9053     return GetDefaultRendererForType(typeName
); 
9057 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const 
9059     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9060     if ( index 
== wxNOT_FOUND 
) 
9062         wxFAIL_MSG(wxT("Unknown data type name")); 
9067     return m_typeRegistry
->GetEditor(index
); 
9071 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const 
9073     int index 
= m_typeRegistry
->FindOrCloneDataType(typeName
); 
9074     if ( index 
== wxNOT_FOUND 
) 
9076         wxFAIL_MSG(wxT("Unknown data type name")); 
9081     return m_typeRegistry
->GetRenderer(index
); 
9085 // ---------------------------------------------------------------------------- 
9087 // ---------------------------------------------------------------------------- 
9089 void wxGrid::EnableDragRowSize( bool enable 
) 
9091     m_canDragRowSize 
= enable
; 
9095 void wxGrid::EnableDragColSize( bool enable 
) 
9097     m_canDragColSize 
= enable
; 
9100 void wxGrid::EnableDragGridSize( bool enable 
) 
9102     m_canDragGridSize 
= enable
; 
9106 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows 
) 
9108     m_defaultRowHeight 
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT 
); 
9110     if ( resizeExistingRows 
) 
9112         // since we are resizing all rows to the default row size, 
9113         // we can simply clear the row heights and row bottoms 
9114         // arrays (which also allows us to take advantage of 
9115         // some speed optimisations) 
9116         m_rowHeights
.Empty(); 
9117         m_rowBottoms
.Empty(); 
9118         if ( !GetBatchCount() ) 
9123 void wxGrid::SetRowSize( int row
, int height 
) 
9125     wxCHECK_RET( row 
>= 0 && row 
< m_numRows
, _T("invalid row index") ); 
9127     if ( m_rowHeights
.IsEmpty() ) 
9129         // need to really create the array 
9133     int h 
= wxMax( 0, height 
); 
9134     int diff 
= h 
- m_rowHeights
[row
]; 
9136     m_rowHeights
[row
] = h
; 
9138     for ( i 
= row
;  i 
< m_numRows
;  i
++ ) 
9140         m_rowBottoms
[i
] += diff
; 
9142     if ( !GetBatchCount() ) 
9146 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols 
) 
9148     m_defaultColWidth 
= wxMax( width
, WXGRID_MIN_COL_WIDTH 
); 
9150     if ( resizeExistingCols 
) 
9152         // since we are resizing all columns to the default column size, 
9153         // we can simply clear the col widths and col rights 
9154         // arrays (which also allows us to take advantage of 
9155         // some speed optimisations) 
9156         m_colWidths
.Empty(); 
9157         m_colRights
.Empty(); 
9158         if ( !GetBatchCount() ) 
9163 void wxGrid::SetColSize( int col
, int width 
) 
9165     wxCHECK_RET( col 
>= 0 && col 
< m_numCols
, _T("invalid column index") ); 
9167     // should we check that it's bigger than GetColMinimalWidth(col) here? 
9169     if ( m_colWidths
.IsEmpty() ) 
9171         // need to really create the array 
9175     // DJC MAPTEK if < 0 calc new width from label 
9179       wxArrayString lines
; 
9180       wxClientDC 
dc(m_colLabelWin
); 
9181       dc
.SetFont(GetLabelFont()); 
9182       StringToLines(GetColLabelValue(col
), lines
); 
9183       GetTextBoxSize(dc
, lines
, &w
, &h
); 
9186     int w 
= wxMax( 0, width 
); 
9187     int diff 
= w 
- m_colWidths
[col
]; 
9188     m_colWidths
[col
] = w
; 
9191     for ( i 
= col
;  i 
< m_numCols
;  i
++ ) 
9193         m_colRights
[i
] += diff
; 
9195     if ( !GetBatchCount() ) 
9200 void wxGrid::SetColMinimalWidth( int col
, int width 
) 
9202     m_colMinWidths
.Put(col
, width
); 
9205 void wxGrid::SetRowMinimalHeight( int row
, int width 
) 
9207     m_rowMinHeights
.Put(row
, width
); 
9210 int wxGrid::GetColMinimalWidth(int col
) const 
9212     long value 
= m_colMinWidths
.Get(col
); 
9213     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_COL_WIDTH
; 
9216 int wxGrid::GetRowMinimalHeight(int row
) const 
9218     long value 
= m_rowMinHeights
.Get(row
); 
9219     return value 
!= wxNOT_FOUND 
? (int)value 
: WXGRID_MIN_ROW_HEIGHT
; 
9222 // ---------------------------------------------------------------------------- 
9224 // ---------------------------------------------------------------------------- 
9226 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column 
) 
9228     wxClientDC 
dc(m_gridWin
); 
9230     // init both of them to avoid compiler warnings, even if weo nly need one 
9238     wxCoord extent
, extentMax 
= 0; 
9239     int max 
= column 
? m_numRows 
: m_numCols
; 
9240     for ( int rowOrCol 
= 0; rowOrCol 
< max
; rowOrCol
++ ) 
9247         wxGridCellAttr
* attr 
= GetCellAttr(row
, col
); 
9248         wxGridCellRenderer
* renderer 
= attr
->GetRenderer(this, row
, col
); 
9251             wxSize size 
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
); 
9252             extent 
= column 
? size
.x 
: size
.y
; 
9253             if ( extent 
> extentMax 
) 
9264     // now also compare with the column label extent 
9266     dc
.SetFont( GetLabelFont() ); 
9269         dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h 
); 
9271         dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h 
); 
9273     extent 
= column 
? w 
: h
; 
9274     if ( extent 
> extentMax 
) 
9281         // empty column - give default extent (notice that if extentMax is less 
9282         // than default extent but != 0, it's ok) 
9283         extentMax 
= column 
? m_defaultColWidth 
: m_defaultRowHeight
; 
9289             // leave some space around text 
9300         SetColSize(col
, extentMax
); 
9301         if ( !GetBatchCount() ) 
9304             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9305             wxRect 
rect ( CellToRect( 0, col 
) ); 
9307             CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
); 
9308             rect
.width 
= cw 
- rect
.x
; 
9309             rect
.height 
= m_colLabelHeight
; 
9310             m_colLabelWin
->Refresh( TRUE
, &rect 
); 
9315         SetRowSize(row
, extentMax
); 
9316         if ( !GetBatchCount() ) 
9319             m_gridWin
->GetClientSize( &cw
, &ch 
); 
9320             wxRect 
rect ( CellToRect( row
, 0 ) ); 
9322             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9323             rect
.width 
= m_rowLabelWidth
; 
9324             rect
.height 
= ch 
- rect
.y
; 
9325             m_rowLabelWin
->Refresh( TRUE
, &rect 
); 
9331             SetColMinimalWidth(col
, extentMax
); 
9333             SetRowMinimalHeight(row
, extentMax
); 
9337 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
) 
9339     int width 
= m_rowLabelWidth
; 
9344     for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9348             AutoSizeColumn(col
, setAsMin
); 
9351         width 
+= GetColWidth(col
); 
9360 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
) 
9362     int height 
= m_colLabelHeight
; 
9367     for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9371             AutoSizeRow(row
, setAsMin
); 
9374         height 
+= GetRowHeight(row
); 
9383 void wxGrid::AutoSize() 
9387     wxSize 
size(SetOrCalcColumnSizes(FALSE
), SetOrCalcRowSizes(FALSE
)); 
9389     // round up the size to a multiple of scroll step - this ensures that we 
9390     // won't get the scrollbars if we're sized exactly to this width 
9391     // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary 
9393     wxSize 
sizeFit(GetScrollX(size
.x 
+ m_extraWidth 
+ 1) * GRID_SCROLL_LINE_X
, 
9394                    GetScrollY(size
.y 
+ m_extraHeight 
+ 1) * GRID_SCROLL_LINE_Y
); 
9396     // distribute the extra space between the columns/rows to avoid having 
9397     // extra white space 
9399     // Remove the extra m_extraWidth + 1 added above 
9400     wxCoord diff 
= sizeFit
.x 
- size
.x 
+ (m_extraWidth 
+ 1); 
9401     if ( diff 
&& m_numCols 
) 
9403         // try to resize the columns uniformly 
9404         wxCoord diffPerCol 
= diff 
/ m_numCols
; 
9407             for ( int col 
= 0; col 
< m_numCols
; col
++ ) 
9409                 SetColSize(col
, GetColWidth(col
) + diffPerCol
); 
9413         // add remaining amount to the last columns 
9414         diff 
-= diffPerCol 
* m_numCols
; 
9417             for ( int col 
= m_numCols 
- 1; col 
>= m_numCols 
- diff
; col
-- ) 
9419                 SetColSize(col
, GetColWidth(col
) + 1); 
9425     diff 
= sizeFit
.y 
- size
.y 
- (m_extraHeight 
+ 1); 
9426     if ( diff 
&& m_numRows 
) 
9428         // try to resize the columns uniformly 
9429         wxCoord diffPerRow 
= diff 
/ m_numRows
; 
9432             for ( int row 
= 0; row 
< m_numRows
; row
++ ) 
9434                 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
); 
9438         // add remaining amount to the last rows 
9439         diff 
-= diffPerRow 
* m_numRows
; 
9442             for ( int row 
= m_numRows 
- 1; row 
>= m_numRows 
- diff
; row
-- ) 
9444                 SetRowSize(row
, GetRowHeight(row
) + 1); 
9451     SetClientSize(sizeFit
); 
9454 wxSize 
wxGrid::DoGetBestSize() const 
9456     // don't set sizes, only calculate them 
9457     wxGrid 
*self 
= (wxGrid 
*)this;  // const_cast 
9460     width 
= self
->SetOrCalcColumnSizes(TRUE
); 
9461     height 
= self
->SetOrCalcRowSizes(TRUE
); 
9463     int maxwidth
, maxheight
; 
9464     wxDisplaySize( & maxwidth
, & maxheight 
); 
9466     if ( width 
> maxwidth 
) width 
= maxwidth
; 
9467     if ( height 
> maxheight 
) height 
= maxheight
; 
9469     return wxSize( width
, height 
); 
9478 wxPen
& wxGrid::GetDividerPen() const 
9483 // ---------------------------------------------------------------------------- 
9484 // cell value accessor functions 
9485 // ---------------------------------------------------------------------------- 
9487 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s 
) 
9491         m_table
->SetValue( row
, col
, s 
); 
9492         if ( !GetBatchCount() ) 
9495             wxRect 
rect( CellToRect( row
, col 
) ); 
9497             rect
.width 
= m_gridWin
->GetClientSize().GetWidth(); 
9498             CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
); 
9499             m_gridWin
->Refresh( FALSE
, &rect 
); 
9502         if ( m_currentCellCoords
.GetRow() == row 
&& 
9503              m_currentCellCoords
.GetCol() == col 
&& 
9504              IsCellEditControlShown()) 
9505              // Note: If we are using IsCellEditControlEnabled, 
9506              // this interacts badly with calling SetCellValue from 
9507              // an EVT_GRID_CELL_CHANGE handler. 
9509             HideCellEditControl(); 
9510             ShowCellEditControl(); // will reread data from table 
9517 // ------ Block, row and col selection 
9520 void wxGrid::SelectRow( int row
, bool addToSelected 
) 
9522     if ( IsSelection() && !addToSelected 
) 
9526         m_selection
->SelectRow( row
, FALSE
, addToSelected 
); 
9530 void wxGrid::SelectCol( int col
, bool addToSelected 
) 
9532     if ( IsSelection() && !addToSelected 
) 
9536         m_selection
->SelectCol( col
, FALSE
, addToSelected 
); 
9540 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
, 
9541                           bool addToSelected 
) 
9543     if ( IsSelection() && !addToSelected 
) 
9547         m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
, 
9548                                   FALSE
, addToSelected 
); 
9552 void wxGrid::SelectAll() 
9554     if ( m_numRows 
> 0 && m_numCols 
> 0 ) 
9557             m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 ); 
9562 // ------ Cell, row and col deselection 
9565 void wxGrid::DeselectRow( int row 
) 
9570     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows 
) 
9572         if ( m_selection
->IsInSelection(row
, 0 ) ) 
9573             m_selection
->ToggleCellSelection( row
, 0); 
9577         int nCols 
= GetNumberCols(); 
9578         for ( int i 
= 0; i 
< nCols 
; i
++ ) 
9580             if ( m_selection
->IsInSelection(row
, i 
) ) 
9581                 m_selection
->ToggleCellSelection( row
, i
); 
9586 void wxGrid::DeselectCol( int col 
) 
9591     if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns 
) 
9593         if ( m_selection
->IsInSelection(0, col 
) ) 
9594             m_selection
->ToggleCellSelection( 0, col
); 
9598         int nRows 
= GetNumberRows(); 
9599         for ( int i 
= 0; i 
< nRows 
; i
++ ) 
9601             if ( m_selection
->IsInSelection(i
, col 
) ) 
9602                 m_selection
->ToggleCellSelection(i
, col
); 
9607 void wxGrid::DeselectCell( int row
, int col 
) 
9609     if ( m_selection 
&& m_selection
->IsInSelection(row
, col
) ) 
9610         m_selection
->ToggleCellSelection(row
, col
); 
9613 bool wxGrid::IsSelection() 
9615     return ( m_selection 
&& (m_selection
->IsSelection() || 
9616              ( m_selectingTopLeft 
!= wxGridNoCellCoords 
&& 
9617                m_selectingBottomRight 
!= wxGridNoCellCoords
) ) ); 
9620 bool wxGrid::IsInSelection( int row
, int col 
) const 
9622     return ( m_selection 
&& (m_selection
->IsInSelection( row
, col 
) || 
9623              ( row 
>= m_selectingTopLeft
.GetRow() && 
9624                col 
>= m_selectingTopLeft
.GetCol() && 
9625                row 
<= m_selectingBottomRight
.GetRow() && 
9626                col 
<= m_selectingBottomRight
.GetCol() )) ); 
9629 wxGridCellCoordsArray 
wxGrid::GetSelectedCells() const 
9631     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9632     return m_selection
->m_cellSelection
; 
9634 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockTopLeft() const 
9636     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9637     return m_selection
->m_blockSelectionTopLeft
; 
9639 wxGridCellCoordsArray 
wxGrid::GetSelectionBlockBottomRight() const 
9641     if (!m_selection
) { wxGridCellCoordsArray a
; return a
; } 
9642     return m_selection
->m_blockSelectionBottomRight
; 
9644 wxArrayInt 
wxGrid::GetSelectedRows() const 
9646     if (!m_selection
) { wxArrayInt a
; return a
; } 
9647     return m_selection
->m_rowSelection
; 
9649 wxArrayInt 
wxGrid::GetSelectedCols() const 
9651     if (!m_selection
) { wxArrayInt a
; return a
; } 
9652     return m_selection
->m_colSelection
; 
9656 void wxGrid::ClearSelection() 
9658     m_selectingTopLeft 
= wxGridNoCellCoords
; 
9659     m_selectingBottomRight 
= wxGridNoCellCoords
; 
9661         m_selection
->ClearSelection(); 
9665 // This function returns the rectangle that encloses the given block 
9666 // in device coords clipped to the client size of the grid window. 
9668 wxRect 
wxGrid::BlockToDeviceRect( const wxGridCellCoords 
&topLeft
, 
9669                                   const wxGridCellCoords 
&bottomRight 
) 
9671     wxRect 
rect( wxGridNoCellRect 
); 
9674     cellRect 
= CellToRect( topLeft 
); 
9675     if ( cellRect 
!= wxGridNoCellRect 
) 
9681         rect 
= wxRect( 0, 0, 0, 0 ); 
9684     cellRect 
= CellToRect( bottomRight 
); 
9685     if ( cellRect 
!= wxGridNoCellRect 
) 
9691         return wxGridNoCellRect
; 
9695     int left 
= rect
.GetLeft(); 
9696     int top 
= rect
.GetTop(); 
9697     int right 
= rect
.GetRight(); 
9698     int bottom 
= rect
.GetBottom(); 
9700     int leftCol 
= topLeft
.GetCol(); 
9701     int topRow 
= topLeft
.GetRow(); 
9702     int rightCol 
= bottomRight
.GetCol(); 
9703     int bottomRow 
= bottomRight
.GetRow(); 
9726     for ( j 
= topRow
; j 
<= bottomRow
; j
++ ) 
9728         for ( i 
= leftCol
; i 
<= rightCol
; i
++ ) 
9730             if ((j
==topRow
) || (j
==bottomRow
) || (i
==leftCol
) || (i
==rightCol
)) 
9732                 cellRect 
= CellToRect( j
, i 
); 
9734                 if (cellRect
.x 
< left
) 
9736                 if (cellRect
.y 
< top
) 
9738                 if (cellRect
.x 
+ cellRect
.width 
> right
) 
9739                     right 
= cellRect
.x 
+ cellRect
.width
; 
9740                 if (cellRect
.y 
+ cellRect
.height 
> bottom
) 
9741                     bottom 
= cellRect
.y 
+ cellRect
.height
; 
9743             else i 
= rightCol
; // jump over inner cells. 
9747     // convert to scrolled coords 
9749     CalcScrolledPosition( left
, top
, &left
, &top 
); 
9750     CalcScrolledPosition( right
, bottom
, &right
, &bottom 
); 
9753     m_gridWin
->GetClientSize( &cw
, &ch 
); 
9755     if (right 
< 0 || bottom 
< 0 || left 
> cw 
|| top 
> ch
) 
9756         return wxRect( 0, 0, 0, 0); 
9758     rect
.SetLeft( wxMax(0, left
) ); 
9759     rect
.SetTop( wxMax(0, top
) ); 
9760     rect
.SetRight( wxMin(cw
, right
) ); 
9761     rect
.SetBottom( wxMin(ch
, bottom
) ); 
9769 // ------ Grid event classes 
9772 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent 
) 
9774 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
, 
9775                           int row
, int col
, int x
, int y
, bool sel
, 
9776                           bool control
, bool shift
, bool alt
, bool meta 
) 
9777         : wxNotifyEvent( type
, id 
) 
9784     m_control 
= control
; 
9789     SetEventObject(obj
); 
9793 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent 
) 
9795 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
, 
9796                                   int rowOrCol
, int x
, int y
, 
9797                                   bool control
, bool shift
, bool alt
, bool meta 
) 
9798         : wxNotifyEvent( type
, id 
) 
9800     m_rowOrCol 
= rowOrCol
; 
9803     m_control 
= control
; 
9808     SetEventObject(obj
); 
9812 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent 
) 
9814 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
, 
9815                                                const wxGridCellCoords
& topLeft
, 
9816                                                const wxGridCellCoords
& bottomRight
, 
9817                                                bool sel
, bool control
, 
9818                                                bool shift
, bool alt
, bool meta 
) 
9819         : wxNotifyEvent( type
, id 
) 
9821     m_topLeft     
= topLeft
; 
9822     m_bottomRight 
= bottomRight
; 
9824     m_control     
= control
; 
9829     SetEventObject(obj
); 
9833 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
) 
9835 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
, 
9836                                                    wxObject
* obj
, int row
, 
9837                                                    int col
, wxControl
* ctrl
) 
9838     : wxCommandEvent(type
, id
) 
9840     SetEventObject(obj
); 
9847 #endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID 
9849 #endif // wxUSE_GRID