1 ///////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/grideditors.cpp
3 // Purpose: wxGridCellEditorEvtHandler and wxGrid editors
4 // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
5 // Modified by: Robin Dunn, Vadim Zeitlin, Santiago Palacios
8 // Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
25 #include "wx/dcclient.h"
26 #include "wx/settings.h"
28 #include "wx/textctrl.h"
29 #include "wx/checkbox.h"
30 #include "wx/combobox.h"
31 #include "wx/valtext.h"
34 #include "wx/listbox.h"
37 #include "wx/textfile.h"
38 #include "wx/spinctrl.h"
39 #include "wx/tokenzr.h"
40 #include "wx/renderer.h"
41 #include "wx/headerctrl.h"
43 #include "wx/generic/gridsel.h"
44 #include "wx/generic/grideditors.h"
45 #include "wx/generic/private/grid.h"
47 #if defined(__WXMOTIF__)
48 #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)
50 #define WXUNUSED_MOTIF(identifier) identifier
53 #if defined(__WXGTK__)
54 #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)
56 #define WXUNUSED_GTK(identifier) identifier
59 // Required for wxIs... functions
62 // ============================================================================
64 // ============================================================================
66 // ----------------------------------------------------------------------------
67 // wxGridCellEditorEvtHandler
68 // ----------------------------------------------------------------------------
70 void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent
& event
)
72 // Don't disable the cell if we're just starting to edit it
77 m_grid
->DisableCellEditControl();
82 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent
& event
)
84 switch ( event
.GetKeyCode() )
88 m_grid
->DisableCellEditControl();
92 m_grid
->GetEventHandler()->ProcessEvent( event
);
96 case WXK_NUMPAD_ENTER
:
97 if (!m_grid
->GetEventHandler()->ProcessEvent(event
))
98 m_editor
->HandleReturn(event
);
107 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent
& event
)
109 int row
= m_grid
->GetGridCursorRow();
110 int col
= m_grid
->GetGridCursorCol();
111 wxRect rect
= m_grid
->CellToRect( row
, col
);
113 m_grid
->GetGridWindow()->GetClientSize( &cw
, &ch
);
115 // if cell width is smaller than grid client area, cell is wholly visible
116 bool wholeCellVisible
= (rect
.GetWidth() < cw
);
118 switch ( event
.GetKeyCode() )
123 case WXK_NUMPAD_ENTER
:
128 if ( wholeCellVisible
)
130 // no special processing needed...
135 // do special processing for partly visible cell...
137 // get the widths of all cells previous to this one
139 for ( int i
= 0; i
< col
; i
++ )
141 colXPos
+= m_grid
->GetColSize(i
);
144 int xUnit
= 1, yUnit
= 1;
145 m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
);
148 m_grid
->Scroll(colXPos
/ xUnit
- 1, m_grid
->GetScrollPos(wxVERTICAL
));
152 m_grid
->Scroll(colXPos
/ xUnit
, m_grid
->GetScrollPos(wxVERTICAL
));
160 if ( wholeCellVisible
)
162 // no special processing needed...
167 // do special processing for partly visible cell...
170 wxString value
= m_grid
->GetCellValue(row
, col
);
171 if ( wxEmptyString
!= value
)
173 // get width of cell CONTENTS (text)
175 wxFont font
= m_grid
->GetCellFont(row
, col
);
176 m_grid
->GetTextExtent(value
, &textWidth
, &y
, NULL
, NULL
, &font
);
178 // try to RIGHT align the text by scrolling
179 int client_right
= m_grid
->GetGridWindow()->GetClientSize().GetWidth();
181 // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far,
182 // otherwise the last part of the cell content might be hidden below the scroll bar
183 // FIXME: maybe there is a more suitable correction?
184 textWidth
-= (client_right
- (m_grid
->GetScrollLineX() * 2));
191 // get the widths of all cells previous to this one
193 for ( int i
= 0; i
< col
; i
++ )
195 colXPos
+= m_grid
->GetColSize(i
);
198 // and add the (modified) text width of the cell contents
199 // as we'd like to see the last part of the cell contents
200 colXPos
+= textWidth
;
202 int xUnit
= 1, yUnit
= 1;
203 m_grid
->GetScrollPixelsPerUnit(&xUnit
, &yUnit
);
204 m_grid
->Scroll(colXPos
/ xUnit
- 1, m_grid
->GetScrollPos(wxVERTICAL
));
215 // ----------------------------------------------------------------------------
217 // ----------------------------------------------------------------------------
219 wxGridCellEditor::wxGridCellEditor()
225 wxGridCellEditor::~wxGridCellEditor()
230 void wxGridCellEditor::Create(wxWindow
* WXUNUSED(parent
),
231 wxWindowID
WXUNUSED(id
),
232 wxEvtHandler
* evtHandler
)
235 m_control
->PushEventHandler(evtHandler
);
238 void wxGridCellEditor::PaintBackground(const wxRect
& rectCell
,
239 wxGridCellAttr
*attr
)
241 // erase the background because we might not fill the cell
242 wxClientDC
dc(m_control
->GetParent());
243 wxGridWindow
* gridWindow
= wxDynamicCast(m_control
->GetParent(), wxGridWindow
);
245 gridWindow
->GetOwner()->PrepareDC(dc
);
247 dc
.SetPen(*wxTRANSPARENT_PEN
);
248 dc
.SetBrush(wxBrush(attr
->GetBackgroundColour()));
249 dc
.DrawRectangle(rectCell
);
251 // redraw the control we just painted over
252 m_control
->Refresh();
255 void wxGridCellEditor::Destroy()
259 m_control
->PopEventHandler( true /* delete it*/ );
261 m_control
->Destroy();
266 void wxGridCellEditor::Show(bool show
, wxGridCellAttr
*attr
)
268 wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!"));
270 m_control
->Show(show
);
274 // set the colours/fonts if we have any
277 m_colFgOld
= m_control
->GetForegroundColour();
278 m_control
->SetForegroundColour(attr
->GetTextColour());
280 m_colBgOld
= m_control
->GetBackgroundColour();
281 m_control
->SetBackgroundColour(attr
->GetBackgroundColour());
283 // Workaround for GTK+1 font setting problem on some platforms
284 #if !defined(__WXGTK__) || defined(__WXGTK20__)
285 m_fontOld
= m_control
->GetFont();
286 m_control
->SetFont(attr
->GetFont());
289 // can't do anything more in the base class version, the other
290 // attributes may only be used by the derived classes
295 // restore the standard colours fonts
296 if ( m_colFgOld
.Ok() )
298 m_control
->SetForegroundColour(m_colFgOld
);
299 m_colFgOld
= wxNullColour
;
302 if ( m_colBgOld
.Ok() )
304 m_control
->SetBackgroundColour(m_colBgOld
);
305 m_colBgOld
= wxNullColour
;
308 // Workaround for GTK+1 font setting problem on some platforms
309 #if !defined(__WXGTK__) || defined(__WXGTK20__)
310 if ( m_fontOld
.Ok() )
312 m_control
->SetFont(m_fontOld
);
313 m_fontOld
= wxNullFont
;
319 void wxGridCellEditor::SetSize(const wxRect
& rect
)
321 wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!"));
323 m_control
->SetSize(rect
, wxSIZE_ALLOW_MINUS_ONE
);
326 void wxGridCellEditor::HandleReturn(wxKeyEvent
& event
)
331 bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent
& event
)
333 bool ctrl
= event
.ControlDown();
334 bool alt
= event
.AltDown();
337 // On the Mac the Alt key is more like shift and is used for entry of
338 // valid characters, so check for Ctrl and Meta instead.
339 alt
= event
.MetaDown();
342 // Assume it's not a valid char if ctrl or alt is down, but if both are
343 // down then it may be because of an AltGr key combination, so let them
344 // through in that case.
345 if ((ctrl
|| alt
) && !(ctrl
&& alt
))
349 // if the unicode key code is not really a unicode character (it may
350 // be a function key or etc., the platforms appear to always give us a
351 // small value in this case) then fallback to the ASCII key code but
352 // don't do anything for function keys or etc.
353 if ( event
.GetUnicodeKey() > 127 && event
.GetKeyCode() > 127 )
356 if ( event
.GetKeyCode() > 255 )
363 void wxGridCellEditor::StartingKey(wxKeyEvent
& event
)
368 void wxGridCellEditor::StartingClick()
374 // ----------------------------------------------------------------------------
375 // wxGridCellTextEditor
376 // ----------------------------------------------------------------------------
378 wxGridCellTextEditor::wxGridCellTextEditor()
383 void wxGridCellTextEditor::Create(wxWindow
* parent
,
385 wxEvtHandler
* evtHandler
)
387 DoCreate(parent
, id
, evtHandler
);
390 void wxGridCellTextEditor::DoCreate(wxWindow
* parent
,
392 wxEvtHandler
* evtHandler
,
395 style
|= wxTE_PROCESS_ENTER
| wxTE_PROCESS_TAB
| wxNO_BORDER
;
397 m_control
= new wxTextCtrl(parent
, id
, wxEmptyString
,
398 wxDefaultPosition
, wxDefaultSize
,
401 // set max length allowed in the textctrl, if the parameter was set
402 if ( m_maxChars
!= 0 )
404 Text()->SetMaxLength(m_maxChars
);
407 wxGridCellEditor::Create(parent
, id
, evtHandler
);
410 void wxGridCellTextEditor::PaintBackground(const wxRect
& WXUNUSED(rectCell
),
411 wxGridCellAttr
* WXUNUSED(attr
))
413 // as we fill the entire client area,
414 // don't do anything here to minimize flicker
417 void wxGridCellTextEditor::SetSize(const wxRect
& rectOrig
)
419 wxRect
rect(rectOrig
);
421 // Make the edit control large enough to allow for internal margins
423 // TODO: remove this if the text ctrl sizing is improved esp. for unix
425 #if defined(__WXGTK__)
433 #elif defined(__WXMSW__)
447 int extra_x
= ( rect
.x
> 2 ) ? 2 : 1;
448 int extra_y
= ( rect
.y
> 2 ) ? 2 : 1;
450 #if defined(__WXMOTIF__)
455 rect
.SetLeft( wxMax(0, rect
.x
- extra_x
) );
456 rect
.SetTop( wxMax(0, rect
.y
- extra_y
) );
457 rect
.SetRight( rect
.GetRight() + 2 * extra_x
);
458 rect
.SetBottom( rect
.GetBottom() + 2 * extra_y
);
461 wxGridCellEditor::SetSize(rect
);
464 void wxGridCellTextEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
466 wxASSERT_MSG(m_control
, wxT("The wxGridCellEditor must be created first!"));
468 m_value
= grid
->GetTable()->GetValue(row
, col
);
470 DoBeginEdit(m_value
);
473 void wxGridCellTextEditor::DoBeginEdit(const wxString
& startValue
)
475 Text()->SetValue(startValue
);
476 Text()->SetInsertionPointEnd();
477 Text()->SetSelection(-1, -1);
481 bool wxGridCellTextEditor::EndEdit(const wxString
& WXUNUSED(oldval
),
484 wxCHECK_MSG( m_control
, false,
485 "wxGridCellTextEditor must be created first!" );
487 const wxString value
= Text()->GetValue();
488 if ( value
== m_value
)
499 void wxGridCellTextEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
501 grid
->GetTable()->SetValue(row
, col
, m_value
);
505 void wxGridCellTextEditor::Reset()
507 wxASSERT_MSG( m_control
, "wxGridCellTextEditor must be created first!" );
512 void wxGridCellTextEditor::DoReset(const wxString
& startValue
)
514 Text()->SetValue(startValue
);
515 Text()->SetInsertionPointEnd();
518 bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent
& event
)
520 return wxGridCellEditor::IsAcceptedKey(event
);
523 void wxGridCellTextEditor::StartingKey(wxKeyEvent
& event
)
525 // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no
526 // longer an appropriate way to get the character into the text control.
527 // Do it ourselves instead. We know that if we get this far that we have
528 // a valid character, so not a whole lot of testing needs to be done.
530 wxTextCtrl
* tc
= Text();
535 ch
= event
.GetUnicodeKey();
537 ch
= (wxChar
)event
.GetKeyCode();
539 ch
= (wxChar
)event
.GetKeyCode();
545 // delete the character at the cursor
546 pos
= tc
->GetInsertionPoint();
547 if (pos
< tc
->GetLastPosition())
548 tc
->Remove(pos
, pos
+ 1);
552 // delete the character before the cursor
553 pos
= tc
->GetInsertionPoint();
555 tc
->Remove(pos
- 1, pos
);
564 void wxGridCellTextEditor::HandleReturn( wxKeyEvent
&
565 WXUNUSED_GTK(WXUNUSED_MOTIF(event
)) )
567 #if defined(__WXMOTIF__) || defined(__WXGTK__)
568 // wxMotif needs a little extra help...
569 size_t pos
= (size_t)( Text()->GetInsertionPoint() );
570 wxString
s( Text()->GetValue() );
571 s
= s
.Left(pos
) + wxT("\n") + s
.Mid(pos
);
573 Text()->SetInsertionPoint( pos
);
575 // the other ports can handle a Return key press
581 void wxGridCellTextEditor::SetParameters(const wxString
& params
)
591 if ( params
.ToLong(&tmp
) )
593 m_maxChars
= (size_t)tmp
;
597 wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params
.c_str() );
602 // return the value in the text control
603 wxString
wxGridCellTextEditor::GetValue() const
605 return Text()->GetValue();
608 // ----------------------------------------------------------------------------
609 // wxGridCellNumberEditor
610 // ----------------------------------------------------------------------------
612 wxGridCellNumberEditor::wxGridCellNumberEditor(int min
, int max
)
618 void wxGridCellNumberEditor::Create(wxWindow
* parent
,
620 wxEvtHandler
* evtHandler
)
625 // create a spin ctrl
626 m_control
= new wxSpinCtrl(parent
, wxID_ANY
, wxEmptyString
,
627 wxDefaultPosition
, wxDefaultSize
,
631 wxGridCellEditor::Create(parent
, id
, evtHandler
);
636 // just a text control
637 wxGridCellTextEditor::Create(parent
, id
, evtHandler
);
640 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
));
645 void wxGridCellNumberEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
647 // first get the value
648 wxGridTableBase
*table
= grid
->GetTable();
649 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
651 m_value
= table
->GetValueAsLong(row
, col
);
656 wxString sValue
= table
->GetValue(row
, col
);
657 if (! sValue
.ToLong(&m_value
) && ! sValue
.empty())
659 wxFAIL_MSG( _T("this cell doesn't have numeric value") );
667 Spin()->SetValue((int)m_value
);
673 DoBeginEdit(GetString());
677 bool wxGridCellNumberEditor::EndEdit(const wxString
& oldval
, wxString
*newval
)
685 value
= Spin()->GetValue();
686 if ( value
== m_value
)
689 text
.Printf(wxT("%ld"), value
);
691 else // using unconstrained input
692 #endif // wxUSE_SPINCTRL
694 text
= Text()->GetValue();
697 if ( oldval
.empty() )
700 else // non-empty text now (maybe 0)
702 if ( !text
.ToLong(&value
) )
705 // if value == m_value == 0 but old text was "" and new one is
706 // "0" something still did change
707 if ( value
== m_value
&& (value
|| !oldval
.empty()) )
720 void wxGridCellNumberEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
722 wxGridTableBase
* const table
= grid
->GetTable();
723 if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
724 table
->SetValueAsLong(row
, col
, m_value
);
726 table
->SetValue(row
, col
, wxString::Format("%ld", m_value
));
729 void wxGridCellNumberEditor::Reset()
734 Spin()->SetValue((int)m_value
);
739 DoReset(GetString());
743 bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent
& event
)
745 if ( wxGridCellEditor::IsAcceptedKey(event
) )
747 int keycode
= event
.GetKeyCode();
748 if ( (keycode
< 128) &&
749 (wxIsdigit(keycode
) || keycode
== '+' || keycode
== '-'))
758 void wxGridCellNumberEditor::StartingKey(wxKeyEvent
& event
)
760 int keycode
= event
.GetKeyCode();
763 if ( wxIsdigit(keycode
) || keycode
== '+' || keycode
== '-')
765 wxGridCellTextEditor::StartingKey(event
);
774 if ( wxIsdigit(keycode
) )
776 wxSpinCtrl
* spin
= (wxSpinCtrl
*)m_control
;
777 spin
->SetValue(keycode
- '0');
778 spin
->SetSelection(1,1);
787 void wxGridCellNumberEditor::SetParameters(const wxString
& params
)
798 if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) )
802 if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) )
806 // skip the error message below
811 wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params
.c_str());
815 // return the value in the spin control if it is there (the text control otherwise)
816 wxString
wxGridCellNumberEditor::GetValue() const
823 long value
= Spin()->GetValue();
824 s
.Printf(wxT("%ld"), value
);
829 s
= Text()->GetValue();
835 // ----------------------------------------------------------------------------
836 // wxGridCellFloatEditor
837 // ----------------------------------------------------------------------------
839 wxGridCellFloatEditor::wxGridCellFloatEditor(int width
, int precision
)
842 m_precision
= precision
;
845 void wxGridCellFloatEditor::Create(wxWindow
* parent
,
847 wxEvtHandler
* evtHandler
)
849 wxGridCellTextEditor::Create(parent
, id
, evtHandler
);
852 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC
));
856 void wxGridCellFloatEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
858 // first get the value
859 wxGridTableBase
* const table
= grid
->GetTable();
860 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) )
862 m_value
= table
->GetValueAsDouble(row
, col
);
868 const wxString value
= table
->GetValue(row
, col
);
869 if ( !value
.empty() )
871 if ( !value
.ToDouble(&m_value
) )
873 wxFAIL_MSG( _T("this cell doesn't have float value") );
879 DoBeginEdit(GetString());
882 bool wxGridCellFloatEditor::EndEdit(const wxString
& oldval
, wxString
*newval
)
884 const wxString
text(Text()->GetValue());
889 if ( !text
.ToDouble(&value
) )
892 else // new value is empty string
894 if ( oldval
.empty() )
895 return false; // nothing changed
900 // the test for empty strings ensures that we don't skip the value setting
901 // when "" is replaced by "0" or vice versa as "" numeric value is also 0.
902 if ( wxIsSameDouble(value
, m_value
) && !text
.empty() && !oldval
.empty() )
903 return false; // nothing changed
913 void wxGridCellFloatEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
915 wxGridTableBase
* const table
= grid
->GetTable();
917 if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_FLOAT
) )
918 table
->SetValueAsDouble(row
, col
, m_value
);
920 table
->SetValue(row
, col
, Text()->GetValue());
923 void wxGridCellFloatEditor::Reset()
925 DoReset(GetString());
928 void wxGridCellFloatEditor::StartingKey(wxKeyEvent
& event
)
930 int keycode
= event
.GetKeyCode();
932 tmpbuf
[0] = (char) keycode
;
934 wxString
strbuf(tmpbuf
, *wxConvCurrent
);
937 bool is_decimal_point
= ( strbuf
==
938 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
) );
940 bool is_decimal_point
= ( strbuf
== _T(".") );
943 if ( wxIsdigit(keycode
) || keycode
== '+' || keycode
== '-'
944 || is_decimal_point
)
946 wxGridCellTextEditor::StartingKey(event
);
955 void wxGridCellFloatEditor::SetParameters(const wxString
& params
)
966 if ( params
.BeforeFirst(_T(',')).ToLong(&tmp
) )
970 if ( params
.AfterFirst(_T(',')).ToLong(&tmp
) )
972 m_precision
= (int)tmp
;
974 // skip the error message below
979 wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params
.c_str());
983 wxString
wxGridCellFloatEditor::GetString() const
986 if ( m_precision
== -1 && m_width
!= -1)
989 fmt
.Printf(_T("%%%d.f"), m_width
);
991 else if ( m_precision
!= -1 && m_width
== -1)
994 fmt
.Printf(_T("%%.%df"), m_precision
);
996 else if ( m_precision
!= -1 && m_width
!= -1 )
998 fmt
.Printf(_T("%%%d.%df"), m_width
, m_precision
);
1002 // default width/precision
1006 return wxString::Format(fmt
, m_value
);
1009 bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent
& event
)
1011 if ( wxGridCellEditor::IsAcceptedKey(event
) )
1013 const int keycode
= event
.GetKeyCode();
1014 if ( isascii(keycode
) )
1017 tmpbuf
[0] = (char) keycode
;
1019 wxString
strbuf(tmpbuf
, *wxConvCurrent
);
1022 const wxString decimalPoint
=
1023 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT
, wxLOCALE_CAT_NUMBER
);
1025 const wxString
decimalPoint(_T('.'));
1028 // accept digits, 'e' as in '1e+6', also '-', '+', and '.'
1029 if ( wxIsdigit(keycode
) ||
1030 tolower(keycode
) == 'e' ||
1031 keycode
== decimalPoint
||
1043 #endif // wxUSE_TEXTCTRL
1047 // ----------------------------------------------------------------------------
1048 // wxGridCellBoolEditor
1049 // ----------------------------------------------------------------------------
1051 // the default values for GetValue()
1052 wxString
wxGridCellBoolEditor::ms_stringValues
[2] = { _T(""), _T("1") };
1054 void wxGridCellBoolEditor::Create(wxWindow
* parent
,
1056 wxEvtHandler
* evtHandler
)
1058 m_control
= new wxCheckBox(parent
, id
, wxEmptyString
,
1059 wxDefaultPosition
, wxDefaultSize
,
1062 wxGridCellEditor::Create(parent
, id
, evtHandler
);
1065 void wxGridCellBoolEditor::SetSize(const wxRect
& r
)
1067 bool resize
= false;
1068 wxSize size
= m_control
->GetSize();
1069 wxCoord minSize
= wxMin(r
.width
, r
.height
);
1071 // check if the checkbox is not too big/small for this cell
1072 wxSize sizeBest
= m_control
->GetBestSize();
1073 if ( !(size
== sizeBest
) )
1075 // reset to default size if it had been made smaller
1081 if ( size
.x
>= minSize
|| size
.y
>= minSize
)
1083 // leave 1 pixel margin
1084 size
.x
= size
.y
= minSize
- 2;
1091 m_control
->SetSize(size
);
1094 // position it in the centre of the rectangle (TODO: support alignment?)
1096 #if defined(__WXGTK__) || defined (__WXMOTIF__)
1097 // the checkbox without label still has some space to the right in wxGTK,
1098 // so shift it to the right
1100 #elif defined(__WXMSW__)
1101 // here too, but in other way
1106 int hAlign
= wxALIGN_CENTRE
;
1107 int vAlign
= wxALIGN_CENTRE
;
1109 GetCellAttr()->GetAlignment(& hAlign
, & vAlign
);
1112 if (hAlign
== wxALIGN_LEFT
)
1120 y
= r
.y
+ r
.height
/ 2 - size
.y
/ 2;
1122 else if (hAlign
== wxALIGN_RIGHT
)
1124 x
= r
.x
+ r
.width
- size
.x
- 2;
1125 y
= r
.y
+ r
.height
/ 2 - size
.y
/ 2;
1127 else if (hAlign
== wxALIGN_CENTRE
)
1129 x
= r
.x
+ r
.width
/ 2 - size
.x
/ 2;
1130 y
= r
.y
+ r
.height
/ 2 - size
.y
/ 2;
1133 m_control
->Move(x
, y
);
1136 void wxGridCellBoolEditor::Show(bool show
, wxGridCellAttr
*attr
)
1138 m_control
->Show(show
);
1142 wxColour colBg
= attr
? attr
->GetBackgroundColour() : *wxLIGHT_GREY
;
1143 CBox()->SetBackgroundColour(colBg
);
1147 void wxGridCellBoolEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1149 wxASSERT_MSG(m_control
,
1150 wxT("The wxGridCellEditor must be created first!"));
1152 if (grid
->GetTable()->CanGetValueAs(row
, col
, wxGRID_VALUE_BOOL
))
1154 m_value
= grid
->GetTable()->GetValueAsBool(row
, col
);
1158 wxString
cellval( grid
->GetTable()->GetValue(row
, col
) );
1160 if ( cellval
== ms_stringValues
[false] )
1162 else if ( cellval
== ms_stringValues
[true] )
1166 // do not try to be smart here and convert it to true or false
1167 // because we'll still overwrite it with something different and
1168 // this risks to be very surprising for the user code, let them
1170 wxFAIL_MSG( _T("invalid value for a cell with bool editor!") );
1174 CBox()->SetValue(m_value
);
1178 bool wxGridCellBoolEditor::EndEdit(const wxString
& WXUNUSED(oldval
),
1181 bool value
= CBox()->GetValue();
1182 if ( value
== m_value
)
1188 *newval
= GetValue();
1193 void wxGridCellBoolEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
1195 wxGridTableBase
* const table
= grid
->GetTable();
1196 if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_BOOL
) )
1197 table
->SetValueAsBool(row
, col
, m_value
);
1199 table
->SetValue(row
, col
, GetValue());
1202 void wxGridCellBoolEditor::Reset()
1204 wxASSERT_MSG(m_control
,
1205 wxT("The wxGridCellEditor must be created first!"));
1207 CBox()->SetValue(m_value
);
1210 void wxGridCellBoolEditor::StartingClick()
1212 CBox()->SetValue(!CBox()->GetValue());
1215 bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent
& event
)
1217 if ( wxGridCellEditor::IsAcceptedKey(event
) )
1219 int keycode
= event
.GetKeyCode();
1232 void wxGridCellBoolEditor::StartingKey(wxKeyEvent
& event
)
1234 int keycode
= event
.GetKeyCode();
1238 CBox()->SetValue(!CBox()->GetValue());
1242 CBox()->SetValue(true);
1246 CBox()->SetValue(false);
1251 wxString
wxGridCellBoolEditor::GetValue() const
1253 return ms_stringValues
[CBox()->GetValue()];
1257 wxGridCellBoolEditor::UseStringValues(const wxString
& valueTrue
,
1258 const wxString
& valueFalse
)
1260 ms_stringValues
[false] = valueFalse
;
1261 ms_stringValues
[true] = valueTrue
;
1265 wxGridCellBoolEditor::IsTrueValue(const wxString
& value
)
1267 return value
== ms_stringValues
[true];
1270 #endif // wxUSE_CHECKBOX
1274 // ----------------------------------------------------------------------------
1275 // wxGridCellChoiceEditor
1276 // ----------------------------------------------------------------------------
1278 wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString
& choices
,
1280 : m_choices(choices
),
1281 m_allowOthers(allowOthers
) { }
1283 wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count
,
1284 const wxString choices
[],
1286 : m_allowOthers(allowOthers
)
1290 m_choices
.Alloc(count
);
1291 for ( size_t n
= 0; n
< count
; n
++ )
1293 m_choices
.Add(choices
[n
]);
1298 wxGridCellEditor
*wxGridCellChoiceEditor::Clone() const
1300 wxGridCellChoiceEditor
*editor
= new wxGridCellChoiceEditor
;
1301 editor
->m_allowOthers
= m_allowOthers
;
1302 editor
->m_choices
= m_choices
;
1307 void wxGridCellChoiceEditor::Create(wxWindow
* parent
,
1309 wxEvtHandler
* evtHandler
)
1311 int style
= wxTE_PROCESS_ENTER
|
1315 if ( !m_allowOthers
)
1316 style
|= wxCB_READONLY
;
1317 m_control
= new wxComboBox(parent
, id
, wxEmptyString
,
1318 wxDefaultPosition
, wxDefaultSize
,
1322 wxGridCellEditor::Create(parent
, id
, evtHandler
);
1325 void wxGridCellChoiceEditor::PaintBackground(const wxRect
& rectCell
,
1326 wxGridCellAttr
* attr
)
1328 // as we fill the entire client area, don't do anything here to minimize
1331 // TODO: It doesn't actually fill the client area since the height of a
1332 // combo always defaults to the standard. Until someone has time to
1333 // figure out the right rectangle to paint, just do it the normal way.
1334 wxGridCellEditor::PaintBackground(rectCell
, attr
);
1337 void wxGridCellChoiceEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1339 wxASSERT_MSG(m_control
,
1340 wxT("The wxGridCellEditor must be created first!"));
1342 wxGridCellEditorEvtHandler
* evtHandler
= NULL
;
1344 evtHandler
= wxDynamicCast(m_control
->GetEventHandler(), wxGridCellEditorEvtHandler
);
1346 // Don't immediately end if we get a kill focus event within BeginEdit
1348 evtHandler
->SetInSetFocus(true);
1350 m_value
= grid
->GetTable()->GetValue(row
, col
);
1352 Reset(); // this updates combo box to correspond to m_value
1354 Combo()->SetFocus();
1358 // When dropping down the menu, a kill focus event
1359 // happens after this point, so we can't reset the flag yet.
1360 #if !defined(__WXGTK20__)
1361 evtHandler
->SetInSetFocus(false);
1366 bool wxGridCellChoiceEditor::EndEdit(const wxString
& WXUNUSED(oldval
),
1369 const wxString value
= Combo()->GetValue();
1370 if ( value
== m_value
)
1381 void wxGridCellChoiceEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
1383 grid
->GetTable()->SetValue(row
, col
, m_value
);
1386 void wxGridCellChoiceEditor::Reset()
1390 Combo()->SetValue(m_value
);
1391 Combo()->SetInsertionPointEnd();
1393 else // the combobox is read-only
1395 // find the right position, or default to the first if not found
1396 int pos
= Combo()->FindString(m_value
);
1397 if (pos
== wxNOT_FOUND
)
1399 Combo()->SetSelection(pos
);
1403 void wxGridCellChoiceEditor::SetParameters(const wxString
& params
)
1413 wxStringTokenizer
tk(params
, _T(','));
1414 while ( tk
.HasMoreTokens() )
1416 m_choices
.Add(tk
.GetNextToken());
1420 // return the value in the text control
1421 wxString
wxGridCellChoiceEditor::GetValue() const
1423 return Combo()->GetValue();
1426 #endif // wxUSE_COMBOBOX
1430 // ----------------------------------------------------------------------------
1431 // wxGridCellEnumEditor
1432 // ----------------------------------------------------------------------------
1434 // A cell editor which displays an enum number as a textual equivalent. eg
1435 // data in cell is 0,1,2 ... n the cell could be displayed as
1436 // "John","Fred"..."Bob" in the combo choice box
1438 wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString
& choices
)
1439 :wxGridCellChoiceEditor()
1443 if (!choices
.empty())
1444 SetParameters(choices
);
1447 wxGridCellEditor
*wxGridCellEnumEditor::Clone() const
1449 wxGridCellEnumEditor
*editor
= new wxGridCellEnumEditor();
1450 editor
->m_index
= m_index
;
1454 void wxGridCellEnumEditor::BeginEdit(int row
, int col
, wxGrid
* grid
)
1456 wxASSERT_MSG(m_control
,
1457 wxT("The wxGridCellEnumEditor must be Created first!"));
1459 wxGridTableBase
*table
= grid
->GetTable();
1461 if ( table
->CanGetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
1463 m_index
= table
->GetValueAsLong(row
, col
);
1467 wxString startValue
= table
->GetValue(row
, col
);
1468 if (startValue
.IsNumber() && !startValue
.empty())
1470 startValue
.ToLong(&m_index
);
1478 Combo()->SetSelection(m_index
);
1479 Combo()->SetInsertionPointEnd();
1480 Combo()->SetFocus();
1484 bool wxGridCellEnumEditor::EndEdit(const wxString
& WXUNUSED(oldval
),
1487 long idx
= Combo()->GetSelection();
1488 if ( idx
== m_index
)
1494 newval
->Printf("%ld", m_index
);
1499 void wxGridCellEnumEditor::ApplyEdit(int row
, int col
, wxGrid
* grid
)
1501 wxGridTableBase
* const table
= grid
->GetTable();
1502 if ( table
->CanSetValueAs(row
, col
, wxGRID_VALUE_NUMBER
) )
1503 table
->SetValueAsLong(row
, col
, m_index
);
1505 table
->SetValue(row
, col
, wxString::Format("%ld", m_index
));
1508 #endif // wxUSE_COMBOBOX
1510 // ----------------------------------------------------------------------------
1511 // wxGridCellAutoWrapStringEditor
1512 // ----------------------------------------------------------------------------
1515 wxGridCellAutoWrapStringEditor::Create(wxWindow
* parent
,
1517 wxEvtHandler
* evtHandler
)
1519 wxGridCellTextEditor::DoCreate(parent
, id
, evtHandler
,
1520 wxTE_MULTILINE
| wxTE_RICH
);
1524 #endif // wxUSE_GRID