1 ///////////////////////////////////////////////////////////////////////////
2 // Name: generic/grid.cpp
3 // Purpose: wxGrid and related classes
4 // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
5 // Modified by: Robin Dunn, Vadim Zeitlin
8 // Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "grid.h"
24 // For compilers that support precompilatixon, includes "wx/wx.h".
25 #include "wx/wxprec.h"
37 #include "wx/dcclient.h"
38 #include "wx/settings.h"
40 #include "wx/textctrl.h"
41 #include "wx/checkbox.h"
42 #include "wx/combobox.h"
43 #include "wx/valtext.h"
47 #include "wx/textfile.h"
48 #include "wx/spinctrl.h"
49 #include "wx/tokenzr.h"
52 #include "wx/generic/gridsel.h"
54 #if defined(__WXMOTIF__)
55 #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)
57 #define WXUNUSED_MOTIF(identifier) identifier
60 #if defined(__WXGTK__)
61 #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)
63 #define WXUNUSED_GTK(identifier) identifier
66 // Required for wxIs... functions
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridCellAttr
*, wxArrayAttrs
,
74 class WXDLLIMPEXP_ADV
);
76 struct wxGridCellWithAttr
78 wxGridCellWithAttr(int row
, int col
, wxGridCellAttr
*attr_
)
79 : coords(row
, col
), attr(attr_
)
88 wxGridCellCoords coords
;
92 // DECLARE_NO_COPY_CLASS(wxGridCellWithAttr)
93 // without rewriting the macros, which require a public copy constructor.
96 WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr
, wxGridCellWithAttrArray
,
97 class WXDLLIMPEXP_ADV
);
99 #include "wx/arrimpl.cpp"
101 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
)
102 WX_DEFINE_OBJARRAY(wxGridCellWithAttrArray
)
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_CLICK
)
109 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_CLICK
)
110 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_LEFT_DCLICK
)
111 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_RIGHT_DCLICK
)
112 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_BEGIN_DRAG
)
113 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_CLICK
)
114 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_CLICK
)
115 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_LEFT_DCLICK
)
116 DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK
)
117 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE
)
118 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE
)
119 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT
)
120 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE
)
121 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL
)
122 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_SHOWN
)
123 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_HIDDEN
)
124 DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED
)
126 // ----------------------------------------------------------------------------
128 // ----------------------------------------------------------------------------
130 class WXDLLIMPEXP_ADV wxGridRowLabelWindow
: public wxWindow
133 wxGridRowLabelWindow() { m_owner
= (wxGrid
*)NULL
; }
134 wxGridRowLabelWindow( wxGrid
*parent
, wxWindowID id
,
135 const wxPoint
&pos
, const wxSize
&size
);
140 void OnPaint( wxPaintEvent
& event
);
141 void OnMouseEvent( wxMouseEvent
& event
);
142 void OnMouseWheel( wxMouseEvent
& event
);
143 void OnKeyDown( wxKeyEvent
& event
);
144 void OnKeyUp( wxKeyEvent
& );
146 DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow
)
147 DECLARE_EVENT_TABLE()
148 DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow
)
152 class WXDLLIMPEXP_ADV wxGridColLabelWindow
: public wxWindow
155 wxGridColLabelWindow() { m_owner
= (wxGrid
*)NULL
; }
156 wxGridColLabelWindow( wxGrid
*parent
, wxWindowID id
,
157 const wxPoint
&pos
, const wxSize
&size
);
162 void OnPaint( wxPaintEvent
&event
);
163 void OnMouseEvent( wxMouseEvent
& event
);
164 void OnMouseWheel( wxMouseEvent
& event
);
165 void OnKeyDown( wxKeyEvent
& event
);
166 void OnKeyUp( wxKeyEvent
& );
168 DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow
)
169 DECLARE_EVENT_TABLE()
170 DECLARE_NO_COPY_CLASS(wxGridColLabelWindow
)
174 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow
: public wxWindow
177 wxGridCornerLabelWindow() { m_owner
= (wxGrid
*)NULL
; }
178 wxGridCornerLabelWindow( wxGrid
*parent
, wxWindowID id
,
179 const wxPoint
&pos
, const wxSize
&size
);
184 void OnMouseEvent( wxMouseEvent
& event
);
185 void OnMouseWheel( wxMouseEvent
& event
);
186 void OnKeyDown( wxKeyEvent
& event
);
187 void OnKeyUp( wxKeyEvent
& );
188 void OnPaint( wxPaintEvent
& event
);
190 DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow
)
191 DECLARE_EVENT_TABLE()
192 DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow
)
195 class WXDLLIMPEXP_ADV wxGridWindow
: public wxWindow
200 m_owner
= (wxGrid
*)NULL
;
201 m_rowLabelWin
= (wxGridRowLabelWindow
*)NULL
;
202 m_colLabelWin
= (wxGridColLabelWindow
*)NULL
;
205 wxGridWindow( wxGrid
*parent
,
206 wxGridRowLabelWindow
*rowLblWin
,
207 wxGridColLabelWindow
*colLblWin
,
208 wxWindowID id
, const wxPoint
&pos
, const wxSize
&size
);
211 void ScrollWindow( int dx
, int dy
, const wxRect
*rect
);
213 wxGrid
* GetOwner() { return m_owner
; }
217 wxGridRowLabelWindow
*m_rowLabelWin
;
218 wxGridColLabelWindow
*m_colLabelWin
;
220 void OnPaint( wxPaintEvent
&event
);
221 void OnMouseWheel( wxMouseEvent
& event
);
222 void OnMouseEvent( wxMouseEvent
& event
);
223 void OnKeyDown( wxKeyEvent
& );
224 void OnKeyUp( wxKeyEvent
& );
225 void OnEraseBackground( wxEraseEvent
& );
226 void OnFocus( wxFocusEvent
& );
228 DECLARE_DYNAMIC_CLASS(wxGridWindow
)
229 DECLARE_EVENT_TABLE()
230 DECLARE_NO_COPY_CLASS(wxGridWindow
)
235 class wxGridCellEditorEvtHandler
: public wxEvtHandler
238 wxGridCellEditorEvtHandler()
239 : m_grid(0), m_editor(0)
241 wxGridCellEditorEvtHandler(wxGrid
* grid
, wxGridCellEditor
* editor
)
242 : m_grid(grid
), m_editor(editor
)
245 void OnKeyDown(wxKeyEvent
& event
);
246 void OnChar(wxKeyEvent
& event
);
250 wxGridCellEditor
* m_editor
;
251 DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler
)
252 DECLARE_EVENT_TABLE()
253 DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler
)
257 IMPLEMENT_DYNAMIC_CLASS( wxGridCellEditorEvtHandler
, wxEvtHandler
)
258 BEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler
, wxEvtHandler
)
259 EVT_KEY_DOWN( wxGridCellEditorEvtHandler::OnKeyDown
)
260 EVT_CHAR( wxGridCellEditorEvtHandler::OnChar
)
265 // ----------------------------------------------------------------------------
266 // the internal data representation used by wxGridCellAttrProvider
267 // ----------------------------------------------------------------------------
269 // this class stores attributes set for cells
270 class WXDLLIMPEXP_ADV wxGridCellAttrData
273 void SetAttr(wxGridCellAttr
*attr
, int row
, int col
);
274 wxGridCellAttr
*GetAttr(int row
, int col
) const;
275 void UpdateAttrRows( size_t pos
, int numRows
);
276 void UpdateAttrCols( size_t pos
, int numCols
);
279 // searches for the attr for given cell, returns wxNOT_FOUND if not found
280 int FindIndex(int row
, int col
) const;
282 wxGridCellWithAttrArray m_attrs
;
285 // this class stores attributes set for rows or columns
286 class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
289 // empty ctor to suppress warnings
290 wxGridRowOrColAttrData() { }
291 ~wxGridRowOrColAttrData();
293 void SetAttr(wxGridCellAttr
*attr
, int rowOrCol
);
294 wxGridCellAttr
*GetAttr(int rowOrCol
) const;
295 void UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols
);
298 wxArrayInt m_rowsOrCols
;
299 wxArrayAttrs m_attrs
;
302 // NB: this is just a wrapper around 3 objects: one which stores cell
303 // attributes, and 2 others for row/col ones
304 class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
307 wxGridCellAttrData m_cellAttrs
;
308 wxGridRowOrColAttrData m_rowAttrs
,
313 // ----------------------------------------------------------------------------
314 // data structures used for the data type registry
315 // ----------------------------------------------------------------------------
317 struct wxGridDataTypeInfo
319 wxGridDataTypeInfo(const wxString
& typeName
,
320 wxGridCellRenderer
* renderer
,
321 wxGridCellEditor
* editor
)
322 : m_typeName(typeName
), m_renderer(renderer
), m_editor(editor
)
325 ~wxGridDataTypeInfo()
327 wxSafeDecRef(m_renderer
);
328 wxSafeDecRef(m_editor
);
332 wxGridCellRenderer
* m_renderer
;
333 wxGridCellEditor
* m_editor
;
335 DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo
)
339 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo
*, wxGridDataTypeInfoArray
,
340 class WXDLLIMPEXP_ADV
);
343 class WXDLLIMPEXP_ADV wxGridTypeRegistry
346 wxGridTypeRegistry() {}
347 ~wxGridTypeRegistry();
349 void RegisterDataType(const wxString
& typeName
,
350 wxGridCellRenderer
* renderer
,
351 wxGridCellEditor
* editor
);
353 // find one of already registered data types
354 int FindRegisteredDataType(const wxString
& typeName
);
356 // try to FindRegisteredDataType(), if this fails and typeName is one of
357 // standard typenames, register it and return its index
358 int FindDataType(const wxString
& typeName
);
360 // try to FindDataType(), if it fails see if it is not one of already
361 // registered data types with some params in which case clone the
362 // registered data type and set params for it
363 int FindOrCloneDataType(const wxString
& typeName
);
365 wxGridCellRenderer
* GetRenderer(int index
);
366 wxGridCellEditor
* GetEditor(int index
);
369 wxGridDataTypeInfoArray m_typeinfo
;
372 // ----------------------------------------------------------------------------
373 // conditional compilation
374 // ----------------------------------------------------------------------------
376 #ifndef WXGRID_DRAW_LINES
377 #define WXGRID_DRAW_LINES 1
380 // ----------------------------------------------------------------------------
382 // ----------------------------------------------------------------------------
384 //#define DEBUG_ATTR_CACHE
385 #ifdef DEBUG_ATTR_CACHE
386 static size_t gs_nAttrCacheHits
= 0;
387 static size_t gs_nAttrCacheMisses
= 0;
388 #endif // DEBUG_ATTR_CACHE
390 // ----------------------------------------------------------------------------
392 // ----------------------------------------------------------------------------
394 wxGridCellCoords
wxGridNoCellCoords( -1, -1 );
395 wxRect
wxGridNoCellRect( -1, -1, -1, -1 );
398 // TODO: this doesn't work at all, grid cells have different sizes and approx
399 // calculations don't work as because of the size mismatch scrollbars
400 // sometimes fail to be shown when they should be or vice versa
402 // The scroll bars may be a little flakey once in a while, but that is
403 // surely much less horrible than having scroll lines of only 1!!!
406 // Well, it's still seriously broken so it might be better but needs
409 static const size_t GRID_SCROLL_LINE_X
= 15; // 1;
410 static const size_t GRID_SCROLL_LINE_Y
= GRID_SCROLL_LINE_X
;
412 // the size of hash tables used a bit everywhere (the max number of elements
413 // in these hash tables is the number of rows/columns)
414 static const int GRID_HASH_SIZE
= 100;
417 // ----------------------------------------------------------------------------
419 // ----------------------------------------------------------------------------
421 static inline int GetScrollX(int x
)
423 return (x
+ GRID_SCROLL_LINE_X
- 1) / GRID_SCROLL_LINE_X
;
426 static inline int GetScrollY(int y
)
428 return (y
+ GRID_SCROLL_LINE_Y
- 1) / GRID_SCROLL_LINE_Y
;
432 // ============================================================================
434 // ============================================================================
436 // ----------------------------------------------------------------------------
438 // ----------------------------------------------------------------------------
440 wxGridCellEditor::wxGridCellEditor()
447 wxGridCellEditor::~wxGridCellEditor()
452 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
),
453 wxWindowID
WXUNUSED(id
),
454 wxEvtHandler
* evtHandler
)
457 m_control
->PushEventHandler(evtHandler
);
460 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
,
461 wxGridCellAttr
*attr
)
463 // erase the background because we might not fill the cell
464 wxClientDC
dc(m_control
->GetParent());
465 wxGridWindow
* gridWindow
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
);
467 gridWindow
->GetOwner()->PrepareDC(dc
);
469 dc
.SetPen(*wxTRANSPARENT_PEN
);
470 dc
.SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
));
471 dc
.DrawRectangle(rectCell
);
473 // redraw the control we just painted over
474 m_control
->Refresh();
477 void wxGridCellEditor::Destroy()
481 m_control
->PopEventHandler(true /* delete it*/);
483 m_control
->Destroy();
488 void wxGridCellEditor::Show(bool show
, wxGridCellAttr
*attr
)
490 wxASSERT_MSG(m_control
,
491 wxT("The wxGridCellEditor must be Created first!"));
492 m_control
->Show(show
);
496 // set the colours/fonts if we have any
499 m_colFgOld
= m_control
->GetForegroundColour();
500 m_control
->SetForegroundColour(attr
->GetTextColour());
502 m_colBgOld
= m_control
->GetBackgroundColour();
503 m_control
->SetBackgroundColour(attr
->GetBackgroundColour());
505 // Workaround for GTK+1 font setting problem on some platforms
506 #if !defined(__WXGTK__) || defined(__WXGTK20__)
507 m_fontOld
= m_control
->GetFont();
508 m_control
->SetFont(attr
->GetFont());
510 // can't do anything more in the base class version, the other
511 // attributes may only be used by the derived classes
516 // restore the standard colours fonts
517 if ( m_colFgOld
.Ok() )
519 m_control
->SetForegroundColour(m_colFgOld
);
520 m_colFgOld
= wxNullColour
;
523 if ( m_colBgOld
.Ok() )
525 m_control
->SetBackgroundColour(m_colBgOld
);
526 m_colBgOld
= wxNullColour
;
528 // Workaround for GTK+1 font setting problem on some platforms
529 #if !defined(__WXGTK__) || defined(__WXGTK20__)
530 if ( m_fontOld
.Ok() )
532 m_control
->SetFont(m_fontOld
);
533 m_fontOld
= wxNullFont
;
539 void wxGridCellEditor::SetSize(const wxRect
& rect
)
541 wxASSERT_MSG(m_control
,
542 wxT("The wxGridCellEditor must be Created first!"));
543 m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
);
546 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
)
551 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
)
553 // accept the simple key presses, not anything with Ctrl/Alt/Meta
554 return !(event
.ControlDown() || event
.AltDown());
557 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
)
562 void wxGridCellEditor::StartingClick()
568 // ----------------------------------------------------------------------------
569 // wxGridCellTextEditor
570 // ----------------------------------------------------------------------------
572 wxGridCellTextEditor::wxGridCellTextEditor()
577 void wxGridCellTextEditor::Create(wxWindow
* parent
,
579 wxEvtHandler
* evtHandler
)
581 m_control
= new wxTextCtrl(parent
, id
, wxEmptyString
,
582 wxDefaultPosition
, wxDefaultSize
583 #if defined(__WXMSW__)
584 , wxTE_PROCESS_TAB
| wxTE_AUTO_SCROLL
588 // set max length allowed in the textctrl, if the parameter was set
591 ((wxTextCtrl
*)m_control
)->SetMaxLength(m_maxChars
);
594 wxGridCellEditor::Create(parent
, id
, evtHandler
);
597 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
),
598 wxGridCellAttr
* WXUNUSED(attr
))
600 // as we fill the entire client area, don't do anything here to minimize
604 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
)
606 wxRect
rect(rectOrig
);
608 // Make the edit control large enough to allow for internal
611 // TODO: remove this if the text ctrl sizing is improved esp. for
614 #if defined(__WXGTK__)
623 int extra_x
= ( rect
.x
> 2 )? 2 : 1;
625 // MB: treat MSW separately here otherwise the caret doesn't show
626 // when the editor is in the first row.
627 #if defined(__WXMSW__)
630 int extra_y
= ( rect
.y
> 2 )? 2 : 1;
633 #if defined(__WXMOTIF__)
637 rect
.SetLeft( wxMax(0, rect
.x
- extra_x
) );
638 rect
.SetTop( wxMax(0, rect
.y
- extra_y
) );
639 rect
.SetRight( rect
.GetRight() + 2*extra_x
);
640 rect
.SetBottom( rect
.GetBottom() + 2*extra_y
);
643 wxGridCellEditor::SetSize(rect
);
646 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
648 wxASSERT_MSG(m_control
,
649 wxT("The wxGridCellEditor must be Created first!"));
651 m_startValue
= grid
->GetTable()->GetValue(row
, col
);
653 DoBeginEdit(m_startValue
);
656 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
)
658 Text()->SetValue(startValue
);
659 Text()->SetInsertionPointEnd();
660 Text()->SetSelection(-1,-1);
664 bool wxGridCellTextEditor::EndEdit(int row
, int col
,
667 wxASSERT_MSG(m_control
,
668 wxT("The wxGridCellEditor must be Created first!"));
670 bool changed
= false;
671 wxString value
= Text()->GetValue();
672 if (value
!= m_startValue
)
676 grid
->GetTable()->SetValue(row
, col
, value
);
678 m_startValue
= wxEmptyString
;
679 // No point in setting the text of the hidden control
680 //Text()->SetValue(m_startValue);
686 void wxGridCellTextEditor::Reset()
688 wxASSERT_MSG(m_control
,
689 wxT("The wxGridCellEditor must be Created first!"));
691 DoReset(m_startValue
);
694 void wxGridCellTextEditor::DoReset(const wxString
& startValue
)
696 Text()->SetValue(startValue
);
697 Text()->SetInsertionPointEnd();
700 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
)
702 if ( wxGridCellEditor::IsAcceptedKey(event
) )
704 int keycode
= event
.GetKeyCode();
718 case WXK_NUMPAD_MULTIPLY
:
722 case WXK_NUMPAD_SUBTRACT
:
724 case WXK_NUMPAD_DECIMAL
:
726 case WXK_NUMPAD_DIVIDE
:
730 // accept 8 bit chars too if isprint() agrees
731 if ( (keycode
< 255) && (wxIsprint(keycode
)) )
739 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
)
741 if ( !Text()->EmulateKeyPress(event
) )
747 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
&
748 WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) )
750 #if defined(__WXMOTIF__) || defined(__WXGTK__)
751 // wxMotif needs a little extra help...
752 size_t pos
= (size_t)( Text()->GetInsertionPoint() );
753 wxString
s( Text()->GetValue() );
754 s
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
);
756 Text()->SetInsertionPoint( pos
);
758 // the other ports can handle a Return key press
764 void wxGridCellTextEditor::SetParameters(const wxString
& params
)
774 if ( !params
.ToLong(&tmp
) )
776 wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str());
780 m_maxChars
= (size_t)tmp
;
785 // return the value in the text control
786 wxString
wxGridCellTextEditor::GetValue() const
788 return Text()->GetValue();
791 // ----------------------------------------------------------------------------
792 // wxGridCellNumberEditor
793 // ----------------------------------------------------------------------------
795 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
)
801 void wxGridCellNumberEditor::Create(wxWindow
* parent
,
803 wxEvtHandler
* evtHandler
)
807 // create a spin ctrl
808 m_control
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
,
809 wxDefaultPosition
, wxDefaultSize
,
813 wxGridCellEditor::Create(parent
, id
, evtHandler
);
817 // just a text control
818 wxGridCellTextEditor::Create(parent
, id
, evtHandler
);
821 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
));
822 #endif // wxUSE_VALIDATORS
826 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
828 // first get the value
829 wxGridTableBase
*table
= grid
->GetTable();
830 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
832 m_valueOld
= table
->GetValueAsLong(row
, col
);
837 wxString sValue
= table
->GetValue(row
, col
);
838 if (! sValue
.ToLong(&m_valueOld
) && ! sValue
.IsEmpty())
840 wxFAIL_MSG( _T("this cell doesn't have numeric value") );
847 Spin()->SetValue((int)m_valueOld
);
852 DoBeginEdit(GetString());
856 bool wxGridCellNumberEditor::EndEdit(int row
, int col
,
865 value
= Spin()->GetValue();
866 changed
= value
!= m_valueOld
;
868 text
= wxString::Format(wxT("%ld"), value
);
872 text
= Text()->GetValue();
873 changed
= (text
.IsEmpty() || text
.ToLong(&value
)) && (value
!= m_valueOld
);
878 if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
))
879 grid
->GetTable()->SetValueAsLong(row
, col
, value
);
881 grid
->GetTable()->SetValue(row
, col
, text
);
887 void wxGridCellNumberEditor::Reset()
891 Spin()->SetValue((int)m_valueOld
);
895 DoReset(GetString());
899 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
)
901 if ( wxGridCellEditor::IsAcceptedKey(event
) )
903 int keycode
= event
.GetKeyCode();
919 case WXK_NUMPAD_SUBTRACT
:
925 if ( (keycode
< 128) && wxIsdigit(keycode
) )
933 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
)
937 int keycode
= event
.GetKeyCode();
938 if ( wxIsdigit(keycode
) || keycode
== '+' || keycode
== '-'
939 || keycode
== WXK_NUMPAD0
940 || keycode
== WXK_NUMPAD1
941 || keycode
== WXK_NUMPAD2
942 || keycode
== WXK_NUMPAD3
943 || keycode
== WXK_NUMPAD4
944 || keycode
== WXK_NUMPAD5
945 || keycode
== WXK_NUMPAD6
946 || keycode
== WXK_NUMPAD7
947 || keycode
== WXK_NUMPAD8
948 || keycode
== WXK_NUMPAD9
949 || keycode
== WXK_ADD
950 || keycode
== WXK_NUMPAD_ADD
951 || keycode
== WXK_SUBTRACT
952 || keycode
== WXK_NUMPAD_SUBTRACT
)
954 wxGridCellTextEditor::StartingKey(event
);
964 void wxGridCellNumberEditor::SetParameters(const wxString
& params
)
975 if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) )
979 if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) )
983 // skip the error message below
988 wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str());
992 // return the value in the spin control if it is there (the text control otherwise)
993 wxString
wxGridCellNumberEditor::GetValue() const
999 long value
= Spin()->GetValue();
1000 s
.Printf(wxT("%ld"), value
);
1004 s
= Text()->GetValue();
1009 // ----------------------------------------------------------------------------
1010 // wxGridCellFloatEditor
1011 // ----------------------------------------------------------------------------
1013 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
)
1016 m_precision
= precision
;
1019 void wxGridCellFloatEditor::Create(wxWindow
* parent
,
1021 wxEvtHandler
* evtHandler
)
1023 wxGridCellTextEditor::Create(parent
, id
, evtHandler
);
1025 #if wxUSE_VALIDATORS
1026 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
));
1027 #endif // wxUSE_VALIDATORS
1030 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1032 // first get the value
1033 wxGridTableBase
*table
= grid
->GetTable();
1034 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) )
1036 m_valueOld
= table
->GetValueAsDouble(row
, col
);
1041 wxString sValue
= table
->GetValue(row
, col
);
1042 if (! sValue
.ToDouble(&m_valueOld
) && ! sValue
.IsEmpty())
1044 wxFAIL_MSG( _T("this cell doesn't have float value") );
1049 DoBeginEdit(GetString());
1052 bool wxGridCellFloatEditor::EndEdit(int row
, int col
,
1056 wxString
text(Text()->GetValue());
1058 if ( (text
.IsEmpty() || text
.ToDouble(&value
)) && (value
!= m_valueOld
) )
1060 if (grid
->GetTable()->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
))
1061 grid
->GetTable()->SetValueAsDouble(row
, col
, value
);
1063 grid
->GetTable()->SetValue(row
, col
, text
);
1070 void wxGridCellFloatEditor::Reset()
1072 DoReset(GetString());
1075 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
)
1077 int keycode
= event
.GetKeyCode();
1079 tmpbuf
[0] = (char) keycode
;
1081 wxString
strbuf(tmpbuf
, *wxConvCurrent
);
1082 bool is_decimal_point
= ( strbuf
==
1083 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) );
1084 if ( wxIsdigit(keycode
) || keycode
== '+' || keycode
== '-'
1086 || keycode
== WXK_NUMPAD0
1087 || keycode
== WXK_NUMPAD1
1088 || keycode
== WXK_NUMPAD2
1089 || keycode
== WXK_NUMPAD3
1090 || keycode
== WXK_NUMPAD4
1091 || keycode
== WXK_NUMPAD5
1092 || keycode
== WXK_NUMPAD6
1093 || keycode
== WXK_NUMPAD7
1094 || keycode
== WXK_NUMPAD8
1095 || keycode
== WXK_NUMPAD9
1096 || keycode
== WXK_ADD
1097 || keycode
== WXK_NUMPAD_ADD
1098 || keycode
== WXK_SUBTRACT
1099 || keycode
== WXK_NUMPAD_SUBTRACT
)
1101 wxGridCellTextEditor::StartingKey(event
);
1103 // skip Skip() below
1110 void wxGridCellFloatEditor::SetParameters(const wxString
& params
)
1121 if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) )
1125 if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) )
1127 m_precision
= (int)tmp
;
1129 // skip the error message below
1134 wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str());
1138 wxString
wxGridCellFloatEditor::GetString() const
1141 if ( m_width
== -1 )
1143 // default width/precision
1146 else if ( m_precision
== -1 )
1148 // default precision
1149 fmt
.Printf(_T("%%%d.f"), m_width
);
1153 fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
);
1156 return wxString::Format(fmt
, m_valueOld
);
1159 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
)
1161 if ( wxGridCellEditor::IsAcceptedKey(event
) )
1163 int keycode
= event
.GetKeyCode();
1177 case WXK_NUMPAD_ADD
:
1179 case WXK_NUMPAD_SUBTRACT
:
1181 case WXK_NUMPAD_DECIMAL
:
1186 // additionally accept 'e' as in '1e+6', also '-', '+', and '.'
1188 tmpbuf
[0] = (char) keycode
;
1190 wxString
strbuf(tmpbuf
, *wxConvCurrent
);
1191 bool is_decimal_point
=
1192 ( strbuf
== wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
,
1193 wxLOCALE_CAT_NUMBER
) );
1194 if ( (keycode
< 128) &&
1195 (wxIsdigit(keycode
) || tolower(keycode
) == 'e' ||
1196 is_decimal_point
|| keycode
== '+' || keycode
== '-') )
1205 #endif // wxUSE_TEXTCTRL
1209 // ----------------------------------------------------------------------------
1210 // wxGridCellBoolEditor
1211 // ----------------------------------------------------------------------------
1213 void wxGridCellBoolEditor::Create(wxWindow
* parent
,
1215 wxEvtHandler
* evtHandler
)
1217 m_control
= new wxCheckBox(parent
, id
, wxEmptyString
,
1218 wxDefaultPosition
, wxDefaultSize
,
1221 wxGridCellEditor::Create(parent
, id
, evtHandler
);
1224 void wxGridCellBoolEditor::SetSize(const wxRect
& r
)
1226 bool resize
= false;
1227 wxSize size
= m_control
->GetSize();
1228 wxCoord minSize
= wxMin(r
.width
, r
.height
);
1230 // check if the checkbox is not too big/small for this cell
1231 wxSize sizeBest
= m_control
->GetBestSize();
1232 if ( !(size
== sizeBest
) )
1234 // reset to default size if it had been made smaller
1240 if ( size
.x
>= minSize
|| size
.y
>= minSize
)
1242 // leave 1 pixel margin
1243 size
.x
= size
.y
= minSize
- 2;
1250 m_control
->SetSize(size
);
1253 // position it in the centre of the rectangle (TODO: support alignment?)
1255 #if defined(__WXGTK__) || defined (__WXMOTIF__)
1256 // the checkbox without label still has some space to the right in wxGTK,
1257 // so shift it to the right
1259 #elif defined(__WXMSW__)
1260 // here too, but in other way
1265 int hAlign
= wxALIGN_CENTRE
;
1266 int vAlign
= wxALIGN_CENTRE
;
1268 GetCellAttr()->GetAlignment(& hAlign
, & vAlign
);
1271 if (hAlign
== wxALIGN_LEFT
)
1277 y
= r
.y
+ r
.height
/2 - size
.y
/2;
1279 else if (hAlign
== wxALIGN_RIGHT
)
1281 x
= r
.x
+ r
.width
- size
.x
- 2;
1282 y
= r
.y
+ r
.height
/2 - size
.y
/2;
1284 else if (hAlign
== wxALIGN_CENTRE
)
1286 x
= r
.x
+ r
.width
/2 - size
.x
/2;
1287 y
= r
.y
+ r
.height
/2 - size
.y
/2;
1290 m_control
->Move(x
, y
);
1293 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr
*attr
)
1295 m_control
->Show(show
);
1299 wxColour colBg
= attr
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
;
1300 CBox()->SetBackgroundColour(colBg
);
1304 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1306 wxASSERT_MSG(m_control
,
1307 wxT("The wxGridCellEditor must be Created first!"));
1309 if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
))
1310 m_startValue
= grid
->GetTable()->GetValueAsBool(row
, col
);
1313 wxString
cellval( grid
->GetTable()->GetValue(row
, col
) );
1314 m_startValue
= !( !cellval
|| (cellval
== wxT("0")) );
1316 CBox()->SetValue(m_startValue
);
1320 bool wxGridCellBoolEditor::EndEdit(int row
, int col
,
1323 wxASSERT_MSG(m_control
,
1324 wxT("The wxGridCellEditor must be Created first!"));
1326 bool changed
= false;
1327 bool value
= CBox()->GetValue();
1328 if ( value
!= m_startValue
)
1333 if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
))
1334 grid
->GetTable()->SetValueAsBool(row
, col
, value
);
1336 grid
->GetTable()->SetValue(row
, col
, value
? _T("1") : wxEmptyString
);
1342 void wxGridCellBoolEditor::Reset()
1344 wxASSERT_MSG(m_control
,
1345 wxT("The wxGridCellEditor must be Created first!"));
1347 CBox()->SetValue(m_startValue
);
1350 void wxGridCellBoolEditor::StartingClick()
1352 CBox()->SetValue(!CBox()->GetValue());
1355 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
)
1357 if ( wxGridCellEditor::IsAcceptedKey(event
) )
1359 int keycode
= event
.GetKeyCode();
1363 case WXK_NUMPAD_MULTIPLY
:
1365 case WXK_NUMPAD_ADD
:
1367 case WXK_NUMPAD_SUBTRACT
:
1378 // return the value as "1" for true and the empty string for false
1379 wxString
wxGridCellBoolEditor::GetValue() const
1381 bool bSet
= CBox()->GetValue();
1382 return bSet
? _T("1") : wxEmptyString
;
1385 #endif // wxUSE_CHECKBOX
1389 // ----------------------------------------------------------------------------
1390 // wxGridCellChoiceEditor
1391 // ----------------------------------------------------------------------------
1393 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
,
1395 : m_choices(choices
),
1396 m_allowOthers(allowOthers
) { }
1398 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
,
1399 const wxString choices
[],
1401 : m_allowOthers(allowOthers
)
1405 m_choices
.Alloc(count
);
1406 for ( size_t n
= 0; n
< count
; n
++ )
1408 m_choices
.Add(choices
[n
]);
1413 wxGridCellEditor
*wxGridCellChoiceEditor::Clone() const
1415 wxGridCellChoiceEditor
*editor
= new wxGridCellChoiceEditor
;
1416 editor
->m_allowOthers
= m_allowOthers
;
1417 editor
->m_choices
= m_choices
;
1422 void wxGridCellChoiceEditor::Create(wxWindow
* parent
,
1424 wxEvtHandler
* evtHandler
)
1426 m_control
= new wxComboBox(parent
, id
, wxEmptyString
,
1427 wxDefaultPosition
, wxDefaultSize
,
1429 m_allowOthers
? 0 : wxCB_READONLY
);
1431 wxGridCellEditor::Create(parent
, id
, evtHandler
);
1434 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
,
1435 wxGridCellAttr
* attr
)
1437 // as we fill the entire client area, don't do anything here to minimize
1440 // TODO: It doesn't actually fill the client area since the height of a
1441 // combo always defaults to the standard... Until someone has time to
1442 // figure out the right rectangle to paint, just do it the normal way...
1443 wxGridCellEditor::PaintBackground(rectCell
, attr
);
1446 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1448 wxASSERT_MSG(m_control
,
1449 wxT("The wxGridCellEditor must be Created first!"));
1451 m_startValue
= grid
->GetTable()->GetValue(row
, col
);
1454 Combo()->SetValue(m_startValue
);
1457 // find the right position, or default to the first if not found
1458 int pos
= Combo()->FindString(m_startValue
);
1461 Combo()->SetSelection(pos
);
1463 Combo()->SetInsertionPointEnd();
1464 Combo()->SetFocus();
1467 bool wxGridCellChoiceEditor::EndEdit(int row
, int col
,
1470 wxString value
= Combo()->GetValue();
1471 if ( value
== m_startValue
)
1474 grid
->GetTable()->SetValue(row
, col
, value
);
1479 void wxGridCellChoiceEditor::Reset()
1481 Combo()->SetValue(m_startValue
);
1482 Combo()->SetInsertionPointEnd();
1485 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
)
1495 wxStringTokenizer
tk(params
, _T(','));
1496 while ( tk
.HasMoreTokens() )
1498 m_choices
.Add(tk
.GetNextToken());
1502 // return the value in the text control
1503 wxString
wxGridCellChoiceEditor::GetValue() const
1505 return Combo()->GetValue();
1508 #endif // wxUSE_COMBOBOX
1510 // ----------------------------------------------------------------------------
1511 // wxGridCellEditorEvtHandler
1512 // ----------------------------------------------------------------------------
1514 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
)
1516 switch ( event
.GetKeyCode() )
1520 m_grid
->DisableCellEditControl();
1524 m_grid
->GetEventHandler()->ProcessEvent( event
);
1528 case WXK_NUMPAD_ENTER
:
1529 if (!m_grid
->GetEventHandler()->ProcessEvent(event
))
1530 m_editor
->HandleReturn(event
);
1539 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
)
1541 switch ( event
.GetKeyCode() )
1546 case WXK_NUMPAD_ENTER
:
1554 // ----------------------------------------------------------------------------
1555 // wxGridCellWorker is an (almost) empty common base class for
1556 // wxGridCellRenderer and wxGridCellEditor managing ref counting
1557 // ----------------------------------------------------------------------------
1559 void wxGridCellWorker::SetParameters(const wxString
& WXUNUSED(params
))
1564 wxGridCellWorker::~wxGridCellWorker()
1568 // ============================================================================
1570 // ============================================================================
1572 // ----------------------------------------------------------------------------
1573 // wxGridCellRenderer
1574 // ----------------------------------------------------------------------------
1576 void wxGridCellRenderer::Draw(wxGrid
& grid
,
1577 wxGridCellAttr
& attr
,
1580 int WXUNUSED(row
), int WXUNUSED(col
),
1583 dc
.SetBackgroundMode( wxSOLID
);
1585 // grey out fields if the grid is disabled
1586 if( grid
.IsEnabled() )
1590 dc
.SetBrush( wxBrush(grid
.GetSelectionBackground(), wxSOLID
) );
1594 dc
.SetBrush( wxBrush(attr
.GetBackgroundColour(), wxSOLID
) );
1599 dc
.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
), wxSOLID
));
1602 dc
.SetPen( *wxTRANSPARENT_PEN
);
1603 dc
.DrawRectangle(rect
);
1606 // ----------------------------------------------------------------------------
1607 // wxGridCellStringRenderer
1608 // ----------------------------------------------------------------------------
1610 void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid
& grid
,
1611 wxGridCellAttr
& attr
,
1615 dc
.SetBackgroundMode( wxTRANSPARENT
);
1617 // TODO some special colours for attr.IsReadOnly() case?
1619 // different coloured text when the grid is disabled
1620 if( grid
.IsEnabled() )
1624 dc
.SetTextBackground( grid
.GetSelectionBackground() );
1625 dc
.SetTextForeground( grid
.GetSelectionForeground() );
1629 dc
.SetTextBackground( attr
.GetBackgroundColour() );
1630 dc
.SetTextForeground( attr
.GetTextColour() );
1635 dc
.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
));
1636 dc
.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT
));
1639 dc
.SetFont( attr
.GetFont() );
1642 wxSize
wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr
& attr
,
1644 const wxString
& text
)
1646 wxCoord x
= 0, y
= 0, max_x
= 0;
1647 dc
.SetFont(attr
.GetFont());
1648 wxStringTokenizer
tk(text
, _T('\n'));
1649 while ( tk
.HasMoreTokens() )
1651 dc
.GetTextExtent(tk
.GetNextToken(), &x
, &y
);
1652 max_x
= wxMax(max_x
, x
);
1655 y
*= 1 + text
.Freq(wxT('\n')); // multiply by the number of lines.
1657 return wxSize(max_x
, y
);
1660 wxSize
wxGridCellStringRenderer::GetBestSize(wxGrid
& grid
,
1661 wxGridCellAttr
& attr
,
1665 return DoGetBestSize(attr
, dc
, grid
.GetCellValue(row
, col
));
1668 void wxGridCellStringRenderer::Draw(wxGrid
& grid
,
1669 wxGridCellAttr
& attr
,
1671 const wxRect
& rectCell
,
1675 wxRect rect
= rectCell
;
1678 // erase only this cells background, overflow cells should have been erased
1679 wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
1682 attr
.GetAlignment(&hAlign
, &vAlign
);
1684 int overflowCols
= 0;
1686 if (attr
.GetOverflow())
1688 int cols
= grid
.GetNumberCols();
1689 int best_width
= GetBestSize(grid
,attr
,dc
,row
,col
).GetWidth();
1690 int cell_rows
, cell_cols
;
1691 attr
.GetSize( &cell_rows
, &cell_cols
); // shouldn't get here if <=0
1692 if ((best_width
> rectCell
.width
) && (col
< cols
) && grid
.GetTable())
1694 int i
, c_cols
, c_rows
;
1695 for (i
= col
+cell_cols
; i
< cols
; i
++)
1697 bool is_empty
= true;
1698 for (int j
=row
; j
<row
+cell_rows
; j
++)
1700 // check w/ anchor cell for multicell block
1701 grid
.GetCellSize(j
, i
, &c_rows
, &c_cols
);
1702 if (c_rows
> 0) c_rows
= 0;
1703 if (!grid
.GetTable()->IsEmptyCell(j
+c_rows
, i
))
1710 rect
.width
+= grid
.GetColSize(i
);
1716 if (rect
.width
>= best_width
) break;
1718 overflowCols
= i
- col
- cell_cols
+ 1;
1719 if (overflowCols
>= cols
) overflowCols
= cols
- 1;
1722 if (overflowCols
> 0) // redraw overflow cells w/ proper hilight
1724 hAlign
= wxALIGN_LEFT
; // if oveflowed then it's left aligned
1726 clip
.x
+= rectCell
.width
;
1727 // draw each overflow cell individually
1728 int col_end
= col
+cell_cols
+overflowCols
;
1729 if (col_end
>= grid
.GetNumberCols())
1730 col_end
= grid
.GetNumberCols() - 1;
1731 for (int i
= col
+cell_cols
; i
<= col_end
; i
++)
1733 clip
.width
= grid
.GetColSize(i
) - 1;
1734 dc
.DestroyClippingRegion();
1735 dc
.SetClippingRegion(clip
);
1737 SetTextColoursAndFont(grid
, attr
, dc
,
1738 grid
.IsInSelection(row
,i
));
1740 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
),
1741 rect
, hAlign
, vAlign
);
1742 clip
.x
+= grid
.GetColSize(i
) - 1;
1748 dc
.DestroyClippingRegion();
1752 // now we only have to draw the text
1753 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
1755 grid
.DrawTextRectangle(dc
, grid
.GetCellValue(row
, col
),
1756 rect
, hAlign
, vAlign
);
1759 // ----------------------------------------------------------------------------
1760 // wxGridCellNumberRenderer
1761 // ----------------------------------------------------------------------------
1763 wxString
wxGridCellNumberRenderer::GetString(wxGrid
& grid
, int row
, int col
)
1765 wxGridTableBase
*table
= grid
.GetTable();
1767 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
1769 text
.Printf(_T("%ld"), table
->GetValueAsLong(row
, col
));
1773 text
= table
->GetValue(row
, col
);
1779 void wxGridCellNumberRenderer::Draw(wxGrid
& grid
,
1780 wxGridCellAttr
& attr
,
1782 const wxRect
& rectCell
,
1786 wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
1788 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
1790 // draw the text right aligned by default
1792 attr
.GetAlignment(&hAlign
, &vAlign
);
1793 hAlign
= wxALIGN_RIGHT
;
1795 wxRect rect
= rectCell
;
1798 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
1801 wxSize
wxGridCellNumberRenderer::GetBestSize(wxGrid
& grid
,
1802 wxGridCellAttr
& attr
,
1806 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
1809 // ----------------------------------------------------------------------------
1810 // wxGridCellFloatRenderer
1811 // ----------------------------------------------------------------------------
1813 wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width
, int precision
)
1816 SetPrecision(precision
);
1819 wxGridCellRenderer
*wxGridCellFloatRenderer::Clone() const
1821 wxGridCellFloatRenderer
*renderer
= new wxGridCellFloatRenderer
;
1822 renderer
->m_width
= m_width
;
1823 renderer
->m_precision
= m_precision
;
1824 renderer
->m_format
= m_format
;
1829 wxString
wxGridCellFloatRenderer::GetString(wxGrid
& grid
, int row
, int col
)
1831 wxGridTableBase
*table
= grid
.GetTable();
1836 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) )
1838 val
= table
->GetValueAsDouble(row
, col
);
1843 text
= table
->GetValue(row
, col
);
1844 hasDouble
= text
.ToDouble(&val
);
1851 if ( m_width
== -1 )
1853 if ( m_precision
== -1 )
1855 // default width/precision
1856 m_format
= _T("%f");
1860 m_format
.Printf(_T("%%.%df"), m_precision
);
1863 else if ( m_precision
== -1 )
1865 // default precision
1866 m_format
.Printf(_T("%%%d.f"), m_width
);
1870 m_format
.Printf(_T("%%%d.%df"), m_width
, m_precision
);
1874 text
.Printf(m_format
, val
);
1877 //else: text already contains the string
1882 void wxGridCellFloatRenderer::Draw(wxGrid
& grid
,
1883 wxGridCellAttr
& attr
,
1885 const wxRect
& rectCell
,
1889 wxGridCellRenderer::Draw(grid
, attr
, dc
, rectCell
, row
, col
, isSelected
);
1891 SetTextColoursAndFont(grid
, attr
, dc
, isSelected
);
1893 // draw the text right aligned by default
1895 attr
.GetAlignment(&hAlign
, &vAlign
);
1896 hAlign
= wxALIGN_RIGHT
;
1898 wxRect rect
= rectCell
;
1901 grid
.DrawTextRectangle(dc
, GetString(grid
, row
, col
), rect
, hAlign
, vAlign
);
1904 wxSize
wxGridCellFloatRenderer::GetBestSize(wxGrid
& grid
,
1905 wxGridCellAttr
& attr
,
1909 return DoGetBestSize(attr
, dc
, GetString(grid
, row
, col
));
1912 void wxGridCellFloatRenderer::SetParameters(const wxString
& params
)
1916 // reset to defaults
1922 wxString tmp
= params
.BeforeFirst(_T(','));
1926 if ( tmp
.ToLong(&width
) )
1928 SetWidth((int)width
);
1932 wxLogDebug(_T("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params
.c_str());
1936 tmp
= params
.AfterFirst(_T(','));
1940 if ( tmp
.ToLong(&precision
) )
1942 SetPrecision((int)precision
);
1946 wxLogDebug(_T("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params
.c_str());
1954 // ----------------------------------------------------------------------------
1955 // wxGridCellBoolRenderer
1956 // ----------------------------------------------------------------------------
1958 wxSize
wxGridCellBoolRenderer::ms_sizeCheckMark
;
1960 // FIXME these checkbox size calculations are really ugly...
1962 // between checkmark and box
1963 static const wxCoord wxGRID_CHECKMARK_MARGIN
= 2;
1965 wxSize
wxGridCellBoolRenderer::GetBestSize(wxGrid
& grid
,
1966 wxGridCellAttr
& WXUNUSED(attr
),
1971 // compute it only once (no locks for MT safeness in GUI thread...)
1972 if ( !ms_sizeCheckMark
.x
)
1974 // get checkbox size
1975 wxCheckBox
*checkbox
= new wxCheckBox(&grid
, wxID_ANY
, wxEmptyString
);
1976 wxSize size
= checkbox
->GetBestSize();
1977 wxCoord checkSize
= size
.y
+ 2*wxGRID_CHECKMARK_MARGIN
;
1979 // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result
1980 #if defined(__WXGTK__) || defined(__WXMOTIF__)
1981 checkSize
-= size
.y
/ 2;
1986 ms_sizeCheckMark
.x
= ms_sizeCheckMark
.y
= checkSize
;
1989 return ms_sizeCheckMark
;
1992 void wxGridCellBoolRenderer::Draw(wxGrid
& grid
,
1993 wxGridCellAttr
& attr
,
1999 wxGridCellRenderer::Draw(grid
, attr
, dc
, rect
, row
, col
, isSelected
);
2001 // draw a check mark in the centre (ignoring alignment - TODO)
2002 wxSize size
= GetBestSize(grid
, attr
, dc
, row
, col
);
2004 // don't draw outside the cell
2005 wxCoord minSize
= wxMin(rect
.width
, rect
.height
);
2006 if ( size
.x
>= minSize
|| size
.y
>= minSize
)
2008 // and even leave (at least) 1 pixel margin
2009 size
.x
= size
.y
= minSize
- 2;
2012 // draw a border around checkmark
2014 attr
.GetAlignment(& hAlign
, &vAlign
);
2017 if (hAlign
== wxALIGN_CENTRE
)
2019 rectBorder
.x
= rect
.x
+ rect
.width
/2 - size
.x
/2;
2020 rectBorder
.y
= rect
.y
+ rect
.height
/2 - size
.y
/2;
2021 rectBorder
.width
= size
.x
;
2022 rectBorder
.height
= size
.y
;
2024 else if (hAlign
== wxALIGN_LEFT
)
2026 rectBorder
.x
= rect
.x
+ 2;
2027 rectBorder
.y
= rect
.y
+ rect
.height
/2 - size
.y
/2;
2028 rectBorder
.width
= size
.x
;
2029 rectBorder
.height
= size
.y
;
2031 else if (hAlign
== wxALIGN_RIGHT
)
2033 rectBorder
.x
= rect
.x
+ rect
.width
- size
.x
- 2;
2034 rectBorder
.y
= rect
.y
+ rect
.height
/2 - size
.y
/2;
2035 rectBorder
.width
= size
.x
;
2036 rectBorder
.height
= size
.y
;
2040 if ( grid
.GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
) )
2041 value
= grid
.GetTable()->GetValueAsBool(row
, col
);
2044 wxString
cellval( grid
.GetTable()->GetValue(row
, col
) );
2045 value
= !( !cellval
|| (cellval
== wxT("0")) );
2050 wxRect rectMark
= rectBorder
;
2052 // MSW DrawCheckMark() is weird (and should probably be changed...)
2053 rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
/2);
2057 rectMark
.Inflate(-wxGRID_CHECKMARK_MARGIN
);
2060 dc
.SetTextForeground(attr
.GetTextColour());
2061 dc
.DrawCheckMark(rectMark
);
2064 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
2065 dc
.SetPen(wxPen(attr
.GetTextColour(), 1, wxSOLID
));
2066 dc
.DrawRectangle(rectBorder
);
2069 // ----------------------------------------------------------------------------
2071 // ----------------------------------------------------------------------------
2073 void wxGridCellAttr::Init(wxGridCellAttr
*attrDefault
)
2077 m_isReadOnly
= Unset
;
2082 m_attrkind
= wxGridCellAttr::Cell
;
2084 m_sizeRows
= m_sizeCols
= 1;
2085 m_overflow
= UnsetOverflow
;
2087 SetDefAttr(attrDefault
);
2090 wxGridCellAttr
*wxGridCellAttr::Clone() const
2092 wxGridCellAttr
*attr
= new wxGridCellAttr(m_defGridAttr
);
2094 if ( HasTextColour() )
2095 attr
->SetTextColour(GetTextColour());
2096 if ( HasBackgroundColour() )
2097 attr
->SetBackgroundColour(GetBackgroundColour());
2099 attr
->SetFont(GetFont());
2100 if ( HasAlignment() )
2101 attr
->SetAlignment(m_hAlign
, m_vAlign
);
2103 attr
->SetSize( m_sizeRows
, m_sizeCols
);
2107 attr
->SetRenderer(m_renderer
);
2108 m_renderer
->IncRef();
2112 attr
->SetEditor(m_editor
);
2117 attr
->SetReadOnly();
2119 attr
->SetKind( m_attrkind
);
2124 void wxGridCellAttr::MergeWith(wxGridCellAttr
*mergefrom
)
2126 if ( !HasTextColour() && mergefrom
->HasTextColour() )
2127 SetTextColour(mergefrom
->GetTextColour());
2128 if ( !HasBackgroundColour() && mergefrom
->HasBackgroundColour() )
2129 SetBackgroundColour(mergefrom
->GetBackgroundColour());
2130 if ( !HasFont() && mergefrom
->HasFont() )
2131 SetFont(mergefrom
->GetFont());
2132 if ( !HasAlignment() && mergefrom
->HasAlignment() ){
2134 mergefrom
->GetAlignment( &hAlign
, &vAlign
);
2135 SetAlignment(hAlign
, vAlign
);
2138 mergefrom
->GetSize( &m_sizeRows
, &m_sizeCols
);
2140 // Directly access member functions as GetRender/Editor don't just return
2141 // m_renderer/m_editor
2143 // Maybe add support for merge of Render and Editor?
2144 if (!HasRenderer() && mergefrom
->HasRenderer() )
2146 m_renderer
= mergefrom
->m_renderer
;
2147 m_renderer
->IncRef();
2149 if ( !HasEditor() && mergefrom
->HasEditor() )
2151 m_editor
= mergefrom
->m_editor
;
2154 if ( !HasReadWriteMode() && mergefrom
->HasReadWriteMode() )
2155 SetReadOnly(mergefrom
->IsReadOnly());
2157 if (!HasOverflowMode() && mergefrom
->HasOverflowMode() )
2158 SetOverflow(mergefrom
->GetOverflow());
2160 SetDefAttr(mergefrom
->m_defGridAttr
);
2163 void wxGridCellAttr::SetSize(int num_rows
, int num_cols
)
2165 // The size of a cell is normally 1,1
2167 // If this cell is larger (2,2) then this is the top left cell
2168 // the other cells that will be covered (lower right cells) must be
2169 // set to negative or zero values such that
2170 // row + num_rows of the covered cell points to the larger cell (this cell)
2171 // same goes for the col + num_cols.
2173 // Size of 0,0 is NOT valid, neither is <=0 and any positive value
2175 wxASSERT_MSG( (!((num_rows
>0)&&(num_cols
<=0)) ||
2176 !((num_rows
<=0)&&(num_cols
>0)) ||
2177 !((num_rows
==0)&&(num_cols
==0))),
2178 wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values"));
2180 m_sizeRows
= num_rows
;
2181 m_sizeCols
= num_cols
;
2184 const wxColour
& wxGridCellAttr::GetTextColour() const
2186 if (HasTextColour())
2190 else if (m_defGridAttr
&& m_defGridAttr
!= this)
2192 return m_defGridAttr
->GetTextColour();
2196 wxFAIL_MSG(wxT("Missing default cell attribute"));
2197 return wxNullColour
;
2202 const wxColour
& wxGridCellAttr::GetBackgroundColour() const
2204 if (HasBackgroundColour())
2206 else if (m_defGridAttr
&& m_defGridAttr
!= this)
2207 return m_defGridAttr
->GetBackgroundColour();
2210 wxFAIL_MSG(wxT("Missing default cell attribute"));
2211 return wxNullColour
;
2216 const wxFont
& wxGridCellAttr::GetFont() const
2220 else if (m_defGridAttr
&& m_defGridAttr
!= this)
2221 return m_defGridAttr
->GetFont();
2224 wxFAIL_MSG(wxT("Missing default cell attribute"));
2230 void wxGridCellAttr::GetAlignment(int *hAlign
, int *vAlign
) const
2234 if ( hAlign
) *hAlign
= m_hAlign
;
2235 if ( vAlign
) *vAlign
= m_vAlign
;
2237 else if (m_defGridAttr
&& m_defGridAttr
!= this)
2238 m_defGridAttr
->GetAlignment(hAlign
, vAlign
);
2241 wxFAIL_MSG(wxT("Missing default cell attribute"));
2245 void wxGridCellAttr::GetSize( int *num_rows
, int *num_cols
) const
2247 if ( num_rows
) *num_rows
= m_sizeRows
;
2248 if ( num_cols
) *num_cols
= m_sizeCols
;
2251 // GetRenderer and GetEditor use a slightly different decision path about
2252 // which attribute to use. If a non-default attr object has one then it is
2253 // used, otherwise the default editor or renderer is fetched from the grid and
2254 // used. It should be the default for the data type of the cell. If it is
2255 // NULL (because the table has a type that the grid does not have in its
2256 // registry,) then the grid's default editor or renderer is used.
2258 wxGridCellRenderer
* wxGridCellAttr::GetRenderer(wxGrid
* grid
, int row
, int col
) const
2260 wxGridCellRenderer
*renderer
;
2262 if ( m_renderer
&& this != m_defGridAttr
)
2264 // use the cells renderer if it has one
2265 renderer
= m_renderer
;
2268 else // no non default cell renderer
2270 // get default renderer for the data type
2273 // GetDefaultRendererForCell() will do IncRef() for us
2274 renderer
= grid
->GetDefaultRendererForCell(row
, col
);
2283 if (m_defGridAttr
&& this != m_defGridAttr
)
2285 // if we still don't have one then use the grid default
2286 // (no need for IncRef() here neither)
2287 renderer
= m_defGridAttr
->GetRenderer(NULL
, 0, 0);
2289 else // default grid attr
2291 // use m_renderer which we had decided not to use initially
2292 renderer
= m_renderer
;
2299 // we're supposed to always find something
2300 wxASSERT_MSG(renderer
, wxT("Missing default cell renderer"));
2305 // same as above, except for s/renderer/editor/g
2306 wxGridCellEditor
* wxGridCellAttr::GetEditor(wxGrid
* grid
, int row
, int col
) const
2308 wxGridCellEditor
*editor
;
2310 if ( m_editor
&& this != m_defGridAttr
)
2312 // use the cells editor if it has one
2316 else // no non default cell editor
2318 // get default editor for the data type
2321 // GetDefaultEditorForCell() will do IncRef() for us
2322 editor
= grid
->GetDefaultEditorForCell(row
, col
);
2331 if ( m_defGridAttr
&& this != m_defGridAttr
)
2333 // if we still don't have one then use the grid default
2334 // (no need for IncRef() here neither)
2335 editor
= m_defGridAttr
->GetEditor(NULL
, 0, 0);
2337 else // default grid attr
2339 // use m_editor which we had decided not to use initially
2347 // we're supposed to always find something
2348 wxASSERT_MSG(editor
, wxT("Missing default cell editor"));
2353 // ----------------------------------------------------------------------------
2354 // wxGridCellAttrData
2355 // ----------------------------------------------------------------------------
2357 void wxGridCellAttrData::SetAttr(wxGridCellAttr
*attr
, int row
, int col
)
2359 int n
= FindIndex(row
, col
);
2360 if ( n
== wxNOT_FOUND
)
2362 // add the attribute
2363 m_attrs
.Add(new wxGridCellWithAttr(row
, col
, attr
));
2367 // free the old attribute
2368 m_attrs
[(size_t)n
].attr
->DecRef();
2372 // change the attribute
2373 m_attrs
[(size_t)n
].attr
= attr
;
2377 // remove this attribute
2378 m_attrs
.RemoveAt((size_t)n
);
2383 wxGridCellAttr
*wxGridCellAttrData::GetAttr(int row
, int col
) const
2385 wxGridCellAttr
*attr
= (wxGridCellAttr
*)NULL
;
2387 int n
= FindIndex(row
, col
);
2388 if ( n
!= wxNOT_FOUND
)
2390 attr
= m_attrs
[(size_t)n
].attr
;
2397 void wxGridCellAttrData::UpdateAttrRows( size_t pos
, int numRows
)
2399 size_t count
= m_attrs
.GetCount();
2400 for ( size_t n
= 0; n
< count
; n
++ )
2402 wxGridCellCoords
& coords
= m_attrs
[n
].coords
;
2403 wxCoord row
= coords
.GetRow();
2404 if ((size_t)row
>= pos
)
2408 // If rows inserted, include row counter where necessary
2409 coords
.SetRow(row
+ numRows
);
2411 else if (numRows
< 0)
2413 // If rows deleted ...
2414 if ((size_t)row
>= pos
- numRows
)
2416 // ...either decrement row counter (if row still exists)...
2417 coords
.SetRow(row
+ numRows
);
2421 // ...or remove the attribute
2422 m_attrs
.RemoveAt((size_t)n
);
2430 void wxGridCellAttrData::UpdateAttrCols( size_t pos
, int numCols
)
2432 size_t count
= m_attrs
.GetCount();
2433 for ( size_t n
= 0; n
< count
; n
++ )
2435 wxGridCellCoords
& coords
= m_attrs
[n
].coords
;
2436 wxCoord col
= coords
.GetCol();
2437 if ( (size_t)col
>= pos
)
2441 // If rows inserted, include row counter where necessary
2442 coords
.SetCol(col
+ numCols
);
2444 else if (numCols
< 0)
2446 // If rows deleted ...
2447 if ((size_t)col
>= pos
- numCols
)
2449 // ...either decrement row counter (if row still exists)...
2450 coords
.SetCol(col
+ numCols
);
2454 // ...or remove the attribute
2455 m_attrs
.RemoveAt((size_t)n
);
2463 int wxGridCellAttrData::FindIndex(int row
, int col
) const
2465 size_t count
= m_attrs
.GetCount();
2466 for ( size_t n
= 0; n
< count
; n
++ )
2468 const wxGridCellCoords
& coords
= m_attrs
[n
].coords
;
2469 if ( (coords
.GetRow() == row
) && (coords
.GetCol() == col
) )
2478 // ----------------------------------------------------------------------------
2479 // wxGridRowOrColAttrData
2480 // ----------------------------------------------------------------------------
2482 wxGridRowOrColAttrData::~wxGridRowOrColAttrData()
2484 size_t count
= m_attrs
.Count();
2485 for ( size_t n
= 0; n
< count
; n
++ )
2487 m_attrs
[n
]->DecRef();
2491 wxGridCellAttr
*wxGridRowOrColAttrData::GetAttr(int rowOrCol
) const
2493 wxGridCellAttr
*attr
= (wxGridCellAttr
*)NULL
;
2495 int n
= m_rowsOrCols
.Index(rowOrCol
);
2496 if ( n
!= wxNOT_FOUND
)
2498 attr
= m_attrs
[(size_t)n
];
2505 void wxGridRowOrColAttrData::SetAttr(wxGridCellAttr
*attr
, int rowOrCol
)
2507 int i
= m_rowsOrCols
.Index(rowOrCol
);
2508 if ( i
== wxNOT_FOUND
)
2510 // add the attribute
2511 m_rowsOrCols
.Add(rowOrCol
);
2516 size_t n
= (size_t)i
;
2519 // change the attribute
2520 m_attrs
[n
]->DecRef();
2525 // remove this attribute
2526 m_attrs
[n
]->DecRef();
2527 m_rowsOrCols
.RemoveAt(n
);
2528 m_attrs
.RemoveAt(n
);
2533 void wxGridRowOrColAttrData::UpdateAttrRowsOrCols( size_t pos
, int numRowsOrCols
)
2535 size_t count
= m_attrs
.GetCount();
2536 for ( size_t n
= 0; n
< count
; n
++ )
2538 int & rowOrCol
= m_rowsOrCols
[n
];
2539 if ( (size_t)rowOrCol
>= pos
)
2541 if ( numRowsOrCols
> 0 )
2543 // If rows inserted, include row counter where necessary
2544 rowOrCol
+= numRowsOrCols
;
2546 else if ( numRowsOrCols
< 0)
2548 // If rows deleted, either decrement row counter (if row still exists)
2549 if ((size_t)rowOrCol
>= pos
- numRowsOrCols
)
2550 rowOrCol
+= numRowsOrCols
;
2553 m_rowsOrCols
.RemoveAt((size_t)n
);
2554 m_attrs
.RemoveAt((size_t)n
);
2562 // ----------------------------------------------------------------------------
2563 // wxGridCellAttrProvider
2564 // ----------------------------------------------------------------------------
2566 wxGridCellAttrProvider::wxGridCellAttrProvider()
2568 m_data
= (wxGridCellAttrProviderData
*)NULL
;
2571 wxGridCellAttrProvider::~wxGridCellAttrProvider()
2576 void wxGridCellAttrProvider::InitData()
2578 m_data
= new wxGridCellAttrProviderData
;
2581 wxGridCellAttr
*wxGridCellAttrProvider::GetAttr(int row
, int col
,
2582 wxGridCellAttr::wxAttrKind kind
) const
2584 wxGridCellAttr
*attr
= (wxGridCellAttr
*)NULL
;
2589 case (wxGridCellAttr::Any
):
2590 //Get cached merge attributes.
2591 // Currenlty not used as no cache implemented as not mutiable
2592 // attr = m_data->m_mergeAttr.GetAttr(row, col);
2595 //Basicaly implement old version.
2596 //Also check merge cache, so we don't have to re-merge every time..
2597 wxGridCellAttr
*attrcell
= m_data
->m_cellAttrs
.GetAttr(row
, col
);
2598 wxGridCellAttr
*attrrow
= m_data
->m_rowAttrs
.GetAttr(row
);
2599 wxGridCellAttr
*attrcol
= m_data
->m_colAttrs
.GetAttr(col
);
2601 if((attrcell
!= attrrow
) && (attrrow
!= attrcol
) && (attrcell
!= attrcol
)){
2602 // Two or more are non NULL
2603 attr
= new wxGridCellAttr
;
2604 attr
->SetKind(wxGridCellAttr::Merged
);
2608 attr
->MergeWith(attrcell
);
2612 attr
->MergeWith(attrcol
);
2616 attr
->MergeWith(attrrow
);
2619 //store merge attr if cache implemented
2621 //m_data->m_mergeAttr.SetAttr(attr, row, col);
2625 // one or none is non null return it or null.
2626 if(attrrow
) attr
= attrrow
;
2642 case (wxGridCellAttr::Cell
):
2643 attr
= m_data
->m_cellAttrs
.GetAttr(row
, col
);
2645 case (wxGridCellAttr::Col
):
2646 attr
= m_data
->m_colAttrs
.GetAttr(col
);
2648 case (wxGridCellAttr::Row
):
2649 attr
= m_data
->m_rowAttrs
.GetAttr(row
);
2653 // (wxGridCellAttr::Default):
2654 // (wxGridCellAttr::Merged):
2661 void wxGridCellAttrProvider::SetAttr(wxGridCellAttr
*attr
,
2667 m_data
->m_cellAttrs
.SetAttr(attr
, row
, col
);
2670 void wxGridCellAttrProvider::SetRowAttr(wxGridCellAttr
*attr
, int row
)
2675 m_data
->m_rowAttrs
.SetAttr(attr
, row
);
2678 void wxGridCellAttrProvider::SetColAttr(wxGridCellAttr
*attr
, int col
)
2683 m_data
->m_colAttrs
.SetAttr(attr
, col
);
2686 void wxGridCellAttrProvider::UpdateAttrRows( size_t pos
, int numRows
)
2690 m_data
->m_cellAttrs
.UpdateAttrRows( pos
, numRows
);
2692 m_data
->m_rowAttrs
.UpdateAttrRowsOrCols( pos
, numRows
);
2696 void wxGridCellAttrProvider::UpdateAttrCols( size_t pos
, int numCols
)
2700 m_data
->m_cellAttrs
.UpdateAttrCols( pos
, numCols
);
2702 m_data
->m_colAttrs
.UpdateAttrRowsOrCols( pos
, numCols
);
2706 // ----------------------------------------------------------------------------
2707 // wxGridTypeRegistry
2708 // ----------------------------------------------------------------------------
2710 wxGridTypeRegistry::~wxGridTypeRegistry()
2712 size_t count
= m_typeinfo
.Count();
2713 for ( size_t i
= 0; i
< count
; i
++ )
2714 delete m_typeinfo
[i
];
2718 void wxGridTypeRegistry::RegisterDataType(const wxString
& typeName
,
2719 wxGridCellRenderer
* renderer
,
2720 wxGridCellEditor
* editor
)
2722 wxGridDataTypeInfo
* info
= new wxGridDataTypeInfo(typeName
, renderer
, editor
);
2724 // is it already registered?
2725 int loc
= FindRegisteredDataType(typeName
);
2726 if ( loc
!= wxNOT_FOUND
)
2728 delete m_typeinfo
[loc
];
2729 m_typeinfo
[loc
] = info
;
2733 m_typeinfo
.Add(info
);
2737 int wxGridTypeRegistry::FindRegisteredDataType(const wxString
& typeName
)
2739 size_t count
= m_typeinfo
.GetCount();
2740 for ( size_t i
= 0; i
< count
; i
++ )
2742 if ( typeName
== m_typeinfo
[i
]->m_typeName
)
2751 int wxGridTypeRegistry::FindDataType(const wxString
& typeName
)
2753 int index
= FindRegisteredDataType(typeName
);
2754 if ( index
== wxNOT_FOUND
)
2756 // check whether this is one of the standard ones, in which case
2757 // register it "on the fly"
2759 if ( typeName
== wxGRID_VALUE_STRING
)
2761 RegisterDataType(wxGRID_VALUE_STRING
,
2762 new wxGridCellStringRenderer
,
2763 new wxGridCellTextEditor
);
2765 #endif // wxUSE_TEXTCTRL
2767 if ( typeName
== wxGRID_VALUE_BOOL
)
2769 RegisterDataType(wxGRID_VALUE_BOOL
,
2770 new wxGridCellBoolRenderer
,
2771 new wxGridCellBoolEditor
);
2773 #endif // wxUSE_CHECKBOX
2775 if ( typeName
== wxGRID_VALUE_NUMBER
)
2777 RegisterDataType(wxGRID_VALUE_NUMBER
,
2778 new wxGridCellNumberRenderer
,
2779 new wxGridCellNumberEditor
);
2781 else if ( typeName
== wxGRID_VALUE_FLOAT
)
2783 RegisterDataType(wxGRID_VALUE_FLOAT
,
2784 new wxGridCellFloatRenderer
,
2785 new wxGridCellFloatEditor
);
2787 #endif // wxUSE_TEXTCTRL
2789 if ( typeName
== wxGRID_VALUE_CHOICE
)
2791 RegisterDataType(wxGRID_VALUE_CHOICE
,
2792 new wxGridCellStringRenderer
,
2793 new wxGridCellChoiceEditor
);
2795 #endif // wxUSE_COMBOBOX
2800 // we get here only if just added the entry for this type, so return
2802 index
= m_typeinfo
.GetCount() - 1;
2808 int wxGridTypeRegistry::FindOrCloneDataType(const wxString
& typeName
)
2810 int index
= FindDataType(typeName
);
2811 if ( index
== wxNOT_FOUND
)
2813 // the first part of the typename is the "real" type, anything after ':'
2814 // are the parameters for the renderer
2815 index
= FindDataType(typeName
.BeforeFirst(_T(':')));
2816 if ( index
== wxNOT_FOUND
)
2821 wxGridCellRenderer
*renderer
= GetRenderer(index
);
2822 wxGridCellRenderer
*rendererOld
= renderer
;
2823 renderer
= renderer
->Clone();
2824 rendererOld
->DecRef();
2826 wxGridCellEditor
*editor
= GetEditor(index
);
2827 wxGridCellEditor
*editorOld
= editor
;
2828 editor
= editor
->Clone();
2829 editorOld
->DecRef();
2831 // do it even if there are no parameters to reset them to defaults
2832 wxString params
= typeName
.AfterFirst(_T(':'));
2833 renderer
->SetParameters(params
);
2834 editor
->SetParameters(params
);
2836 // register the new typename
2837 RegisterDataType(typeName
, renderer
, editor
);
2839 // we just registered it, it's the last one
2840 index
= m_typeinfo
.GetCount() - 1;
2846 wxGridCellRenderer
* wxGridTypeRegistry::GetRenderer(int index
)
2848 wxGridCellRenderer
* renderer
= m_typeinfo
[index
]->m_renderer
;
2854 wxGridCellEditor
* wxGridTypeRegistry::GetEditor(int index
)
2856 wxGridCellEditor
* editor
= m_typeinfo
[index
]->m_editor
;
2862 // ----------------------------------------------------------------------------
2864 // ----------------------------------------------------------------------------
2866 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject
)
2869 wxGridTableBase::wxGridTableBase()
2871 m_view
= (wxGrid
*) NULL
;
2872 m_attrProvider
= (wxGridCellAttrProvider
*) NULL
;
2875 wxGridTableBase::~wxGridTableBase()
2877 delete m_attrProvider
;
2880 void wxGridTableBase::SetAttrProvider(wxGridCellAttrProvider
*attrProvider
)
2882 delete m_attrProvider
;
2883 m_attrProvider
= attrProvider
;
2886 bool wxGridTableBase::CanHaveAttributes()
2888 if ( ! GetAttrProvider() )
2890 // use the default attr provider by default
2891 SetAttrProvider(new wxGridCellAttrProvider
);
2896 wxGridCellAttr
*wxGridTableBase::GetAttr(int row
, int col
, wxGridCellAttr::wxAttrKind kind
)
2898 if ( m_attrProvider
)
2899 return m_attrProvider
->GetAttr(row
, col
, kind
);
2901 return (wxGridCellAttr
*)NULL
;
2904 void wxGridTableBase::SetAttr(wxGridCellAttr
* attr
, int row
, int col
)
2906 if ( m_attrProvider
)
2908 attr
->SetKind(wxGridCellAttr::Cell
);
2909 m_attrProvider
->SetAttr(attr
, row
, col
);
2913 // as we take ownership of the pointer and don't store it, we must
2919 void wxGridTableBase::SetRowAttr(wxGridCellAttr
*attr
, int row
)
2921 if ( m_attrProvider
)
2923 attr
->SetKind(wxGridCellAttr::Row
);
2924 m_attrProvider
->SetRowAttr(attr
, row
);
2928 // as we take ownership of the pointer and don't store it, we must
2934 void wxGridTableBase::SetColAttr(wxGridCellAttr
*attr
, int col
)
2936 if ( m_attrProvider
)
2938 attr
->SetKind(wxGridCellAttr::Col
);
2939 m_attrProvider
->SetColAttr(attr
, col
);
2943 // as we take ownership of the pointer and don't store it, we must
2949 bool wxGridTableBase::InsertRows( size_t WXUNUSED(pos
),
2950 size_t WXUNUSED(numRows
) )
2952 wxFAIL_MSG( wxT("Called grid table class function InsertRows\nbut your derived table class does not override this function") );
2957 bool wxGridTableBase::AppendRows( size_t WXUNUSED(numRows
) )
2959 wxFAIL_MSG( wxT("Called grid table class function AppendRows\nbut your derived table class does not override this function"));
2964 bool wxGridTableBase::DeleteRows( size_t WXUNUSED(pos
),
2965 size_t WXUNUSED(numRows
) )
2967 wxFAIL_MSG( wxT("Called grid table class function DeleteRows\nbut your derived table class does not override this function"));
2972 bool wxGridTableBase::InsertCols( size_t WXUNUSED(pos
),
2973 size_t WXUNUSED(numCols
) )
2975 wxFAIL_MSG( wxT("Called grid table class function InsertCols\nbut your derived table class does not override this function"));
2980 bool wxGridTableBase::AppendCols( size_t WXUNUSED(numCols
) )
2982 wxFAIL_MSG(wxT("Called grid table class function AppendCols\nbut your derived table class does not override this function"));
2987 bool wxGridTableBase::DeleteCols( size_t WXUNUSED(pos
),
2988 size_t WXUNUSED(numCols
) )
2990 wxFAIL_MSG( wxT("Called grid table class function DeleteCols\nbut your derived table class does not override this function"));
2996 wxString
wxGridTableBase::GetRowLabelValue( int row
)
2999 s
<< row
+ 1; // RD: Starting the rows at zero confuses users, no matter
3000 // how much it makes sense to us geeks.
3004 wxString
wxGridTableBase::GetColLabelValue( int col
)
3006 // default col labels are:
3007 // cols 0 to 25 : A-Z
3008 // cols 26 to 675 : AA-ZZ
3013 for ( n
= 1; ; n
++ )
3015 s
+= (wxChar
) (_T('A') + (wxChar
)( col%26
));
3017 if ( col
< 0 ) break;
3020 // reverse the string...
3022 for ( i
= 0; i
< n
; i
++ )
3031 wxString
wxGridTableBase::GetTypeName( int WXUNUSED(row
), int WXUNUSED(col
) )
3033 return wxGRID_VALUE_STRING
;
3036 bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row
), int WXUNUSED(col
),
3037 const wxString
& typeName
)
3039 return typeName
== wxGRID_VALUE_STRING
;
3042 bool wxGridTableBase::CanSetValueAs( int row
, int col
, const wxString
& typeName
)
3044 return CanGetValueAs(row
, col
, typeName
);
3047 long wxGridTableBase::GetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
) )
3052 double wxGridTableBase::GetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
) )
3057 bool wxGridTableBase::GetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
) )
3062 void wxGridTableBase::SetValueAsLong( int WXUNUSED(row
), int WXUNUSED(col
),
3063 long WXUNUSED(value
) )
3067 void wxGridTableBase::SetValueAsDouble( int WXUNUSED(row
), int WXUNUSED(col
),
3068 double WXUNUSED(value
) )
3072 void wxGridTableBase::SetValueAsBool( int WXUNUSED(row
), int WXUNUSED(col
),
3073 bool WXUNUSED(value
) )
3078 void* wxGridTableBase::GetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
),
3079 const wxString
& WXUNUSED(typeName
) )
3084 void wxGridTableBase::SetValueAsCustom( int WXUNUSED(row
), int WXUNUSED(col
),
3085 const wxString
& WXUNUSED(typeName
),
3086 void* WXUNUSED(value
) )
3090 //////////////////////////////////////////////////////////////////////
3092 // Message class for the grid table to send requests and notifications
3096 wxGridTableMessage::wxGridTableMessage()
3098 m_table
= (wxGridTableBase
*) NULL
;
3104 wxGridTableMessage::wxGridTableMessage( wxGridTableBase
*table
, int id
,
3105 int commandInt1
, int commandInt2
)
3109 m_comInt1
= commandInt1
;
3110 m_comInt2
= commandInt2
;
3115 //////////////////////////////////////////////////////////////////////
3117 // A basic grid table for string data. An object of this class will
3118 // created by wxGrid if you don't specify an alternative table class.
3121 WX_DEFINE_OBJARRAY(wxGridStringArray
)
3123 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase
)
3125 wxGridStringTable::wxGridStringTable()
3130 wxGridStringTable::wxGridStringTable( int numRows
, int numCols
)
3133 m_data
.Alloc( numRows
);
3136 sa
.Alloc( numCols
);
3137 sa
.Add( wxEmptyString
, numCols
);
3139 m_data
.Add( sa
, numRows
);
3142 wxGridStringTable::~wxGridStringTable()
3146 int wxGridStringTable::GetNumberRows()
3148 return m_data
.GetCount();
3151 int wxGridStringTable::GetNumberCols()
3153 if ( m_data
.GetCount() > 0 )
3154 return m_data
[0].GetCount();
3159 wxString
wxGridStringTable::GetValue( int row
, int col
)
3161 wxCHECK_MSG( (row
< GetNumberRows()) && (col
< GetNumberCols()),
3163 _T("invalid row or column index in wxGridStringTable") );
3165 return m_data
[row
][col
];
3168 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& value
)
3170 wxCHECK_RET( (row
< GetNumberRows()) && (col
< GetNumberCols()),
3171 _T("invalid row or column index in wxGridStringTable") );
3173 m_data
[row
][col
] = value
;
3176 bool wxGridStringTable::IsEmptyCell( int row
, int col
)
3178 wxCHECK_MSG( (row
< GetNumberRows()) && (col
< GetNumberCols()),
3180 _T("invalid row or column index in wxGridStringTable") );
3182 return (m_data
[row
][col
] == wxEmptyString
);
3185 void wxGridStringTable::Clear()
3188 int numRows
, numCols
;
3190 numRows
= m_data
.GetCount();
3193 numCols
= m_data
[0].GetCount();
3195 for ( row
= 0; row
< numRows
; row
++ )
3197 for ( col
= 0; col
< numCols
; col
++ )
3199 m_data
[row
][col
] = wxEmptyString
;
3206 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows
)
3208 size_t curNumRows
= m_data
.GetCount();
3209 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() :
3210 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
3212 if ( pos
>= curNumRows
)
3214 return AppendRows( numRows
);
3218 sa
.Alloc( curNumCols
);
3219 sa
.Add( wxEmptyString
, curNumCols
);
3220 m_data
.Insert( sa
, pos
, numRows
);
3223 wxGridTableMessage
msg( this,
3224 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
,
3228 GetView()->ProcessTableMessage( msg
);
3234 bool wxGridStringTable::AppendRows( size_t numRows
)
3236 size_t curNumRows
= m_data
.GetCount();
3237 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() :
3238 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
3241 if ( curNumCols
> 0 )
3243 sa
.Alloc( curNumCols
);
3244 sa
.Add( wxEmptyString
, curNumCols
);
3247 m_data
.Add( sa
, numRows
);
3251 wxGridTableMessage
msg( this,
3252 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
,
3255 GetView()->ProcessTableMessage( msg
);
3261 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows
)
3263 size_t curNumRows
= m_data
.GetCount();
3265 if ( pos
>= curNumRows
)
3267 wxFAIL_MSG( wxString::Format
3269 wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"),
3271 (unsigned long)numRows
,
3272 (unsigned long)curNumRows
3278 if ( numRows
> curNumRows
- pos
)
3280 numRows
= curNumRows
- pos
;
3283 if ( numRows
>= curNumRows
)
3289 m_data
.RemoveAt( pos
, numRows
);
3293 wxGridTableMessage
msg( this,
3294 wxGRIDTABLE_NOTIFY_ROWS_DELETED
,
3298 GetView()->ProcessTableMessage( msg
);
3304 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols
)
3308 size_t curNumRows
= m_data
.GetCount();
3309 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() :
3310 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
3312 if ( pos
>= curNumCols
)
3314 return AppendCols( numCols
);
3317 for ( row
= 0; row
< curNumRows
; row
++ )
3319 for ( col
= pos
; col
< pos
+ numCols
; col
++ )
3321 m_data
[row
].Insert( wxEmptyString
, col
);
3326 wxGridTableMessage
msg( this,
3327 wxGRIDTABLE_NOTIFY_COLS_INSERTED
,
3331 GetView()->ProcessTableMessage( msg
);
3337 bool wxGridStringTable::AppendCols( size_t numCols
)
3341 size_t curNumRows
= m_data
.GetCount();
3345 // TODO: something better than this ?
3347 wxFAIL_MSG( wxT("Unable to append cols to a grid table with no rows.\nCall AppendRows() first") );
3352 for ( row
= 0; row
< curNumRows
; row
++ )
3354 m_data
[row
].Add( wxEmptyString
, numCols
);
3359 wxGridTableMessage
msg( this,
3360 wxGRIDTABLE_NOTIFY_COLS_APPENDED
,
3363 GetView()->ProcessTableMessage( msg
);
3369 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols
)
3373 size_t curNumRows
= m_data
.GetCount();
3374 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() :
3375 ( GetView() ? GetView()->GetNumberCols() : 0 ) );
3377 if ( pos
>= curNumCols
)
3379 wxFAIL_MSG( wxString::Format
3381 wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"),
3383 (unsigned long)numCols
,
3384 (unsigned long)curNumCols
3389 if ( numCols
> curNumCols
- pos
)
3391 numCols
= curNumCols
- pos
;
3394 for ( row
= 0; row
< curNumRows
; row
++ )
3396 if ( numCols
>= curNumCols
)
3398 m_data
[row
].Clear();
3402 m_data
[row
].RemoveAt( pos
, numCols
);
3407 wxGridTableMessage
msg( this,
3408 wxGRIDTABLE_NOTIFY_COLS_DELETED
,
3412 GetView()->ProcessTableMessage( msg
);
3418 wxString
wxGridStringTable::GetRowLabelValue( int row
)
3420 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
3422 // using default label
3424 return wxGridTableBase::GetRowLabelValue( row
);
3428 return m_rowLabels
[ row
];
3432 wxString
wxGridStringTable::GetColLabelValue( int col
)
3434 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
3436 // using default label
3438 return wxGridTableBase::GetColLabelValue( col
);
3442 return m_colLabels
[ col
];
3446 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value
)
3448 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
3450 int n
= m_rowLabels
.GetCount();
3452 for ( i
= n
; i
<= row
; i
++ )
3454 m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) );
3458 m_rowLabels
[row
] = value
;
3461 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value
)
3463 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
3465 int n
= m_colLabels
.GetCount();
3467 for ( i
= n
; i
<= col
; i
++ )
3469 m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) );
3473 m_colLabels
[col
] = value
;
3478 //////////////////////////////////////////////////////////////////////
3479 //////////////////////////////////////////////////////////////////////
3481 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow
)
3483 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow
)
3484 EVT_PAINT( wxGridRowLabelWindow::OnPaint
)
3485 EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel
)
3486 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent
)
3487 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown
)
3488 EVT_KEY_UP( wxGridRowLabelWindow::OnKeyUp
)
3491 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid
*parent
,
3493 const wxPoint
&pos
, const wxSize
&size
)
3494 : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE
)
3499 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3503 // NO - don't do this because it will set both the x and y origin
3504 // coords to match the parent scrolled window and we just want to
3505 // set the y coord - MB
3507 // m_owner->PrepareDC( dc );
3510 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
3511 dc
.SetDeviceOrigin( 0, -y
);
3513 wxArrayInt rows
= m_owner
->CalcRowLabelsExposed( GetUpdateRegion() );
3514 m_owner
->DrawRowLabels( dc
, rows
);
3518 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
3520 m_owner
->ProcessRowLabelMouseEvent( event
);
3524 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent
& event
)
3526 m_owner
->GetEventHandler()->ProcessEvent(event
);
3530 // This seems to be required for wxMotif otherwise the mouse
3531 // cursor must be in the cell edit control to get key events
3533 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event
)
3535 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3538 void wxGridRowLabelWindow::OnKeyUp( wxKeyEvent
& event
)
3540 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3545 //////////////////////////////////////////////////////////////////////
3547 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow
)
3549 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow
)
3550 EVT_PAINT( wxGridColLabelWindow::OnPaint
)
3551 EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel
)
3552 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent
)
3553 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown
)
3554 EVT_KEY_UP( wxGridColLabelWindow::OnKeyUp
)
3557 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid
*parent
,
3559 const wxPoint
&pos
, const wxSize
&size
)
3560 : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE
)
3565 void wxGridColLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3569 // NO - don't do this because it will set both the x and y origin
3570 // coords to match the parent scrolled window and we just want to
3571 // set the x coord - MB
3573 // m_owner->PrepareDC( dc );
3576 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
3577 dc
.SetDeviceOrigin( -x
, 0 );
3579 wxArrayInt cols
= m_owner
->CalcColLabelsExposed( GetUpdateRegion() );
3580 m_owner
->DrawColLabels( dc
, cols
);
3584 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
3586 m_owner
->ProcessColLabelMouseEvent( event
);
3589 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent
& event
)
3591 m_owner
->GetEventHandler()->ProcessEvent(event
);
3595 // This seems to be required for wxMotif otherwise the mouse
3596 // cursor must be in the cell edit control to get key events
3598 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event
)
3600 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3603 void wxGridColLabelWindow::OnKeyUp( wxKeyEvent
& event
)
3605 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3610 //////////////////////////////////////////////////////////////////////
3612 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow
)
3614 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow
)
3615 EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel
)
3616 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent
)
3617 EVT_PAINT( wxGridCornerLabelWindow::OnPaint
)
3618 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown
)
3619 EVT_KEY_UP( wxGridCornerLabelWindow::OnKeyUp
)
3622 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid
*parent
,
3624 const wxPoint
&pos
, const wxSize
&size
)
3625 : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
|wxFULL_REPAINT_ON_RESIZE
)
3630 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
3634 int client_height
= 0;
3635 int client_width
= 0;
3636 GetClientSize( &client_width
, &client_height
);
3638 dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) );
3639 dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 );
3640 dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 );
3641 dc
.DrawLine( 0, 0, client_width
, 0 );
3642 dc
.DrawLine( 0, 0, 0, client_height
);
3644 dc
.SetPen( *wxWHITE_PEN
);
3645 dc
.DrawLine( 1, 1, client_width
-1, 1 );
3646 dc
.DrawLine( 1, 1, 1, client_height
-1 );
3650 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
3652 m_owner
->ProcessCornerLabelMouseEvent( event
);
3656 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent
& event
)
3658 m_owner
->GetEventHandler()->ProcessEvent(event
);
3661 // This seems to be required for wxMotif otherwise the mouse
3662 // cursor must be in the cell edit control to get key events
3664 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event
)
3666 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3669 void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent
& event
)
3671 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3676 //////////////////////////////////////////////////////////////////////
3678 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxWindow
)
3680 BEGIN_EVENT_TABLE( wxGridWindow
, wxWindow
)
3681 EVT_PAINT( wxGridWindow::OnPaint
)
3682 EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel
)
3683 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent
)
3684 EVT_KEY_DOWN( wxGridWindow::OnKeyDown
)
3685 EVT_KEY_UP( wxGridWindow::OnKeyUp
)
3686 EVT_SET_FOCUS( wxGridWindow::OnFocus
)
3687 EVT_KILL_FOCUS( wxGridWindow::OnFocus
)
3688 EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground
)
3691 wxGridWindow::wxGridWindow( wxGrid
*parent
,
3692 wxGridRowLabelWindow
*rowLblWin
,
3693 wxGridColLabelWindow
*colLblWin
,
3696 const wxSize
&size
)
3697 : wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
| wxBORDER_NONE
| wxCLIP_CHILDREN
|wxFULL_REPAINT_ON_RESIZE
,
3698 wxT("grid window") )
3702 m_rowLabelWin
= rowLblWin
;
3703 m_colLabelWin
= colLblWin
;
3707 void wxGridWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
3709 wxPaintDC
dc( this );
3710 m_owner
->PrepareDC( dc
);
3711 wxRegion reg
= GetUpdateRegion();
3712 wxGridCellCoordsArray DirtyCells
= m_owner
->CalcCellsExposed( reg
);
3713 m_owner
->DrawGridCellArea( dc
, DirtyCells
);
3714 #if WXGRID_DRAW_LINES
3715 m_owner
->DrawAllGridLines( dc
, reg
);
3717 m_owner
->DrawGridSpace( dc
);
3718 m_owner
->DrawHighlight( dc
, DirtyCells
);
3722 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect
*rect
)
3724 wxWindow::ScrollWindow( dx
, dy
, rect
);
3725 m_rowLabelWin
->ScrollWindow( 0, dy
, rect
);
3726 m_colLabelWin
->ScrollWindow( dx
, 0, rect
);
3730 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event
)
3732 m_owner
->ProcessGridCellMouseEvent( event
);
3735 void wxGridWindow::OnMouseWheel( wxMouseEvent
& event
)
3737 m_owner
->GetEventHandler()->ProcessEvent(event
);
3740 // This seems to be required for wxMotif/wxGTK otherwise the mouse
3741 // cursor must be in the cell edit control to get key events
3743 void wxGridWindow::OnKeyDown( wxKeyEvent
& event
)
3745 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3748 void wxGridWindow::OnKeyUp( wxKeyEvent
& event
)
3750 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) ) event
.Skip();
3753 void wxGridWindow::OnEraseBackground( wxEraseEvent
& WXUNUSED(event
) )
3757 void wxGridWindow::OnFocus(wxFocusEvent
& event
)
3759 if ( !m_owner
->GetEventHandler()->ProcessEvent( event
) )
3763 //////////////////////////////////////////////////////////////////////
3765 // Internal Helper function for computing row or column from some
3766 // (unscrolled) coordinate value, using either
3767 // m_defaultRowHeight/m_defaultColWidth or binary search on array
3768 // of m_rowBottoms/m_ColRights to speed up the search!
3770 // Internal helper macros for simpler use of that function
3772 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
,
3773 const wxArrayInt
& BorderArray
, int nMax
,
3776 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
3777 m_minAcceptableColWidth, \
3778 m_colRights, m_numCols, true)
3779 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
3780 m_minAcceptableRowHeight, \
3781 m_rowBottoms, m_numRows, true)
3782 /////////////////////////////////////////////////////////////////////
3784 #if wxUSE_EXTENDED_RTTI
3785 WX_DEFINE_FLAGS( wxGridStyle
)
3787 wxBEGIN_FLAGS( wxGridStyle
)
3788 // new style border flags, we put them first to
3789 // use them for streaming out
3790 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
3791 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
3792 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
3793 wxFLAGS_MEMBER(wxBORDER_RAISED
)
3794 wxFLAGS_MEMBER(wxBORDER_STATIC
)
3795 wxFLAGS_MEMBER(wxBORDER_NONE
)
3797 // old style border flags
3798 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
3799 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
3800 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
3801 wxFLAGS_MEMBER(wxRAISED_BORDER
)
3802 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
3803 wxFLAGS_MEMBER(wxBORDER
)
3805 // standard window styles
3806 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
3807 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
3808 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
3809 wxFLAGS_MEMBER(wxWANTS_CHARS
)
3810 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
3811 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
3812 wxFLAGS_MEMBER(wxVSCROLL
)
3813 wxFLAGS_MEMBER(wxHSCROLL
)
3815 wxEND_FLAGS( wxGridStyle
)
3817 IMPLEMENT_DYNAMIC_CLASS_XTI(wxGrid
, wxScrolledWindow
,"wx/grid.h")
3819 wxBEGIN_PROPERTIES_TABLE(wxGrid
)
3820 wxHIDE_PROPERTY( Children
)
3821 wxPROPERTY_FLAGS( WindowStyle
, wxGridStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
3822 wxEND_PROPERTIES_TABLE()
3824 wxBEGIN_HANDLERS_TABLE(wxGrid
)
3825 wxEND_HANDLERS_TABLE()
3827 wxCONSTRUCTOR_5( wxGrid
, wxWindow
* , Parent
, wxWindowID
, Id
, wxPoint
, Position
, wxSize
, Size
, long , WindowStyle
)
3830 TODO : Expose more information of a list's layout etc. via appropriate objects (\81Ã la NotebookPageInfo)
3833 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow
)
3836 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow
)
3837 EVT_PAINT( wxGrid::OnPaint
)
3838 EVT_SIZE( wxGrid::OnSize
)
3839 EVT_KEY_DOWN( wxGrid::OnKeyDown
)
3840 EVT_KEY_UP( wxGrid::OnKeyUp
)
3841 EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground
)
3846 // in order to make sure that a size event is not
3847 // trigerred in a unfinished state
3848 m_cornerLabelWin
= NULL
;
3849 m_rowLabelWin
= NULL
;
3850 m_colLabelWin
= NULL
;
3854 wxGrid::wxGrid( wxWindow
*parent
,
3859 const wxString
& name
)
3860 : wxScrolledWindow( parent
, id
, pos
, size
, (style
| wxWANTS_CHARS
), name
),
3861 m_colMinWidths(GRID_HASH_SIZE
),
3862 m_rowMinHeights(GRID_HASH_SIZE
)
3865 SetBestFittingSize(size
);
3868 bool wxGrid::Create(wxWindow
*parent
, wxWindowID id
,
3869 const wxPoint
& pos
, const wxSize
& size
,
3870 long style
, const wxString
& name
)
3872 if (!wxScrolledWindow::Create(parent
, id
, pos
, size
,
3873 style
| wxWANTS_CHARS
, name
))
3876 m_colMinWidths
= wxLongToLongHashMap(GRID_HASH_SIZE
) ;
3877 m_rowMinHeights
= wxLongToLongHashMap(GRID_HASH_SIZE
) ;
3880 SetBestFittingSize(size
);
3888 // Must do this or ~wxScrollHelper will pop the wrong event handler
3889 SetTargetWindow(this);
3891 wxSafeDecRef(m_defaultCellAttr
);
3893 #ifdef DEBUG_ATTR_CACHE
3894 size_t total
= gs_nAttrCacheHits
+ gs_nAttrCacheMisses
;
3895 wxPrintf(_T("wxGrid attribute cache statistics: "
3896 "total: %u, hits: %u (%u%%)\n"),
3897 total
, gs_nAttrCacheHits
,
3898 total
? (gs_nAttrCacheHits
*100) / total
: 0);
3904 delete m_typeRegistry
;
3910 // ----- internal init and update functions
3913 // NOTE: If using the default visual attributes works everywhere then this can
3914 // be removed as well as the #else cases below.
3915 #define _USE_VISATTR 0
3918 #include "wx/listbox.h"
3921 void wxGrid::Create()
3923 m_created
= false; // set to true by CreateGrid
3925 m_table
= (wxGridTableBase
*) NULL
;
3928 m_cellEditCtrlEnabled
= false;
3930 m_defaultCellAttr
= new wxGridCellAttr();
3932 // Set default cell attributes
3933 m_defaultCellAttr
->SetDefAttr(m_defaultCellAttr
);
3934 m_defaultCellAttr
->SetKind(wxGridCellAttr::Default
);
3935 m_defaultCellAttr
->SetFont(GetFont());
3936 m_defaultCellAttr
->SetAlignment(wxALIGN_LEFT
, wxALIGN_TOP
);
3937 m_defaultCellAttr
->SetRenderer(new wxGridCellStringRenderer
);
3938 m_defaultCellAttr
->SetEditor(new wxGridCellTextEditor
);
3941 wxVisualAttributes gva
= wxListBox::GetClassDefaultAttributes();
3942 wxVisualAttributes lva
= wxPanel::GetClassDefaultAttributes();
3944 m_defaultCellAttr
->SetTextColour(gva
.colFg
);
3945 m_defaultCellAttr
->SetBackgroundColour(gva
.colBg
);
3948 m_defaultCellAttr
->SetTextColour(
3949 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
));
3950 m_defaultCellAttr
->SetBackgroundColour(
3951 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
3956 m_currentCellCoords
= wxGridNoCellCoords
;
3958 m_rowLabelWidth
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
3959 m_colLabelHeight
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
3961 // create the type registry
3962 m_typeRegistry
= new wxGridTypeRegistry
;
3965 // subwindow components that make up the wxGrid
3966 m_cornerLabelWin
= new wxGridCornerLabelWindow( this,
3971 m_rowLabelWin
= new wxGridRowLabelWindow( this,
3976 m_colLabelWin
= new wxGridColLabelWindow( this,
3981 m_gridWin
= new wxGridWindow( this,
3988 SetTargetWindow( m_gridWin
);
3991 wxColour gfg
= gva
.colFg
;
3992 wxColour gbg
= gva
.colBg
;
3993 wxColour lfg
= lva
.colFg
;
3994 wxColour lbg
= lva
.colBg
;
3996 wxColour gfg
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT
);
3997 wxColour gbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW
);
3998 wxColour lfg
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT
);
3999 wxColour lbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
4001 m_cornerLabelWin
->SetOwnForegroundColour(lfg
);
4002 m_cornerLabelWin
->SetOwnBackgroundColour(lbg
);
4003 m_rowLabelWin
->SetOwnForegroundColour(lfg
);
4004 m_rowLabelWin
->SetOwnBackgroundColour(lbg
);
4005 m_colLabelWin
->SetOwnForegroundColour(lfg
);
4006 m_colLabelWin
->SetOwnBackgroundColour(lbg
);
4008 m_gridWin
->SetOwnForegroundColour(gfg
);
4009 m_gridWin
->SetOwnBackgroundColour(gbg
);
4015 bool wxGrid::CreateGrid( int numRows
, int numCols
,
4016 wxGrid::wxGridSelectionModes selmode
)
4018 wxCHECK_MSG( !m_created
,
4020 wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") );
4022 m_numRows
= numRows
;
4023 m_numCols
= numCols
;
4025 m_table
= new wxGridStringTable( m_numRows
, m_numCols
);
4026 m_table
->SetView( this );
4028 m_selection
= new wxGridSelection( this, selmode
);
4037 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode
)
4039 wxCHECK_RET( m_created
,
4040 wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") );
4042 m_selection
->SetSelectionMode( selmode
);
4045 wxGrid::wxGridSelectionModes
wxGrid::GetSelectionMode() const
4047 wxCHECK_MSG( m_created
, wxGrid::wxGridSelectCells
,
4048 wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") );
4050 return m_selection
->GetSelectionMode();
4053 bool wxGrid::SetTable( wxGridTableBase
*table
, bool takeOwnership
,
4054 wxGrid::wxGridSelectionModes selmode
)
4058 // stop all processing
4063 wxGridTableBase
*t
=m_table
;
4076 m_numRows
= table
->GetNumberRows();
4077 m_numCols
= table
->GetNumberCols();
4080 m_table
->SetView( this );
4083 m_selection
= new wxGridSelection( this, selmode
);
4096 m_rowLabelWidth
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
4097 m_colLabelHeight
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
4099 if ( m_rowLabelWin
)
4101 m_labelBackgroundColour
= m_rowLabelWin
->GetBackgroundColour();
4105 m_labelBackgroundColour
= wxColour( _T("WHITE") );
4108 m_labelTextColour
= wxColour( _T("BLACK") );
4111 m_attrCache
.row
= -1;
4112 m_attrCache
.col
= -1;
4113 m_attrCache
.attr
= NULL
;
4115 // TODO: something better than this ?
4117 m_labelFont
= this->GetFont();
4118 m_labelFont
.SetWeight( wxBOLD
);
4120 m_rowLabelHorizAlign
= wxALIGN_CENTRE
;
4121 m_rowLabelVertAlign
= wxALIGN_CENTRE
;
4123 m_colLabelHorizAlign
= wxALIGN_CENTRE
;
4124 m_colLabelVertAlign
= wxALIGN_CENTRE
;
4125 m_colLabelTextOrientation
= wxHORIZONTAL
;
4127 m_defaultColWidth
= WXGRID_DEFAULT_COL_WIDTH
;
4128 m_defaultRowHeight
= m_gridWin
->GetCharHeight();
4130 m_minAcceptableColWidth
= WXGRID_MIN_COL_WIDTH
;
4131 m_minAcceptableRowHeight
= WXGRID_MIN_ROW_HEIGHT
;
4133 #if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl()
4134 m_defaultRowHeight
+= 8;
4136 m_defaultRowHeight
+= 4;
4139 m_gridLineColour
= wxColour( 192,192,192 );
4140 m_gridLinesEnabled
= true;
4141 m_cellHighlightColour
= *wxBLACK
;
4142 m_cellHighlightPenWidth
= 2;
4143 m_cellHighlightROPenWidth
= 1;
4145 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
4146 m_winCapture
= (wxWindow
*)NULL
;
4147 m_canDragRowSize
= true;
4148 m_canDragColSize
= true;
4149 m_canDragGridSize
= true;
4150 m_canDragCell
= false;
4152 m_dragRowOrCol
= -1;
4153 m_isDragging
= false;
4154 m_startDragPos
= wxDefaultPosition
;
4156 m_waitForSlowClick
= false;
4158 m_rowResizeCursor
= wxCursor( wxCURSOR_SIZENS
);
4159 m_colResizeCursor
= wxCursor( wxCURSOR_SIZEWE
);
4161 m_currentCellCoords
= wxGridNoCellCoords
;
4163 m_selectingTopLeft
= wxGridNoCellCoords
;
4164 m_selectingBottomRight
= wxGridNoCellCoords
;
4165 m_selectionBackground
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
4166 m_selectionForeground
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
4168 m_editable
= true; // default for whole grid
4170 m_inOnKeyDown
= false;
4176 m_scrollLineX
= GRID_SCROLL_LINE_X
;
4177 m_scrollLineY
= GRID_SCROLL_LINE_Y
;
4180 // ----------------------------------------------------------------------------
4181 // the idea is to call these functions only when necessary because they create
4182 // quite big arrays which eat memory mostly unnecessary - in particular, if
4183 // default widths/heights are used for all rows/columns, we may not use these
4186 // with some extra code, it should be possible to only store the
4187 // widths/heights different from default ones but this will be done later...
4188 // ----------------------------------------------------------------------------
4190 void wxGrid::InitRowHeights()
4192 m_rowHeights
.Empty();
4193 m_rowBottoms
.Empty();
4195 m_rowHeights
.Alloc( m_numRows
);
4196 m_rowBottoms
.Alloc( m_numRows
);
4200 m_rowHeights
.Add( m_defaultRowHeight
, m_numRows
);
4202 for ( int i
= 0; i
< m_numRows
; i
++ )
4204 rowBottom
+= m_defaultRowHeight
;
4205 m_rowBottoms
.Add( rowBottom
);
4209 void wxGrid::InitColWidths()
4211 m_colWidths
.Empty();
4212 m_colRights
.Empty();
4214 m_colWidths
.Alloc( m_numCols
);
4215 m_colRights
.Alloc( m_numCols
);
4218 m_colWidths
.Add( m_defaultColWidth
, m_numCols
);
4220 for ( int i
= 0; i
< m_numCols
; i
++ )
4222 colRight
+= m_defaultColWidth
;
4223 m_colRights
.Add( colRight
);
4227 int wxGrid::GetColWidth(int col
) const
4229 return m_colWidths
.IsEmpty() ? m_defaultColWidth
: m_colWidths
[col
];
4232 int wxGrid::GetColLeft(int col
) const
4234 return m_colRights
.IsEmpty() ? col
* m_defaultColWidth
4235 : m_colRights
[col
] - m_colWidths
[col
];
4238 int wxGrid::GetColRight(int col
) const
4240 return m_colRights
.IsEmpty() ? (col
+ 1) * m_defaultColWidth
4244 int wxGrid::GetRowHeight(int row
) const
4246 return m_rowHeights
.IsEmpty() ? m_defaultRowHeight
: m_rowHeights
[row
];
4249 int wxGrid::GetRowTop(int row
) const
4251 return m_rowBottoms
.IsEmpty() ? row
* m_defaultRowHeight
4252 : m_rowBottoms
[row
] - m_rowHeights
[row
];
4255 int wxGrid::GetRowBottom(int row
) const
4257 return m_rowBottoms
.IsEmpty() ? (row
+ 1) * m_defaultRowHeight
4258 : m_rowBottoms
[row
];
4261 void wxGrid::CalcDimensions()
4264 GetClientSize( &cw
, &ch
);
4266 if ( m_rowLabelWin
->IsShown() )
4267 cw
-= m_rowLabelWidth
;
4268 if ( m_colLabelWin
->IsShown() )
4269 ch
-= m_colLabelHeight
;
4272 int w
= m_numCols
> 0 ? GetColRight(m_numCols
- 1) + m_extraWidth
+ 1 : 0;
4273 int h
= m_numRows
> 0 ? GetRowBottom(m_numRows
- 1) + m_extraHeight
+ 1 : 0;
4275 // take into account editor if shown
4276 if( IsCellEditControlShown() )
4279 int r
= m_currentCellCoords
.GetRow();
4280 int c
= m_currentCellCoords
.GetCol();
4281 int x
= GetColLeft(c
);
4282 int y
= GetRowTop(r
);
4284 // how big is the editor
4285 wxGridCellAttr
* attr
= GetCellAttr(r
, c
);
4286 wxGridCellEditor
* editor
= attr
->GetEditor(this, r
, c
);
4287 editor
->GetControl()->GetSize(&w2
, &h2
);
4290 if( w2
> w
) w
= w2
;
4291 if( h2
> h
) h
= h2
;
4296 // preserve (more or less) the previous position
4298 GetViewStart( &x
, &y
);
4300 // ensure the position is valid for the new scroll ranges
4302 x
= wxMax( w
- 1, 0 );
4304 y
= wxMax( h
- 1, 0 );
4306 // do set scrollbar parameters
4307 SetScrollbars( GRID_SCROLL_LINE_X
, GRID_SCROLL_LINE_Y
,
4308 GetScrollX(w
), GetScrollY(h
), x
, y
,
4309 GetBatchCount() != 0);
4311 // if our OnSize() hadn't been called (it would if we have scrollbars), we
4312 // still must reposition the children
4317 void wxGrid::CalcWindowSizes()
4319 // escape if the window is has not been fully created yet
4321 if ( m_cornerLabelWin
== NULL
)
4325 GetClientSize( &cw
, &ch
);
4327 if ( m_cornerLabelWin
&& m_cornerLabelWin
->IsShown() )
4328 m_cornerLabelWin
->SetSize( 0, 0, m_rowLabelWidth
, m_colLabelHeight
);
4330 if ( m_colLabelWin
&& m_colLabelWin
->IsShown() )
4331 m_colLabelWin
->SetSize( m_rowLabelWidth
, 0, cw
-m_rowLabelWidth
, m_colLabelHeight
);
4333 if ( m_rowLabelWin
&& m_rowLabelWin
->IsShown() )
4334 m_rowLabelWin
->SetSize( 0, m_colLabelHeight
, m_rowLabelWidth
, ch
-m_colLabelHeight
);
4336 if ( m_gridWin
&& m_gridWin
->IsShown() )
4337 m_gridWin
->SetSize( m_rowLabelWidth
, m_colLabelHeight
, cw
-m_rowLabelWidth
, ch
-m_colLabelHeight
);
4341 // this is called when the grid table sends a message to say that it
4342 // has been redimensioned
4344 bool wxGrid::Redimension( wxGridTableMessage
& msg
)
4347 bool result
= false;
4349 // Clear the attribute cache as the attribute might refer to a different
4350 // cell than stored in the cache after adding/removing rows/columns.
4352 // By the same reasoning, the editor should be dismissed if columns are
4353 // added or removed. And for consistency, it should IMHO always be
4354 // removed, not only if the cell "underneath" it actually changes.
4355 // For now, I intentionally do not save the editor's content as the
4356 // cell it might want to save that stuff to might no longer exist.
4357 HideCellEditControl();
4359 // if we were using the default widths/heights so far, we must change them
4361 if ( m_colWidths
.IsEmpty() )
4366 if ( m_rowHeights
.IsEmpty() )
4372 switch ( msg
.GetId() )
4374 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
4376 size_t pos
= msg
.GetCommandInt();
4377 int numRows
= msg
.GetCommandInt2();
4379 m_numRows
+= numRows
;
4381 if ( !m_rowHeights
.IsEmpty() )
4383 m_rowHeights
.Insert( m_defaultRowHeight
, pos
, numRows
);
4384 m_rowBottoms
.Insert( 0, pos
, numRows
);
4387 if ( pos
> 0 ) bottom
= m_rowBottoms
[pos
-1];
4389 for ( i
= pos
; i
< m_numRows
; i
++ )
4391 bottom
+= m_rowHeights
[i
];
4392 m_rowBottoms
[i
] = bottom
;
4395 if ( m_currentCellCoords
== wxGridNoCellCoords
)
4397 // if we have just inserted cols into an empty grid the current
4398 // cell will be undefined...
4400 SetCurrentCell( 0, 0 );
4404 m_selection
->UpdateRows( pos
, numRows
);
4405 wxGridCellAttrProvider
* attrProvider
= m_table
->GetAttrProvider();
4407 attrProvider
->UpdateAttrRows( pos
, numRows
);
4409 if ( !GetBatchCount() )
4412 m_rowLabelWin
->Refresh();
4418 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
4420 int numRows
= msg
.GetCommandInt();
4421 int oldNumRows
= m_numRows
;
4422 m_numRows
+= numRows
;
4424 if ( !m_rowHeights
.IsEmpty() )
4426 m_rowHeights
.Add( m_defaultRowHeight
, numRows
);
4427 m_rowBottoms
.Add( 0, numRows
);
4430 if ( oldNumRows
> 0 ) bottom
= m_rowBottoms
[oldNumRows
-1];
4432 for ( i
= oldNumRows
; i
< m_numRows
; i
++ )
4434 bottom
+= m_rowHeights
[i
];
4435 m_rowBottoms
[i
] = bottom
;
4438 if ( m_currentCellCoords
== wxGridNoCellCoords
)
4440 // if we have just inserted cols into an empty grid the current
4441 // cell will be undefined...
4443 SetCurrentCell( 0, 0 );
4445 if ( !GetBatchCount() )
4448 m_rowLabelWin
->Refresh();
4454 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
4456 size_t pos
= msg
.GetCommandInt();
4457 int numRows
= msg
.GetCommandInt2();
4458 m_numRows
-= numRows
;
4460 if ( !m_rowHeights
.IsEmpty() )
4462 m_rowHeights
.RemoveAt( pos
, numRows
);
4463 m_rowBottoms
.RemoveAt( pos
, numRows
);
4466 for ( i
= 0; i
< m_numRows
; i
++ )
4468 h
+= m_rowHeights
[i
];
4469 m_rowBottoms
[i
] = h
;
4474 m_currentCellCoords
= wxGridNoCellCoords
;
4478 if ( m_currentCellCoords
.GetRow() >= m_numRows
)
4479 m_currentCellCoords
.Set( 0, 0 );
4483 m_selection
->UpdateRows( pos
, -((int)numRows
) );
4484 wxGridCellAttrProvider
* attrProvider
= m_table
->GetAttrProvider();
4486 attrProvider
->UpdateAttrRows( pos
, -((int)numRows
) );
4487 // ifdef'd out following patch from Paul Gammans
4489 // No need to touch column attributes, unless we
4490 // removed _all_ rows, in this case, we remove
4491 // all column attributes.
4492 // I hate to do this here, but the
4493 // needed data is not available inside UpdateAttrRows.
4494 if ( !GetNumberRows() )
4495 attrProvider
->UpdateAttrCols( 0, -GetNumberCols() );
4498 if ( !GetBatchCount() )
4501 m_rowLabelWin
->Refresh();
4507 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
4509 size_t pos
= msg
.GetCommandInt();
4510 int numCols
= msg
.GetCommandInt2();
4511 m_numCols
+= numCols
;
4513 if ( !m_colWidths
.IsEmpty() )
4515 m_colWidths
.Insert( m_defaultColWidth
, pos
, numCols
);
4516 m_colRights
.Insert( 0, pos
, numCols
);
4519 if ( pos
> 0 ) right
= m_colRights
[pos
-1];
4521 for ( i
= pos
; i
< m_numCols
; i
++ )
4523 right
+= m_colWidths
[i
];
4524 m_colRights
[i
] = right
;
4527 if ( m_currentCellCoords
== wxGridNoCellCoords
)
4529 // if we have just inserted cols into an empty grid the current
4530 // cell will be undefined...
4532 SetCurrentCell( 0, 0 );
4536 m_selection
->UpdateCols( pos
, numCols
);
4537 wxGridCellAttrProvider
* attrProvider
= m_table
->GetAttrProvider();
4539 attrProvider
->UpdateAttrCols( pos
, numCols
);
4540 if ( !GetBatchCount() )
4543 m_colLabelWin
->Refresh();
4550 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
4552 int numCols
= msg
.GetCommandInt();
4553 int oldNumCols
= m_numCols
;
4554 m_numCols
+= numCols
;
4555 if ( !m_colWidths
.IsEmpty() )
4557 m_colWidths
.Add( m_defaultColWidth
, numCols
);
4558 m_colRights
.Add( 0, numCols
);
4561 if ( oldNumCols
> 0 ) right
= m_colRights
[oldNumCols
-1];
4563 for ( i
= oldNumCols
; i
< m_numCols
; i
++ )
4565 right
+= m_colWidths
[i
];
4566 m_colRights
[i
] = right
;
4569 if ( m_currentCellCoords
== wxGridNoCellCoords
)
4571 // if we have just inserted cols into an empty grid the current
4572 // cell will be undefined...
4574 SetCurrentCell( 0, 0 );
4576 if ( !GetBatchCount() )
4579 m_colLabelWin
->Refresh();
4585 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
4587 size_t pos
= msg
.GetCommandInt();
4588 int numCols
= msg
.GetCommandInt2();
4589 m_numCols
-= numCols
;
4591 if ( !m_colWidths
.IsEmpty() )
4593 m_colWidths
.RemoveAt( pos
, numCols
);
4594 m_colRights
.RemoveAt( pos
, numCols
);
4597 for ( i
= 0; i
< m_numCols
; i
++ )
4599 w
+= m_colWidths
[i
];
4605 m_currentCellCoords
= wxGridNoCellCoords
;
4609 if ( m_currentCellCoords
.GetCol() >= m_numCols
)
4610 m_currentCellCoords
.Set( 0, 0 );
4614 m_selection
->UpdateCols( pos
, -((int)numCols
) );
4615 wxGridCellAttrProvider
* attrProvider
= m_table
->GetAttrProvider();
4617 attrProvider
->UpdateAttrCols( pos
, -((int)numCols
) );
4618 // ifdef'd out following patch from Paul Gammans
4620 // No need to touch row attributes, unless we
4621 // removed _all_ columns, in this case, we remove
4622 // all row attributes.
4623 // I hate to do this here, but the
4624 // needed data is not available inside UpdateAttrCols.
4625 if ( !GetNumberCols() )
4626 attrProvider
->UpdateAttrRows( 0, -GetNumberRows() );
4629 if ( !GetBatchCount() )
4632 m_colLabelWin
->Refresh();
4639 if (result
&& !GetBatchCount() )
4640 m_gridWin
->Refresh();
4645 wxArrayInt
wxGrid::CalcRowLabelsExposed( const wxRegion
& reg
)
4647 wxRegionIterator
iter( reg
);
4650 wxArrayInt rowlabels
;
4657 // TODO: remove this when we can...
4658 // There is a bug in wxMotif that gives garbage update
4659 // rectangles if you jump-scroll a long way by clicking the
4660 // scrollbar with middle button. This is a work-around
4662 #if defined(__WXMOTIF__)
4664 m_gridWin
->GetClientSize( &cw
, &ch
);
4665 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
4666 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
4669 // logical bounds of update region
4672 CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top
);
4673 CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom
);
4675 // find the row labels within these bounds
4678 for ( row
= internalYToRow(top
); row
< m_numRows
; row
++ )
4680 if ( GetRowBottom(row
) < top
)
4683 if ( GetRowTop(row
) > bottom
)
4686 rowlabels
.Add( row
);
4696 wxArrayInt
wxGrid::CalcColLabelsExposed( const wxRegion
& reg
)
4698 wxRegionIterator
iter( reg
);
4701 wxArrayInt colLabels
;
4708 // TODO: remove this when we can...
4709 // There is a bug in wxMotif that gives garbage update
4710 // rectangles if you jump-scroll a long way by clicking the
4711 // scrollbar with middle button. This is a work-around
4713 #if defined(__WXMOTIF__)
4715 m_gridWin
->GetClientSize( &cw
, &ch
);
4716 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
4717 r
.SetRight( wxMin( r
.GetRight(), cw
) );
4720 // logical bounds of update region
4723 CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy
);
4724 CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy
);
4726 // find the cells within these bounds
4729 for ( col
= internalXToCol(left
); col
< m_numCols
; col
++ )
4731 if ( GetColRight(col
) < left
)
4734 if ( GetColLeft(col
) > right
)
4737 colLabels
.Add( col
);
4746 wxGridCellCoordsArray
wxGrid::CalcCellsExposed( const wxRegion
& reg
)
4748 wxRegionIterator
iter( reg
);
4751 wxGridCellCoordsArray cellsExposed
;
4753 int left
, top
, right
, bottom
;
4758 // TODO: remove this when we can...
4759 // There is a bug in wxMotif that gives garbage update
4760 // rectangles if you jump-scroll a long way by clicking the
4761 // scrollbar with middle button. This is a work-around
4763 #if defined(__WXMOTIF__)
4765 m_gridWin
->GetClientSize( &cw
, &ch
);
4766 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
4767 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
4768 r
.SetRight( wxMin( r
.GetRight(), cw
) );
4769 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
4772 // logical bounds of update region
4774 CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
4775 CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
4777 // find the cells within these bounds
4780 for ( row
= internalYToRow(top
); row
< m_numRows
; row
++ )
4782 if ( GetRowBottom(row
) <= top
)
4785 if ( GetRowTop(row
) > bottom
)
4788 for ( col
= internalXToCol(left
); col
< m_numCols
; col
++ )
4790 if ( GetColRight(col
) <= left
)
4793 if ( GetColLeft(col
) > right
)
4796 cellsExposed
.Add( wxGridCellCoords( row
, col
) );
4803 return cellsExposed
;
4807 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event
)
4810 wxPoint
pos( event
.GetPosition() );
4811 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
4813 if ( event
.Dragging() )
4817 m_isDragging
= true;
4818 m_rowLabelWin
->CaptureMouse();
4821 if ( event
.LeftIsDown() )
4823 switch( m_cursorMode
)
4825 case WXGRID_CURSOR_RESIZE_ROW
:
4827 int cw
, ch
, left
, dummy
;
4828 m_gridWin
->GetClientSize( &cw
, &ch
);
4829 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
4831 wxClientDC
dc( m_gridWin
);
4834 GetRowTop(m_dragRowOrCol
) +
4835 GetRowMinimalHeight(m_dragRowOrCol
) );
4836 dc
.SetLogicalFunction(wxINVERT
);
4837 if ( m_dragLastPos
>= 0 )
4839 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
4841 dc
.DrawLine( left
, y
, left
+cw
, y
);
4846 case WXGRID_CURSOR_SELECT_ROW
:
4847 if ( (row
= YToRow( y
)) >= 0 )
4851 m_selection
->SelectRow( row
,
4852 event
.ControlDown(),
4859 // default label to suppress warnings about "enumeration value
4860 // 'xxx' not handled in switch
4868 if ( m_isDragging
&& (event
.Entering() || event
.Leaving()) )
4873 if (m_rowLabelWin
->HasCapture()) m_rowLabelWin
->ReleaseMouse();
4874 m_isDragging
= false;
4877 // ------------ Entering or leaving the window
4879 if ( event
.Entering() || event
.Leaving() )
4881 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
);
4885 // ------------ Left button pressed
4887 else if ( event
.LeftDown() )
4889 // don't send a label click event for a hit on the
4890 // edge of the row label - this is probably the user
4891 // wanting to resize the row
4893 if ( YToEdgeOfRow(y
) < 0 )
4897 !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event
) )
4899 if ( !event
.ShiftDown() && !event
.ControlDown() )
4903 if ( event
.ShiftDown() )
4905 m_selection
->SelectBlock( m_currentCellCoords
.GetRow(),
4908 GetNumberCols() - 1,
4909 event
.ControlDown(),
4916 m_selection
->SelectRow( row
,
4917 event
.ControlDown(),
4924 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW
, m_rowLabelWin
);
4929 // starting to drag-resize a row
4931 if ( CanDragRowSize() )
4932 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
);
4937 // ------------ Left double click
4939 else if (event
.LeftDClick() )
4941 int row
= YToEdgeOfRow(y
);
4946 !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event
) )
4948 // no default action at the moment
4953 // adjust row height depending on label text
4954 AutoSizeRowLabelSize( row
);
4956 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
);
4962 // ------------ Left button released
4964 else if ( event
.LeftUp() )
4966 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
4968 DoEndDragResizeRow();
4970 // Note: we are ending the event *after* doing
4971 // default processing in this case
4973 SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event
);
4976 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
);
4981 // ------------ Right button down
4983 else if ( event
.RightDown() )
4987 !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event
) )
4989 // no default action at the moment
4994 // ------------ Right double click
4996 else if ( event
.RightDClick() )
5000 !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event
) )
5002 // no default action at the moment
5007 // ------------ No buttons down and mouse moving
5009 else if ( event
.Moving() )
5011 m_dragRowOrCol
= YToEdgeOfRow( y
);
5012 if ( m_dragRowOrCol
>= 0 )
5014 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5016 // don't capture the mouse yet
5017 if ( CanDragRowSize() )
5018 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
, m_rowLabelWin
, false);
5021 else if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
5023 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_rowLabelWin
, false);
5029 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event
)
5032 wxPoint
pos( event
.GetPosition() );
5033 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
5035 if ( event
.Dragging() )
5039 m_isDragging
= true;
5040 m_colLabelWin
->CaptureMouse();
5043 if ( event
.LeftIsDown() )
5045 switch( m_cursorMode
)
5047 case WXGRID_CURSOR_RESIZE_COL
:
5049 int cw
, ch
, dummy
, top
;
5050 m_gridWin
->GetClientSize( &cw
, &ch
);
5051 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
5053 wxClientDC
dc( m_gridWin
);
5056 x
= wxMax( x
, GetColLeft(m_dragRowOrCol
) +
5057 GetColMinimalWidth(m_dragRowOrCol
));
5058 dc
.SetLogicalFunction(wxINVERT
);
5059 if ( m_dragLastPos
>= 0 )
5061 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
5063 dc
.DrawLine( x
, top
, x
, top
+ch
);
5068 case WXGRID_CURSOR_SELECT_COL
:
5069 if ( (col
= XToCol( x
)) >= 0 )
5073 m_selection
->SelectCol( col
,
5074 event
.ControlDown(),
5081 // default label to suppress warnings about "enumeration value
5082 // 'xxx' not handled in switch
5090 if ( m_isDragging
&& (event
.Entering() || event
.Leaving()) )
5095 if (m_colLabelWin
->HasCapture()) m_colLabelWin
->ReleaseMouse();
5096 m_isDragging
= false;
5099 // ------------ Entering or leaving the window
5101 if ( event
.Entering() || event
.Leaving() )
5103 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
);
5107 // ------------ Left button pressed
5109 else if ( event
.LeftDown() )
5111 // don't send a label click event for a hit on the
5112 // edge of the col label - this is probably the user
5113 // wanting to resize the col
5115 if ( XToEdgeOfCol(x
) < 0 )
5119 !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event
) )
5121 if ( !event
.ShiftDown() && !event
.ControlDown() )
5125 if ( event
.ShiftDown() )
5127 m_selection
->SelectBlock( 0,
5128 m_currentCellCoords
.GetCol(),
5129 GetNumberRows() - 1, col
,
5130 event
.ControlDown(),
5137 m_selection
->SelectCol( col
,
5138 event
.ControlDown(),
5145 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL
, m_colLabelWin
);
5150 // starting to drag-resize a col
5152 if ( CanDragColSize() )
5153 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
);
5158 // ------------ Left double click
5160 if ( event
.LeftDClick() )
5162 int col
= XToEdgeOfCol(x
);
5167 ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event
) )
5169 // no default action at the moment
5174 // adjust column width depending on label text
5175 AutoSizeColLabelSize( col
);
5177 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
);
5183 // ------------ Left button released
5185 else if ( event
.LeftUp() )
5187 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
5189 DoEndDragResizeCol();
5191 // Note: we are ending the event *after* doing
5192 // default processing in this case
5194 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event
);
5197 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
);
5202 // ------------ Right button down
5204 else if ( event
.RightDown() )
5208 !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event
) )
5210 // no default action at the moment
5215 // ------------ Right double click
5217 else if ( event
.RightDClick() )
5221 !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event
) )
5223 // no default action at the moment
5228 // ------------ No buttons down and mouse moving
5230 else if ( event
.Moving() )
5232 m_dragRowOrCol
= XToEdgeOfCol( x
);
5233 if ( m_dragRowOrCol
>= 0 )
5235 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5237 // don't capture the cursor yet
5238 if ( CanDragColSize() )
5239 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
, m_colLabelWin
, false);
5242 else if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
5244 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
, m_colLabelWin
, false);
5250 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event
)
5252 if ( event
.LeftDown() )
5254 // indicate corner label by having both row and
5257 if ( !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event
) )
5263 else if ( event
.LeftDClick() )
5265 SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event
);
5268 else if ( event
.RightDown() )
5270 if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event
) )
5272 // no default action at the moment
5276 else if ( event
.RightDClick() )
5278 if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event
) )
5280 // no default action at the moment
5285 void wxGrid::ChangeCursorMode(CursorMode mode
,
5290 static const wxChar
*cursorModes
[] =
5299 wxLogTrace(_T("grid"),
5300 _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"),
5301 win
== m_colLabelWin
? _T("colLabelWin")
5302 : win
? _T("rowLabelWin")
5304 cursorModes
[m_cursorMode
], cursorModes
[mode
]);
5305 #endif // __WXDEBUG__
5307 if ( mode
== m_cursorMode
&&
5308 win
== m_winCapture
&&
5309 captureMouse
== (m_winCapture
!= NULL
))
5314 // by default use the grid itself
5320 if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse();
5321 m_winCapture
= (wxWindow
*)NULL
;
5324 m_cursorMode
= mode
;
5326 switch ( m_cursorMode
)
5328 case WXGRID_CURSOR_RESIZE_ROW
:
5329 win
->SetCursor( m_rowResizeCursor
);
5332 case WXGRID_CURSOR_RESIZE_COL
:
5333 win
->SetCursor( m_colResizeCursor
);
5337 win
->SetCursor( *wxSTANDARD_CURSOR
);
5340 // we need to capture mouse when resizing
5341 bool resize
= m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
||
5342 m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
;
5344 if ( captureMouse
&& resize
)
5346 win
->CaptureMouse();
5351 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event
)
5354 wxPoint
pos( event
.GetPosition() );
5355 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
5357 wxGridCellCoords coords
;
5358 XYToCell( x
, y
, coords
);
5360 int cell_rows
, cell_cols
;
5361 bool isFirstDrag
= !m_isDragging
;
5362 GetCellSize( coords
.GetRow(), coords
.GetCol(), &cell_rows
, &cell_cols
);
5363 if ((cell_rows
< 0) || (cell_cols
< 0))
5365 coords
.SetRow(coords
.GetRow() + cell_rows
);
5366 coords
.SetCol(coords
.GetCol() + cell_cols
);
5369 if ( event
.Dragging() )
5371 //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol());
5373 // Don't start doing anything until the mouse has been drug at
5374 // least 3 pixels in any direction...
5377 if (m_startDragPos
== wxDefaultPosition
)
5379 m_startDragPos
= pos
;
5382 if (abs(m_startDragPos
.x
- pos
.x
) < 4 && abs(m_startDragPos
.y
- pos
.y
) < 4)
5386 m_isDragging
= true;
5387 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5389 // Hide the edit control, so it
5390 // won't interfer with drag-shrinking.
5391 if ( IsCellEditControlShown() )
5393 HideCellEditControl();
5394 SaveEditControlValue();
5397 // Have we captured the mouse yet?
5400 m_winCapture
= m_gridWin
;
5401 m_winCapture
->CaptureMouse();
5404 if ( coords
!= wxGridNoCellCoords
)
5406 if ( event
.ControlDown() )
5408 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
5409 m_selectingKeyboard
= coords
;
5410 HighlightBlock ( m_selectingKeyboard
, coords
);
5412 else if ( CanDragCell() )
5416 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
5417 m_selectingKeyboard
= coords
;
5419 SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG
,
5427 if ( !IsSelection() )
5429 HighlightBlock( coords
, coords
);
5433 HighlightBlock( m_currentCellCoords
, coords
);
5437 if (! IsVisible(coords
))
5439 MakeCellVisible(coords
);
5440 // TODO: need to introduce a delay or something here. The
5441 // scrolling is way to fast, at least on MSW - also on GTK.
5445 else if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
5447 int cw
, ch
, left
, dummy
;
5448 m_gridWin
->GetClientSize( &cw
, &ch
);
5449 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
5451 wxClientDC
dc( m_gridWin
);
5453 y
= wxMax( y
, GetRowTop(m_dragRowOrCol
) +
5454 GetRowMinimalHeight(m_dragRowOrCol
) );
5455 dc
.SetLogicalFunction(wxINVERT
);
5456 if ( m_dragLastPos
>= 0 )
5458 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
5460 dc
.DrawLine( left
, y
, left
+cw
, y
);
5463 else if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
5465 int cw
, ch
, dummy
, top
;
5466 m_gridWin
->GetClientSize( &cw
, &ch
);
5467 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
5469 wxClientDC
dc( m_gridWin
);
5471 x
= wxMax( x
, GetColLeft(m_dragRowOrCol
) +
5472 GetColMinimalWidth(m_dragRowOrCol
) );
5473 dc
.SetLogicalFunction(wxINVERT
);
5474 if ( m_dragLastPos
>= 0 )
5476 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
5478 dc
.DrawLine( x
, top
, x
, top
+ch
);
5485 m_isDragging
= false;
5486 m_startDragPos
= wxDefaultPosition
;
5488 // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
5489 // immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
5492 if ( event
.Entering() || event
.Leaving() )
5494 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5495 m_gridWin
->SetCursor( *wxSTANDARD_CURSOR
);
5500 // ------------ Left button pressed
5502 if ( event
.LeftDown() && coords
!= wxGridNoCellCoords
)
5504 if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK
,
5509 if ( !event
.ControlDown() )
5511 if ( event
.ShiftDown() )
5515 m_selection
->SelectBlock( m_currentCellCoords
.GetRow(),
5516 m_currentCellCoords
.GetCol(),
5519 event
.ControlDown(),
5525 else if ( XToEdgeOfCol(x
) < 0 &&
5526 YToEdgeOfRow(y
) < 0 )
5528 DisableCellEditControl();
5529 MakeCellVisible( coords
);
5531 if ( event
.ControlDown() )
5535 m_selection
->ToggleCellSelection( coords
.GetRow(),
5537 event
.ControlDown(),
5542 m_selectingTopLeft
= wxGridNoCellCoords
;
5543 m_selectingBottomRight
= wxGridNoCellCoords
;
5544 m_selectingKeyboard
= coords
;
5548 m_waitForSlowClick
= m_currentCellCoords
== coords
&& coords
!= wxGridNoCellCoords
;
5549 SetCurrentCell( coords
);
5552 if ( m_selection
->GetSelectionMode() !=
5553 wxGrid::wxGridSelectCells
)
5555 HighlightBlock( coords
, coords
);
5564 // ------------ Left double click
5566 else if ( event
.LeftDClick() && coords
!= wxGridNoCellCoords
)
5568 DisableCellEditControl();
5570 if ( XToEdgeOfCol(x
) < 0 && YToEdgeOfRow(y
) < 0 )
5572 if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK
,
5577 // we want double click to select a cell and start editing
5578 // (i.e. to behave in same way as sequence of two slow clicks):
5579 m_waitForSlowClick
= true;
5586 // ------------ Left button released
5588 else if ( event
.LeftUp() )
5590 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5594 if (m_winCapture
->HasCapture()) m_winCapture
->ReleaseMouse();
5595 m_winCapture
= NULL
;
5598 if ( coords
== m_currentCellCoords
&& m_waitForSlowClick
&& CanEnableCellControl())
5601 EnableCellEditControl();
5603 wxGridCellAttr
* attr
= GetCellAttr(coords
);
5604 wxGridCellEditor
*editor
= attr
->GetEditor(this, coords
.GetRow(), coords
.GetCol());
5605 editor
->StartingClick();
5609 m_waitForSlowClick
= false;
5611 else if ( m_selectingTopLeft
!= wxGridNoCellCoords
&&
5612 m_selectingBottomRight
!= wxGridNoCellCoords
)
5616 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(),
5617 m_selectingTopLeft
.GetCol(),
5618 m_selectingBottomRight
.GetRow(),
5619 m_selectingBottomRight
.GetCol(),
5620 event
.ControlDown(),
5626 m_selectingTopLeft
= wxGridNoCellCoords
;
5627 m_selectingBottomRight
= wxGridNoCellCoords
;
5629 // Show the edit control, if it has been hidden for
5631 ShowCellEditControl();
5634 else if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
5636 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5637 DoEndDragResizeRow();
5639 // Note: we are ending the event *after* doing
5640 // default processing in this case
5642 SendEvent( wxEVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event
);
5644 else if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
5646 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5647 DoEndDragResizeCol();
5649 // Note: we are ending the event *after* doing
5650 // default processing in this case
5652 SendEvent( wxEVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event
);
5659 // ------------ Right button down
5661 else if ( event
.RightDown() && coords
!= wxGridNoCellCoords
)
5663 DisableCellEditControl();
5664 if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK
,
5669 // no default action at the moment
5674 // ------------ Right double click
5676 else if ( event
.RightDClick() && coords
!= wxGridNoCellCoords
)
5678 DisableCellEditControl();
5679 if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK
,
5684 // no default action at the moment
5688 // ------------ Moving and no button action
5690 else if ( event
.Moving() && !event
.IsButton() )
5692 if( coords
.GetRow() < 0 || coords
.GetCol() < 0 )
5694 // out of grid cell area
5695 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5699 int dragRow
= YToEdgeOfRow( y
);
5700 int dragCol
= XToEdgeOfCol( x
);
5702 // Dragging on the corner of a cell to resize in both
5703 // directions is not implemented yet...
5705 if ( dragRow
>= 0 && dragCol
>= 0 )
5707 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5713 m_dragRowOrCol
= dragRow
;
5715 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5717 if ( CanDragRowSize() && CanDragGridSize() )
5718 ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW
);
5723 m_dragRowOrCol
= dragCol
;
5731 m_dragRowOrCol
= dragCol
;
5733 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
5735 if ( CanDragColSize() && CanDragGridSize() )
5736 ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL
);
5742 // Neither on a row or col edge
5744 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
5746 ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL
);
5752 void wxGrid::DoEndDragResizeRow()
5754 if ( m_dragLastPos
>= 0 )
5756 // erase the last line and resize the row
5758 int cw
, ch
, left
, dummy
;
5759 m_gridWin
->GetClientSize( &cw
, &ch
);
5760 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
5762 wxClientDC
dc( m_gridWin
);
5764 dc
.SetLogicalFunction( wxINVERT
);
5765 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
5766 HideCellEditControl();
5767 SaveEditControlValue();
5769 int rowTop
= GetRowTop(m_dragRowOrCol
);
5770 SetRowSize( m_dragRowOrCol
,
5771 wxMax( m_dragLastPos
- rowTop
, m_minAcceptableRowHeight
) );
5773 if ( !GetBatchCount() )
5775 // Only needed to get the correct rect.y:
5776 wxRect
rect ( CellToRect( m_dragRowOrCol
, 0 ) );
5778 CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
);
5779 rect
.width
= m_rowLabelWidth
;
5780 rect
.height
= ch
- rect
.y
;
5781 m_rowLabelWin
->Refresh( true, &rect
);
5783 // if there is a multicell block, paint all of it
5786 int i
, cell_rows
, cell_cols
, subtract_rows
= 0;
5787 int leftCol
= XToCol(left
);
5788 int rightCol
= internalXToCol(left
+cw
);
5791 for (i
=leftCol
; i
<rightCol
; i
++)
5793 GetCellSize(m_dragRowOrCol
, i
, &cell_rows
, &cell_cols
);
5794 if (cell_rows
< subtract_rows
)
5795 subtract_rows
= cell_rows
;
5797 rect
.y
= GetRowTop(m_dragRowOrCol
+ subtract_rows
);
5798 CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
);
5799 rect
.height
= ch
- rect
.y
;
5802 m_gridWin
->Refresh( false, &rect
);
5805 ShowCellEditControl();
5810 void wxGrid::DoEndDragResizeCol()
5812 if ( m_dragLastPos
>= 0 )
5814 // erase the last line and resize the col
5816 int cw
, ch
, dummy
, top
;
5817 m_gridWin
->GetClientSize( &cw
, &ch
);
5818 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
5820 wxClientDC
dc( m_gridWin
);
5822 dc
.SetLogicalFunction( wxINVERT
);
5823 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
5824 HideCellEditControl();
5825 SaveEditControlValue();
5827 int colLeft
= GetColLeft(m_dragRowOrCol
);
5828 SetColSize( m_dragRowOrCol
,
5829 wxMax( m_dragLastPos
- colLeft
,
5830 GetColMinimalWidth(m_dragRowOrCol
) ) );
5832 if ( !GetBatchCount() )
5834 // Only needed to get the correct rect.x:
5835 wxRect
rect ( CellToRect( 0, m_dragRowOrCol
) );
5837 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
);
5838 rect
.width
= cw
- rect
.x
;
5839 rect
.height
= m_colLabelHeight
;
5840 m_colLabelWin
->Refresh( true, &rect
);
5842 // if there is a multicell block, paint all of it
5845 int i
, cell_rows
, cell_cols
, subtract_cols
= 0;
5846 int topRow
= YToRow(top
);
5847 int bottomRow
= internalYToRow(top
+cw
);
5850 for (i
=topRow
; i
<bottomRow
; i
++)
5852 GetCellSize(i
, m_dragRowOrCol
, &cell_rows
, &cell_cols
);
5853 if (cell_cols
< subtract_cols
)
5854 subtract_cols
= cell_cols
;
5856 rect
.x
= GetColLeft(m_dragRowOrCol
+ subtract_cols
);
5857 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
);
5858 rect
.width
= cw
- rect
.x
;
5861 m_gridWin
->Refresh( false, &rect
);
5864 ShowCellEditControl();
5871 // ------ interaction with data model
5873 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg
)
5875 switch ( msg
.GetId() )
5877 case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
:
5878 return GetModelValues();
5880 case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
:
5881 return SetModelValues();
5883 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
5884 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
5885 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
5886 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
5887 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
5888 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
5889 return Redimension( msg
);
5898 // The behaviour of this function depends on the grid table class
5899 // Clear() function. For the default wxGridStringTable class the
5900 // behavious is to replace all cell contents with wxEmptyString but
5901 // not to change the number of rows or cols.
5903 void wxGrid::ClearGrid()
5907 if (IsCellEditControlEnabled())
5908 DisableCellEditControl();
5911 if ( !GetBatchCount() ) m_gridWin
->Refresh();
5916 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
5918 // TODO: something with updateLabels flag
5922 wxFAIL_MSG( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") );
5928 if (IsCellEditControlEnabled())
5929 DisableCellEditControl();
5931 bool done
= m_table
->InsertRows( pos
, numRows
);
5934 // the table will have sent the results of the insert row
5935 // operation to this view object as a grid table message
5941 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) )
5943 // TODO: something with updateLabels flag
5947 wxFAIL_MSG( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") );
5953 bool done
= m_table
&& m_table
->AppendRows( numRows
);
5955 // the table will have sent the results of the append row
5956 // operation to this view object as a grid table message
5962 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
5964 // TODO: something with updateLabels flag
5968 wxFAIL_MSG( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") );
5974 if (IsCellEditControlEnabled())
5975 DisableCellEditControl();
5977 bool done
= m_table
->DeleteRows( pos
, numRows
);
5979 // the table will have sent the results of the delete row
5980 // operation to this view object as a grid table message
5986 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
5988 // TODO: something with updateLabels flag
5992 wxFAIL_MSG( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") );
5998 if (IsCellEditControlEnabled())
5999 DisableCellEditControl();
6001 bool done
= m_table
->InsertCols( pos
, numCols
);
6003 // the table will have sent the results of the insert col
6004 // operation to this view object as a grid table message
6010 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) )
6012 // TODO: something with updateLabels flag
6016 wxFAIL_MSG( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") );
6022 bool done
= m_table
->AppendCols( numCols
);
6024 // the table will have sent the results of the append col
6025 // operation to this view object as a grid table message
6031 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
6033 // TODO: something with updateLabels flag
6037 wxFAIL_MSG( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") );
6043 if (IsCellEditControlEnabled())
6044 DisableCellEditControl();
6046 bool done
= m_table
->DeleteCols( pos
, numCols
);
6048 // the table will have sent the results of the delete col
6049 // operation to this view object as a grid table message
6057 // ----- event handlers
6060 // Generate a grid event based on a mouse event and
6061 // return the result of ProcessEvent()
6063 int wxGrid::SendEvent( const wxEventType type
,
6065 wxMouseEvent
& mouseEv
)
6070 if ( type
== wxEVT_GRID_ROW_SIZE
|| type
== wxEVT_GRID_COL_SIZE
)
6072 int rowOrCol
= (row
== -1 ? col
: row
);
6074 wxGridSizeEvent
gridEvt( GetId(),
6078 mouseEv
.GetX() + GetRowLabelSize(),
6079 mouseEv
.GetY() + GetColLabelSize(),
6080 mouseEv
.ControlDown(),
6081 mouseEv
.ShiftDown(),
6083 mouseEv
.MetaDown() );
6085 claimed
= GetEventHandler()->ProcessEvent(gridEvt
);
6086 vetoed
= !gridEvt
.IsAllowed();
6088 else if ( type
== wxEVT_GRID_RANGE_SELECT
)
6090 // Right now, it should _never_ end up here!
6091 wxGridRangeSelectEvent
gridEvt( GetId(),
6095 m_selectingBottomRight
,
6097 mouseEv
.ControlDown(),
6098 mouseEv
.ShiftDown(),
6100 mouseEv
.MetaDown() );
6102 claimed
= GetEventHandler()->ProcessEvent(gridEvt
);
6103 vetoed
= !gridEvt
.IsAllowed();
6107 wxGridEvent
gridEvt( GetId(),
6111 mouseEv
.GetX() + GetRowLabelSize(),
6112 mouseEv
.GetY() + GetColLabelSize(),
6114 mouseEv
.ControlDown(),
6115 mouseEv
.ShiftDown(),
6117 mouseEv
.MetaDown() );
6118 claimed
= GetEventHandler()->ProcessEvent(gridEvt
);
6119 vetoed
= !gridEvt
.IsAllowed();
6122 // A Veto'd event may not be `claimed' so test this first
6123 if (vetoed
) return -1;
6124 return claimed
? 1 : 0;
6128 // Generate a grid event of specified type and return the result
6129 // of ProcessEvent().
6131 int wxGrid::SendEvent( const wxEventType type
,
6137 if ( type
== wxEVT_GRID_ROW_SIZE
|| type
== wxEVT_GRID_COL_SIZE
)
6139 int rowOrCol
= (row
== -1 ? col
: row
);
6141 wxGridSizeEvent
gridEvt( GetId(),
6146 claimed
= GetEventHandler()->ProcessEvent(gridEvt
);
6147 vetoed
= !gridEvt
.IsAllowed();
6151 wxGridEvent
gridEvt( GetId(),
6156 claimed
= GetEventHandler()->ProcessEvent(gridEvt
);
6157 vetoed
= !gridEvt
.IsAllowed();
6160 // A Veto'd event may not be `claimed' so test this first
6161 if (vetoed
) return -1;
6162 return claimed
? 1 : 0;
6166 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
6168 wxPaintDC
dc(this); // needed to prevent zillions of paint events on MSW
6171 void wxGrid::Refresh(bool eraseb
, const wxRect
* rect
)
6173 // Don't do anything if between Begin/EndBatch...
6174 // EndBatch() will do all this on the last nested one anyway.
6175 if (! GetBatchCount())
6177 // Refresh to get correct scrolled position:
6178 wxScrolledWindow::Refresh(eraseb
,rect
);
6182 int rect_x
, rect_y
, rectWidth
, rectHeight
;
6183 int width_label
, width_cell
, height_label
, height_cell
;
6186 //Copy rectangle can get scroll offsets..
6187 rect_x
= rect
->GetX();
6188 rect_y
= rect
->GetY();
6189 rectWidth
= rect
->GetWidth();
6190 rectHeight
= rect
->GetHeight();
6192 width_label
= m_rowLabelWidth
- rect_x
;
6193 if (width_label
> rectWidth
) width_label
= rectWidth
;
6195 height_label
= m_colLabelHeight
- rect_y
;
6196 if (height_label
> rectHeight
) height_label
= rectHeight
;
6198 if (rect_x
> m_rowLabelWidth
)
6200 x
= rect_x
- m_rowLabelWidth
;
6201 width_cell
= rectWidth
;
6206 width_cell
= rectWidth
- (m_rowLabelWidth
- rect_x
);
6209 if (rect_y
> m_colLabelHeight
)
6211 y
= rect_y
- m_colLabelHeight
;
6212 height_cell
= rectHeight
;
6217 height_cell
= rectHeight
- (m_colLabelHeight
- rect_y
);
6220 // Paint corner label part intersecting rect.
6221 if ( width_label
> 0 && height_label
> 0 )
6223 wxRect
anotherrect(rect_x
, rect_y
, width_label
, height_label
);
6224 m_cornerLabelWin
->Refresh(eraseb
, &anotherrect
);
6227 // Paint col labels part intersecting rect.
6228 if ( width_cell
> 0 && height_label
> 0 )
6230 wxRect
anotherrect(x
, rect_y
, width_cell
, height_label
);
6231 m_colLabelWin
->Refresh(eraseb
, &anotherrect
);
6234 // Paint row labels part intersecting rect.
6235 if ( width_label
> 0 && height_cell
> 0 )
6237 wxRect
anotherrect(rect_x
, y
, width_label
, height_cell
);
6238 m_rowLabelWin
->Refresh(eraseb
, &anotherrect
);
6241 // Paint cell area part intersecting rect.
6242 if ( width_cell
> 0 && height_cell
> 0 )
6244 wxRect
anotherrect(x
, y
, width_cell
, height_cell
);
6245 m_gridWin
->Refresh(eraseb
, &anotherrect
);
6250 m_cornerLabelWin
->Refresh(eraseb
, NULL
);
6251 m_colLabelWin
->Refresh(eraseb
, NULL
);
6252 m_rowLabelWin
->Refresh(eraseb
, NULL
);
6253 m_gridWin
->Refresh(eraseb
, NULL
);
6258 void wxGrid::OnSize( wxSizeEvent
& event
)
6260 // position the child windows
6263 // don't call CalcDimensions() from here, the base class handles the size
6269 void wxGrid::OnKeyDown( wxKeyEvent
& event
)
6271 if ( m_inOnKeyDown
)
6273 // shouldn't be here - we are going round in circles...
6275 wxFAIL_MSG( wxT("wxGrid::OnKeyDown called while already active") );
6278 m_inOnKeyDown
= true;
6280 // propagate the event up and see if it gets processed
6282 wxWindow
*parent
= GetParent();
6283 wxKeyEvent
keyEvt( event
);
6284 keyEvt
.SetEventObject( parent
);
6286 if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt
) )
6289 // try local handlers
6291 switch ( event
.GetKeyCode() )
6294 if ( event
.ControlDown() )
6296 MoveCursorUpBlock( event
.ShiftDown() );
6300 MoveCursorUp( event
.ShiftDown() );
6305 if ( event
.ControlDown() )
6307 MoveCursorDownBlock( event
.ShiftDown() );
6311 MoveCursorDown( event
.ShiftDown() );
6316 if ( event
.ControlDown() )
6318 MoveCursorLeftBlock( event
.ShiftDown() );
6322 MoveCursorLeft( event
.ShiftDown() );
6327 if ( event
.ControlDown() )
6329 MoveCursorRightBlock( event
.ShiftDown() );
6333 MoveCursorRight( event
.ShiftDown() );
6338 case WXK_NUMPAD_ENTER
:
6339 if ( event
.ControlDown() )
6341 event
.Skip(); // to let the edit control have the return
6345 if ( GetGridCursorRow() < GetNumberRows()-1 )
6347 MoveCursorDown( event
.ShiftDown() );
6351 // at the bottom of a column
6352 DisableCellEditControl();
6362 if (event
.ShiftDown())
6364 if ( GetGridCursorCol() > 0 )
6366 MoveCursorLeft( false );
6371 DisableCellEditControl();
6376 if ( GetGridCursorCol() < GetNumberCols()-1 )
6378 MoveCursorRight( false );
6383 DisableCellEditControl();
6389 if ( event
.ControlDown() )
6391 MakeCellVisible( 0, 0 );
6392 SetCurrentCell( 0, 0 );
6401 if ( event
.ControlDown() )
6403 MakeCellVisible( m_numRows
-1, m_numCols
-1 );
6404 SetCurrentCell( m_numRows
-1, m_numCols
-1 );
6421 if ( event
.ControlDown() )
6425 m_selection
->ToggleCellSelection( m_currentCellCoords
.GetRow(),
6426 m_currentCellCoords
.GetCol(),
6427 event
.ControlDown(),
6434 if ( !IsEditable() )
6436 MoveCursorRight( false );
6439 // Otherwise fall through to default
6442 // is it possible to edit the current cell at all?
6443 if ( !IsCellEditControlEnabled() && CanEnableCellControl() )
6445 // yes, now check whether the cells editor accepts the key
6446 int row
= m_currentCellCoords
.GetRow();
6447 int col
= m_currentCellCoords
.GetCol();
6448 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
6449 wxGridCellEditor
*editor
= attr
->GetEditor(this, row
, col
);
6451 // <F2> is special and will always start editing, for
6452 // other keys - ask the editor itself
6453 if ( (event
.GetKeyCode() == WXK_F2
&& !event
.HasModifiers())
6454 || editor
->IsAcceptedKey(event
) )
6456 // ensure cell is visble
6457 MakeCellVisible(row
, col
);
6458 EnableCellEditControl();
6460 // a problem can arise if the cell is not completely
6461 // visible (even after calling MakeCellVisible the
6462 // control is not created and calling StartingKey will
6464 if( editor
->IsCreated() && m_cellEditCtrlEnabled
) editor
->StartingKey(event
);
6476 // let others process char events with modifiers or all
6477 // char events for readonly cells
6484 m_inOnKeyDown
= false;
6487 void wxGrid::OnKeyUp( wxKeyEvent
& event
)
6489 // try local handlers
6491 if ( event
.GetKeyCode() == WXK_SHIFT
)
6493 if ( m_selectingTopLeft
!= wxGridNoCellCoords
&&
6494 m_selectingBottomRight
!= wxGridNoCellCoords
)
6498 m_selection
->SelectBlock( m_selectingTopLeft
.GetRow(),
6499 m_selectingTopLeft
.GetCol(),
6500 m_selectingBottomRight
.GetRow(),
6501 m_selectingBottomRight
.GetCol(),
6502 event
.ControlDown(),
6509 m_selectingTopLeft
= wxGridNoCellCoords
;
6510 m_selectingBottomRight
= wxGridNoCellCoords
;
6511 m_selectingKeyboard
= wxGridNoCellCoords
;
6515 void wxGrid::OnEraseBackground(wxEraseEvent
&)
6519 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords
)
6521 if ( SendEvent( wxEVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) )
6523 // the event has been intercepted - do nothing
6527 wxClientDC
dc(m_gridWin
);
6530 if ( m_currentCellCoords
!= wxGridNoCellCoords
)
6532 DisableCellEditControl();
6534 if ( IsVisible( m_currentCellCoords
, false ) )
6537 r
= BlockToDeviceRect(m_currentCellCoords
, m_currentCellCoords
);
6538 if ( !m_gridLinesEnabled
)
6546 wxGridCellCoordsArray cells
= CalcCellsExposed( r
);
6548 // Otherwise refresh redraws the highlight!
6549 m_currentCellCoords
= coords
;
6551 DrawGridCellArea(dc
,cells
);
6552 DrawAllGridLines( dc
, r
);
6556 m_currentCellCoords
= coords
;
6558 wxGridCellAttr
* attr
= GetCellAttr(coords
);
6559 DrawCellHighlight(dc
, attr
);
6564 void wxGrid::HighlightBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
6567 wxGridCellCoords updateTopLeft
, updateBottomRight
;
6571 if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows
)
6574 rightCol
= GetNumberCols() - 1;
6576 else if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns
)
6579 bottomRow
= GetNumberRows() - 1;
6583 if ( topRow
> bottomRow
)
6590 if ( leftCol
> rightCol
)
6597 updateTopLeft
= wxGridCellCoords( topRow
, leftCol
);
6598 updateBottomRight
= wxGridCellCoords( bottomRow
, rightCol
);
6600 // First the case that we selected a completely new area
6601 if ( m_selectingTopLeft
== wxGridNoCellCoords
||
6602 m_selectingBottomRight
== wxGridNoCellCoords
)
6605 rect
= BlockToDeviceRect( wxGridCellCoords ( topRow
, leftCol
),
6606 wxGridCellCoords ( bottomRow
, rightCol
) );
6607 m_gridWin
->Refresh( false, &rect
);
6609 // Now handle changing an existing selection area.
6610 else if ( m_selectingTopLeft
!= updateTopLeft
||
6611 m_selectingBottomRight
!= updateBottomRight
)
6613 // Compute two optimal update rectangles:
6614 // Either one rectangle is a real subset of the
6615 // other, or they are (almost) disjoint!
6617 bool need_refresh
[4];
6621 need_refresh
[3] = false;
6624 // Store intermediate values
6625 wxCoord oldLeft
= m_selectingTopLeft
.GetCol();
6626 wxCoord oldTop
= m_selectingTopLeft
.GetRow();
6627 wxCoord oldRight
= m_selectingBottomRight
.GetCol();
6628 wxCoord oldBottom
= m_selectingBottomRight
.GetRow();
6630 // Determine the outer/inner coordinates.
6631 if (oldLeft
> leftCol
)
6637 if (oldTop
> topRow
)
6643 if (oldRight
< rightCol
)
6646 oldRight
= rightCol
;
6649 if (oldBottom
< bottomRow
)
6652 oldBottom
= bottomRow
;
6656 // Now, either the stuff marked old is the outer
6657 // rectangle or we don't have a situation where one
6658 // is contained in the other.
6660 if ( oldLeft
< leftCol
)
6662 // Refresh the newly selected or deselected
6663 // area to the left of the old or new selection.
6664 need_refresh
[0] = true;
6665 rect
[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop
,
6667 wxGridCellCoords ( oldBottom
,
6671 if ( oldTop
< topRow
)
6673 // Refresh the newly selected or deselected
6674 // area above the old or new selection.
6675 need_refresh
[1] = true;
6676 rect
[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop
,
6678 wxGridCellCoords ( topRow
- 1,
6682 if ( oldRight
> rightCol
)
6684 // Refresh the newly selected or deselected
6685 // area to the right of the old or new selection.
6686 need_refresh
[2] = true;
6687 rect
[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop
,
6689 wxGridCellCoords ( oldBottom
,
6693 if ( oldBottom
> bottomRow
)
6695 // Refresh the newly selected or deselected
6696 // area below the old or new selection.
6697 need_refresh
[3] = true;
6698 rect
[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow
+ 1,
6700 wxGridCellCoords ( oldBottom
,
6704 // various Refresh() calls
6705 for (i
= 0; i
< 4; i
++ )
6706 if ( need_refresh
[i
] && rect
[i
] != wxGridNoCellRect
)
6707 m_gridWin
->Refresh( false, &(rect
[i
]) );
6710 m_selectingTopLeft
= updateTopLeft
;
6711 m_selectingBottomRight
= updateBottomRight
;
6715 // ------ functions to get/send data (see also public functions)
6718 bool wxGrid::GetModelValues()
6720 // Hide the editor, so it won't hide a changed value.
6721 HideCellEditControl();
6725 // all we need to do is repaint the grid
6727 m_gridWin
->Refresh();
6735 bool wxGrid::SetModelValues()
6739 // Disable the editor, so it won't hide a changed value.
6740 // Do we also want to save the current value of the editor first?
6742 DisableCellEditControl();
6746 for ( row
= 0; row
< m_numRows
; row
++ )
6748 for ( col
= 0; col
< m_numCols
; col
++ )
6750 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) );
6762 // Note - this function only draws cells that are in the list of
6763 // exposed cells (usually set from the update region by
6764 // CalcExposedCells)
6766 void wxGrid::DrawGridCellArea( wxDC
& dc
, const wxGridCellCoordsArray
& cells
)
6768 if ( !m_numRows
|| !m_numCols
) return;
6770 int i
, numCells
= cells
.GetCount();
6771 int row
, col
, cell_rows
, cell_cols
;
6772 wxGridCellCoordsArray redrawCells
;
6774 for ( i
= numCells
-1; i
>= 0; i
-- )
6776 row
= cells
[i
].GetRow();
6777 col
= cells
[i
].GetCol();
6778 GetCellSize( row
, col
, &cell_rows
, &cell_cols
);
6780 // If this cell is part of a multicell block, find owner for repaint
6781 if ( cell_rows
<= 0 || cell_cols
<= 0 )
6783 wxGridCellCoords
cell(row
+cell_rows
, col
+cell_cols
);
6784 bool marked
= false;
6785 for ( int j
= 0; j
< numCells
; j
++ )
6787 if ( cell
== cells
[j
] )
6795 int count
= redrawCells
.GetCount();
6796 for (int j
= 0; j
< count
; j
++)
6798 if ( cell
== redrawCells
[j
] )
6804 if (!marked
) redrawCells
.Add( cell
);
6806 continue; // don't bother drawing this cell
6809 // If this cell is empty, find cell to left that might want to overflow
6810 if (m_table
&& m_table
->IsEmptyCell(row
, col
))
6812 for ( int l
= 0; l
< cell_rows
; l
++ )
6814 // find a cell in this row to left alreay marked for repaint
6816 for (int k
= 0; k
< int(redrawCells
.GetCount()); k
++)
6817 if ((redrawCells
[k
].GetCol() < left
) &&
6818 (redrawCells
[k
].GetRow() == row
))
6819 left
=redrawCells
[k
].GetCol();
6821 if (left
== col
) left
= 0; // oh well
6823 for (int j
= col
-1; j
>= left
; j
--)
6825 if (!m_table
->IsEmptyCell(row
+l
, j
))
6827 if (GetCellOverflow(row
+l
, j
))
6829 wxGridCellCoords
cell(row
+l
, j
);
6830 bool marked
= false;
6832 for (int k
= 0; k
< numCells
; k
++)
6834 if ( cell
== cells
[k
] )
6842 int count
= redrawCells
.GetCount();
6843 for (int k
= 0; k
< count
; k
++)
6845 if ( cell
== redrawCells
[k
] )
6851 if (!marked
) redrawCells
.Add( cell
);
6859 DrawCell( dc
, cells
[i
] );
6862 numCells
= redrawCells
.GetCount();
6864 for ( i
= numCells
- 1; i
>= 0; i
-- )
6866 DrawCell( dc
, redrawCells
[i
] );
6871 void wxGrid::DrawGridSpace( wxDC
& dc
)
6874 m_gridWin
->GetClientSize( &cw
, &ch
);
6877 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
6879 int rightCol
= m_numCols
> 0 ? GetColRight(m_numCols
- 1) : 0;
6880 int bottomRow
= m_numRows
> 0 ? GetRowBottom(m_numRows
- 1) : 0 ;
6882 if ( right
> rightCol
|| bottom
> bottomRow
)
6885 CalcUnscrolledPosition( 0, 0, &left
, &top
);
6887 dc
.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID
) );
6888 dc
.SetPen( *wxTRANSPARENT_PEN
);
6890 if ( right
> rightCol
)
6892 dc
.DrawRectangle( rightCol
, top
, right
- rightCol
, ch
);
6895 if ( bottom
> bottomRow
)
6897 dc
.DrawRectangle( left
, bottomRow
, cw
, bottom
- bottomRow
);
6903 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords
)
6905 int row
= coords
.GetRow();
6906 int col
= coords
.GetCol();
6908 if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 )
6911 // we draw the cell border ourselves
6912 #if !WXGRID_DRAW_LINES
6913 if ( m_gridLinesEnabled
)
6914 DrawCellBorder( dc
, coords
);
6917 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
6919 bool isCurrent
= coords
== m_currentCellCoords
;
6921 wxRect rect
= CellToRect( row
, col
);
6923 // if the editor is shown, we should use it and not the renderer
6924 // Note: However, only if it is really _shown_, i.e. not hidden!
6925 if ( isCurrent
&& IsCellEditControlShown() )
6927 wxGridCellEditor
*editor
= attr
->GetEditor(this, row
, col
);
6928 editor
->PaintBackground(rect
, attr
);
6933 // but all the rest is drawn by the cell renderer and hence may be
6935 wxGridCellRenderer
*renderer
= attr
->GetRenderer(this, row
, col
);
6936 renderer
->Draw(*this, *attr
, dc
, rect
, row
, col
, IsInSelection(coords
));
6943 void wxGrid::DrawCellHighlight( wxDC
& dc
, const wxGridCellAttr
*attr
)
6945 int row
= m_currentCellCoords
.GetRow();
6946 int col
= m_currentCellCoords
.GetCol();
6948 if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 )
6951 wxRect rect
= CellToRect(row
, col
);
6953 // hmmm... what could we do here to show that the cell is disabled?
6954 // for now, I just draw a thinner border than for the other ones, but
6955 // it doesn't look really good
6957 int penWidth
= attr
->IsReadOnly() ? m_cellHighlightROPenWidth
: m_cellHighlightPenWidth
;
6961 // The center of th drawn line is where the position/width/height of
6962 // the rectangle is actually at, (on wxMSW atr least,) so we will
6963 // reduce the size of the rectangle to compensate for the thickness of
6964 // the line. If this is too strange on non wxMSW platforms then
6965 // please #ifdef this appropriately.
6966 rect
.x
+= penWidth
/2;
6967 rect
.y
+= penWidth
/2;
6968 rect
.width
-= penWidth
-1;
6969 rect
.height
-= penWidth
-1;
6972 // Now draw the rectangle
6973 // use the cellHighlightColour if the cell is inside a selection, this
6974 // will ensure the cell is always visible.
6975 dc
.SetPen(wxPen(IsInSelection(row
,col
)?m_selectionForeground
:m_cellHighlightColour
, penWidth
, wxSOLID
));
6976 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
6977 dc
.DrawRectangle(rect
);
6981 // VZ: my experiments with 3d borders...
6983 // how to properly set colours for arbitrary bg?
6984 wxCoord x1
= rect
.x
,
6986 x2
= rect
.x
+ rect
.width
-1,
6987 y2
= rect
.y
+ rect
.height
-1;
6989 dc
.SetPen(*wxWHITE_PEN
);
6990 dc
.DrawLine(x1
, y1
, x2
, y1
);
6991 dc
.DrawLine(x1
, y1
, x1
, y2
);
6993 dc
.DrawLine(x1
+ 1, y2
- 1, x2
- 1, y2
- 1);
6994 dc
.DrawLine(x2
- 1, y1
+ 1, x2
- 1, y2
);
6996 dc
.SetPen(*wxBLACK_PEN
);
6997 dc
.DrawLine(x1
, y2
, x2
, y2
);
6998 dc
.DrawLine(x2
, y1
, x2
, y2
+1);
7003 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords
)
7005 int row
= coords
.GetRow();
7006 int col
= coords
.GetCol();
7007 if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 )
7010 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
7012 wxRect rect
= CellToRect( row
, col
);
7014 // right hand border
7016 dc
.DrawLine( rect
.x
+ rect
.width
, rect
.y
,
7017 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
+ 1 );
7021 dc
.DrawLine( rect
.x
, rect
.y
+ rect
.height
,
7022 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
7025 void wxGrid::DrawHighlight(wxDC
& dc
,const wxGridCellCoordsArray
& cells
)
7027 // This if block was previously in wxGrid::OnPaint but that doesn't
7028 // seem to get called under wxGTK - MB
7030 if ( m_currentCellCoords
== wxGridNoCellCoords
&&
7031 m_numRows
&& m_numCols
)
7033 m_currentCellCoords
.Set(0, 0);
7036 if ( IsCellEditControlShown() )
7038 // don't show highlight when the edit control is shown
7042 // if the active cell was repainted, repaint its highlight too because it
7043 // might have been damaged by the grid lines
7044 size_t count
= cells
.GetCount();
7045 for ( size_t n
= 0; n
< count
; n
++ )
7047 if ( cells
[n
] == m_currentCellCoords
)
7049 wxGridCellAttr
* attr
= GetCellAttr(m_currentCellCoords
);
7050 DrawCellHighlight(dc
, attr
);
7058 // TODO: remove this ???
7059 // This is used to redraw all grid lines e.g. when the grid line colour
7062 void wxGrid::DrawAllGridLines( wxDC
& dc
, const wxRegion
& WXUNUSED(reg
) )
7064 #if !WXGRID_DRAW_LINES
7068 if ( !m_gridLinesEnabled
||
7070 !m_numCols
) return;
7072 int top
, bottom
, left
, right
;
7074 #if 0 //#ifndef __WXGTK__
7078 m_gridWin
->GetClientSize(&cw
, &ch
);
7080 // virtual coords of visible area
7082 CalcUnscrolledPosition( 0, 0, &left
, &top
);
7083 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
7088 reg
.GetBox(x
, y
, w
, h
);
7089 CalcUnscrolledPosition( x
, y
, &left
, &top
);
7090 CalcUnscrolledPosition( x
+ w
, y
+ h
, &right
, &bottom
);
7094 m_gridWin
->GetClientSize(&cw
, &ch
);
7095 CalcUnscrolledPosition( 0, 0, &left
, &top
);
7096 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
7099 // avoid drawing grid lines past the last row and col
7101 right
= wxMin( right
, GetColRight(m_numCols
- 1) );
7102 bottom
= wxMin( bottom
, GetRowBottom(m_numRows
- 1) );
7104 // no gridlines inside multicells, clip them out
7105 int leftCol
= internalXToCol(left
);
7106 int topRow
= internalYToRow(top
);
7107 int rightCol
= internalXToCol(right
);
7108 int bottomRow
= internalYToRow(bottom
);
7109 wxRegion
clippedcells(0, 0, cw
, ch
);
7112 int i
, j
, cell_rows
, cell_cols
;
7115 for (j
=topRow
; j
<bottomRow
; j
++)
7117 for (i
=leftCol
; i
<rightCol
; i
++)
7119 GetCellSize( j
, i
, &cell_rows
, &cell_cols
);
7120 if ((cell_rows
> 1) || (cell_cols
> 1))
7122 rect
= CellToRect(j
,i
);
7123 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
7124 clippedcells
.Subtract(rect
);
7126 else if ((cell_rows
< 0) || (cell_cols
< 0))
7128 rect
= CellToRect(j
+cell_rows
, i
+cell_cols
);
7129 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
7130 clippedcells
.Subtract(rect
);
7134 dc
.SetClippingRegion( clippedcells
);
7136 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
7138 // horizontal grid lines
7140 // already declared above - int i;
7141 for ( i
= internalYToRow(top
); i
< m_numRows
; i
++ )
7143 int bot
= GetRowBottom(i
) - 1;
7152 dc
.DrawLine( left
, bot
, right
, bot
);
7157 // vertical grid lines
7159 for ( i
= internalXToCol(left
); i
< m_numCols
; i
++ )
7161 int colRight
= GetColRight(i
) - 1;
7162 if ( colRight
> right
)
7167 if ( colRight
>= left
)
7169 dc
.DrawLine( colRight
, top
, colRight
, bottom
);
7172 dc
.DestroyClippingRegion();
7176 void wxGrid::DrawRowLabels( wxDC
& dc
,const wxArrayInt
& rows
)
7178 if ( !m_numRows
) return;
7181 size_t numLabels
= rows
.GetCount();
7183 for ( i
= 0; i
< numLabels
; i
++ )
7185 DrawRowLabel( dc
, rows
[i
] );
7190 void wxGrid::DrawRowLabel( wxDC
& dc
, int row
)
7192 if ( GetRowHeight(row
) <= 0 )
7195 int rowTop
= GetRowTop(row
),
7196 rowBottom
= GetRowBottom(row
) - 1;
7198 dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) );
7199 dc
.DrawLine( m_rowLabelWidth
-1, rowTop
,
7200 m_rowLabelWidth
-1, rowBottom
);
7202 dc
.DrawLine( 0, rowTop
, 0, rowBottom
);
7204 dc
.DrawLine( 0, rowBottom
, m_rowLabelWidth
, rowBottom
);
7206 dc
.SetPen( *wxWHITE_PEN
);
7207 dc
.DrawLine( 1, rowTop
, 1, rowBottom
);
7208 dc
.DrawLine( 1, rowTop
, m_rowLabelWidth
-1, rowTop
);
7210 dc
.SetBackgroundMode( wxTRANSPARENT
);
7211 dc
.SetTextForeground( GetLabelTextColour() );
7212 dc
.SetFont( GetLabelFont() );
7215 GetRowLabelAlignment( &hAlign
, &vAlign
);
7219 rect
.SetY( GetRowTop(row
) + 2 );
7220 rect
.SetWidth( m_rowLabelWidth
- 4 );
7221 rect
.SetHeight( GetRowHeight(row
) - 4 );
7222 DrawTextRectangle( dc
, GetRowLabelValue( row
), rect
, hAlign
, vAlign
);
7226 void wxGrid::DrawColLabels( wxDC
& dc
,const wxArrayInt
& cols
)
7228 if ( !m_numCols
) return;
7231 size_t numLabels
= cols
.GetCount();
7233 for ( i
= 0; i
< numLabels
; i
++ )
7235 DrawColLabel( dc
, cols
[i
] );
7240 void wxGrid::DrawColLabel( wxDC
& dc
, int col
)
7242 if ( GetColWidth(col
) <= 0 )
7245 int colLeft
= GetColLeft(col
),
7246 colRight
= GetColRight(col
) - 1;
7248 dc
.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
),1, wxSOLID
) );
7249 dc
.DrawLine( colRight
, 0,
7250 colRight
, m_colLabelHeight
-1 );
7252 dc
.DrawLine( colLeft
, 0, colRight
, 0 );
7254 dc
.DrawLine( colLeft
, m_colLabelHeight
-1,
7255 colRight
+1, m_colLabelHeight
-1 );
7257 dc
.SetPen( *wxWHITE_PEN
);
7258 dc
.DrawLine( colLeft
, 1, colLeft
, m_colLabelHeight
-1 );
7259 dc
.DrawLine( colLeft
, 1, colRight
, 1 );
7261 dc
.SetBackgroundMode( wxTRANSPARENT
);
7262 dc
.SetTextForeground( GetLabelTextColour() );
7263 dc
.SetFont( GetLabelFont() );
7265 int hAlign
, vAlign
, orient
;
7266 GetColLabelAlignment( &hAlign
, &vAlign
);
7267 orient
= GetColLabelTextOrientation();
7270 rect
.SetX( colLeft
+ 2 );
7272 rect
.SetWidth( GetColWidth(col
) - 4 );
7273 rect
.SetHeight( m_colLabelHeight
- 4 );
7274 DrawTextRectangle( dc
, GetColLabelValue( col
), rect
, hAlign
, vAlign
, orient
);
7277 void wxGrid::DrawTextRectangle( wxDC
& dc
,
7278 const wxString
& value
,
7282 int textOrientation
)
7284 wxArrayString lines
;
7286 StringToLines( value
, lines
);
7289 //Forward to new API.
7290 DrawTextRectangle( dc
,
7299 void wxGrid::DrawTextRectangle( wxDC
& dc
,
7300 const wxArrayString
& lines
,
7304 int textOrientation
)
7306 long textWidth
, textHeight
;
7307 long lineWidth
, lineHeight
;
7310 dc
.SetClippingRegion( rect
);
7312 nLines
= lines
.GetCount();
7316 float x
= 0.0, y
= 0.0;
7318 if( textOrientation
== wxHORIZONTAL
)
7319 GetTextBoxSize(dc
, lines
, &textWidth
, &textHeight
);
7321 GetTextBoxSize( dc
, lines
, &textHeight
, &textWidth
);
7325 case wxALIGN_BOTTOM
:
7326 if( textOrientation
== wxHORIZONTAL
)
7327 y
= rect
.y
+ (rect
.height
- textHeight
- 1);
7329 x
= rect
.x
+ rect
.width
- textWidth
;
7332 case wxALIGN_CENTRE
:
7333 if( textOrientation
== wxHORIZONTAL
)
7334 y
= rect
.y
+ ((rect
.height
- textHeight
)/2);
7336 x
= rect
.x
+ ((rect
.width
- textWidth
)/2);
7341 if( textOrientation
== wxHORIZONTAL
)
7348 // Align each line of a multi-line label
7349 for( l
= 0; l
< nLines
; l
++ )
7351 dc
.GetTextExtent(lines
[l
], &lineWidth
, &lineHeight
);
7353 switch( horizAlign
)
7356 if( textOrientation
== wxHORIZONTAL
)
7357 x
= rect
.x
+ (rect
.width
- lineWidth
- 1);
7359 y
= rect
.y
+ lineWidth
+ 1;
7362 case wxALIGN_CENTRE
:
7363 if( textOrientation
== wxHORIZONTAL
)
7364 x
= rect
.x
+ ((rect
.width
- lineWidth
)/2);
7366 y
= rect
.y
+ rect
.height
- ((rect
.height
- lineWidth
)/2);
7371 if( textOrientation
== wxHORIZONTAL
)
7374 y
= rect
.y
+ rect
.height
- 1;
7378 if( textOrientation
== wxHORIZONTAL
)
7380 dc
.DrawText( lines
[l
], (int)x
, (int)y
);
7385 dc
.DrawRotatedText( lines
[l
], (int)x
, (int)y
, 90.0 );
7390 dc
.DestroyClippingRegion();
7394 // Split multi line text up into an array of strings. Any existing
7395 // contents of the string array are preserved.
7397 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines
)
7401 wxString eol
= wxTextFile::GetEOL( wxTextFileType_Unix
);
7402 wxString tVal
= wxTextFile::Translate( value
, wxTextFileType_Unix
);
7404 while ( startPos
< (int)tVal
.Length() )
7406 pos
= tVal
.Mid(startPos
).Find( eol
);
7411 else if ( pos
== 0 )
7413 lines
.Add( wxEmptyString
);
7417 lines
.Add( value
.Mid(startPos
, pos
) );
7421 if ( startPos
< (int)value
.Length() )
7423 lines
.Add( value
.Mid( startPos
) );
7428 void wxGrid::GetTextBoxSize( wxDC
& dc
,
7429 const wxArrayString
& lines
,
7430 long *width
, long *height
)
7437 for ( i
= 0; i
< lines
.GetCount(); i
++ )
7439 dc
.GetTextExtent( lines
[i
], &lineW
, &lineH
);
7440 w
= wxMax( w
, lineW
);
7449 // ------ Batch processing.
7451 void wxGrid::EndBatch()
7453 if ( m_batchCount
> 0 )
7456 if ( !m_batchCount
)
7459 m_rowLabelWin
->Refresh();
7460 m_colLabelWin
->Refresh();
7461 m_cornerLabelWin
->Refresh();
7462 m_gridWin
->Refresh();
7467 // Use this, rather than wxWindow::Refresh(), to force an immediate
7468 // repainting of the grid. Has no effect if you are already inside a
7469 // BeginBatch / EndBatch block.
7471 void wxGrid::ForceRefresh()
7479 // ------ Edit control functions
7483 void wxGrid::EnableEditing( bool edit
)
7485 // TODO: improve this ?
7487 if ( edit
!= m_editable
)
7489 if(!edit
) EnableCellEditControl(edit
);
7495 void wxGrid::EnableCellEditControl( bool enable
)
7500 if ( m_currentCellCoords
== wxGridNoCellCoords
)
7501 SetCurrentCell( 0, 0 );
7503 if ( enable
!= m_cellEditCtrlEnabled
)
7507 if (SendEvent( wxEVT_GRID_EDITOR_SHOWN
) <0)
7510 // this should be checked by the caller!
7511 wxASSERT_MSG( CanEnableCellControl(),
7512 _T("can't enable editing for this cell!") );
7514 // do it before ShowCellEditControl()
7515 m_cellEditCtrlEnabled
= enable
;
7517 ShowCellEditControl();
7521 //FIXME:add veto support
7522 SendEvent( wxEVT_GRID_EDITOR_HIDDEN
);
7524 HideCellEditControl();
7525 SaveEditControlValue();
7527 // do it after HideCellEditControl()
7528 m_cellEditCtrlEnabled
= enable
;
7533 bool wxGrid::IsCurrentCellReadOnly() const
7536 wxGridCellAttr
* attr
= ((wxGrid
*)this)->GetCellAttr(m_currentCellCoords
);
7537 bool readonly
= attr
->IsReadOnly();
7543 bool wxGrid::CanEnableCellControl() const
7545 return m_editable
&& (m_currentCellCoords
!= wxGridNoCellCoords
) &&
7546 !IsCurrentCellReadOnly();
7550 bool wxGrid::IsCellEditControlEnabled() const
7552 // the cell edit control might be disable for all cells or just for the
7553 // current one if it's read only
7554 return m_cellEditCtrlEnabled
? !IsCurrentCellReadOnly() : false;
7557 bool wxGrid::IsCellEditControlShown() const
7559 bool isShown
= false;
7561 if ( m_cellEditCtrlEnabled
)
7563 int row
= m_currentCellCoords
.GetRow();
7564 int col
= m_currentCellCoords
.GetCol();
7565 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
7566 wxGridCellEditor
* editor
= attr
->GetEditor((wxGrid
*) this, row
, col
);
7571 if ( editor
->IsCreated() )
7573 isShown
= editor
->GetControl()->IsShown();
7583 void wxGrid::ShowCellEditControl()
7585 if ( IsCellEditControlEnabled() )
7587 if ( !IsVisible( m_currentCellCoords
) )
7589 m_cellEditCtrlEnabled
= false;
7594 wxRect rect
= CellToRect( m_currentCellCoords
);
7595 int row
= m_currentCellCoords
.GetRow();
7596 int col
= m_currentCellCoords
.GetCol();
7598 // if this is part of a multicell, find owner (topleft)
7599 int cell_rows
, cell_cols
;
7600 GetCellSize( row
, col
, &cell_rows
, &cell_cols
);
7601 if ( cell_rows
<= 0 || cell_cols
<= 0 )
7605 m_currentCellCoords
.SetRow( row
);
7606 m_currentCellCoords
.SetCol( col
);
7609 // convert to scrolled coords
7611 CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
7613 // done in PaintBackground()
7615 // erase the highlight and the cell contents because the editor
7616 // might not cover the entire cell
7617 wxClientDC
dc( m_gridWin
);
7619 dc
.SetBrush(*wxLIGHT_GREY_BRUSH
); //wxBrush(attr->GetBackgroundColour(), wxSOLID));
7620 dc
.SetPen(*wxTRANSPARENT_PEN
);
7621 dc
.DrawRectangle(rect
);
7624 // cell is shifted by one pixel
7625 // However, don't allow x or y to become negative
7626 // since the SetSize() method interprets that as
7633 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
7634 wxGridCellEditor
* editor
= attr
->GetEditor(this, row
, col
);
7635 if ( !editor
->IsCreated() )
7637 editor
->Create(m_gridWin
, wxID_ANY
,
7638 new wxGridCellEditorEvtHandler(this, editor
));
7640 wxGridEditorCreatedEvent
evt(GetId(),
7641 wxEVT_GRID_EDITOR_CREATED
,
7645 editor
->GetControl());
7646 GetEventHandler()->ProcessEvent(evt
);
7650 // resize editor to overflow into righthand cells if allowed
7651 int maxWidth
= rect
.width
;
7652 wxString value
= GetCellValue(row
, col
);
7653 if ( (value
!= wxEmptyString
) && (attr
->GetOverflow()) )
7656 GetTextExtent(value
, &maxWidth
, &y
,
7657 NULL
, NULL
, &attr
->GetFont());
7658 if (maxWidth
< rect
.width
) maxWidth
= rect
.width
;
7660 int client_right
= m_gridWin
->GetClientSize().GetWidth();
7661 if (rect
.x
+maxWidth
> client_right
)
7662 maxWidth
= client_right
- rect
.x
;
7664 if ((maxWidth
> rect
.width
) && (col
< m_numCols
) && m_table
)
7666 GetCellSize( row
, col
, &cell_rows
, &cell_cols
);
7667 // may have changed earlier
7668 for (int i
= col
+cell_cols
; i
< m_numCols
; i
++)
7671 GetCellSize( row
, i
, &c_rows
, &c_cols
);
7672 // looks weird going over a multicell
7673 if (m_table
->IsEmptyCell(row
,i
) &&
7674 (rect
.width
< maxWidth
) && (c_rows
== 1))
7675 rect
.width
+= GetColWidth(i
);
7679 if (rect
.GetRight() > client_right
)
7680 rect
.SetRight(client_right
-1);
7683 editor
->SetCellAttr(attr
);
7684 editor
->SetSize( rect
);
7685 editor
->Show( true, attr
);
7687 // recalc dimensions in case we need to
7688 // expand the scrolled window to account for editor
7691 editor
->BeginEdit(row
, col
, this);
7692 editor
->SetCellAttr(NULL
);
7701 void wxGrid::HideCellEditControl()
7703 if ( IsCellEditControlEnabled() )
7705 int row
= m_currentCellCoords
.GetRow();
7706 int col
= m_currentCellCoords
.GetCol();
7708 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
7709 wxGridCellEditor
*editor
= attr
->GetEditor(this, row
, col
);
7710 editor
->Show( false );
7713 m_gridWin
->SetFocus();
7714 // refresh whole row to the right
7715 wxRect
rect( CellToRect(row
, col
) );
7716 CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
7717 rect
.width
= m_gridWin
->GetClientSize().GetWidth() - rect
.x
;
7718 m_gridWin
->Refresh( false, &rect
);
7723 void wxGrid::SaveEditControlValue()
7725 if ( IsCellEditControlEnabled() )
7727 int row
= m_currentCellCoords
.GetRow();
7728 int col
= m_currentCellCoords
.GetCol();
7730 wxString oldval
= GetCellValue(row
,col
);
7732 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
7733 wxGridCellEditor
* editor
= attr
->GetEditor(this, row
, col
);
7734 bool changed
= editor
->EndEdit(row
, col
, this);
7741 if ( SendEvent( wxEVT_GRID_CELL_CHANGE
,
7742 m_currentCellCoords
.GetRow(),
7743 m_currentCellCoords
.GetCol() ) < 0 ) {
7745 // Event has been vetoed, set the data back.
7746 SetCellValue(row
,col
,oldval
);
7754 // ------ Grid location functions
7755 // Note that all of these functions work with the logical coordinates of
7756 // grid cells and labels so you will need to convert from device
7757 // coordinates for mouse events etc.
7760 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords
)
7762 int row
= YToRow(y
);
7763 int col
= XToCol(x
);
7765 if ( row
== -1 || col
== -1 )
7767 coords
= wxGridNoCellCoords
;
7771 coords
.Set( row
, col
);
7776 // Internal Helper function for computing row or column from some
7777 // (unscrolled) coordinate value, using either
7778 // m_defaultRowHeight/m_defaultColWidth or binary search on array
7779 // of m_rowBottoms/m_ColRights to speed up the search!
7781 static int CoordToRowOrCol(int coord
, int defaultDist
, int minDist
,
7782 const wxArrayInt
& BorderArray
, int nMax
,
7787 return clipToMinMax
&& (nMax
> 0) ? 0 : -1;
7793 size_t i_max
= coord
/ defaultDist
,
7796 if (BorderArray
.IsEmpty())
7798 if((int) i_max
< nMax
)
7800 return clipToMinMax
? nMax
- 1 : -1;
7803 if ( i_max
>= BorderArray
.GetCount())
7804 i_max
= BorderArray
.GetCount() - 1;
7807 if ( coord
>= BorderArray
[i_max
])
7811 i_max
= coord
/ minDist
;
7813 i_max
= BorderArray
.GetCount() - 1;
7815 if ( i_max
>= BorderArray
.GetCount())
7816 i_max
= BorderArray
.GetCount() - 1;
7818 if ( coord
>= BorderArray
[i_max
])
7819 return clipToMinMax
? (int)i_max
: -1;
7820 if ( coord
< BorderArray
[0] )
7823 while ( i_max
- i_min
> 0 )
7825 wxCHECK_MSG(BorderArray
[i_min
] <= coord
&& coord
< BorderArray
[i_max
],
7826 0, _T("wxGrid: internal error in CoordToRowOrCol"));
7827 if (coord
>= BorderArray
[ i_max
- 1])
7831 int median
= i_min
+ (i_max
- i_min
+ 1) / 2;
7832 if (coord
< BorderArray
[median
])
7840 int wxGrid::YToRow( int y
)
7842 return CoordToRowOrCol(y
, m_defaultRowHeight
,
7843 m_minAcceptableRowHeight
, m_rowBottoms
, m_numRows
, false);
7847 int wxGrid::XToCol( int x
)
7849 return CoordToRowOrCol(x
, m_defaultColWidth
,
7850 m_minAcceptableColWidth
, m_colRights
, m_numCols
, false);
7854 // return the row number that that the y coord is near the edge of, or
7855 // -1 if not near an edge
7857 int wxGrid::YToEdgeOfRow( int y
)
7860 i
= internalYToRow(y
);
7862 if ( GetRowHeight(i
) > WXGRID_LABEL_EDGE_ZONE
)
7864 // We know that we are in row i, test whether we are
7865 // close enough to lower or upper border, respectively.
7866 if ( abs(GetRowBottom(i
) - y
) < WXGRID_LABEL_EDGE_ZONE
)
7868 else if( i
> 0 && y
- GetRowTop(i
) < WXGRID_LABEL_EDGE_ZONE
)
7876 // return the col number that that the x coord is near the edge of, or
7877 // -1 if not near an edge
7879 int wxGrid::XToEdgeOfCol( int x
)
7882 i
= internalXToCol(x
);
7884 if ( GetColWidth(i
) > WXGRID_LABEL_EDGE_ZONE
)
7886 // We know that we are in column i, test whether we are
7887 // close enough to right or left border, respectively.
7888 if ( abs(GetColRight(i
) - x
) < WXGRID_LABEL_EDGE_ZONE
)
7890 else if( i
> 0 && x
- GetColLeft(i
) < WXGRID_LABEL_EDGE_ZONE
)
7898 wxRect
wxGrid::CellToRect( int row
, int col
)
7900 wxRect
rect( -1, -1, -1, -1 );
7902 if ( row
>= 0 && row
< m_numRows
&&
7903 col
>= 0 && col
< m_numCols
)
7905 int i
, cell_rows
, cell_cols
;
7906 rect
.width
= rect
.height
= 0;
7907 GetCellSize( row
, col
, &cell_rows
, &cell_cols
);
7908 // if negative then find multicell owner
7909 if (cell_rows
< 0) row
+= cell_rows
;
7910 if (cell_cols
< 0) col
+= cell_cols
;
7911 GetCellSize( row
, col
, &cell_rows
, &cell_cols
);
7913 rect
.x
= GetColLeft(col
);
7914 rect
.y
= GetRowTop(row
);
7915 for (i
=col
; i
<col
+cell_cols
; i
++)
7916 rect
.width
+= GetColWidth(i
);
7917 for (i
=row
; i
<row
+cell_rows
; i
++)
7918 rect
.height
+= GetRowHeight(i
);
7921 // if grid lines are enabled, then the area of the cell is a bit smaller
7922 if (m_gridLinesEnabled
) {
7930 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible
)
7932 // get the cell rectangle in logical coords
7934 wxRect
r( CellToRect( row
, col
) );
7936 // convert to device coords
7938 int left
, top
, right
, bottom
;
7939 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
7940 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
7942 // check against the client area of the grid window
7945 m_gridWin
->GetClientSize( &cw
, &ch
);
7947 if ( wholeCellVisible
)
7949 // is the cell wholly visible ?
7951 return ( left
>= 0 && right
<= cw
&&
7952 top
>= 0 && bottom
<= ch
);
7956 // is the cell partly visible ?
7958 return ( ((left
>=0 && left
< cw
) || (right
> 0 && right
<= cw
)) &&
7959 ((top
>=0 && top
< ch
) || (bottom
> 0 && bottom
<= ch
)) );
7964 // make the specified cell location visible by doing a minimal amount
7967 void wxGrid::MakeCellVisible( int row
, int col
)
7971 int xpos
= -1, ypos
= -1;
7973 if ( row
>= 0 && row
< m_numRows
&&
7974 col
>= 0 && col
< m_numCols
)
7976 // get the cell rectangle in logical coords
7978 wxRect
r( CellToRect( row
, col
) );
7980 // convert to device coords
7982 int left
, top
, right
, bottom
;
7983 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
7984 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
7987 m_gridWin
->GetClientSize( &cw
, &ch
);
7993 else if ( bottom
> ch
)
7995 int h
= r
.GetHeight();
7997 for ( i
= row
-1; i
>= 0; i
-- )
7999 int rowHeight
= GetRowHeight(i
);
8000 if ( h
+ rowHeight
> ch
)
8007 // we divide it later by GRID_SCROLL_LINE, make sure that we don't
8008 // have rounding errors (this is important, because if we do, we
8009 // might not scroll at all and some cells won't be redrawn)
8011 // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full
8013 ypos
+= GRID_SCROLL_LINE_Y
;
8020 else if ( right
> cw
)
8022 // position the view so that the cell is on the right
8024 CalcUnscrolledPosition(0, 0, &x0
, &y0
);
8025 xpos
= x0
+ (right
- cw
);
8027 // see comment for ypos above
8028 xpos
+= GRID_SCROLL_LINE_X
;
8031 if ( xpos
!= -1 || ypos
!= -1 )
8034 xpos
/= GRID_SCROLL_LINE_X
;
8036 ypos
/= GRID_SCROLL_LINE_Y
;
8037 Scroll( xpos
, ypos
);
8045 // ------ Grid cursor movement functions
8048 bool wxGrid::MoveCursorUp( bool expandSelection
)
8050 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
8051 m_currentCellCoords
.GetRow() >= 0 )
8053 if ( expandSelection
)
8055 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
8056 m_selectingKeyboard
= m_currentCellCoords
;
8057 if ( m_selectingKeyboard
.GetRow() > 0 )
8059 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() - 1 );
8060 MakeCellVisible( m_selectingKeyboard
.GetRow(),
8061 m_selectingKeyboard
.GetCol() );
8062 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8065 else if ( m_currentCellCoords
.GetRow() > 0 )
8068 MakeCellVisible( m_currentCellCoords
.GetRow() - 1,
8069 m_currentCellCoords
.GetCol() );
8070 SetCurrentCell( m_currentCellCoords
.GetRow() - 1,
8071 m_currentCellCoords
.GetCol() );
8082 bool wxGrid::MoveCursorDown( bool expandSelection
)
8084 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
8085 m_currentCellCoords
.GetRow() < m_numRows
)
8087 if ( expandSelection
)
8089 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
8090 m_selectingKeyboard
= m_currentCellCoords
;
8091 if ( m_selectingKeyboard
.GetRow() < m_numRows
-1 )
8093 m_selectingKeyboard
.SetRow( m_selectingKeyboard
.GetRow() + 1 );
8094 MakeCellVisible( m_selectingKeyboard
.GetRow(),
8095 m_selectingKeyboard
.GetCol() );
8096 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8099 else if ( m_currentCellCoords
.GetRow() < m_numRows
- 1 )
8102 MakeCellVisible( m_currentCellCoords
.GetRow() + 1,
8103 m_currentCellCoords
.GetCol() );
8104 SetCurrentCell( m_currentCellCoords
.GetRow() + 1,
8105 m_currentCellCoords
.GetCol() );
8116 bool wxGrid::MoveCursorLeft( bool expandSelection
)
8118 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
8119 m_currentCellCoords
.GetCol() >= 0 )
8121 if ( expandSelection
)
8123 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
8124 m_selectingKeyboard
= m_currentCellCoords
;
8125 if ( m_selectingKeyboard
.GetCol() > 0 )
8127 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() - 1 );
8128 MakeCellVisible( m_selectingKeyboard
.GetRow(),
8129 m_selectingKeyboard
.GetCol() );
8130 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8133 else if ( m_currentCellCoords
.GetCol() > 0 )
8136 MakeCellVisible( m_currentCellCoords
.GetRow(),
8137 m_currentCellCoords
.GetCol() - 1 );
8138 SetCurrentCell( m_currentCellCoords
.GetRow(),
8139 m_currentCellCoords
.GetCol() - 1 );
8150 bool wxGrid::MoveCursorRight( bool expandSelection
)
8152 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
8153 m_currentCellCoords
.GetCol() < m_numCols
)
8155 if ( expandSelection
)
8157 if ( m_selectingKeyboard
== wxGridNoCellCoords
)
8158 m_selectingKeyboard
= m_currentCellCoords
;
8159 if ( m_selectingKeyboard
.GetCol() < m_numCols
- 1 )
8161 m_selectingKeyboard
.SetCol( m_selectingKeyboard
.GetCol() + 1 );
8162 MakeCellVisible( m_selectingKeyboard
.GetRow(),
8163 m_selectingKeyboard
.GetCol() );
8164 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8167 else if ( m_currentCellCoords
.GetCol() < m_numCols
- 1 )
8170 MakeCellVisible( m_currentCellCoords
.GetRow(),
8171 m_currentCellCoords
.GetCol() + 1 );
8172 SetCurrentCell( m_currentCellCoords
.GetRow(),
8173 m_currentCellCoords
.GetCol() + 1 );
8184 bool wxGrid::MovePageUp()
8186 if ( m_currentCellCoords
== wxGridNoCellCoords
) return false;
8188 int row
= m_currentCellCoords
.GetRow();
8192 m_gridWin
->GetClientSize( &cw
, &ch
);
8194 int y
= GetRowTop(row
);
8195 int newRow
= internalYToRow( y
- ch
+ 1 );
8197 if ( newRow
== row
)
8199 //row > 0 , so newrow can never be less than 0 here.
8203 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
8204 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
8212 bool wxGrid::MovePageDown()
8214 if ( m_currentCellCoords
== wxGridNoCellCoords
) return false;
8216 int row
= m_currentCellCoords
.GetRow();
8217 if ( (row
+1) < m_numRows
)
8220 m_gridWin
->GetClientSize( &cw
, &ch
);
8222 int y
= GetRowTop(row
);
8223 int newRow
= internalYToRow( y
+ ch
);
8224 if ( newRow
== row
)
8226 // row < m_numRows , so newrow can't overflow here.
8230 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
8231 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
8239 bool wxGrid::MoveCursorUpBlock( bool expandSelection
)
8242 m_currentCellCoords
!= wxGridNoCellCoords
&&
8243 m_currentCellCoords
.GetRow() > 0 )
8245 int row
= m_currentCellCoords
.GetRow();
8246 int col
= m_currentCellCoords
.GetCol();
8248 if ( m_table
->IsEmptyCell(row
, col
) )
8250 // starting in an empty cell: find the next block of
8256 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8259 else if ( m_table
->IsEmptyCell(row
-1, col
) )
8261 // starting at the top of a block: find the next block
8267 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8272 // starting within a block: find the top of the block
8277 if ( m_table
->IsEmptyCell(row
, col
) )
8285 MakeCellVisible( row
, col
);
8286 if ( expandSelection
)
8288 m_selectingKeyboard
= wxGridCellCoords( row
, col
);
8289 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8294 SetCurrentCell( row
, col
);
8302 bool wxGrid::MoveCursorDownBlock( bool expandSelection
)
8305 m_currentCellCoords
!= wxGridNoCellCoords
&&
8306 m_currentCellCoords
.GetRow() < m_numRows
-1 )
8308 int row
= m_currentCellCoords
.GetRow();
8309 int col
= m_currentCellCoords
.GetCol();
8311 if ( m_table
->IsEmptyCell(row
, col
) )
8313 // starting in an empty cell: find the next block of
8316 while ( row
< m_numRows
-1 )
8319 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8322 else if ( m_table
->IsEmptyCell(row
+1, col
) )
8324 // starting at the bottom of a block: find the next block
8327 while ( row
< m_numRows
-1 )
8330 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8335 // starting within a block: find the bottom of the block
8337 while ( row
< m_numRows
-1 )
8340 if ( m_table
->IsEmptyCell(row
, col
) )
8348 MakeCellVisible( row
, col
);
8349 if ( expandSelection
)
8351 m_selectingKeyboard
= wxGridCellCoords( row
, col
);
8352 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8357 SetCurrentCell( row
, col
);
8366 bool wxGrid::MoveCursorLeftBlock( bool expandSelection
)
8369 m_currentCellCoords
!= wxGridNoCellCoords
&&
8370 m_currentCellCoords
.GetCol() > 0 )
8372 int row
= m_currentCellCoords
.GetRow();
8373 int col
= m_currentCellCoords
.GetCol();
8375 if ( m_table
->IsEmptyCell(row
, col
) )
8377 // starting in an empty cell: find the next block of
8383 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8386 else if ( m_table
->IsEmptyCell(row
, col
-1) )
8388 // starting at the left of a block: find the next block
8394 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8399 // starting within a block: find the left of the block
8404 if ( m_table
->IsEmptyCell(row
, col
) )
8412 MakeCellVisible( row
, col
);
8413 if ( expandSelection
)
8415 m_selectingKeyboard
= wxGridCellCoords( row
, col
);
8416 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8421 SetCurrentCell( row
, col
);
8430 bool wxGrid::MoveCursorRightBlock( bool expandSelection
)
8433 m_currentCellCoords
!= wxGridNoCellCoords
&&
8434 m_currentCellCoords
.GetCol() < m_numCols
-1 )
8436 int row
= m_currentCellCoords
.GetRow();
8437 int col
= m_currentCellCoords
.GetCol();
8439 if ( m_table
->IsEmptyCell(row
, col
) )
8441 // starting in an empty cell: find the next block of
8444 while ( col
< m_numCols
-1 )
8447 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8450 else if ( m_table
->IsEmptyCell(row
, col
+1) )
8452 // starting at the right of a block: find the next block
8455 while ( col
< m_numCols
-1 )
8458 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
8463 // starting within a block: find the right of the block
8465 while ( col
< m_numCols
-1 )
8468 if ( m_table
->IsEmptyCell(row
, col
) )
8476 MakeCellVisible( row
, col
);
8477 if ( expandSelection
)
8479 m_selectingKeyboard
= wxGridCellCoords( row
, col
);
8480 HighlightBlock( m_currentCellCoords
, m_selectingKeyboard
);
8485 SetCurrentCell( row
, col
);
8497 // ------ Label values and formatting
8500 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert
)
8502 *horiz
= m_rowLabelHorizAlign
;
8503 *vert
= m_rowLabelVertAlign
;
8506 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert
)
8508 *horiz
= m_colLabelHorizAlign
;
8509 *vert
= m_colLabelVertAlign
;
8512 int wxGrid::GetColLabelTextOrientation()
8514 return m_colLabelTextOrientation
;
8517 wxString
wxGrid::GetRowLabelValue( int row
)
8521 return m_table
->GetRowLabelValue( row
);
8531 wxString
wxGrid::GetColLabelValue( int col
)
8535 return m_table
->GetColLabelValue( col
);
8546 void wxGrid::SetRowLabelSize( int width
)
8548 width
= wxMax( width
, 0 );
8549 if ( width
!= m_rowLabelWidth
)
8553 m_rowLabelWin
->Show( false );
8554 m_cornerLabelWin
->Show( false );
8556 else if ( m_rowLabelWidth
== 0 )
8558 m_rowLabelWin
->Show( true );
8559 if ( m_colLabelHeight
> 0 ) m_cornerLabelWin
->Show( true );
8562 m_rowLabelWidth
= width
;
8564 wxScrolledWindow::Refresh( true );
8569 void wxGrid::SetColLabelSize( int height
)
8571 height
= wxMax( height
, 0 );
8572 if ( height
!= m_colLabelHeight
)
8576 m_colLabelWin
->Show( false );
8577 m_cornerLabelWin
->Show( false );
8579 else if ( m_colLabelHeight
== 0 )
8581 m_colLabelWin
->Show( true );
8582 if ( m_rowLabelWidth
> 0 ) m_cornerLabelWin
->Show( true );
8585 m_colLabelHeight
= height
;
8587 wxScrolledWindow::Refresh( true );
8592 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour
)
8594 if ( m_labelBackgroundColour
!= colour
)
8596 m_labelBackgroundColour
= colour
;
8597 m_rowLabelWin
->SetBackgroundColour( colour
);
8598 m_colLabelWin
->SetBackgroundColour( colour
);
8599 m_cornerLabelWin
->SetBackgroundColour( colour
);
8601 if ( !GetBatchCount() )
8603 m_rowLabelWin
->Refresh();
8604 m_colLabelWin
->Refresh();
8605 m_cornerLabelWin
->Refresh();
8610 void wxGrid::SetLabelTextColour( const wxColour
& colour
)
8612 if ( m_labelTextColour
!= colour
)
8614 m_labelTextColour
= colour
;
8615 if ( !GetBatchCount() )
8617 m_rowLabelWin
->Refresh();
8618 m_colLabelWin
->Refresh();
8623 void wxGrid::SetLabelFont( const wxFont
& font
)
8626 if ( !GetBatchCount() )
8628 m_rowLabelWin
->Refresh();
8629 m_colLabelWin
->Refresh();
8633 void wxGrid::SetRowLabelAlignment( int horiz
, int vert
)
8635 // allow old (incorrect) defs to be used
8638 case wxLEFT
: horiz
= wxALIGN_LEFT
; break;
8639 case wxRIGHT
: horiz
= wxALIGN_RIGHT
; break;
8640 case wxCENTRE
: horiz
= wxALIGN_CENTRE
; break;
8645 case wxTOP
: vert
= wxALIGN_TOP
; break;
8646 case wxBOTTOM
: vert
= wxALIGN_BOTTOM
; break;
8647 case wxCENTRE
: vert
= wxALIGN_CENTRE
; break;
8650 if ( horiz
== wxALIGN_LEFT
|| horiz
== wxALIGN_CENTRE
|| horiz
== wxALIGN_RIGHT
)
8652 m_rowLabelHorizAlign
= horiz
;
8655 if ( vert
== wxALIGN_TOP
|| vert
== wxALIGN_CENTRE
|| vert
== wxALIGN_BOTTOM
)
8657 m_rowLabelVertAlign
= vert
;
8660 if ( !GetBatchCount() )
8662 m_rowLabelWin
->Refresh();
8666 void wxGrid::SetColLabelAlignment( int horiz
, int vert
)
8668 // allow old (incorrect) defs to be used
8671 case wxLEFT
: horiz
= wxALIGN_LEFT
; break;
8672 case wxRIGHT
: horiz
= wxALIGN_RIGHT
; break;
8673 case wxCENTRE
: horiz
= wxALIGN_CENTRE
; break;
8678 case wxTOP
: vert
= wxALIGN_TOP
; break;
8679 case wxBOTTOM
: vert
= wxALIGN_BOTTOM
; break;
8680 case wxCENTRE
: vert
= wxALIGN_CENTRE
; break;
8683 if ( horiz
== wxALIGN_LEFT
|| horiz
== wxALIGN_CENTRE
|| horiz
== wxALIGN_RIGHT
)
8685 m_colLabelHorizAlign
= horiz
;
8688 if ( vert
== wxALIGN_TOP
|| vert
== wxALIGN_CENTRE
|| vert
== wxALIGN_BOTTOM
)
8690 m_colLabelVertAlign
= vert
;
8693 if ( !GetBatchCount() )
8695 m_colLabelWin
->Refresh();
8699 // Note: under MSW, the default column label font must be changed because it
8700 // does not support vertical printing
8702 // Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD);
8703 // pGrid->SetLabelFont(font);
8704 // pGrid->SetColLabelTextOrientation(wxVERTICAL);
8706 void wxGrid::SetColLabelTextOrientation( int textOrientation
)
8708 if( textOrientation
== wxHORIZONTAL
|| textOrientation
== wxVERTICAL
)
8710 m_colLabelTextOrientation
= textOrientation
;
8713 if ( !GetBatchCount() )
8715 m_colLabelWin
->Refresh();
8719 void wxGrid::SetRowLabelValue( int row
, const wxString
& s
)
8723 m_table
->SetRowLabelValue( row
, s
);
8724 if ( !GetBatchCount() )
8726 wxRect rect
= CellToRect( row
, 0);
8727 if ( rect
.height
> 0 )
8729 CalcScrolledPosition(0, rect
.y
, &rect
.x
, &rect
.y
);
8731 rect
.width
= m_rowLabelWidth
;
8732 m_rowLabelWin
->Refresh( true, &rect
);
8738 void wxGrid::SetColLabelValue( int col
, const wxString
& s
)
8742 m_table
->SetColLabelValue( col
, s
);
8743 if ( !GetBatchCount() )
8745 wxRect rect
= CellToRect( 0, col
);
8746 if ( rect
.width
> 0 )
8748 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &rect
.y
);
8750 rect
.height
= m_colLabelHeight
;
8751 m_colLabelWin
->Refresh( true, &rect
);
8757 void wxGrid::SetGridLineColour( const wxColour
& colour
)
8759 if ( m_gridLineColour
!= colour
)
8761 m_gridLineColour
= colour
;
8763 wxClientDC
dc( m_gridWin
);
8765 DrawAllGridLines( dc
, wxRegion() );
8770 void wxGrid::SetCellHighlightColour( const wxColour
& colour
)
8772 if ( m_cellHighlightColour
!= colour
)
8774 m_cellHighlightColour
= colour
;
8776 wxClientDC
dc( m_gridWin
);
8778 wxGridCellAttr
* attr
= GetCellAttr(m_currentCellCoords
);
8779 DrawCellHighlight(dc
, attr
);
8784 void wxGrid::SetCellHighlightPenWidth(int width
)
8786 if (m_cellHighlightPenWidth
!= width
) {
8787 m_cellHighlightPenWidth
= width
;
8789 // Just redrawing the cell highlight is not enough since that won't
8790 // make any visible change if the the thickness is getting smaller.
8791 int row
= m_currentCellCoords
.GetRow();
8792 int col
= m_currentCellCoords
.GetCol();
8793 if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 )
8795 wxRect rect
= CellToRect(row
, col
);
8796 m_gridWin
->Refresh(true, &rect
);
8800 void wxGrid::SetCellHighlightROPenWidth(int width
)
8802 if (m_cellHighlightROPenWidth
!= width
) {
8803 m_cellHighlightROPenWidth
= width
;
8805 // Just redrawing the cell highlight is not enough since that won't
8806 // make any visible change if the the thickness is getting smaller.
8807 int row
= m_currentCellCoords
.GetRow();
8808 int col
= m_currentCellCoords
.GetCol();
8809 if ( GetColWidth(col
) <= 0 || GetRowHeight(row
) <= 0 )
8811 wxRect rect
= CellToRect(row
, col
);
8812 m_gridWin
->Refresh(true, &rect
);
8816 void wxGrid::EnableGridLines( bool enable
)
8818 if ( enable
!= m_gridLinesEnabled
)
8820 m_gridLinesEnabled
= enable
;
8822 if ( !GetBatchCount() )
8826 wxClientDC
dc( m_gridWin
);
8828 DrawAllGridLines( dc
, wxRegion() );
8832 m_gridWin
->Refresh();
8839 int wxGrid::GetDefaultRowSize()
8841 return m_defaultRowHeight
;
8844 int wxGrid::GetRowSize( int row
)
8846 wxCHECK_MSG( row
>= 0 && row
< m_numRows
, 0, _T("invalid row index") );
8848 return GetRowHeight(row
);
8851 int wxGrid::GetDefaultColSize()
8853 return m_defaultColWidth
;
8856 int wxGrid::GetColSize( int col
)
8858 wxCHECK_MSG( col
>= 0 && col
< m_numCols
, 0, _T("invalid column index") );
8860 return GetColWidth(col
);
8863 // ============================================================================
8864 // access to the grid attributes: each of them has a default value in the grid
8865 // itself and may be overidden on a per-cell basis
8866 // ============================================================================
8868 // ----------------------------------------------------------------------------
8869 // setting default attributes
8870 // ----------------------------------------------------------------------------
8872 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& col
)
8874 m_defaultCellAttr
->SetBackgroundColour(col
);
8876 m_gridWin
->SetBackgroundColour(col
);
8880 void wxGrid::SetDefaultCellTextColour( const wxColour
& col
)
8882 m_defaultCellAttr
->SetTextColour(col
);
8885 void wxGrid::SetDefaultCellAlignment( int horiz
, int vert
)
8887 m_defaultCellAttr
->SetAlignment(horiz
, vert
);
8890 void wxGrid::SetDefaultCellOverflow( bool allow
)
8892 m_defaultCellAttr
->SetOverflow(allow
);
8895 void wxGrid::SetDefaultCellFont( const wxFont
& font
)
8897 m_defaultCellAttr
->SetFont(font
);
8901 // For editors and renderers the type registry takes precedence over the
8902 // default attr, so we need to register the new editor/renderer for the string
8903 // data type in order to make setting a default editor/renderer appear to
8906 void wxGrid::SetDefaultRenderer(wxGridCellRenderer
*renderer
)
8908 RegisterDataType(wxGRID_VALUE_STRING
,
8910 GetDefaultEditorForType(wxGRID_VALUE_STRING
));
8913 void wxGrid::SetDefaultEditor(wxGridCellEditor
*editor
)
8915 RegisterDataType(wxGRID_VALUE_STRING
,
8916 GetDefaultRendererForType(wxGRID_VALUE_STRING
),
8920 // ----------------------------------------------------------------------------
8921 // access to the default attrbiutes
8922 // ----------------------------------------------------------------------------
8924 wxColour
wxGrid::GetDefaultCellBackgroundColour()
8926 return m_defaultCellAttr
->GetBackgroundColour();
8929 wxColour
wxGrid::GetDefaultCellTextColour()
8931 return m_defaultCellAttr
->GetTextColour();
8934 wxFont
wxGrid::GetDefaultCellFont()
8936 return m_defaultCellAttr
->GetFont();
8939 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert
)
8941 m_defaultCellAttr
->GetAlignment(horiz
, vert
);
8944 bool wxGrid::GetDefaultCellOverflow()
8946 return m_defaultCellAttr
->GetOverflow();
8949 wxGridCellRenderer
*wxGrid::GetDefaultRenderer() const
8951 return m_defaultCellAttr
->GetRenderer(NULL
, 0, 0);
8954 wxGridCellEditor
*wxGrid::GetDefaultEditor() const
8956 return m_defaultCellAttr
->GetEditor(NULL
,0,0);
8959 // ----------------------------------------------------------------------------
8960 // access to cell attributes
8961 // ----------------------------------------------------------------------------
8963 wxColour
wxGrid::GetCellBackgroundColour(int row
, int col
)
8965 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
8966 wxColour colour
= attr
->GetBackgroundColour();
8971 wxColour
wxGrid::GetCellTextColour( int row
, int col
)
8973 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
8974 wxColour colour
= attr
->GetTextColour();
8979 wxFont
wxGrid::GetCellFont( int row
, int col
)
8981 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
8982 wxFont font
= attr
->GetFont();
8987 void wxGrid::GetCellAlignment( int row
, int col
, int *horiz
, int *vert
)
8989 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
8990 attr
->GetAlignment(horiz
, vert
);
8994 bool wxGrid::GetCellOverflow( int row
, int col
)
8996 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
8997 bool allow
= attr
->GetOverflow();
9002 void wxGrid::GetCellSize( int row
, int col
, int *num_rows
, int *num_cols
)
9004 wxGridCellAttr
*attr
= GetCellAttr(row
, col
);
9005 attr
->GetSize( num_rows
, num_cols
);
9009 wxGridCellRenderer
* wxGrid::GetCellRenderer(int row
, int col
)
9011 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
9012 wxGridCellRenderer
* renderer
= attr
->GetRenderer(this, row
, col
);
9018 wxGridCellEditor
* wxGrid::GetCellEditor(int row
, int col
)
9020 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
9021 wxGridCellEditor
* editor
= attr
->GetEditor(this, row
, col
);
9027 bool wxGrid::IsReadOnly(int row
, int col
) const
9029 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
9030 bool isReadOnly
= attr
->IsReadOnly();
9035 // ----------------------------------------------------------------------------
9036 // attribute support: cache, automatic provider creation, ...
9037 // ----------------------------------------------------------------------------
9039 bool wxGrid::CanHaveAttributes()
9046 return m_table
->CanHaveAttributes();
9049 void wxGrid::ClearAttrCache()
9051 if ( m_attrCache
.row
!= -1 )
9053 wxSafeDecRef(m_attrCache
.attr
);
9054 m_attrCache
.attr
= NULL
;
9055 m_attrCache
.row
= -1;
9059 void wxGrid::CacheAttr(int row
, int col
, wxGridCellAttr
*attr
) const
9063 wxGrid
*self
= (wxGrid
*)this; // const_cast
9065 self
->ClearAttrCache();
9066 self
->m_attrCache
.row
= row
;
9067 self
->m_attrCache
.col
= col
;
9068 self
->m_attrCache
.attr
= attr
;
9073 bool wxGrid::LookupAttr(int row
, int col
, wxGridCellAttr
**attr
) const
9075 if ( row
== m_attrCache
.row
&& col
== m_attrCache
.col
)
9077 *attr
= m_attrCache
.attr
;
9078 wxSafeIncRef(m_attrCache
.attr
);
9080 #ifdef DEBUG_ATTR_CACHE
9081 gs_nAttrCacheHits
++;
9088 #ifdef DEBUG_ATTR_CACHE
9089 gs_nAttrCacheMisses
++;
9095 wxGridCellAttr
*wxGrid::GetCellAttr(int row
, int col
) const
9097 wxGridCellAttr
*attr
= NULL
;
9098 // Additional test to avoid looking at the cache e.g. for
9099 // wxNoCellCoords, as this will confuse memory management.
9102 if ( !LookupAttr(row
, col
, &attr
) )
9104 attr
= m_table
? m_table
->GetAttr(row
, col
, wxGridCellAttr::Any
)
9105 : (wxGridCellAttr
*)NULL
;
9106 CacheAttr(row
, col
, attr
);
9111 attr
->SetDefAttr(m_defaultCellAttr
);
9115 attr
= m_defaultCellAttr
;
9122 wxGridCellAttr
*wxGrid::GetOrCreateCellAttr(int row
, int col
) const
9124 wxGridCellAttr
*attr
= (wxGridCellAttr
*)NULL
;
9125 bool canHave
= ((wxGrid
*)this)->CanHaveAttributes();
9127 wxCHECK_MSG( canHave
, attr
, _T("Cell attributes not allowed"));
9128 wxCHECK_MSG( m_table
, attr
, _T("must have a table") );
9130 attr
= m_table
->GetAttr(row
, col
, wxGridCellAttr::Cell
);
9133 attr
= new wxGridCellAttr(m_defaultCellAttr
);
9135 // artificially inc the ref count to match DecRef() in caller
9137 m_table
->SetAttr(attr
, row
, col
);
9143 // ----------------------------------------------------------------------------
9144 // setting column attributes (wrappers around SetColAttr)
9145 // ----------------------------------------------------------------------------
9147 void wxGrid::SetColFormatBool(int col
)
9149 SetColFormatCustom(col
, wxGRID_VALUE_BOOL
);
9152 void wxGrid::SetColFormatNumber(int col
)
9154 SetColFormatCustom(col
, wxGRID_VALUE_NUMBER
);
9157 void wxGrid::SetColFormatFloat(int col
, int width
, int precision
)
9159 wxString typeName
= wxGRID_VALUE_FLOAT
;
9160 if ( (width
!= -1) || (precision
!= -1) )
9162 typeName
<< _T(':') << width
<< _T(',') << precision
;
9165 SetColFormatCustom(col
, typeName
);
9168 void wxGrid::SetColFormatCustom(int col
, const wxString
& typeName
)
9170 wxGridCellAttr
*attr
= m_table
->GetAttr(-1, col
, wxGridCellAttr::Col
);
9172 attr
= new wxGridCellAttr
;
9173 wxGridCellRenderer
*renderer
= GetDefaultRendererForType(typeName
);
9174 attr
->SetRenderer(renderer
);
9176 SetColAttr(col
, attr
);
9180 // ----------------------------------------------------------------------------
9181 // setting cell attributes: this is forwarded to the table
9182 // ----------------------------------------------------------------------------
9184 void wxGrid::SetAttr(int row
, int col
, wxGridCellAttr
*attr
)
9186 if ( CanHaveAttributes() )
9188 m_table
->SetAttr(attr
, row
, col
);
9197 void wxGrid::SetRowAttr(int row
, wxGridCellAttr
*attr
)
9199 if ( CanHaveAttributes() )
9201 m_table
->SetRowAttr(attr
, row
);
9210 void wxGrid::SetColAttr(int col
, wxGridCellAttr
*attr
)
9212 if ( CanHaveAttributes() )
9214 m_table
->SetColAttr(attr
, col
);
9223 void wxGrid::SetCellBackgroundColour( int row
, int col
, const wxColour
& colour
)
9225 if ( CanHaveAttributes() )
9227 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9228 attr
->SetBackgroundColour(colour
);
9233 void wxGrid::SetCellTextColour( int row
, int col
, const wxColour
& colour
)
9235 if ( CanHaveAttributes() )
9237 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9238 attr
->SetTextColour(colour
);
9243 void wxGrid::SetCellFont( int row
, int col
, const wxFont
& font
)
9245 if ( CanHaveAttributes() )
9247 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9248 attr
->SetFont(font
);
9253 void wxGrid::SetCellAlignment( int row
, int col
, int horiz
, int vert
)
9255 if ( CanHaveAttributes() )
9257 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9258 attr
->SetAlignment(horiz
, vert
);
9263 void wxGrid::SetCellOverflow( int row
, int col
, bool allow
)
9265 if ( CanHaveAttributes() )
9267 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9268 attr
->SetOverflow(allow
);
9273 void wxGrid::SetCellSize( int row
, int col
, int num_rows
, int num_cols
)
9275 if ( CanHaveAttributes() )
9277 int cell_rows
, cell_cols
;
9279 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9280 attr
->GetSize(&cell_rows
, &cell_cols
);
9281 attr
->SetSize(num_rows
, num_cols
);
9284 // Cannot set the size of a cell to 0 or negative values
9285 // While it is perfectly legal to do that, this function cannot
9286 // handle all the possibilies, do it by hand by getting the CellAttr.
9287 // You can only set the size of a cell to 1,1 or greater with this fn
9288 wxASSERT_MSG( !((cell_rows
< 1) || (cell_cols
< 1)),
9289 wxT("wxGrid::SetCellSize setting cell size that is already part of another cell"));
9290 wxASSERT_MSG( !((num_rows
< 1) || (num_cols
< 1)),
9291 wxT("wxGrid::SetCellSize setting cell size to < 1"));
9293 // if this was already a multicell then "turn off" the other cells first
9294 if ((cell_rows
> 1) || (cell_rows
> 1))
9297 for (j
=row
; j
<row
+cell_rows
; j
++)
9299 for (i
=col
; i
<col
+cell_cols
; i
++)
9301 if ((i
!= col
) || (j
!= row
))
9303 wxGridCellAttr
*attr_stub
= GetOrCreateCellAttr(j
, i
);
9304 attr_stub
->SetSize( 1, 1 );
9305 attr_stub
->DecRef();
9311 // mark the cells that will be covered by this cell to
9312 // negative or zero values to point back at this cell
9313 if (((num_rows
> 1) || (num_cols
> 1)) && (num_rows
>= 1) && (num_cols
>= 1))
9316 for (j
=row
; j
<row
+num_rows
; j
++)
9318 for (i
=col
; i
<col
+num_cols
; i
++)
9320 if ((i
!= col
) || (j
!= row
))
9322 wxGridCellAttr
*attr_stub
= GetOrCreateCellAttr(j
, i
);
9323 attr_stub
->SetSize( row
-j
, col
-i
);
9324 attr_stub
->DecRef();
9332 void wxGrid::SetCellRenderer(int row
, int col
, wxGridCellRenderer
*renderer
)
9334 if ( CanHaveAttributes() )
9336 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9337 attr
->SetRenderer(renderer
);
9342 void wxGrid::SetCellEditor(int row
, int col
, wxGridCellEditor
* editor
)
9344 if ( CanHaveAttributes() )
9346 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9347 attr
->SetEditor(editor
);
9352 void wxGrid::SetReadOnly(int row
, int col
, bool isReadOnly
)
9354 if ( CanHaveAttributes() )
9356 wxGridCellAttr
*attr
= GetOrCreateCellAttr(row
, col
);
9357 attr
->SetReadOnly(isReadOnly
);
9362 // ----------------------------------------------------------------------------
9363 // Data type registration
9364 // ----------------------------------------------------------------------------
9366 void wxGrid::RegisterDataType(const wxString
& typeName
,
9367 wxGridCellRenderer
* renderer
,
9368 wxGridCellEditor
* editor
)
9370 m_typeRegistry
->RegisterDataType(typeName
, renderer
, editor
);
9374 wxGridCellEditor
* wxGrid::GetDefaultEditorForCell(int row
, int col
) const
9376 wxString typeName
= m_table
->GetTypeName(row
, col
);
9377 return GetDefaultEditorForType(typeName
);
9380 wxGridCellRenderer
* wxGrid::GetDefaultRendererForCell(int row
, int col
) const
9382 wxString typeName
= m_table
->GetTypeName(row
, col
);
9383 return GetDefaultRendererForType(typeName
);
9387 wxGrid::GetDefaultEditorForType(const wxString
& typeName
) const
9389 int index
= m_typeRegistry
->FindOrCloneDataType(typeName
);
9390 if ( index
== wxNOT_FOUND
)
9392 wxFAIL_MSG(wxT("Unknown data type name"));
9397 return m_typeRegistry
->GetEditor(index
);
9401 wxGrid::GetDefaultRendererForType(const wxString
& typeName
) const
9403 int index
= m_typeRegistry
->FindOrCloneDataType(typeName
);
9404 if ( index
== wxNOT_FOUND
)
9406 wxFAIL_MSG(wxT("Unknown data type name"));
9411 return m_typeRegistry
->GetRenderer(index
);
9415 // ----------------------------------------------------------------------------
9417 // ----------------------------------------------------------------------------
9419 void wxGrid::EnableDragRowSize( bool enable
)
9421 m_canDragRowSize
= enable
;
9425 void wxGrid::EnableDragColSize( bool enable
)
9427 m_canDragColSize
= enable
;
9430 void wxGrid::EnableDragGridSize( bool enable
)
9432 m_canDragGridSize
= enable
;
9435 void wxGrid::EnableDragCell( bool enable
)
9437 m_canDragCell
= enable
;
9440 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows
)
9442 m_defaultRowHeight
= wxMax( height
, m_minAcceptableRowHeight
);
9444 if ( resizeExistingRows
)
9446 // since we are resizing all rows to the default row size,
9447 // we can simply clear the row heights and row bottoms
9448 // arrays (which also allows us to take advantage of
9449 // some speed optimisations)
9450 m_rowHeights
.Empty();
9451 m_rowBottoms
.Empty();
9452 if ( !GetBatchCount() )
9457 void wxGrid::SetRowSize( int row
, int height
)
9459 wxCHECK_RET( row
>= 0 && row
< m_numRows
, _T("invalid row index") );
9461 // See comment in SetColSize
9462 if ( height
< GetRowMinimalAcceptableHeight()) { return; }
9464 if ( m_rowHeights
.IsEmpty() )
9466 // need to really create the array
9470 int h
= wxMax( 0, height
);
9471 int diff
= h
- m_rowHeights
[row
];
9473 m_rowHeights
[row
] = h
;
9475 for ( i
= row
; i
< m_numRows
; i
++ )
9477 m_rowBottoms
[i
] += diff
;
9479 if ( !GetBatchCount() )
9483 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols
)
9485 m_defaultColWidth
= wxMax( width
, m_minAcceptableColWidth
);
9487 if ( resizeExistingCols
)
9489 // since we are resizing all columns to the default column size,
9490 // we can simply clear the col widths and col rights
9491 // arrays (which also allows us to take advantage of
9492 // some speed optimisations)
9493 m_colWidths
.Empty();
9494 m_colRights
.Empty();
9495 if ( !GetBatchCount() )
9500 void wxGrid::SetColSize( int col
, int width
)
9502 wxCHECK_RET( col
>= 0 && col
< m_numCols
, _T("invalid column index") );
9504 // should we check that it's bigger than GetColMinimalWidth(col) here?
9506 // No, because it is reasonable to assume the library user know's
9507 // what he is doing. However whe should test against the weaker
9508 // constariant of minimalAcceptableWidth, as this breaks rendering
9510 // This test then fixes sf.net bug #645734
9512 if ( width
< GetColMinimalAcceptableWidth()) { return; }
9514 if ( m_colWidths
.IsEmpty() )
9516 // need to really create the array
9520 // if < 0 calc new width from label
9524 wxArrayString lines
;
9525 wxClientDC
dc(m_colLabelWin
);
9526 dc
.SetFont(GetLabelFont());
9527 StringToLines(GetColLabelValue(col
), lines
);
9528 GetTextBoxSize(dc
, lines
, &w
, &h
);
9531 int w
= wxMax( 0, width
);
9532 int diff
= w
- m_colWidths
[col
];
9533 m_colWidths
[col
] = w
;
9536 for ( i
= col
; i
< m_numCols
; i
++ )
9538 m_colRights
[i
] += diff
;
9540 if ( !GetBatchCount() )
9545 void wxGrid::SetColMinimalWidth( int col
, int width
)
9547 if (width
> GetColMinimalAcceptableWidth()) {
9548 wxLongToLongHashMap::key_type key
= (wxLongToLongHashMap::key_type
)col
;
9549 m_colMinWidths
[key
] = width
;
9553 void wxGrid::SetRowMinimalHeight( int row
, int width
)
9555 if (width
> GetRowMinimalAcceptableHeight()) {
9556 wxLongToLongHashMap::key_type key
= (wxLongToLongHashMap::key_type
)row
;
9557 m_rowMinHeights
[key
] = width
;
9561 int wxGrid::GetColMinimalWidth(int col
) const
9563 wxLongToLongHashMap::key_type key
= (wxLongToLongHashMap::key_type
)col
;
9564 wxLongToLongHashMap::const_iterator it
= m_colMinWidths
.find(key
);
9565 return it
!= m_colMinWidths
.end() ? (int)it
->second
: m_minAcceptableColWidth
;
9568 int wxGrid::GetRowMinimalHeight(int row
) const
9570 wxLongToLongHashMap::key_type key
= (wxLongToLongHashMap::key_type
)row
;
9571 wxLongToLongHashMap::const_iterator it
= m_rowMinHeights
.find(key
);
9572 return it
!= m_rowMinHeights
.end() ? (int)it
->second
: m_minAcceptableRowHeight
;
9575 void wxGrid::SetColMinimalAcceptableWidth( int width
)
9577 // We do allow a width of 0 since this gives us
9578 // an easy way to temporarily hidding columns.
9581 m_minAcceptableColWidth
= width
;
9584 void wxGrid::SetRowMinimalAcceptableHeight( int height
)
9586 // We do allow a height of 0 since this gives us
9587 // an easy way to temporarily hidding rows.
9590 m_minAcceptableRowHeight
= height
;
9593 int wxGrid::GetColMinimalAcceptableWidth() const
9595 return m_minAcceptableColWidth
;
9598 int wxGrid::GetRowMinimalAcceptableHeight() const
9600 return m_minAcceptableRowHeight
;
9603 // ----------------------------------------------------------------------------
9605 // ----------------------------------------------------------------------------
9607 void wxGrid::AutoSizeColOrRow( int colOrRow
, bool setAsMin
, bool column
)
9609 wxClientDC
dc(m_gridWin
);
9611 //Cancel editting of cell
9612 HideCellEditControl();
9613 SaveEditControlValue();
9615 // init both of them to avoid compiler warnings, even if weo nly need one
9623 wxCoord extent
, extentMax
= 0;
9624 int max
= column
? m_numRows
: m_numCols
;
9625 for ( int rowOrCol
= 0; rowOrCol
< max
; rowOrCol
++ )
9632 wxGridCellAttr
* attr
= GetCellAttr(row
, col
);
9633 wxGridCellRenderer
* renderer
= attr
->GetRenderer(this, row
, col
);
9636 wxSize size
= renderer
->GetBestSize(*this, *attr
, dc
, row
, col
);
9637 extent
= column
? size
.x
: size
.y
;
9638 if ( extent
> extentMax
)
9649 // now also compare with the column label extent
9651 dc
.SetFont( GetLabelFont() );
9655 dc
.GetTextExtent( GetColLabelValue(col
), &w
, &h
);
9656 if( GetColLabelTextOrientation() == wxVERTICAL
)
9660 dc
.GetTextExtent( GetRowLabelValue(row
), &w
, &h
);
9662 extent
= column
? w
: h
;
9663 if ( extent
> extentMax
)
9670 // empty column - give default extent (notice that if extentMax is less
9671 // than default extent but != 0, it's ok)
9672 extentMax
= column
? m_defaultColWidth
: m_defaultRowHeight
;
9678 // leave some space around text
9689 SetColSize(col
, extentMax
);
9690 if ( !GetBatchCount() )
9693 m_gridWin
->GetClientSize( &cw
, &ch
);
9694 wxRect
rect ( CellToRect( 0, col
) );
9696 CalcScrolledPosition(rect
.x
, 0, &rect
.x
, &dummy
);
9697 rect
.width
= cw
- rect
.x
;
9698 rect
.height
= m_colLabelHeight
;
9699 m_colLabelWin
->Refresh( true, &rect
);
9704 SetRowSize(row
, extentMax
);
9705 if ( !GetBatchCount() )
9708 m_gridWin
->GetClientSize( &cw
, &ch
);
9709 wxRect
rect ( CellToRect( row
, 0 ) );
9711 CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
);
9712 rect
.width
= m_rowLabelWidth
;
9713 rect
.height
= ch
- rect
.y
;
9714 m_rowLabelWin
->Refresh( true, &rect
);
9720 SetColMinimalWidth(col
, extentMax
);
9722 SetRowMinimalHeight(row
, extentMax
);
9726 int wxGrid::SetOrCalcColumnSizes(bool calcOnly
, bool setAsMin
)
9728 int width
= m_rowLabelWidth
;
9733 for ( int col
= 0; col
< m_numCols
; col
++ )
9737 AutoSizeColumn(col
, setAsMin
);
9740 width
+= GetColWidth(col
);
9749 int wxGrid::SetOrCalcRowSizes(bool calcOnly
, bool setAsMin
)
9751 int height
= m_colLabelHeight
;
9756 for ( int row
= 0; row
< m_numRows
; row
++ )
9760 AutoSizeRow(row
, setAsMin
);
9763 height
+= GetRowHeight(row
);
9772 void wxGrid::AutoSize()
9776 wxSize
size(SetOrCalcColumnSizes(false), SetOrCalcRowSizes(false));
9778 // round up the size to a multiple of scroll step - this ensures that we
9779 // won't get the scrollbars if we're sized exactly to this width
9780 // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary
9782 wxSize
sizeFit(GetScrollX(size
.x
+ m_extraWidth
+ 1) * GRID_SCROLL_LINE_X
,
9783 GetScrollY(size
.y
+ m_extraHeight
+ 1) * GRID_SCROLL_LINE_Y
);
9785 // distribute the extra space between the columns/rows to avoid having
9786 // extra white space
9788 // Remove the extra m_extraWidth + 1 added above
9789 wxCoord diff
= sizeFit
.x
- size
.x
+ (m_extraWidth
+ 1);
9790 if ( diff
&& m_numCols
)
9792 // try to resize the columns uniformly
9793 wxCoord diffPerCol
= diff
/ m_numCols
;
9796 for ( int col
= 0; col
< m_numCols
; col
++ )
9798 SetColSize(col
, GetColWidth(col
) + diffPerCol
);
9802 // add remaining amount to the last columns
9803 diff
-= diffPerCol
* m_numCols
;
9806 for ( int col
= m_numCols
- 1; col
>= m_numCols
- diff
; col
-- )
9808 SetColSize(col
, GetColWidth(col
) + 1);
9814 diff
= sizeFit
.y
- size
.y
- (m_extraHeight
+ 1);
9815 if ( diff
&& m_numRows
)
9817 // try to resize the columns uniformly
9818 wxCoord diffPerRow
= diff
/ m_numRows
;
9821 for ( int row
= 0; row
< m_numRows
; row
++ )
9823 SetRowSize(row
, GetRowHeight(row
) + diffPerRow
);
9827 // add remaining amount to the last rows
9828 diff
-= diffPerRow
* m_numRows
;
9831 for ( int row
= m_numRows
- 1; row
>= m_numRows
- diff
; row
-- )
9833 SetRowSize(row
, GetRowHeight(row
) + 1);
9840 SetClientSize(sizeFit
);
9843 void wxGrid::AutoSizeRowLabelSize( int row
)
9845 wxArrayString lines
;
9848 // Hide the edit control, so it
9849 // won't interfer with drag-shrinking.
9850 if( IsCellEditControlShown() )
9852 HideCellEditControl();
9853 SaveEditControlValue();
9856 // autosize row height depending on label text
9857 StringToLines( GetRowLabelValue( row
), lines
);
9858 wxClientDC
dc( m_rowLabelWin
);
9859 GetTextBoxSize( dc
, lines
, &w
, &h
);
9860 if( h
< m_defaultRowHeight
)
9861 h
= m_defaultRowHeight
;
9866 void wxGrid::AutoSizeColLabelSize( int col
)
9868 wxArrayString lines
;
9871 // Hide the edit control, so it
9872 // won't interfer with drag-shrinking.
9873 if( IsCellEditControlShown() )
9875 HideCellEditControl();
9876 SaveEditControlValue();
9879 // autosize column width depending on label text
9880 StringToLines( GetColLabelValue( col
), lines
);
9881 wxClientDC
dc( m_colLabelWin
);
9882 if( GetColLabelTextOrientation() == wxHORIZONTAL
)
9883 GetTextBoxSize( dc
, lines
, &w
, &h
);
9885 GetTextBoxSize( dc
, lines
, &h
, &w
);
9886 if( w
< m_defaultColWidth
)
9887 w
= m_defaultColWidth
;
9892 wxSize
wxGrid::DoGetBestSize() const
9894 // don't set sizes, only calculate them
9895 wxGrid
*self
= (wxGrid
*)this; // const_cast
9898 width
= self
->SetOrCalcColumnSizes(true);
9899 height
= self
->SetOrCalcRowSizes(true);
9901 if (!width
) width
=100;
9902 if (!height
) height
=80;
9904 // Round up to a multiple the scroll rate NOTE: this still doesn't get rid
9905 // of the scrollbars, is there any magic incantaion for that?
9907 GetScrollPixelsPerUnit(&xpu
, &ypu
);
9909 width
+= 1 + xpu
- (width
% xpu
);
9911 height
+= 1 + ypu
- (height
% ypu
);
9913 // limit to 1/4 of the screen size
9914 int maxwidth
, maxheight
;
9915 wxDisplaySize( & maxwidth
, & maxheight
);
9918 if ( width
> maxwidth
) width
= maxwidth
;
9919 if ( height
> maxheight
) height
= maxheight
;
9922 wxSize
best(width
, height
);
9923 // NOTE: This size should be cached, but first we need to add calls to
9924 // InvalidateBestSize everywhere that could change the results of this
9926 // CacheBestSize(size);
9936 wxPen
& wxGrid::GetDividerPen() const
9941 // ----------------------------------------------------------------------------
9942 // cell value accessor functions
9943 // ----------------------------------------------------------------------------
9945 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s
)
9949 m_table
->SetValue( row
, col
, s
);
9950 if ( !GetBatchCount() )
9953 wxRect
rect( CellToRect( row
, col
) );
9955 rect
.width
= m_gridWin
->GetClientSize().GetWidth();
9956 CalcScrolledPosition(0, rect
.y
, &dummy
, &rect
.y
);
9957 m_gridWin
->Refresh( false, &rect
);
9960 if ( m_currentCellCoords
.GetRow() == row
&&
9961 m_currentCellCoords
.GetCol() == col
&&
9962 IsCellEditControlShown())
9963 // Note: If we are using IsCellEditControlEnabled,
9964 // this interacts badly with calling SetCellValue from
9965 // an EVT_GRID_CELL_CHANGE handler.
9967 HideCellEditControl();
9968 ShowCellEditControl(); // will reread data from table
9975 // ------ Block, row and col selection
9978 void wxGrid::SelectRow( int row
, bool addToSelected
)
9980 if ( IsSelection() && !addToSelected
)
9984 m_selection
->SelectRow( row
, false, addToSelected
);
9988 void wxGrid::SelectCol( int col
, bool addToSelected
)
9990 if ( IsSelection() && !addToSelected
)
9994 m_selection
->SelectCol( col
, false, addToSelected
);
9998 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
,
9999 bool addToSelected
)
10001 if ( IsSelection() && !addToSelected
)
10005 m_selection
->SelectBlock( topRow
, leftCol
, bottomRow
, rightCol
,
10006 false, addToSelected
);
10010 void wxGrid::SelectAll()
10012 if ( m_numRows
> 0 && m_numCols
> 0 )
10015 m_selection
->SelectBlock( 0, 0, m_numRows
-1, m_numCols
-1 );
10020 // ------ Cell, row and col deselection
10023 void wxGrid::DeselectRow( int row
)
10025 if ( !m_selection
)
10028 if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectRows
)
10030 if ( m_selection
->IsInSelection(row
, 0 ) )
10031 m_selection
->ToggleCellSelection( row
, 0);
10035 int nCols
= GetNumberCols();
10036 for ( int i
= 0; i
< nCols
; i
++ )
10038 if ( m_selection
->IsInSelection(row
, i
) )
10039 m_selection
->ToggleCellSelection( row
, i
);
10044 void wxGrid::DeselectCol( int col
)
10046 if ( !m_selection
)
10049 if ( m_selection
->GetSelectionMode() == wxGrid::wxGridSelectColumns
)
10051 if ( m_selection
->IsInSelection(0, col
) )
10052 m_selection
->ToggleCellSelection( 0, col
);
10056 int nRows
= GetNumberRows();
10057 for ( int i
= 0; i
< nRows
; i
++ )
10059 if ( m_selection
->IsInSelection(i
, col
) )
10060 m_selection
->ToggleCellSelection(i
, col
);
10065 void wxGrid::DeselectCell( int row
, int col
)
10067 if ( m_selection
&& m_selection
->IsInSelection(row
, col
) )
10068 m_selection
->ToggleCellSelection(row
, col
);
10071 bool wxGrid::IsSelection()
10073 return ( m_selection
&& (m_selection
->IsSelection() ||
10074 ( m_selectingTopLeft
!= wxGridNoCellCoords
&&
10075 m_selectingBottomRight
!= wxGridNoCellCoords
) ) );
10078 bool wxGrid::IsInSelection( int row
, int col
) const
10080 return ( m_selection
&& (m_selection
->IsInSelection( row
, col
) ||
10081 ( row
>= m_selectingTopLeft
.GetRow() &&
10082 col
>= m_selectingTopLeft
.GetCol() &&
10083 row
<= m_selectingBottomRight
.GetRow() &&
10084 col
<= m_selectingBottomRight
.GetCol() )) );
10087 wxGridCellCoordsArray
wxGrid::GetSelectedCells() const
10089 if (!m_selection
) { wxGridCellCoordsArray a
; return a
; }
10090 return m_selection
->m_cellSelection
;
10092 wxGridCellCoordsArray
wxGrid::GetSelectionBlockTopLeft() const
10094 if (!m_selection
) { wxGridCellCoordsArray a
; return a
; }
10095 return m_selection
->m_blockSelectionTopLeft
;
10097 wxGridCellCoordsArray
wxGrid::GetSelectionBlockBottomRight() const
10099 if (!m_selection
) { wxGridCellCoordsArray a
; return a
; }
10100 return m_selection
->m_blockSelectionBottomRight
;
10102 wxArrayInt
wxGrid::GetSelectedRows() const
10104 if (!m_selection
) { wxArrayInt a
; return a
; }
10105 return m_selection
->m_rowSelection
;
10107 wxArrayInt
wxGrid::GetSelectedCols() const
10109 if (!m_selection
) { wxArrayInt a
; return a
; }
10110 return m_selection
->m_colSelection
;
10114 void wxGrid::ClearSelection()
10116 m_selectingTopLeft
= wxGridNoCellCoords
;
10117 m_selectingBottomRight
= wxGridNoCellCoords
;
10119 m_selection
->ClearSelection();
10123 // This function returns the rectangle that encloses the given block
10124 // in device coords clipped to the client size of the grid window.
10126 wxRect
wxGrid::BlockToDeviceRect( const wxGridCellCoords
&topLeft
,
10127 const wxGridCellCoords
&bottomRight
)
10129 wxRect
rect( wxGridNoCellRect
);
10132 cellRect
= CellToRect( topLeft
);
10133 if ( cellRect
!= wxGridNoCellRect
)
10139 rect
= wxRect( 0, 0, 0, 0 );
10142 cellRect
= CellToRect( bottomRight
);
10143 if ( cellRect
!= wxGridNoCellRect
)
10149 return wxGridNoCellRect
;
10153 int left
= rect
.GetLeft();
10154 int top
= rect
.GetTop();
10155 int right
= rect
.GetRight();
10156 int bottom
= rect
.GetBottom();
10158 int leftCol
= topLeft
.GetCol();
10159 int topRow
= topLeft
.GetRow();
10160 int rightCol
= bottomRight
.GetCol();
10161 int bottomRow
= bottomRight
.GetRow();
10179 topRow
= bottomRow
;
10184 for ( j
= topRow
; j
<= bottomRow
; j
++ )
10186 for ( i
= leftCol
; i
<= rightCol
; i
++ )
10188 if ((j
==topRow
) || (j
==bottomRow
) || (i
==leftCol
) || (i
==rightCol
))
10190 cellRect
= CellToRect( j
, i
);
10192 if (cellRect
.x
< left
)
10194 if (cellRect
.y
< top
)
10196 if (cellRect
.x
+ cellRect
.width
> right
)
10197 right
= cellRect
.x
+ cellRect
.width
;
10198 if (cellRect
.y
+ cellRect
.height
> bottom
)
10199 bottom
= cellRect
.y
+ cellRect
.height
;
10201 else i
= rightCol
; // jump over inner cells.
10205 // convert to scrolled coords
10207 CalcScrolledPosition( left
, top
, &left
, &top
);
10208 CalcScrolledPosition( right
, bottom
, &right
, &bottom
);
10211 m_gridWin
->GetClientSize( &cw
, &ch
);
10213 if (right
< 0 || bottom
< 0 || left
> cw
|| top
> ch
)
10214 return wxRect( 0, 0, 0, 0);
10216 rect
.SetLeft( wxMax(0, left
) );
10217 rect
.SetTop( wxMax(0, top
) );
10218 rect
.SetRight( wxMin(cw
, right
) );
10219 rect
.SetBottom( wxMin(ch
, bottom
) );
10225 // ------ Grid event classes
10228 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxNotifyEvent
)
10230 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
,
10231 int row
, int col
, int x
, int y
, bool sel
,
10232 bool control
, bool shift
, bool alt
, bool meta
)
10233 : wxNotifyEvent( type
, id
)
10240 m_control
= control
;
10245 SetEventObject(obj
);
10249 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxNotifyEvent
)
10251 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
,
10252 int rowOrCol
, int x
, int y
,
10253 bool control
, bool shift
, bool alt
, bool meta
)
10254 : wxNotifyEvent( type
, id
)
10256 m_rowOrCol
= rowOrCol
;
10259 m_control
= control
;
10264 SetEventObject(obj
);
10268 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxNotifyEvent
)
10270 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
,
10271 const wxGridCellCoords
& topLeft
,
10272 const wxGridCellCoords
& bottomRight
,
10273 bool sel
, bool control
,
10274 bool shift
, bool alt
, bool meta
)
10275 : wxNotifyEvent( type
, id
)
10277 m_topLeft
= topLeft
;
10278 m_bottomRight
= bottomRight
;
10280 m_control
= control
;
10285 SetEventObject(obj
);
10289 IMPLEMENT_DYNAMIC_CLASS(wxGridEditorCreatedEvent
, wxCommandEvent
)
10291 wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id
, wxEventType type
,
10292 wxObject
* obj
, int row
,
10293 int col
, wxControl
* ctrl
)
10294 : wxCommandEvent(type
, id
)
10296 SetEventObject(obj
);
10302 #endif // wxUSE_GRID