]> git.saurik.com Git - wxWidgets.git/blame - src/generic/grideditors.cpp
honour wxSP_ARROW_KEYS in wxSpinCtrlGeneric and don't handle the arrows unless it...
[wxWidgets.git] / src / generic / grideditors.cpp
CommitLineData
78e78812
VZ
1///////////////////////////////////////////////////////////////////////////\r
2// Name: src/generic/grideditors.cpp\r
3// Purpose: wxGridCellEditorEvtHandler and wxGrid editors\r
4// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)\r
5// Modified by: Robin Dunn, Vadim Zeitlin, Santiago Palacios\r
6// Created: 1/08/1999\r
7// RCS-ID: $Id$\r
8// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)\r
9// Licence: wxWindows licence\r
10/////////////////////////////////////////////////////////////////////////////\r
11\r
12// For compilers that support precompilation, includes "wx/wx.h".\r
13#include "wx/wxprec.h"\r
14\r
15#ifdef __BORLANDC__\r
16 #pragma hdrstop\r
17#endif\r
18\r
19#if wxUSE_GRID\r
20\r
21#include "wx/grid.h"\r
22\r
23#ifndef WX_PRECOMP\r
24 #include "wx/utils.h"\r
25 #include "wx/dcclient.h"\r
26 #include "wx/settings.h"\r
27 #include "wx/log.h"\r
28 #include "wx/textctrl.h"\r
29 #include "wx/checkbox.h"\r
30 #include "wx/combobox.h"\r
31 #include "wx/valtext.h"\r
32 #include "wx/intl.h"\r
33 #include "wx/math.h"\r
34 #include "wx/listbox.h"\r
35#endif\r
36\r
37#include "wx/textfile.h"\r
38#include "wx/spinctrl.h"\r
39#include "wx/tokenzr.h"\r
40#include "wx/renderer.h"\r
41#include "wx/headerctrl.h"\r
42\r
43#include "wx/generic/gridsel.h"\r
44#include "wx/generic/grideditors.h"\r
45#include "wx/generic/private/grid.h"\r
46\r
47#if defined(__WXMOTIF__)\r
48 #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)\r
49#else\r
50 #define WXUNUSED_MOTIF(identifier) identifier\r
51#endif\r
52\r
53#if defined(__WXGTK__)\r
54 #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)\r
55#else\r
56 #define WXUNUSED_GTK(identifier) identifier\r
57#endif\r
58\r
59// Required for wxIs... functions\r
60#include <ctype.h>\r
61\r
62// ============================================================================\r
63// implementation\r
64// ============================================================================\r
65\r
66// ----------------------------------------------------------------------------\r
67// wxGridCellEditorEvtHandler\r
68// ----------------------------------------------------------------------------\r
69\r
70void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event)\r
71{\r
72 // Don't disable the cell if we're just starting to edit it\r
73 if ( m_inSetFocus )\r
74 {\r
75 event.Skip();\r
76 return;\r
77 }\r
78\r
79 // accept changes\r
80 m_grid->DisableCellEditControl();\r
81\r
82 // notice that we must not skip the event here because the call above may\r
83 // delete the control which received the kill focus event in the first\r
84 // place and if we pretend not having processed the event, the search for a\r
85 // handler for it will continue using the now deleted object resulting in a\r
86 // crash\r
87}\r
88\r
89void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)\r
90{\r
91 switch ( event.GetKeyCode() )\r
92 {\r
93 case WXK_ESCAPE:\r
94 m_editor->Reset();\r
95 m_grid->DisableCellEditControl();\r
96 break;\r
97\r
98 case WXK_TAB:\r
99 m_grid->GetEventHandler()->ProcessEvent( event );\r
100 break;\r
101\r
102 case WXK_RETURN:\r
103 case WXK_NUMPAD_ENTER:\r
104 if (!m_grid->GetEventHandler()->ProcessEvent(event))\r
105 m_editor->HandleReturn(event);\r
106 break;\r
107\r
108 default:\r
109 event.Skip();\r
110 break;\r
111 }\r
112}\r
113\r
114void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)\r
115{\r
116 int row = m_grid->GetGridCursorRow();\r
117 int col = m_grid->GetGridCursorCol();\r
118 wxRect rect = m_grid->CellToRect( row, col );\r
119 int cw, ch;\r
120 m_grid->GetGridWindow()->GetClientSize( &cw, &ch );\r
121\r
122 // if cell width is smaller than grid client area, cell is wholly visible\r
123 bool wholeCellVisible = (rect.GetWidth() < cw);\r
124\r
125 switch ( event.GetKeyCode() )\r
126 {\r
127 case WXK_ESCAPE:\r
128 case WXK_TAB:\r
129 case WXK_RETURN:\r
130 case WXK_NUMPAD_ENTER:\r
131 break;\r
132\r
133 case WXK_HOME:\r
134 {\r
135 if ( wholeCellVisible )\r
136 {\r
137 // no special processing needed...\r
138 event.Skip();\r
139 break;\r
140 }\r
141\r
142 // do special processing for partly visible cell...\r
143\r
144 // get the widths of all cells previous to this one\r
145 int colXPos = 0;\r
146 for ( int i = 0; i < col; i++ )\r
147 {\r
148 colXPos += m_grid->GetColSize(i);\r
149 }\r
150\r
151 int xUnit = 1, yUnit = 1;\r
152 m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);\r
153 if (col != 0)\r
154 {\r
155 m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));\r
156 }\r
157 else\r
158 {\r
159 m_grid->Scroll(colXPos / xUnit, m_grid->GetScrollPos(wxVERTICAL));\r
160 }\r
161 event.Skip();\r
162 break;\r
163 }\r
164\r
165 case WXK_END:\r
166 {\r
167 if ( wholeCellVisible )\r
168 {\r
169 // no special processing needed...\r
170 event.Skip();\r
171 break;\r
172 }\r
173\r
174 // do special processing for partly visible cell...\r
175\r
176 int textWidth = 0;\r
177 wxString value = m_grid->GetCellValue(row, col);\r
178 if ( wxEmptyString != value )\r
179 {\r
180 // get width of cell CONTENTS (text)\r
181 int y;\r
182 wxFont font = m_grid->GetCellFont(row, col);\r
183 m_grid->GetTextExtent(value, &textWidth, &y, NULL, NULL, &font);\r
184\r
185 // try to RIGHT align the text by scrolling\r
186 int client_right = m_grid->GetGridWindow()->GetClientSize().GetWidth();\r
187\r
188 // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far,\r
189 // otherwise the last part of the cell content might be hidden below the scroll bar\r
190 // FIXME: maybe there is a more suitable correction?\r
191 textWidth -= (client_right - (m_grid->GetScrollLineX() * 2));\r
192 if ( textWidth < 0 )\r
193 {\r
194 textWidth = 0;\r
195 }\r
196 }\r
197\r
198 // get the widths of all cells previous to this one\r
199 int colXPos = 0;\r
200 for ( int i = 0; i < col; i++ )\r
201 {\r
202 colXPos += m_grid->GetColSize(i);\r
203 }\r
204\r
205 // and add the (modified) text width of the cell contents\r
206 // as we'd like to see the last part of the cell contents\r
207 colXPos += textWidth;\r
208\r
209 int xUnit = 1, yUnit = 1;\r
210 m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);\r
211 m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));\r
212 event.Skip();\r
213 break;\r
214 }\r
215\r
216 default:\r
217 event.Skip();\r
218 break;\r
219 }\r
220}\r
221\r
222// ----------------------------------------------------------------------------\r
223// wxGridCellEditor\r
224// ----------------------------------------------------------------------------\r
225\r
226wxGridCellEditor::wxGridCellEditor()\r
227{\r
228 m_control = NULL;\r
229 m_attr = NULL;\r
230}\r
231\r
232wxGridCellEditor::~wxGridCellEditor()\r
233{\r
234 Destroy();\r
235}\r
236\r
237void wxGridCellEditor::Create(wxWindow* WXUNUSED(parent),\r
238 wxWindowID WXUNUSED(id),\r
239 wxEvtHandler* evtHandler)\r
240{\r
241 if ( evtHandler )\r
242 m_control->PushEventHandler(evtHandler);\r
243}\r
244\r
245void wxGridCellEditor::PaintBackground(const wxRect& rectCell,\r
246 wxGridCellAttr *attr)\r
247{\r
248 // erase the background because we might not fill the cell\r
249 wxClientDC dc(m_control->GetParent());\r
250 wxGridWindow* gridWindow = wxDynamicCast(m_control->GetParent(), wxGridWindow);\r
251 if (gridWindow)\r
252 gridWindow->GetOwner()->PrepareDC(dc);\r
253\r
254 dc.SetPen(*wxTRANSPARENT_PEN);\r
255 dc.SetBrush(wxBrush(attr->GetBackgroundColour()));\r
256 dc.DrawRectangle(rectCell);\r
257\r
258 // redraw the control we just painted over\r
259 m_control->Refresh();\r
260}\r
261\r
262void wxGridCellEditor::Destroy()\r
263{\r
264 if (m_control)\r
265 {\r
266 m_control->PopEventHandler( true /* delete it*/ );\r
267\r
268 m_control->Destroy();\r
269 m_control = NULL;\r
270 }\r
271}\r
272\r
273void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr)\r
274{\r
275 wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
276\r
277 m_control->Show(show);\r
278\r
279 if ( show )\r
280 {\r
281 // set the colours/fonts if we have any\r
282 if ( attr )\r
283 {\r
284 m_colFgOld = m_control->GetForegroundColour();\r
285 m_control->SetForegroundColour(attr->GetTextColour());\r
286\r
287 m_colBgOld = m_control->GetBackgroundColour();\r
288 m_control->SetBackgroundColour(attr->GetBackgroundColour());\r
289\r
290// Workaround for GTK+1 font setting problem on some platforms\r
291#if !defined(__WXGTK__) || defined(__WXGTK20__)\r
292 m_fontOld = m_control->GetFont();\r
293 m_control->SetFont(attr->GetFont());\r
294#endif\r
295\r
296 // can't do anything more in the base class version, the other\r
297 // attributes may only be used by the derived classes\r
298 }\r
299 }\r
300 else\r
301 {\r
302 // restore the standard colours fonts\r
303 if ( m_colFgOld.Ok() )\r
304 {\r
305 m_control->SetForegroundColour(m_colFgOld);\r
306 m_colFgOld = wxNullColour;\r
307 }\r
308\r
309 if ( m_colBgOld.Ok() )\r
310 {\r
311 m_control->SetBackgroundColour(m_colBgOld);\r
312 m_colBgOld = wxNullColour;\r
313 }\r
314\r
315// Workaround for GTK+1 font setting problem on some platforms\r
316#if !defined(__WXGTK__) || defined(__WXGTK20__)\r
317 if ( m_fontOld.Ok() )\r
318 {\r
319 m_control->SetFont(m_fontOld);\r
320 m_fontOld = wxNullFont;\r
321 }\r
322#endif\r
323 }\r
324}\r
325\r
326void wxGridCellEditor::SetSize(const wxRect& rect)\r
327{\r
328 wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
329\r
330 m_control->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);\r
331}\r
332\r
333void wxGridCellEditor::HandleReturn(wxKeyEvent& event)\r
334{\r
335 event.Skip();\r
336}\r
337\r
338bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)\r
339{\r
340 bool ctrl = event.ControlDown();\r
341 bool alt = event.AltDown();\r
342\r
343#ifdef __WXMAC__\r
344 // On the Mac the Alt key is more like shift and is used for entry of\r
345 // valid characters, so check for Ctrl and Meta instead.\r
346 alt = event.MetaDown();\r
347#endif\r
348\r
349 // Assume it's not a valid char if ctrl or alt is down, but if both are\r
350 // down then it may be because of an AltGr key combination, so let them\r
351 // through in that case.\r
352 if ((ctrl || alt) && !(ctrl && alt))\r
353 return false;\r
354\r
355#if wxUSE_UNICODE\r
356 // if the unicode key code is not really a unicode character (it may\r
357 // be a function key or etc., the platforms appear to always give us a\r
358 // small value in this case) then fallback to the ASCII key code but\r
359 // don't do anything for function keys or etc.\r
360 if ( event.GetUnicodeKey() > 127 && event.GetKeyCode() > 127 )\r
361 return false;\r
362#else\r
363 if ( event.GetKeyCode() > 255 )\r
364 return false;\r
365#endif\r
366\r
367 return true;\r
368}\r
369\r
370void wxGridCellEditor::StartingKey(wxKeyEvent& event)\r
371{\r
372 event.Skip();\r
373}\r
374\r
375void wxGridCellEditor::StartingClick()\r
376{\r
377}\r
378\r
379#if wxUSE_TEXTCTRL\r
380\r
381// ----------------------------------------------------------------------------\r
382// wxGridCellTextEditor\r
383// ----------------------------------------------------------------------------\r
384\r
385wxGridCellTextEditor::wxGridCellTextEditor()\r
386{\r
387 m_maxChars = 0;\r
388}\r
389\r
390void wxGridCellTextEditor::Create(wxWindow* parent,\r
391 wxWindowID id,\r
392 wxEvtHandler* evtHandler)\r
393{\r
394 DoCreate(parent, id, evtHandler);\r
395}\r
396\r
397void wxGridCellTextEditor::DoCreate(wxWindow* parent,\r
398 wxWindowID id,\r
399 wxEvtHandler* evtHandler,\r
400 long style)\r
401{\r
402 style |= wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxNO_BORDER;\r
403\r
404 m_control = new wxTextCtrl(parent, id, wxEmptyString,\r
405 wxDefaultPosition, wxDefaultSize,\r
406 style);\r
407\r
408 // set max length allowed in the textctrl, if the parameter was set\r
409 if ( m_maxChars != 0 )\r
410 {\r
411 Text()->SetMaxLength(m_maxChars);\r
412 }\r
413\r
414 wxGridCellEditor::Create(parent, id, evtHandler);\r
415}\r
416\r
417void wxGridCellTextEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),\r
418 wxGridCellAttr * WXUNUSED(attr))\r
419{\r
420 // as we fill the entire client area,\r
421 // don't do anything here to minimize flicker\r
422}\r
423\r
424void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)\r
425{\r
426 wxRect rect(rectOrig);\r
427\r
428 // Make the edit control large enough to allow for internal margins\r
429 //\r
430 // TODO: remove this if the text ctrl sizing is improved esp. for unix\r
431 //\r
432#if defined(__WXGTK__)\r
433 if (rect.x != 0)\r
434 {\r
435 rect.x += 1;\r
436 rect.y += 1;\r
437 rect.width -= 1;\r
438 rect.height -= 1;\r
439 }\r
440#elif defined(__WXMSW__)\r
441 if ( rect.x == 0 )\r
442 rect.x += 2;\r
443 else\r
444 rect.x += 3;\r
445\r
446 if ( rect.y == 0 )\r
447 rect.y += 2;\r
448 else\r
449 rect.y += 3;\r
450\r
451 rect.width -= 2;\r
452 rect.height -= 2;\r
453#else\r
454 int extra_x = ( rect.x > 2 ) ? 2 : 1;\r
455 int extra_y = ( rect.y > 2 ) ? 2 : 1;\r
456\r
457 #if defined(__WXMOTIF__)\r
458 extra_x *= 2;\r
459 extra_y *= 2;\r
460 #endif\r
461\r
462 rect.SetLeft( wxMax(0, rect.x - extra_x) );\r
463 rect.SetTop( wxMax(0, rect.y - extra_y) );\r
464 rect.SetRight( rect.GetRight() + 2 * extra_x );\r
465 rect.SetBottom( rect.GetBottom() + 2 * extra_y );\r
466#endif\r
467\r
468 wxGridCellEditor::SetSize(rect);\r
469}\r
470\r
471void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)\r
472{\r
473 wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
474\r
475 m_value = grid->GetTable()->GetValue(row, col);\r
476\r
477 DoBeginEdit(m_value);\r
478}\r
479\r
480void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)\r
481{\r
482 Text()->SetValue(startValue);\r
483 Text()->SetInsertionPointEnd();\r
484 Text()->SetSelection(-1, -1);\r
485 Text()->SetFocus();\r
486}\r
487\r
488bool wxGridCellTextEditor::EndEdit(int WXUNUSED(row),\r
489 int WXUNUSED(col),\r
490 const wxGrid* WXUNUSED(grid),\r
491 const wxString& WXUNUSED(oldval),\r
492 wxString *newval)\r
493{\r
494 wxCHECK_MSG( m_control, false,\r
495 "wxGridCellTextEditor must be created first!" );\r
496\r
497 const wxString value = Text()->GetValue();\r
498 if ( value == m_value )\r
499 return false;\r
500\r
501 m_value = value;\r
502\r
503 if ( newval )\r
504 *newval = m_value;\r
505\r
506 return true;\r
507}\r
508\r
509void wxGridCellTextEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
510{\r
511 grid->GetTable()->SetValue(row, col, m_value);\r
512 m_value.clear();\r
513}\r
514\r
515void wxGridCellTextEditor::Reset()\r
516{\r
517 wxASSERT_MSG( m_control, "wxGridCellTextEditor must be created first!" );\r
518\r
519 DoReset(m_value);\r
520}\r
521\r
522void wxGridCellTextEditor::DoReset(const wxString& startValue)\r
523{\r
524 Text()->SetValue(startValue);\r
525 Text()->SetInsertionPointEnd();\r
526}\r
527\r
528bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)\r
529{\r
530 return wxGridCellEditor::IsAcceptedKey(event);\r
531}\r
532\r
533void wxGridCellTextEditor::StartingKey(wxKeyEvent& event)\r
534{\r
535 // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no\r
536 // longer an appropriate way to get the character into the text control.\r
537 // Do it ourselves instead. We know that if we get this far that we have\r
538 // a valid character, so not a whole lot of testing needs to be done.\r
539\r
540 wxTextCtrl* tc = Text();\r
541 wxChar ch;\r
542 long pos;\r
543\r
544#if wxUSE_UNICODE\r
545 ch = event.GetUnicodeKey();\r
546 if (ch <= 127)\r
547 ch = (wxChar)event.GetKeyCode();\r
548#else\r
549 ch = (wxChar)event.GetKeyCode();\r
550#endif\r
551\r
552 switch (ch)\r
553 {\r
554 case WXK_DELETE:\r
555 // delete the character at the cursor\r
556 pos = tc->GetInsertionPoint();\r
557 if (pos < tc->GetLastPosition())\r
558 tc->Remove(pos, pos + 1);\r
559 break;\r
560\r
561 case WXK_BACK:\r
562 // delete the character before the cursor\r
563 pos = tc->GetInsertionPoint();\r
564 if (pos > 0)\r
565 tc->Remove(pos - 1, pos);\r
566 break;\r
567\r
568 default:\r
569 tc->WriteText(ch);\r
570 break;\r
571 }\r
572}\r
573\r
574void wxGridCellTextEditor::HandleReturn( wxKeyEvent&\r
575 WXUNUSED_GTK(WXUNUSED_MOTIF(event)) )\r
576{\r
577#if defined(__WXMOTIF__) || defined(__WXGTK__)\r
578 // wxMotif needs a little extra help...\r
579 size_t pos = (size_t)( Text()->GetInsertionPoint() );\r
580 wxString s( Text()->GetValue() );\r
581 s = s.Left(pos) + wxT("\n") + s.Mid(pos);\r
582 Text()->SetValue(s);\r
583 Text()->SetInsertionPoint( pos );\r
584#else\r
585 // the other ports can handle a Return key press\r
586 //\r
587 event.Skip();\r
588#endif\r
589}\r
590\r
591void wxGridCellTextEditor::SetParameters(const wxString& params)\r
592{\r
593 if ( !params )\r
594 {\r
595 // reset to default\r
596 m_maxChars = 0;\r
597 }\r
598 else\r
599 {\r
600 long tmp;\r
601 if ( params.ToLong(&tmp) )\r
602 {\r
603 m_maxChars = (size_t)tmp;\r
604 }\r
605 else\r
606 {\r
607 wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params.c_str() );\r
608 }\r
609 }\r
610}\r
611\r
612// return the value in the text control\r
613wxString wxGridCellTextEditor::GetValue() const\r
614{\r
615 return Text()->GetValue();\r
616}\r
617\r
618// ----------------------------------------------------------------------------\r
619// wxGridCellNumberEditor\r
620// ----------------------------------------------------------------------------\r
621\r
622wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)\r
623{\r
624 m_min = min;\r
625 m_max = max;\r
626}\r
627\r
628void wxGridCellNumberEditor::Create(wxWindow* parent,\r
629 wxWindowID id,\r
630 wxEvtHandler* evtHandler)\r
631{\r
632#if wxUSE_SPINCTRL\r
633 if ( HasRange() )\r
634 {\r
635 // create a spin ctrl\r
636 m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,\r
637 wxDefaultPosition, wxDefaultSize,\r
638 wxSP_ARROW_KEYS,\r
639 m_min, m_max);\r
640\r
641 wxGridCellEditor::Create(parent, id, evtHandler);\r
642 }\r
643 else\r
644#endif\r
645 {\r
646 // just a text control\r
647 wxGridCellTextEditor::Create(parent, id, evtHandler);\r
648\r
649#if wxUSE_VALIDATORS\r
650 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));\r
651#endif\r
652 }\r
653}\r
654\r
655void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)\r
656{\r
657 // first get the value\r
658 wxGridTableBase *table = grid->GetTable();\r
659 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
660 {\r
661 m_value = table->GetValueAsLong(row, col);\r
662 }\r
663 else\r
664 {\r
665 m_value = 0;\r
666 wxString sValue = table->GetValue(row, col);\r
667 if (! sValue.ToLong(&m_value) && ! sValue.empty())\r
668 {\r
669 wxFAIL_MSG( _T("this cell doesn't have numeric value") );\r
670 return;\r
671 }\r
672 }\r
673\r
674#if wxUSE_SPINCTRL\r
675 if ( HasRange() )\r
676 {\r
677 Spin()->SetValue((int)m_value);\r
678 Spin()->SetFocus();\r
679 }\r
680 else\r
681#endif\r
682 {\r
683 DoBeginEdit(GetString());\r
684 }\r
685}\r
686\r
687bool wxGridCellNumberEditor::EndEdit(int WXUNUSED(row),\r
688 int WXUNUSED(col),\r
689 const wxGrid* WXUNUSED(grid),\r
690 const wxString& oldval, wxString *newval)\r
691{\r
692 long value = 0;\r
693 wxString text;\r
694\r
695#if wxUSE_SPINCTRL\r
696 if ( HasRange() )\r
697 {\r
698 value = Spin()->GetValue();\r
699 if ( value == m_value )\r
700 return false;\r
701\r
702 text.Printf(wxT("%ld"), value);\r
703 }\r
704 else // using unconstrained input\r
705#endif // wxUSE_SPINCTRL\r
706 {\r
707 text = Text()->GetValue();\r
708 if ( text.empty() )\r
709 {\r
710 if ( oldval.empty() )\r
711 return false;\r
712 }\r
713 else // non-empty text now (maybe 0)\r
714 {\r
715 if ( !text.ToLong(&value) )\r
716 return false;\r
717\r
718 // if value == m_value == 0 but old text was "" and new one is\r
719 // "0" something still did change\r
720 if ( value == m_value && (value || !oldval.empty()) )\r
721 return false;\r
722 }\r
723 }\r
724\r
725 m_value = value;\r
726\r
727 if ( newval )\r
728 *newval = text;\r
729\r
730 return true;\r
731}\r
732\r
733void wxGridCellNumberEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
734{\r
735 wxGridTableBase * const table = grid->GetTable();\r
736 if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
737 table->SetValueAsLong(row, col, m_value);\r
738 else\r
739 table->SetValue(row, col, wxString::Format("%ld", m_value));\r
740}\r
741\r
742void wxGridCellNumberEditor::Reset()\r
743{\r
744#if wxUSE_SPINCTRL\r
745 if ( HasRange() )\r
746 {\r
747 Spin()->SetValue((int)m_value);\r
748 }\r
749 else\r
750#endif\r
751 {\r
752 DoReset(GetString());\r
753 }\r
754}\r
755\r
756bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event)\r
757{\r
758 if ( wxGridCellEditor::IsAcceptedKey(event) )\r
759 {\r
760 int keycode = event.GetKeyCode();\r
761 if ( (keycode < 128) &&\r
762 (wxIsdigit(keycode) || keycode == '+' || keycode == '-'))\r
763 {\r
764 return true;\r
765 }\r
766 }\r
767\r
768 return false;\r
769}\r
770\r
771void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)\r
772{\r
773 int keycode = event.GetKeyCode();\r
774 if ( !HasRange() )\r
775 {\r
776 if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-')\r
777 {\r
778 wxGridCellTextEditor::StartingKey(event);\r
779\r
780 // skip Skip() below\r
781 return;\r
782 }\r
783 }\r
784#if wxUSE_SPINCTRL\r
785 else\r
786 {\r
787 if ( wxIsdigit(keycode) )\r
788 {\r
789 wxSpinCtrl* spin = (wxSpinCtrl*)m_control;\r
790 spin->SetValue(keycode - '0');\r
791 spin->SetSelection(1,1);\r
792 return;\r
793 }\r
794 }\r
795#endif\r
796\r
797 event.Skip();\r
798}\r
799\r
800void wxGridCellNumberEditor::SetParameters(const wxString& params)\r
801{\r
802 if ( !params )\r
803 {\r
804 // reset to default\r
805 m_min =\r
806 m_max = -1;\r
807 }\r
808 else\r
809 {\r
810 long tmp;\r
811 if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )\r
812 {\r
813 m_min = (int)tmp;\r
814\r
815 if ( params.AfterFirst(_T(',')).ToLong(&tmp) )\r
816 {\r
817 m_max = (int)tmp;\r
818\r
819 // skip the error message below\r
820 return;\r
821 }\r
822 }\r
823\r
824 wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params.c_str());\r
825 }\r
826}\r
827\r
828// return the value in the spin control if it is there (the text control otherwise)\r
829wxString wxGridCellNumberEditor::GetValue() const\r
830{\r
831 wxString s;\r
832\r
833#if wxUSE_SPINCTRL\r
834 if ( HasRange() )\r
835 {\r
836 long value = Spin()->GetValue();\r
837 s.Printf(wxT("%ld"), value);\r
838 }\r
839 else\r
840#endif\r
841 {\r
842 s = Text()->GetValue();\r
843 }\r
844\r
845 return s;\r
846}\r
847\r
848// ----------------------------------------------------------------------------\r
849// wxGridCellFloatEditor\r
850// ----------------------------------------------------------------------------\r
851\r
852wxGridCellFloatEditor::wxGridCellFloatEditor(int width, int precision)\r
853{\r
854 m_width = width;\r
855 m_precision = precision;\r
856}\r
857\r
858void wxGridCellFloatEditor::Create(wxWindow* parent,\r
859 wxWindowID id,\r
860 wxEvtHandler* evtHandler)\r
861{\r
862 wxGridCellTextEditor::Create(parent, id, evtHandler);\r
863\r
864#if wxUSE_VALIDATORS\r
865 Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));\r
866#endif\r
867}\r
868\r
869void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)\r
870{\r
871 // first get the value\r
872 wxGridTableBase * const table = grid->GetTable();\r
873 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )\r
874 {\r
875 m_value = table->GetValueAsDouble(row, col);\r
876 }\r
877 else\r
878 {\r
879 m_value = 0.0;\r
880\r
881 const wxString value = table->GetValue(row, col);\r
882 if ( !value.empty() )\r
883 {\r
884 if ( !value.ToDouble(&m_value) )\r
885 {\r
886 wxFAIL_MSG( _T("this cell doesn't have float value") );\r
887 return;\r
888 }\r
889 }\r
890 }\r
891\r
892 DoBeginEdit(GetString());\r
893}\r
894\r
895bool wxGridCellFloatEditor::EndEdit(int WXUNUSED(row),\r
896 int WXUNUSED(col),\r
897 const wxGrid* WXUNUSED(grid),\r
898 const wxString& oldval, wxString *newval)\r
899{\r
900 const wxString text(Text()->GetValue());\r
901\r
902 double value;\r
903 if ( !text.empty() )\r
904 {\r
905 if ( !text.ToDouble(&value) )\r
906 return false;\r
907 }\r
908 else // new value is empty string\r
909 {\r
910 if ( oldval.empty() )\r
911 return false; // nothing changed\r
912\r
913 value = 0.;\r
914 }\r
915\r
916 // the test for empty strings ensures that we don't skip the value setting\r
917 // when "" is replaced by "0" or vice versa as "" numeric value is also 0.\r
918 if ( wxIsSameDouble(value, m_value) && !text.empty() && !oldval.empty() )\r
919 return false; // nothing changed\r
920\r
921 m_value = value;\r
922\r
923 if ( newval )\r
924 *newval = text;\r
925\r
926 return true;\r
927}\r
928\r
929void wxGridCellFloatEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
930{\r
931 wxGridTableBase * const table = grid->GetTable();\r
932\r
933 if ( table->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT) )\r
934 table->SetValueAsDouble(row, col, m_value);\r
935 else\r
936 table->SetValue(row, col, Text()->GetValue());\r
937}\r
938\r
939void wxGridCellFloatEditor::Reset()\r
940{\r
941 DoReset(GetString());\r
942}\r
943\r
944void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)\r
945{\r
946 int keycode = event.GetKeyCode();\r
947 char tmpbuf[2];\r
948 tmpbuf[0] = (char) keycode;\r
949 tmpbuf[1] = '\0';\r
950 wxString strbuf(tmpbuf, *wxConvCurrent);\r
951\r
952#if wxUSE_INTL\r
953 bool is_decimal_point = ( strbuf ==\r
954 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) );\r
955#else\r
956 bool is_decimal_point = ( strbuf == _T(".") );\r
957#endif\r
958\r
959 if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'\r
960 || is_decimal_point )\r
961 {\r
962 wxGridCellTextEditor::StartingKey(event);\r
963\r
964 // skip Skip() below\r
965 return;\r
966 }\r
967\r
968 event.Skip();\r
969}\r
970\r
971void wxGridCellFloatEditor::SetParameters(const wxString& params)\r
972{\r
973 if ( !params )\r
974 {\r
975 // reset to default\r
976 m_width =\r
977 m_precision = -1;\r
978 }\r
979 else\r
980 {\r
981 long tmp;\r
982 if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )\r
983 {\r
984 m_width = (int)tmp;\r
985\r
986 if ( params.AfterFirst(_T(',')).ToLong(&tmp) )\r
987 {\r
988 m_precision = (int)tmp;\r
989\r
990 // skip the error message below\r
991 return;\r
992 }\r
993 }\r
994\r
995 wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str());\r
996 }\r
997}\r
998\r
999wxString wxGridCellFloatEditor::GetString() const\r
1000{\r
1001 wxString fmt;\r
1002 if ( m_precision == -1 && m_width != -1)\r
1003 {\r
1004 // default precision\r
1005 fmt.Printf(_T("%%%d.f"), m_width);\r
1006 }\r
1007 else if ( m_precision != -1 && m_width == -1)\r
1008 {\r
1009 // default width\r
1010 fmt.Printf(_T("%%.%df"), m_precision);\r
1011 }\r
1012 else if ( m_precision != -1 && m_width != -1 )\r
1013 {\r
1014 fmt.Printf(_T("%%%d.%df"), m_width, m_precision);\r
1015 }\r
1016 else\r
1017 {\r
1018 // default width/precision\r
1019 fmt = _T("%f");\r
1020 }\r
1021\r
1022 return wxString::Format(fmt, m_value);\r
1023}\r
1024\r
1025bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)\r
1026{\r
1027 if ( wxGridCellEditor::IsAcceptedKey(event) )\r
1028 {\r
1029 const int keycode = event.GetKeyCode();\r
1030 if ( isascii(keycode) )\r
1031 {\r
1032 char tmpbuf[2];\r
1033 tmpbuf[0] = (char) keycode;\r
1034 tmpbuf[1] = '\0';\r
1035 wxString strbuf(tmpbuf, *wxConvCurrent);\r
1036\r
1037#if wxUSE_INTL\r
1038 const wxString decimalPoint =\r
1039 wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);\r
1040#else\r
1041 const wxString decimalPoint(_T('.'));\r
1042#endif\r
1043\r
1044 // accept digits, 'e' as in '1e+6', also '-', '+', and '.'\r
1045 if ( wxIsdigit(keycode) ||\r
1046 tolower(keycode) == 'e' ||\r
1047 keycode == decimalPoint ||\r
1048 keycode == '+' ||\r
1049 keycode == '-' )\r
1050 {\r
1051 return true;\r
1052 }\r
1053 }\r
1054 }\r
1055\r
1056 return false;\r
1057}\r
1058\r
1059#endif // wxUSE_TEXTCTRL\r
1060\r
1061#if wxUSE_CHECKBOX\r
1062\r
1063// ----------------------------------------------------------------------------\r
1064// wxGridCellBoolEditor\r
1065// ----------------------------------------------------------------------------\r
1066\r
1067// the default values for GetValue()\r
1068wxString wxGridCellBoolEditor::ms_stringValues[2] = { _T(""), _T("1") };\r
1069\r
1070void wxGridCellBoolEditor::Create(wxWindow* parent,\r
1071 wxWindowID id,\r
1072 wxEvtHandler* evtHandler)\r
1073{\r
1074 m_control = new wxCheckBox(parent, id, wxEmptyString,\r
1075 wxDefaultPosition, wxDefaultSize,\r
1076 wxNO_BORDER);\r
1077\r
1078 wxGridCellEditor::Create(parent, id, evtHandler);\r
1079}\r
1080\r
1081void wxGridCellBoolEditor::SetSize(const wxRect& r)\r
1082{\r
1083 bool resize = false;\r
1084 wxSize size = m_control->GetSize();\r
1085 wxCoord minSize = wxMin(r.width, r.height);\r
1086\r
1087 // check if the checkbox is not too big/small for this cell\r
1088 wxSize sizeBest = m_control->GetBestSize();\r
1089 if ( !(size == sizeBest) )\r
1090 {\r
1091 // reset to default size if it had been made smaller\r
1092 size = sizeBest;\r
1093\r
1094 resize = true;\r
1095 }\r
1096\r
1097 if ( size.x >= minSize || size.y >= minSize )\r
1098 {\r
1099 // leave 1 pixel margin\r
1100 size.x = size.y = minSize - 2;\r
1101\r
1102 resize = true;\r
1103 }\r
1104\r
1105 if ( resize )\r
1106 {\r
1107 m_control->SetSize(size);\r
1108 }\r
1109\r
1110 // position it in the centre of the rectangle (TODO: support alignment?)\r
1111\r
1112#if defined(__WXGTK__) || defined (__WXMOTIF__)\r
1113 // the checkbox without label still has some space to the right in wxGTK,\r
1114 // so shift it to the right\r
1115 size.x -= 8;\r
1116#elif defined(__WXMSW__)\r
1117 // here too, but in other way\r
1118 size.x += 1;\r
1119 size.y -= 2;\r
1120#endif\r
1121\r
1122 int hAlign = wxALIGN_CENTRE;\r
1123 int vAlign = wxALIGN_CENTRE;\r
1124 if (GetCellAttr())\r
1125 GetCellAttr()->GetAlignment(& hAlign, & vAlign);\r
1126\r
1127 int x = 0, y = 0;\r
1128 if (hAlign == wxALIGN_LEFT)\r
1129 {\r
1130 x = r.x + 2;\r
1131\r
1132#ifdef __WXMSW__\r
1133 x += 2;\r
1134#endif\r
1135\r
1136 y = r.y + r.height / 2 - size.y / 2;\r
1137 }\r
1138 else if (hAlign == wxALIGN_RIGHT)\r
1139 {\r
1140 x = r.x + r.width - size.x - 2;\r
1141 y = r.y + r.height / 2 - size.y / 2;\r
1142 }\r
1143 else if (hAlign == wxALIGN_CENTRE)\r
1144 {\r
1145 x = r.x + r.width / 2 - size.x / 2;\r
1146 y = r.y + r.height / 2 - size.y / 2;\r
1147 }\r
1148\r
1149 m_control->Move(x, y);\r
1150}\r
1151\r
1152void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)\r
1153{\r
1154 m_control->Show(show);\r
1155\r
1156 if ( show )\r
1157 {\r
1158 wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;\r
1159 CBox()->SetBackgroundColour(colBg);\r
1160 }\r
1161}\r
1162\r
1163void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)\r
1164{\r
1165 wxASSERT_MSG(m_control,\r
1166 wxT("The wxGridCellEditor must be created first!"));\r
1167\r
1168 if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))\r
1169 {\r
1170 m_value = grid->GetTable()->GetValueAsBool(row, col);\r
1171 }\r
1172 else\r
1173 {\r
1174 wxString cellval( grid->GetTable()->GetValue(row, col) );\r
1175\r
1176 if ( cellval == ms_stringValues[false] )\r
1177 m_value = false;\r
1178 else if ( cellval == ms_stringValues[true] )\r
1179 m_value = true;\r
1180 else\r
1181 {\r
1182 // do not try to be smart here and convert it to true or false\r
1183 // because we'll still overwrite it with something different and\r
1184 // this risks to be very surprising for the user code, let them\r
1185 // know about it\r
1186 wxFAIL_MSG( _T("invalid value for a cell with bool editor!") );\r
1187 }\r
1188 }\r
1189\r
1190 CBox()->SetValue(m_value);\r
1191 CBox()->SetFocus();\r
1192}\r
1193\r
1194bool wxGridCellBoolEditor::EndEdit(int WXUNUSED(row),\r
1195 int WXUNUSED(col),\r
1196 const wxGrid* WXUNUSED(grid),\r
1197 const wxString& WXUNUSED(oldval),\r
1198 wxString *newval)\r
1199{\r
1200 bool value = CBox()->GetValue();\r
1201 if ( value == m_value )\r
1202 return false;\r
1203\r
1204 m_value = value;\r
1205\r
1206 if ( newval )\r
1207 *newval = GetValue();\r
1208\r
1209 return true;\r
1210}\r
1211\r
1212void wxGridCellBoolEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
1213{\r
1214 wxGridTableBase * const table = grid->GetTable();\r
1215 if ( table->CanSetValueAs(row, col, wxGRID_VALUE_BOOL) )\r
1216 table->SetValueAsBool(row, col, m_value);\r
1217 else\r
1218 table->SetValue(row, col, GetValue());\r
1219}\r
1220\r
1221void wxGridCellBoolEditor::Reset()\r
1222{\r
1223 wxASSERT_MSG(m_control,\r
1224 wxT("The wxGridCellEditor must be created first!"));\r
1225\r
1226 CBox()->SetValue(m_value);\r
1227}\r
1228\r
1229void wxGridCellBoolEditor::StartingClick()\r
1230{\r
1231 CBox()->SetValue(!CBox()->GetValue());\r
1232}\r
1233\r
1234bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)\r
1235{\r
1236 if ( wxGridCellEditor::IsAcceptedKey(event) )\r
1237 {\r
1238 int keycode = event.GetKeyCode();\r
1239 switch ( keycode )\r
1240 {\r
1241 case WXK_SPACE:\r
1242 case '+':\r
1243 case '-':\r
1244 return true;\r
1245 }\r
1246 }\r
1247\r
1248 return false;\r
1249}\r
1250\r
1251void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event)\r
1252{\r
1253 int keycode = event.GetKeyCode();\r
1254 switch ( keycode )\r
1255 {\r
1256 case WXK_SPACE:\r
1257 CBox()->SetValue(!CBox()->GetValue());\r
1258 break;\r
1259\r
1260 case '+':\r
1261 CBox()->SetValue(true);\r
1262 break;\r
1263\r
1264 case '-':\r
1265 CBox()->SetValue(false);\r
1266 break;\r
1267 }\r
1268}\r
1269\r
1270wxString wxGridCellBoolEditor::GetValue() const\r
1271{\r
1272 return ms_stringValues[CBox()->GetValue()];\r
1273}\r
1274\r
1275/* static */ void\r
1276wxGridCellBoolEditor::UseStringValues(const wxString& valueTrue,\r
1277 const wxString& valueFalse)\r
1278{\r
1279 ms_stringValues[false] = valueFalse;\r
1280 ms_stringValues[true] = valueTrue;\r
1281}\r
1282\r
1283/* static */ bool\r
1284wxGridCellBoolEditor::IsTrueValue(const wxString& value)\r
1285{\r
1286 return value == ms_stringValues[true];\r
1287}\r
1288\r
1289#endif // wxUSE_CHECKBOX\r
1290\r
1291#if wxUSE_COMBOBOX\r
1292\r
1293// ----------------------------------------------------------------------------\r
1294// wxGridCellChoiceEditor\r
1295// ----------------------------------------------------------------------------\r
1296\r
1297wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,\r
1298 bool allowOthers)\r
1299 : m_choices(choices),\r
1300 m_allowOthers(allowOthers) { }\r
1301\r
1302wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,\r
1303 const wxString choices[],\r
1304 bool allowOthers)\r
1305 : m_allowOthers(allowOthers)\r
1306{\r
1307 if ( count )\r
1308 {\r
1309 m_choices.Alloc(count);\r
1310 for ( size_t n = 0; n < count; n++ )\r
1311 {\r
1312 m_choices.Add(choices[n]);\r
1313 }\r
1314 }\r
1315}\r
1316\r
1317wxGridCellEditor *wxGridCellChoiceEditor::Clone() const\r
1318{\r
1319 wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;\r
1320 editor->m_allowOthers = m_allowOthers;\r
1321 editor->m_choices = m_choices;\r
1322\r
1323 return editor;\r
1324}\r
1325\r
1326void wxGridCellChoiceEditor::Create(wxWindow* parent,\r
1327 wxWindowID id,\r
1328 wxEvtHandler* evtHandler)\r
1329{\r
1330 int style = wxTE_PROCESS_ENTER |\r
1331 wxTE_PROCESS_TAB |\r
1332 wxBORDER_NONE;\r
1333\r
1334 if ( !m_allowOthers )\r
1335 style |= wxCB_READONLY;\r
1336 m_control = new wxComboBox(parent, id, wxEmptyString,\r
1337 wxDefaultPosition, wxDefaultSize,\r
1338 m_choices,\r
1339 style);\r
1340\r
1341 wxGridCellEditor::Create(parent, id, evtHandler);\r
1342}\r
1343\r
1344void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,\r
1345 wxGridCellAttr * attr)\r
1346{\r
1347 // as we fill the entire client area, don't do anything here to minimize\r
1348 // flicker\r
1349\r
1350 // TODO: It doesn't actually fill the client area since the height of a\r
1351 // combo always defaults to the standard. Until someone has time to\r
1352 // figure out the right rectangle to paint, just do it the normal way.\r
1353 wxGridCellEditor::PaintBackground(rectCell, attr);\r
1354}\r
1355\r
1356void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)\r
1357{\r
1358 wxASSERT_MSG(m_control,\r
1359 wxT("The wxGridCellEditor must be created first!"));\r
1360\r
1361 wxGridCellEditorEvtHandler* evtHandler = NULL;\r
1362 if (m_control)\r
1363 evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler);\r
1364\r
1365 // Don't immediately end if we get a kill focus event within BeginEdit\r
1366 if (evtHandler)\r
1367 evtHandler->SetInSetFocus(true);\r
1368\r
1369 m_value = grid->GetTable()->GetValue(row, col);\r
1370\r
1371 Reset(); // this updates combo box to correspond to m_value\r
1372\r
1373 Combo()->SetFocus();\r
1374\r
1375 if (evtHandler)\r
1376 {\r
1377 // When dropping down the menu, a kill focus event\r
1378 // happens after this point, so we can't reset the flag yet.\r
1379#if !defined(__WXGTK20__)\r
1380 evtHandler->SetInSetFocus(false);\r
1381#endif\r
1382 }\r
1383}\r
1384\r
1385bool wxGridCellChoiceEditor::EndEdit(int WXUNUSED(row),\r
1386 int WXUNUSED(col),\r
1387 const wxGrid* WXUNUSED(grid),\r
1388 const wxString& WXUNUSED(oldval),\r
1389 wxString *newval)\r
1390{\r
1391 const wxString value = Combo()->GetValue();\r
1392 if ( value == m_value )\r
1393 return false;\r
1394\r
1395 m_value = value;\r
1396\r
1397 if ( newval )\r
1398 *newval = value;\r
1399\r
1400 return true;\r
1401}\r
1402\r
1403void wxGridCellChoiceEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
1404{\r
1405 grid->GetTable()->SetValue(row, col, m_value);\r
1406}\r
1407\r
1408void wxGridCellChoiceEditor::Reset()\r
1409{\r
1410 if (m_allowOthers)\r
1411 {\r
1412 Combo()->SetValue(m_value);\r
1413 Combo()->SetInsertionPointEnd();\r
1414 }\r
1415 else // the combobox is read-only\r
1416 {\r
1417 // find the right position, or default to the first if not found\r
1418 int pos = Combo()->FindString(m_value);\r
1419 if (pos == wxNOT_FOUND)\r
1420 pos = 0;\r
1421 Combo()->SetSelection(pos);\r
1422 }\r
1423}\r
1424\r
1425void wxGridCellChoiceEditor::SetParameters(const wxString& params)\r
1426{\r
1427 if ( !params )\r
1428 {\r
1429 // what can we do?\r
1430 return;\r
1431 }\r
1432\r
1433 m_choices.Empty();\r
1434\r
1435 wxStringTokenizer tk(params, _T(','));\r
1436 while ( tk.HasMoreTokens() )\r
1437 {\r
1438 m_choices.Add(tk.GetNextToken());\r
1439 }\r
1440}\r
1441\r
1442// return the value in the text control\r
1443wxString wxGridCellChoiceEditor::GetValue() const\r
1444{\r
1445 return Combo()->GetValue();\r
1446}\r
1447\r
1448#endif // wxUSE_COMBOBOX\r
1449\r
1450#if wxUSE_COMBOBOX\r
1451\r
1452// ----------------------------------------------------------------------------\r
1453// wxGridCellEnumEditor\r
1454// ----------------------------------------------------------------------------\r
1455\r
1456// A cell editor which displays an enum number as a textual equivalent. eg\r
1457// data in cell is 0,1,2 ... n the cell could be displayed as\r
1458// "John","Fred"..."Bob" in the combo choice box\r
1459\r
1460wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString& choices)\r
1461 :wxGridCellChoiceEditor()\r
1462{\r
1463 m_index = -1;\r
1464\r
1465 if (!choices.empty())\r
1466 SetParameters(choices);\r
1467}\r
1468\r
1469wxGridCellEditor *wxGridCellEnumEditor::Clone() const\r
1470{\r
1471 wxGridCellEnumEditor *editor = new wxGridCellEnumEditor();\r
1472 editor->m_index = m_index;\r
1473 return editor;\r
1474}\r
1475\r
1476void wxGridCellEnumEditor::BeginEdit(int row, int col, wxGrid* grid)\r
1477{\r
1478 wxASSERT_MSG(m_control,\r
1479 wxT("The wxGridCellEnumEditor must be Created first!"));\r
1480\r
1481 wxGridTableBase *table = grid->GetTable();\r
1482\r
1483 if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
1484 {\r
1485 m_index = table->GetValueAsLong(row, col);\r
1486 }\r
1487 else\r
1488 {\r
1489 wxString startValue = table->GetValue(row, col);\r
1490 if (startValue.IsNumber() && !startValue.empty())\r
1491 {\r
1492 startValue.ToLong(&m_index);\r
1493 }\r
1494 else\r
1495 {\r
1496 m_index = -1;\r
1497 }\r
1498 }\r
1499\r
1500 Combo()->SetSelection(m_index);\r
1501 Combo()->SetInsertionPointEnd();\r
1502 Combo()->SetFocus();\r
1503\r
1504}\r
1505\r
1506bool wxGridCellEnumEditor::EndEdit(int WXUNUSED(row),\r
1507 int WXUNUSED(col),\r
1508 const wxGrid* WXUNUSED(grid),\r
1509 const wxString& WXUNUSED(oldval),\r
1510 wxString *newval)\r
1511{\r
1512 long idx = Combo()->GetSelection();\r
1513 if ( idx == m_index )\r
1514 return false;\r
1515\r
1516 m_index = idx;\r
1517\r
1518 if ( newval )\r
1519 newval->Printf("%ld", m_index);\r
1520\r
1521 return true;\r
1522}\r
1523\r
1524void wxGridCellEnumEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
1525{\r
1526 wxGridTableBase * const table = grid->GetTable();\r
1527 if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
1528 table->SetValueAsLong(row, col, m_index);\r
1529 else\r
1530 table->SetValue(row, col, wxString::Format("%ld", m_index));\r
1531}\r
1532\r
1533#endif // wxUSE_COMBOBOX\r
1534\r
1535// ----------------------------------------------------------------------------\r
1536// wxGridCellAutoWrapStringEditor\r
1537// ----------------------------------------------------------------------------\r
1538\r
1539void\r
1540wxGridCellAutoWrapStringEditor::Create(wxWindow* parent,\r
1541 wxWindowID id,\r
1542 wxEvtHandler* evtHandler)\r
1543{\r
1544 wxGridCellTextEditor::DoCreate(parent, id, evtHandler,\r
1545 wxTE_MULTILINE | wxTE_RICH);\r
1546}\r
1547\r
1548\r
1549#endif // wxUSE_GRID\r