-/////////////////////////////////////////////////////////////////////////////
-// Name: wx/generic/grideditors.h
-// Purpose: wxGridCellEditorEvtHandler and wxGrid editors
-// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
-// Modified by: Santiago Palacios
-// Created: 1/08/1999
-// RCS-ID: $Id$
-// Copyright: (c) Michael Bedward
-// Licence: wxWindows licence
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef _WX_GENERIC_GRID_EDITORS_H_
-#define _WX_GENERIC_GRID_EDITORS_H_
-
-#include "wx/defs.h"
-
-#if wxUSE_GRID
-
-class wxGridCellEditorEvtHandler : public wxEvtHandler
-{
-public:
- wxGridCellEditorEvtHandler(wxGrid* grid, wxGridCellEditor* editor)
- : m_grid(grid),
- m_editor(editor),
- m_inSetFocus(false)
- {
- }
-
- void OnKillFocus(wxFocusEvent& event);
- void OnKeyDown(wxKeyEvent& event);
- void OnChar(wxKeyEvent& event);
-
- void SetInSetFocus(bool inSetFocus) { m_inSetFocus = inSetFocus; }
-
-private:
- wxGrid *m_grid;
- wxGridCellEditor *m_editor;
-
- // Work around the fact that a focus kill event can be sent to
- // a combobox within a set focus event.
- bool m_inSetFocus;
-
- DECLARE_EVENT_TABLE()
- DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler)
- wxDECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler);
-};
-
-
-#if wxUSE_TEXTCTRL
-
-// the editor for string/text data
-class WXDLLIMPEXP_ADV wxGridCellTextEditor : public wxGridCellEditor
-{
-public:
- wxGridCellTextEditor();
-
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
- virtual void SetSize(const wxRect& rect);
-
- virtual void PaintBackground(const wxRect& rectCell, wxGridCellAttr *attr);
-
- virtual bool IsAcceptedKey(wxKeyEvent& event);
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
- virtual void Reset();
- virtual void StartingKey(wxKeyEvent& event);
- virtual void HandleReturn(wxKeyEvent& event);
-
- // parameters string format is "max_width"
- virtual void SetParameters(const wxString& params);
-
- virtual wxGridCellEditor *Clone() const
- { return new wxGridCellTextEditor; }
-
- // added GetValue so we can get the value which is in the control
- virtual wxString GetValue() const;
-
-protected:
- wxTextCtrl *Text() const { return (wxTextCtrl *)m_control; }
-
- // parts of our virtual functions reused by the derived classes
- void DoCreate(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler,
- long style = 0);
- void DoBeginEdit(const wxString& startValue);
- void DoReset(const wxString& startValue);
-
-private:
- size_t m_maxChars; // max number of chars allowed
- wxString m_value;
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellTextEditor);
-};
-
-// the editor for numeric (long) data
-class WXDLLIMPEXP_ADV wxGridCellNumberEditor : public wxGridCellTextEditor
-{
-public:
- // allows to specify the range - if min == max == -1, no range checking is
- // done
- wxGridCellNumberEditor(int min = -1, int max = -1);
-
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
-
- virtual bool IsAcceptedKey(wxKeyEvent& event);
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
- virtual void Reset();
- virtual void StartingKey(wxKeyEvent& event);
-
- // parameters string format is "min,max"
- virtual void SetParameters(const wxString& params);
-
- virtual wxGridCellEditor *Clone() const
- { return new wxGridCellNumberEditor(m_min, m_max); }
-
- // added GetValue so we can get the value which is in the control
- virtual wxString GetValue() const;
-
-protected:
-#if wxUSE_SPINCTRL
- wxSpinCtrl *Spin() const { return (wxSpinCtrl *)m_control; }
-#endif
-
- // if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl
- bool HasRange() const
- {
-#if wxUSE_SPINCTRL
- return m_min != m_max;
-#else
- return false;
-#endif
- }
-
- // string representation of our value
- wxString GetString() const
- { return wxString::Format(_T("%ld"), m_value); }
-
-private:
- int m_min,
- m_max;
-
- long m_value;
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellNumberEditor);
-};
-
-// the editor for floating point numbers (double) data
-class WXDLLIMPEXP_ADV wxGridCellFloatEditor : public wxGridCellTextEditor
-{
-public:
- wxGridCellFloatEditor(int width = -1, int precision = -1);
-
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
-
- virtual bool IsAcceptedKey(wxKeyEvent& event);
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
- virtual void Reset();
- virtual void StartingKey(wxKeyEvent& event);
-
- virtual wxGridCellEditor *Clone() const
- { return new wxGridCellFloatEditor(m_width, m_precision); }
-
- // parameters string format is "width,precision"
- virtual void SetParameters(const wxString& params);
-
-protected:
- // string representation of our value
- wxString GetString() const;
-
-private:
- int m_width,
- m_precision;
- double m_value;
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellFloatEditor);
-};
-
-#endif // wxUSE_TEXTCTRL
-
-#if wxUSE_CHECKBOX
-
-// the editor for boolean data
-class WXDLLIMPEXP_ADV wxGridCellBoolEditor : public wxGridCellEditor
-{
-public:
- wxGridCellBoolEditor() { }
-
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
-
- virtual void SetSize(const wxRect& rect);
- virtual void Show(bool show, wxGridCellAttr *attr = NULL);
-
- virtual bool IsAcceptedKey(wxKeyEvent& event);
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
- virtual void Reset();
- virtual void StartingClick();
- virtual void StartingKey(wxKeyEvent& event);
-
- virtual wxGridCellEditor *Clone() const
- { return new wxGridCellBoolEditor; }
-
- // added GetValue so we can get the value which is in the control, see
- // also UseStringValues()
- virtual wxString GetValue() const;
-
- // set the string values returned by GetValue() for the true and false
- // states, respectively
- static void UseStringValues(const wxString& valueTrue = _T("1"),
- const wxString& valueFalse = wxEmptyString);
-
- // return true if the given string is equal to the string representation of
- // true value which we currently use
- static bool IsTrueValue(const wxString& value);
-
-protected:
- wxCheckBox *CBox() const { return (wxCheckBox *)m_control; }
-
-private:
- bool m_value;
-
- static wxString ms_stringValues[2];
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellBoolEditor);
-};
-
-#endif // wxUSE_CHECKBOX
-
-#if wxUSE_COMBOBOX
-
-// the editor for string data allowing to choose from the list of strings
-class WXDLLIMPEXP_ADV wxGridCellChoiceEditor : public wxGridCellEditor
-{
-public:
- // if !allowOthers, user can't type a string not in choices array
- wxGridCellChoiceEditor(size_t count = 0,
- const wxString choices[] = NULL,
- bool allowOthers = false);
- wxGridCellChoiceEditor(const wxArrayString& choices,
- bool allowOthers = false);
-
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
-
- virtual void PaintBackground(const wxRect& rectCell, wxGridCellAttr *attr);
-
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
- virtual void Reset();
-
- // parameters string format is "item1[,item2[...,itemN]]"
- virtual void SetParameters(const wxString& params);
-
- virtual wxGridCellEditor *Clone() const;
-
- // added GetValue so we can get the value which is in the control
- virtual wxString GetValue() const;
-
-protected:
- wxComboBox *Combo() const { return (wxComboBox *)m_control; }
-
- wxString m_value;
- wxArrayString m_choices;
- bool m_allowOthers;
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellChoiceEditor);
-};
-
-#endif // wxUSE_COMBOBOX
-
-#if wxUSE_COMBOBOX
-
-class WXDLLIMPEXP_ADV wxGridCellEnumEditor : public wxGridCellChoiceEditor
-{
-public:
- wxGridCellEnumEditor( const wxString& choices = wxEmptyString );
- virtual ~wxGridCellEnumEditor() {}
-
- virtual wxGridCellEditor* Clone() const;
-
- virtual void BeginEdit(int row, int col, wxGrid* grid);
- virtual bool EndEdit(const wxString& oldval, wxString *newval);
- virtual void ApplyEdit(int row, int col, wxGrid* grid);
-
-private:
- long m_index;
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellEnumEditor);
-};
-
-#endif // wxUSE_COMBOBOX
-
-class WXDLLIMPEXP_ADV wxGridCellAutoWrapStringEditor : public wxGridCellTextEditor
-{
-public:
- wxGridCellAutoWrapStringEditor() : wxGridCellTextEditor() { }
- virtual void Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler);
-
- virtual wxGridCellEditor *Clone() const
- { return new wxGridCellAutoWrapStringEditor; }
-
- wxDECLARE_NO_COPY_CLASS(wxGridCellAutoWrapStringEditor);
-};
-
-#endif // wxUSE_GRID
-#endif // _WX_GENERIC_GRID_EDITORS_H_
+/////////////////////////////////////////////////////////////////////////////\r
+// Name: wx/generic/grideditors.h\r
+// Purpose: wxGridCellEditorEvtHandler and wxGrid editors\r
+// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)\r
+// Modified by: Santiago Palacios\r
+// Created: 1/08/1999\r
+// RCS-ID: $Id$\r
+// Copyright: (c) Michael Bedward\r
+// Licence: wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef _WX_GENERIC_GRID_EDITORS_H_\r
+#define _WX_GENERIC_GRID_EDITORS_H_\r
+\r
+#include "wx/defs.h"\r
+\r
+#if wxUSE_GRID\r
+\r
+class wxGridCellEditorEvtHandler : public wxEvtHandler\r
+{\r
+public:\r
+ wxGridCellEditorEvtHandler(wxGrid* grid, wxGridCellEditor* editor)\r
+ : m_grid(grid),\r
+ m_editor(editor),\r
+ m_inSetFocus(false)\r
+ {\r
+ }\r
+\r
+ void OnKillFocus(wxFocusEvent& event);\r
+ void OnKeyDown(wxKeyEvent& event);\r
+ void OnChar(wxKeyEvent& event);\r
+\r
+ void SetInSetFocus(bool inSetFocus) { m_inSetFocus = inSetFocus; }\r
+\r
+private:\r
+ wxGrid *m_grid;\r
+ wxGridCellEditor *m_editor;\r
+\r
+ // Work around the fact that a focus kill event can be sent to\r
+ // a combobox within a set focus event.\r
+ bool m_inSetFocus;\r
+\r
+ DECLARE_EVENT_TABLE()\r
+ DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler)\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler);\r
+};\r
+\r
+\r
+#if wxUSE_TEXTCTRL\r
+\r
+// the editor for string/text data\r
+class WXDLLIMPEXP_ADV wxGridCellTextEditor : public wxGridCellEditor\r
+{\r
+public:\r
+ wxGridCellTextEditor();\r
+\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+ virtual void SetSize(const wxRect& rect);\r
+\r
+ virtual void PaintBackground(const wxRect& rectCell, wxGridCellAttr *attr);\r
+\r
+ virtual bool IsAcceptedKey(wxKeyEvent& event);\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+ virtual void Reset();\r
+ virtual void StartingKey(wxKeyEvent& event);\r
+ virtual void HandleReturn(wxKeyEvent& event);\r
+\r
+ // parameters string format is "max_width"\r
+ virtual void SetParameters(const wxString& params);\r
+\r
+ virtual wxGridCellEditor *Clone() const\r
+ { return new wxGridCellTextEditor; }\r
+\r
+ // added GetValue so we can get the value which is in the control\r
+ virtual wxString GetValue() const;\r
+\r
+protected:\r
+ wxTextCtrl *Text() const { return (wxTextCtrl *)m_control; }\r
+\r
+ // parts of our virtual functions reused by the derived classes\r
+ void DoCreate(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler,\r
+ long style = 0);\r
+ void DoBeginEdit(const wxString& startValue);\r
+ void DoReset(const wxString& startValue);\r
+\r
+private:\r
+ size_t m_maxChars; // max number of chars allowed\r
+ wxString m_value;\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellTextEditor);\r
+};\r
+\r
+// the editor for numeric (long) data\r
+class WXDLLIMPEXP_ADV wxGridCellNumberEditor : public wxGridCellTextEditor\r
+{\r
+public:\r
+ // allows to specify the range - if min == max == -1, no range checking is\r
+ // done\r
+ wxGridCellNumberEditor(int min = -1, int max = -1);\r
+\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+\r
+ virtual bool IsAcceptedKey(wxKeyEvent& event);\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+ virtual void Reset();\r
+ virtual void StartingKey(wxKeyEvent& event);\r
+\r
+ // parameters string format is "min,max"\r
+ virtual void SetParameters(const wxString& params);\r
+\r
+ virtual wxGridCellEditor *Clone() const\r
+ { return new wxGridCellNumberEditor(m_min, m_max); }\r
+\r
+ // added GetValue so we can get the value which is in the control\r
+ virtual wxString GetValue() const;\r
+\r
+protected:\r
+#if wxUSE_SPINCTRL\r
+ wxSpinCtrl *Spin() const { return (wxSpinCtrl *)m_control; }\r
+#endif\r
+\r
+ // if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl\r
+ bool HasRange() const\r
+ {\r
+#if wxUSE_SPINCTRL\r
+ return m_min != m_max;\r
+#else\r
+ return false;\r
+#endif\r
+ }\r
+\r
+ // string representation of our value\r
+ wxString GetString() const\r
+ { return wxString::Format(_T("%ld"), m_value); }\r
+\r
+private:\r
+ int m_min,\r
+ m_max;\r
+\r
+ long m_value;\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellNumberEditor);\r
+};\r
+\r
+// the editor for floating point numbers (double) data\r
+class WXDLLIMPEXP_ADV wxGridCellFloatEditor : public wxGridCellTextEditor\r
+{\r
+public:\r
+ wxGridCellFloatEditor(int width = -1, int precision = -1);\r
+\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+\r
+ virtual bool IsAcceptedKey(wxKeyEvent& event);\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+ virtual void Reset();\r
+ virtual void StartingKey(wxKeyEvent& event);\r
+\r
+ virtual wxGridCellEditor *Clone() const\r
+ { return new wxGridCellFloatEditor(m_width, m_precision); }\r
+\r
+ // parameters string format is "width,precision"\r
+ virtual void SetParameters(const wxString& params);\r
+\r
+protected:\r
+ // string representation of our value\r
+ wxString GetString() const;\r
+\r
+private:\r
+ int m_width,\r
+ m_precision;\r
+ double m_value;\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellFloatEditor);\r
+};\r
+\r
+#endif // wxUSE_TEXTCTRL\r
+\r
+#if wxUSE_CHECKBOX\r
+\r
+// the editor for boolean data\r
+class WXDLLIMPEXP_ADV wxGridCellBoolEditor : public wxGridCellEditor\r
+{\r
+public:\r
+ wxGridCellBoolEditor() { }\r
+\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+\r
+ virtual void SetSize(const wxRect& rect);\r
+ virtual void Show(bool show, wxGridCellAttr *attr = NULL);\r
+\r
+ virtual bool IsAcceptedKey(wxKeyEvent& event);\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+ virtual void Reset();\r
+ virtual void StartingClick();\r
+ virtual void StartingKey(wxKeyEvent& event);\r
+\r
+ virtual wxGridCellEditor *Clone() const\r
+ { return new wxGridCellBoolEditor; }\r
+\r
+ // added GetValue so we can get the value which is in the control, see\r
+ // also UseStringValues()\r
+ virtual wxString GetValue() const;\r
+\r
+ // set the string values returned by GetValue() for the true and false\r
+ // states, respectively\r
+ static void UseStringValues(const wxString& valueTrue = _T("1"),\r
+ const wxString& valueFalse = wxEmptyString);\r
+\r
+ // return true if the given string is equal to the string representation of\r
+ // true value which we currently use\r
+ static bool IsTrueValue(const wxString& value);\r
+\r
+protected:\r
+ wxCheckBox *CBox() const { return (wxCheckBox *)m_control; }\r
+\r
+private:\r
+ bool m_value;\r
+\r
+ static wxString ms_stringValues[2];\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellBoolEditor);\r
+};\r
+\r
+#endif // wxUSE_CHECKBOX\r
+\r
+#if wxUSE_COMBOBOX\r
+\r
+// the editor for string data allowing to choose from the list of strings\r
+class WXDLLIMPEXP_ADV wxGridCellChoiceEditor : public wxGridCellEditor\r
+{\r
+public:\r
+ // if !allowOthers, user can't type a string not in choices array\r
+ wxGridCellChoiceEditor(size_t count = 0,\r
+ const wxString choices[] = NULL,\r
+ bool allowOthers = false);\r
+ wxGridCellChoiceEditor(const wxArrayString& choices,\r
+ bool allowOthers = false);\r
+\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+\r
+ virtual void PaintBackground(const wxRect& rectCell, wxGridCellAttr *attr);\r
+\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+ virtual void Reset();\r
+\r
+ // parameters string format is "item1[,item2[...,itemN]]"\r
+ virtual void SetParameters(const wxString& params);\r
+\r
+ virtual wxGridCellEditor *Clone() const;\r
+\r
+ // added GetValue so we can get the value which is in the control\r
+ virtual wxString GetValue() const;\r
+\r
+protected:\r
+ wxComboBox *Combo() const { return (wxComboBox *)m_control; }\r
+\r
+ wxString m_value;\r
+ wxArrayString m_choices;\r
+ bool m_allowOthers;\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellChoiceEditor);\r
+};\r
+\r
+#endif // wxUSE_COMBOBOX\r
+\r
+#if wxUSE_COMBOBOX\r
+\r
+class WXDLLIMPEXP_ADV wxGridCellEnumEditor : public wxGridCellChoiceEditor\r
+{\r
+public:\r
+ wxGridCellEnumEditor( const wxString& choices = wxEmptyString );\r
+ virtual ~wxGridCellEnumEditor() {}\r
+\r
+ virtual wxGridCellEditor* Clone() const;\r
+\r
+ virtual void BeginEdit(int row, int col, wxGrid* grid);\r
+ virtual bool EndEdit(int row, int col, const wxGrid* grid,\r
+ const wxString& oldval, wxString *newval);\r
+ virtual void ApplyEdit(int row, int col, wxGrid* grid);\r
+\r
+private:\r
+ long m_index;\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellEnumEditor);\r
+};\r
+\r
+#endif // wxUSE_COMBOBOX\r
+\r
+class WXDLLIMPEXP_ADV wxGridCellAutoWrapStringEditor : public wxGridCellTextEditor\r
+{\r
+public:\r
+ wxGridCellAutoWrapStringEditor() : wxGridCellTextEditor() { }\r
+ virtual void Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler);\r
+\r
+ virtual wxGridCellEditor *Clone() const\r
+ { return new wxGridCellAutoWrapStringEditor; }\r
+\r
+ wxDECLARE_NO_COPY_CLASS(wxGridCellAutoWrapStringEditor);\r
+};\r
+\r
+#endif // wxUSE_GRID\r
+\r
+#endif // _WX_GENERIC_GRID_EDITORS_H_\r
-///////////////////////////////////////////////////////////////////////////
-// Name: src/generic/grideditors.cpp
-// Purpose: wxGridCellEditorEvtHandler and wxGrid editors
-// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
-// Modified by: Robin Dunn, Vadim Zeitlin, Santiago Palacios
-// Created: 1/08/1999
-// RCS-ID: $Id$
-// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
-// Licence: wxWindows licence
-/////////////////////////////////////////////////////////////////////////////
-
-// For compilers that support precompilation, includes "wx/wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
- #pragma hdrstop
-#endif
-
-#if wxUSE_GRID
-
-#include "wx/grid.h"
-
-#ifndef WX_PRECOMP
- #include "wx/utils.h"
- #include "wx/dcclient.h"
- #include "wx/settings.h"
- #include "wx/log.h"
- #include "wx/textctrl.h"
- #include "wx/checkbox.h"
- #include "wx/combobox.h"
- #include "wx/valtext.h"
- #include "wx/intl.h"
- #include "wx/math.h"
- #include "wx/listbox.h"
-#endif
-
-#include "wx/textfile.h"
-#include "wx/spinctrl.h"
-#include "wx/tokenzr.h"
-#include "wx/renderer.h"
-#include "wx/headerctrl.h"
-
-#include "wx/generic/gridsel.h"
-#include "wx/generic/grideditors.h"
-#include "wx/generic/private/grid.h"
-
-#if defined(__WXMOTIF__)
- #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)
-#else
- #define WXUNUSED_MOTIF(identifier) identifier
-#endif
-
-#if defined(__WXGTK__)
- #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)
-#else
- #define WXUNUSED_GTK(identifier) identifier
-#endif
-
-// Required for wxIs... functions
-#include <ctype.h>
-
-// ============================================================================
-// implementation
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// wxGridCellEditorEvtHandler
-// ----------------------------------------------------------------------------
-
-void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event)
-{
- // Don't disable the cell if we're just starting to edit it
- if ( m_inSetFocus )
- {
- event.Skip();
- return;
- }
-
- // accept changes
- m_grid->DisableCellEditControl();
-
- // notice that we must not skip the event here because the call above may
- // delete the control which received the kill focus event in the first
- // place and if we pretend not having processed the event, the search for a
- // handler for it will continue using the now deleted object resulting in a
- // crash
-}
-
-void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
-{
- switch ( event.GetKeyCode() )
- {
- case WXK_ESCAPE:
- m_editor->Reset();
- m_grid->DisableCellEditControl();
- break;
-
- case WXK_TAB:
- m_grid->GetEventHandler()->ProcessEvent( event );
- break;
-
- case WXK_RETURN:
- case WXK_NUMPAD_ENTER:
- if (!m_grid->GetEventHandler()->ProcessEvent(event))
- m_editor->HandleReturn(event);
- break;
-
- default:
- event.Skip();
- break;
- }
-}
-
-void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
-{
- int row = m_grid->GetGridCursorRow();
- int col = m_grid->GetGridCursorCol();
- wxRect rect = m_grid->CellToRect( row, col );
- int cw, ch;
- m_grid->GetGridWindow()->GetClientSize( &cw, &ch );
-
- // if cell width is smaller than grid client area, cell is wholly visible
- bool wholeCellVisible = (rect.GetWidth() < cw);
-
- switch ( event.GetKeyCode() )
- {
- case WXK_ESCAPE:
- case WXK_TAB:
- case WXK_RETURN:
- case WXK_NUMPAD_ENTER:
- break;
-
- case WXK_HOME:
- {
- if ( wholeCellVisible )
- {
- // no special processing needed...
- event.Skip();
- break;
- }
-
- // do special processing for partly visible cell...
-
- // get the widths of all cells previous to this one
- int colXPos = 0;
- for ( int i = 0; i < col; i++ )
- {
- colXPos += m_grid->GetColSize(i);
- }
-
- int xUnit = 1, yUnit = 1;
- m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);
- if (col != 0)
- {
- m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));
- }
- else
- {
- m_grid->Scroll(colXPos / xUnit, m_grid->GetScrollPos(wxVERTICAL));
- }
- event.Skip();
- break;
- }
-
- case WXK_END:
- {
- if ( wholeCellVisible )
- {
- // no special processing needed...
- event.Skip();
- break;
- }
-
- // do special processing for partly visible cell...
-
- int textWidth = 0;
- wxString value = m_grid->GetCellValue(row, col);
- if ( wxEmptyString != value )
- {
- // get width of cell CONTENTS (text)
- int y;
- wxFont font = m_grid->GetCellFont(row, col);
- m_grid->GetTextExtent(value, &textWidth, &y, NULL, NULL, &font);
-
- // try to RIGHT align the text by scrolling
- int client_right = m_grid->GetGridWindow()->GetClientSize().GetWidth();
-
- // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far,
- // otherwise the last part of the cell content might be hidden below the scroll bar
- // FIXME: maybe there is a more suitable correction?
- textWidth -= (client_right - (m_grid->GetScrollLineX() * 2));
- if ( textWidth < 0 )
- {
- textWidth = 0;
- }
- }
-
- // get the widths of all cells previous to this one
- int colXPos = 0;
- for ( int i = 0; i < col; i++ )
- {
- colXPos += m_grid->GetColSize(i);
- }
-
- // and add the (modified) text width of the cell contents
- // as we'd like to see the last part of the cell contents
- colXPos += textWidth;
-
- int xUnit = 1, yUnit = 1;
- m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);
- m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));
- event.Skip();
- break;
- }
-
- default:
- event.Skip();
- break;
- }
-}
-
-// ----------------------------------------------------------------------------
-// wxGridCellEditor
-// ----------------------------------------------------------------------------
-
-wxGridCellEditor::wxGridCellEditor()
-{
- m_control = NULL;
- m_attr = NULL;
-}
-
-wxGridCellEditor::~wxGridCellEditor()
-{
- Destroy();
-}
-
-void wxGridCellEditor::Create(wxWindow* WXUNUSED(parent),
- wxWindowID WXUNUSED(id),
- wxEvtHandler* evtHandler)
-{
- if ( evtHandler )
- m_control->PushEventHandler(evtHandler);
-}
-
-void wxGridCellEditor::PaintBackground(const wxRect& rectCell,
- wxGridCellAttr *attr)
-{
- // erase the background because we might not fill the cell
- wxClientDC dc(m_control->GetParent());
- wxGridWindow* gridWindow = wxDynamicCast(m_control->GetParent(), wxGridWindow);
- if (gridWindow)
- gridWindow->GetOwner()->PrepareDC(dc);
-
- dc.SetPen(*wxTRANSPARENT_PEN);
- dc.SetBrush(wxBrush(attr->GetBackgroundColour()));
- dc.DrawRectangle(rectCell);
-
- // redraw the control we just painted over
- m_control->Refresh();
-}
-
-void wxGridCellEditor::Destroy()
-{
- if (m_control)
- {
- m_control->PopEventHandler( true /* delete it*/ );
-
- m_control->Destroy();
- m_control = NULL;
- }
-}
-
-void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr)
-{
- wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));
-
- m_control->Show(show);
-
- if ( show )
- {
- // set the colours/fonts if we have any
- if ( attr )
- {
- m_colFgOld = m_control->GetForegroundColour();
- m_control->SetForegroundColour(attr->GetTextColour());
-
- m_colBgOld = m_control->GetBackgroundColour();
- m_control->SetBackgroundColour(attr->GetBackgroundColour());
-
-// Workaround for GTK+1 font setting problem on some platforms
-#if !defined(__WXGTK__) || defined(__WXGTK20__)
- m_fontOld = m_control->GetFont();
- m_control->SetFont(attr->GetFont());
-#endif
-
- // can't do anything more in the base class version, the other
- // attributes may only be used by the derived classes
- }
- }
- else
- {
- // restore the standard colours fonts
- if ( m_colFgOld.Ok() )
- {
- m_control->SetForegroundColour(m_colFgOld);
- m_colFgOld = wxNullColour;
- }
-
- if ( m_colBgOld.Ok() )
- {
- m_control->SetBackgroundColour(m_colBgOld);
- m_colBgOld = wxNullColour;
- }
-
-// Workaround for GTK+1 font setting problem on some platforms
-#if !defined(__WXGTK__) || defined(__WXGTK20__)
- if ( m_fontOld.Ok() )
- {
- m_control->SetFont(m_fontOld);
- m_fontOld = wxNullFont;
- }
-#endif
- }
-}
-
-void wxGridCellEditor::SetSize(const wxRect& rect)
-{
- wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));
-
- m_control->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);
-}
-
-void wxGridCellEditor::HandleReturn(wxKeyEvent& event)
-{
- event.Skip();
-}
-
-bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)
-{
- bool ctrl = event.ControlDown();
- bool alt = event.AltDown();
-
-#ifdef __WXMAC__
- // On the Mac the Alt key is more like shift and is used for entry of
- // valid characters, so check for Ctrl and Meta instead.
- alt = event.MetaDown();
-#endif
-
- // Assume it's not a valid char if ctrl or alt is down, but if both are
- // down then it may be because of an AltGr key combination, so let them
- // through in that case.
- if ((ctrl || alt) && !(ctrl && alt))
- return false;
-
-#if wxUSE_UNICODE
- // if the unicode key code is not really a unicode character (it may
- // be a function key or etc., the platforms appear to always give us a
- // small value in this case) then fallback to the ASCII key code but
- // don't do anything for function keys or etc.
- if ( event.GetUnicodeKey() > 127 && event.GetKeyCode() > 127 )
- return false;
-#else
- if ( event.GetKeyCode() > 255 )
- return false;
-#endif
-
- return true;
-}
-
-void wxGridCellEditor::StartingKey(wxKeyEvent& event)
-{
- event.Skip();
-}
-
-void wxGridCellEditor::StartingClick()
-{
-}
-
-#if wxUSE_TEXTCTRL
-
-// ----------------------------------------------------------------------------
-// wxGridCellTextEditor
-// ----------------------------------------------------------------------------
-
-wxGridCellTextEditor::wxGridCellTextEditor()
-{
- m_maxChars = 0;
-}
-
-void wxGridCellTextEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
- DoCreate(parent, id, evtHandler);
-}
-
-void wxGridCellTextEditor::DoCreate(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler,
- long style)
-{
- style |= wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxNO_BORDER;
-
- m_control = new wxTextCtrl(parent, id, wxEmptyString,
- wxDefaultPosition, wxDefaultSize,
- style);
-
- // set max length allowed in the textctrl, if the parameter was set
- if ( m_maxChars != 0 )
- {
- Text()->SetMaxLength(m_maxChars);
- }
-
- wxGridCellEditor::Create(parent, id, evtHandler);
-}
-
-void wxGridCellTextEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),
- wxGridCellAttr * WXUNUSED(attr))
-{
- // as we fill the entire client area,
- // don't do anything here to minimize flicker
-}
-
-void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)
-{
- wxRect rect(rectOrig);
-
- // Make the edit control large enough to allow for internal margins
- //
- // TODO: remove this if the text ctrl sizing is improved esp. for unix
- //
-#if defined(__WXGTK__)
- if (rect.x != 0)
- {
- rect.x += 1;
- rect.y += 1;
- rect.width -= 1;
- rect.height -= 1;
- }
-#elif defined(__WXMSW__)
- if ( rect.x == 0 )
- rect.x += 2;
- else
- rect.x += 3;
-
- if ( rect.y == 0 )
- rect.y += 2;
- else
- rect.y += 3;
-
- rect.width -= 2;
- rect.height -= 2;
-#else
- int extra_x = ( rect.x > 2 ) ? 2 : 1;
- int extra_y = ( rect.y > 2 ) ? 2 : 1;
-
- #if defined(__WXMOTIF__)
- extra_x *= 2;
- extra_y *= 2;
- #endif
-
- rect.SetLeft( wxMax(0, rect.x - extra_x) );
- rect.SetTop( wxMax(0, rect.y - extra_y) );
- rect.SetRight( rect.GetRight() + 2 * extra_x );
- rect.SetBottom( rect.GetBottom() + 2 * extra_y );
-#endif
-
- wxGridCellEditor::SetSize(rect);
-}
-
-void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));
-
- m_value = grid->GetTable()->GetValue(row, col);
-
- DoBeginEdit(m_value);
-}
-
-void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)
-{
- Text()->SetValue(startValue);
- Text()->SetInsertionPointEnd();
- Text()->SetSelection(-1, -1);
- Text()->SetFocus();
-}
-
-bool wxGridCellTextEditor::EndEdit(const wxString& WXUNUSED(oldval),
- wxString *newval)
-{
- wxCHECK_MSG( m_control, false,
- "wxGridCellTextEditor must be created first!" );
-
- const wxString value = Text()->GetValue();
- if ( value == m_value )
- return false;
-
- m_value = value;
-
- if ( newval )
- *newval = m_value;
-
- return true;
-}
-
-void wxGridCellTextEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- grid->GetTable()->SetValue(row, col, m_value);
- m_value.clear();
-}
-
-void wxGridCellTextEditor::Reset()
-{
- wxASSERT_MSG( m_control, "wxGridCellTextEditor must be created first!" );
-
- DoReset(m_value);
-}
-
-void wxGridCellTextEditor::DoReset(const wxString& startValue)
-{
- Text()->SetValue(startValue);
- Text()->SetInsertionPointEnd();
-}
-
-bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)
-{
- return wxGridCellEditor::IsAcceptedKey(event);
-}
-
-void wxGridCellTextEditor::StartingKey(wxKeyEvent& event)
-{
- // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no
- // longer an appropriate way to get the character into the text control.
- // Do it ourselves instead. We know that if we get this far that we have
- // a valid character, so not a whole lot of testing needs to be done.
-
- wxTextCtrl* tc = Text();
- wxChar ch;
- long pos;
-
-#if wxUSE_UNICODE
- ch = event.GetUnicodeKey();
- if (ch <= 127)
- ch = (wxChar)event.GetKeyCode();
-#else
- ch = (wxChar)event.GetKeyCode();
-#endif
-
- switch (ch)
- {
- case WXK_DELETE:
- // delete the character at the cursor
- pos = tc->GetInsertionPoint();
- if (pos < tc->GetLastPosition())
- tc->Remove(pos, pos + 1);
- break;
-
- case WXK_BACK:
- // delete the character before the cursor
- pos = tc->GetInsertionPoint();
- if (pos > 0)
- tc->Remove(pos - 1, pos);
- break;
-
- default:
- tc->WriteText(ch);
- break;
- }
-}
-
-void wxGridCellTextEditor::HandleReturn( wxKeyEvent&
- WXUNUSED_GTK(WXUNUSED_MOTIF(event)) )
-{
-#if defined(__WXMOTIF__) || defined(__WXGTK__)
- // wxMotif needs a little extra help...
- size_t pos = (size_t)( Text()->GetInsertionPoint() );
- wxString s( Text()->GetValue() );
- s = s.Left(pos) + wxT("\n") + s.Mid(pos);
- Text()->SetValue(s);
- Text()->SetInsertionPoint( pos );
-#else
- // the other ports can handle a Return key press
- //
- event.Skip();
-#endif
-}
-
-void wxGridCellTextEditor::SetParameters(const wxString& params)
-{
- if ( !params )
- {
- // reset to default
- m_maxChars = 0;
- }
- else
- {
- long tmp;
- if ( params.ToLong(&tmp) )
- {
- m_maxChars = (size_t)tmp;
- }
- else
- {
- wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params.c_str() );
- }
- }
-}
-
-// return the value in the text control
-wxString wxGridCellTextEditor::GetValue() const
-{
- return Text()->GetValue();
-}
-
-// ----------------------------------------------------------------------------
-// wxGridCellNumberEditor
-// ----------------------------------------------------------------------------
-
-wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)
-{
- m_min = min;
- m_max = max;
-}
-
-void wxGridCellNumberEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
-#if wxUSE_SPINCTRL
- if ( HasRange() )
- {
- // create a spin ctrl
- m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,
- wxDefaultPosition, wxDefaultSize,
- wxSP_ARROW_KEYS,
- m_min, m_max);
-
- wxGridCellEditor::Create(parent, id, evtHandler);
- }
- else
-#endif
- {
- // just a text control
- wxGridCellTextEditor::Create(parent, id, evtHandler);
-
-#if wxUSE_VALIDATORS
- Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
-#endif
- }
-}
-
-void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- // first get the value
- wxGridTableBase *table = grid->GetTable();
- if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
- {
- m_value = table->GetValueAsLong(row, col);
- }
- else
- {
- m_value = 0;
- wxString sValue = table->GetValue(row, col);
- if (! sValue.ToLong(&m_value) && ! sValue.empty())
- {
- wxFAIL_MSG( _T("this cell doesn't have numeric value") );
- return;
- }
- }
-
-#if wxUSE_SPINCTRL
- if ( HasRange() )
- {
- Spin()->SetValue((int)m_value);
- Spin()->SetFocus();
- }
- else
-#endif
- {
- DoBeginEdit(GetString());
- }
-}
-
-bool wxGridCellNumberEditor::EndEdit(const wxString& oldval, wxString *newval)
-{
- long value = 0;
- wxString text;
-
-#if wxUSE_SPINCTRL
- if ( HasRange() )
- {
- value = Spin()->GetValue();
- if ( value == m_value )
- return false;
-
- text.Printf(wxT("%ld"), value);
- }
- else // using unconstrained input
-#endif // wxUSE_SPINCTRL
- {
- text = Text()->GetValue();
- if ( text.empty() )
- {
- if ( oldval.empty() )
- return false;
- }
- else // non-empty text now (maybe 0)
- {
- if ( !text.ToLong(&value) )
- return false;
-
- // if value == m_value == 0 but old text was "" and new one is
- // "0" something still did change
- if ( value == m_value && (value || !oldval.empty()) )
- return false;
- }
- }
-
- m_value = value;
-
- if ( newval )
- *newval = text;
-
- return true;
-}
-
-void wxGridCellNumberEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- wxGridTableBase * const table = grid->GetTable();
- if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )
- table->SetValueAsLong(row, col, m_value);
- else
- table->SetValue(row, col, wxString::Format("%ld", m_value));
-}
-
-void wxGridCellNumberEditor::Reset()
-{
-#if wxUSE_SPINCTRL
- if ( HasRange() )
- {
- Spin()->SetValue((int)m_value);
- }
- else
-#endif
- {
- DoReset(GetString());
- }
-}
-
-bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event)
-{
- if ( wxGridCellEditor::IsAcceptedKey(event) )
- {
- int keycode = event.GetKeyCode();
- if ( (keycode < 128) &&
- (wxIsdigit(keycode) || keycode == '+' || keycode == '-'))
- {
- return true;
- }
- }
-
- return false;
-}
-
-void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
-{
- int keycode = event.GetKeyCode();
- if ( !HasRange() )
- {
- if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-')
- {
- wxGridCellTextEditor::StartingKey(event);
-
- // skip Skip() below
- return;
- }
- }
-#if wxUSE_SPINCTRL
- else
- {
- if ( wxIsdigit(keycode) )
- {
- wxSpinCtrl* spin = (wxSpinCtrl*)m_control;
- spin->SetValue(keycode - '0');
- spin->SetSelection(1,1);
- return;
- }
- }
-#endif
-
- event.Skip();
-}
-
-void wxGridCellNumberEditor::SetParameters(const wxString& params)
-{
- if ( !params )
- {
- // reset to default
- m_min =
- m_max = -1;
- }
- else
- {
- long tmp;
- if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
- {
- m_min = (int)tmp;
-
- if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
- {
- m_max = (int)tmp;
-
- // skip the error message below
- return;
- }
- }
-
- wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params.c_str());
- }
-}
-
-// return the value in the spin control if it is there (the text control otherwise)
-wxString wxGridCellNumberEditor::GetValue() const
-{
- wxString s;
-
-#if wxUSE_SPINCTRL
- if ( HasRange() )
- {
- long value = Spin()->GetValue();
- s.Printf(wxT("%ld"), value);
- }
- else
-#endif
- {
- s = Text()->GetValue();
- }
-
- return s;
-}
-
-// ----------------------------------------------------------------------------
-// wxGridCellFloatEditor
-// ----------------------------------------------------------------------------
-
-wxGridCellFloatEditor::wxGridCellFloatEditor(int width, int precision)
-{
- m_width = width;
- m_precision = precision;
-}
-
-void wxGridCellFloatEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
- wxGridCellTextEditor::Create(parent, id, evtHandler);
-
-#if wxUSE_VALIDATORS
- Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
-#endif
-}
-
-void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- // first get the value
- wxGridTableBase * const table = grid->GetTable();
- if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
- {
- m_value = table->GetValueAsDouble(row, col);
- }
- else
- {
- m_value = 0.0;
-
- const wxString value = table->GetValue(row, col);
- if ( !value.empty() )
- {
- if ( !value.ToDouble(&m_value) )
- {
- wxFAIL_MSG( _T("this cell doesn't have float value") );
- return;
- }
- }
- }
-
- DoBeginEdit(GetString());
-}
-
-bool wxGridCellFloatEditor::EndEdit(const wxString& oldval, wxString *newval)
-{
- const wxString text(Text()->GetValue());
-
- double value;
- if ( !text.empty() )
- {
- if ( !text.ToDouble(&value) )
- return false;
- }
- else // new value is empty string
- {
- if ( oldval.empty() )
- return false; // nothing changed
-
- value = 0.;
- }
-
- // the test for empty strings ensures that we don't skip the value setting
- // when "" is replaced by "0" or vice versa as "" numeric value is also 0.
- if ( wxIsSameDouble(value, m_value) && !text.empty() && !oldval.empty() )
- return false; // nothing changed
-
- m_value = value;
-
- if ( newval )
- *newval = text;
-
- return true;
-}
-
-void wxGridCellFloatEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- wxGridTableBase * const table = grid->GetTable();
-
- if ( table->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT) )
- table->SetValueAsDouble(row, col, m_value);
- else
- table->SetValue(row, col, Text()->GetValue());
-}
-
-void wxGridCellFloatEditor::Reset()
-{
- DoReset(GetString());
-}
-
-void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
-{
- int keycode = event.GetKeyCode();
- char tmpbuf[2];
- tmpbuf[0] = (char) keycode;
- tmpbuf[1] = '\0';
- wxString strbuf(tmpbuf, *wxConvCurrent);
-
-#if wxUSE_INTL
- bool is_decimal_point = ( strbuf ==
- wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) );
-#else
- bool is_decimal_point = ( strbuf == _T(".") );
-#endif
-
- if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
- || is_decimal_point )
- {
- wxGridCellTextEditor::StartingKey(event);
-
- // skip Skip() below
- return;
- }
-
- event.Skip();
-}
-
-void wxGridCellFloatEditor::SetParameters(const wxString& params)
-{
- if ( !params )
- {
- // reset to default
- m_width =
- m_precision = -1;
- }
- else
- {
- long tmp;
- if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )
- {
- m_width = (int)tmp;
-
- if ( params.AfterFirst(_T(',')).ToLong(&tmp) )
- {
- m_precision = (int)tmp;
-
- // skip the error message below
- return;
- }
- }
-
- wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str());
- }
-}
-
-wxString wxGridCellFloatEditor::GetString() const
-{
- wxString fmt;
- if ( m_precision == -1 && m_width != -1)
- {
- // default precision
- fmt.Printf(_T("%%%d.f"), m_width);
- }
- else if ( m_precision != -1 && m_width == -1)
- {
- // default width
- fmt.Printf(_T("%%.%df"), m_precision);
- }
- else if ( m_precision != -1 && m_width != -1 )
- {
- fmt.Printf(_T("%%%d.%df"), m_width, m_precision);
- }
- else
- {
- // default width/precision
- fmt = _T("%f");
- }
-
- return wxString::Format(fmt, m_value);
-}
-
-bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
-{
- if ( wxGridCellEditor::IsAcceptedKey(event) )
- {
- const int keycode = event.GetKeyCode();
- if ( isascii(keycode) )
- {
- char tmpbuf[2];
- tmpbuf[0] = (char) keycode;
- tmpbuf[1] = '\0';
- wxString strbuf(tmpbuf, *wxConvCurrent);
-
-#if wxUSE_INTL
- const wxString decimalPoint =
- wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
-#else
- const wxString decimalPoint(_T('.'));
-#endif
-
- // accept digits, 'e' as in '1e+6', also '-', '+', and '.'
- if ( wxIsdigit(keycode) ||
- tolower(keycode) == 'e' ||
- keycode == decimalPoint ||
- keycode == '+' ||
- keycode == '-' )
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-#endif // wxUSE_TEXTCTRL
-
-#if wxUSE_CHECKBOX
-
-// ----------------------------------------------------------------------------
-// wxGridCellBoolEditor
-// ----------------------------------------------------------------------------
-
-// the default values for GetValue()
-wxString wxGridCellBoolEditor::ms_stringValues[2] = { _T(""), _T("1") };
-
-void wxGridCellBoolEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
- m_control = new wxCheckBox(parent, id, wxEmptyString,
- wxDefaultPosition, wxDefaultSize,
- wxNO_BORDER);
-
- wxGridCellEditor::Create(parent, id, evtHandler);
-}
-
-void wxGridCellBoolEditor::SetSize(const wxRect& r)
-{
- bool resize = false;
- wxSize size = m_control->GetSize();
- wxCoord minSize = wxMin(r.width, r.height);
-
- // check if the checkbox is not too big/small for this cell
- wxSize sizeBest = m_control->GetBestSize();
- if ( !(size == sizeBest) )
- {
- // reset to default size if it had been made smaller
- size = sizeBest;
-
- resize = true;
- }
-
- if ( size.x >= minSize || size.y >= minSize )
- {
- // leave 1 pixel margin
- size.x = size.y = minSize - 2;
-
- resize = true;
- }
-
- if ( resize )
- {
- m_control->SetSize(size);
- }
-
- // position it in the centre of the rectangle (TODO: support alignment?)
-
-#if defined(__WXGTK__) || defined (__WXMOTIF__)
- // the checkbox without label still has some space to the right in wxGTK,
- // so shift it to the right
- size.x -= 8;
-#elif defined(__WXMSW__)
- // here too, but in other way
- size.x += 1;
- size.y -= 2;
-#endif
-
- int hAlign = wxALIGN_CENTRE;
- int vAlign = wxALIGN_CENTRE;
- if (GetCellAttr())
- GetCellAttr()->GetAlignment(& hAlign, & vAlign);
-
- int x = 0, y = 0;
- if (hAlign == wxALIGN_LEFT)
- {
- x = r.x + 2;
-
-#ifdef __WXMSW__
- x += 2;
-#endif
-
- y = r.y + r.height / 2 - size.y / 2;
- }
- else if (hAlign == wxALIGN_RIGHT)
- {
- x = r.x + r.width - size.x - 2;
- y = r.y + r.height / 2 - size.y / 2;
- }
- else if (hAlign == wxALIGN_CENTRE)
- {
- x = r.x + r.width / 2 - size.x / 2;
- y = r.y + r.height / 2 - size.y / 2;
- }
-
- m_control->Move(x, y);
-}
-
-void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
-{
- m_control->Show(show);
-
- if ( show )
- {
- wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;
- CBox()->SetBackgroundColour(colBg);
- }
-}
-
-void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- wxASSERT_MSG(m_control,
- wxT("The wxGridCellEditor must be created first!"));
-
- if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))
- {
- m_value = grid->GetTable()->GetValueAsBool(row, col);
- }
- else
- {
- wxString cellval( grid->GetTable()->GetValue(row, col) );
-
- if ( cellval == ms_stringValues[false] )
- m_value = false;
- else if ( cellval == ms_stringValues[true] )
- m_value = true;
- else
- {
- // do not try to be smart here and convert it to true or false
- // because we'll still overwrite it with something different and
- // this risks to be very surprising for the user code, let them
- // know about it
- wxFAIL_MSG( _T("invalid value for a cell with bool editor!") );
- }
- }
-
- CBox()->SetValue(m_value);
- CBox()->SetFocus();
-}
-
-bool wxGridCellBoolEditor::EndEdit(const wxString& WXUNUSED(oldval),
- wxString *newval)
-{
- bool value = CBox()->GetValue();
- if ( value == m_value )
- return false;
-
- m_value = value;
-
- if ( newval )
- *newval = GetValue();
-
- return true;
-}
-
-void wxGridCellBoolEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- wxGridTableBase * const table = grid->GetTable();
- if ( table->CanSetValueAs(row, col, wxGRID_VALUE_BOOL) )
- table->SetValueAsBool(row, col, m_value);
- else
- table->SetValue(row, col, GetValue());
-}
-
-void wxGridCellBoolEditor::Reset()
-{
- wxASSERT_MSG(m_control,
- wxT("The wxGridCellEditor must be created first!"));
-
- CBox()->SetValue(m_value);
-}
-
-void wxGridCellBoolEditor::StartingClick()
-{
- CBox()->SetValue(!CBox()->GetValue());
-}
-
-bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)
-{
- if ( wxGridCellEditor::IsAcceptedKey(event) )
- {
- int keycode = event.GetKeyCode();
- switch ( keycode )
- {
- case WXK_SPACE:
- case '+':
- case '-':
- return true;
- }
- }
-
- return false;
-}
-
-void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event)
-{
- int keycode = event.GetKeyCode();
- switch ( keycode )
- {
- case WXK_SPACE:
- CBox()->SetValue(!CBox()->GetValue());
- break;
-
- case '+':
- CBox()->SetValue(true);
- break;
-
- case '-':
- CBox()->SetValue(false);
- break;
- }
-}
-
-wxString wxGridCellBoolEditor::GetValue() const
-{
- return ms_stringValues[CBox()->GetValue()];
-}
-
-/* static */ void
-wxGridCellBoolEditor::UseStringValues(const wxString& valueTrue,
- const wxString& valueFalse)
-{
- ms_stringValues[false] = valueFalse;
- ms_stringValues[true] = valueTrue;
-}
-
-/* static */ bool
-wxGridCellBoolEditor::IsTrueValue(const wxString& value)
-{
- return value == ms_stringValues[true];
-}
-
-#endif // wxUSE_CHECKBOX
-
-#if wxUSE_COMBOBOX
-
-// ----------------------------------------------------------------------------
-// wxGridCellChoiceEditor
-// ----------------------------------------------------------------------------
-
-wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,
- bool allowOthers)
- : m_choices(choices),
- m_allowOthers(allowOthers) { }
-
-wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
- const wxString choices[],
- bool allowOthers)
- : m_allowOthers(allowOthers)
-{
- if ( count )
- {
- m_choices.Alloc(count);
- for ( size_t n = 0; n < count; n++ )
- {
- m_choices.Add(choices[n]);
- }
- }
-}
-
-wxGridCellEditor *wxGridCellChoiceEditor::Clone() const
-{
- wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;
- editor->m_allowOthers = m_allowOthers;
- editor->m_choices = m_choices;
-
- return editor;
-}
-
-void wxGridCellChoiceEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
- int style = wxTE_PROCESS_ENTER |
- wxTE_PROCESS_TAB |
- wxBORDER_NONE;
-
- if ( !m_allowOthers )
- style |= wxCB_READONLY;
- m_control = new wxComboBox(parent, id, wxEmptyString,
- wxDefaultPosition, wxDefaultSize,
- m_choices,
- style);
-
- wxGridCellEditor::Create(parent, id, evtHandler);
-}
-
-void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,
- wxGridCellAttr * attr)
-{
- // as we fill the entire client area, don't do anything here to minimize
- // flicker
-
- // TODO: It doesn't actually fill the client area since the height of a
- // combo always defaults to the standard. Until someone has time to
- // figure out the right rectangle to paint, just do it the normal way.
- wxGridCellEditor::PaintBackground(rectCell, attr);
-}
-
-void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- wxASSERT_MSG(m_control,
- wxT("The wxGridCellEditor must be created first!"));
-
- wxGridCellEditorEvtHandler* evtHandler = NULL;
- if (m_control)
- evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler);
-
- // Don't immediately end if we get a kill focus event within BeginEdit
- if (evtHandler)
- evtHandler->SetInSetFocus(true);
-
- m_value = grid->GetTable()->GetValue(row, col);
-
- Reset(); // this updates combo box to correspond to m_value
-
- Combo()->SetFocus();
-
- if (evtHandler)
- {
- // When dropping down the menu, a kill focus event
- // happens after this point, so we can't reset the flag yet.
-#if !defined(__WXGTK20__)
- evtHandler->SetInSetFocus(false);
-#endif
- }
-}
-
-bool wxGridCellChoiceEditor::EndEdit(const wxString& WXUNUSED(oldval),
- wxString *newval)
-{
- const wxString value = Combo()->GetValue();
- if ( value == m_value )
- return false;
-
- m_value = value;
-
- if ( newval )
- *newval = value;
-
- return true;
-}
-
-void wxGridCellChoiceEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- grid->GetTable()->SetValue(row, col, m_value);
-}
-
-void wxGridCellChoiceEditor::Reset()
-{
- if (m_allowOthers)
- {
- Combo()->SetValue(m_value);
- Combo()->SetInsertionPointEnd();
- }
- else // the combobox is read-only
- {
- // find the right position, or default to the first if not found
- int pos = Combo()->FindString(m_value);
- if (pos == wxNOT_FOUND)
- pos = 0;
- Combo()->SetSelection(pos);
- }
-}
-
-void wxGridCellChoiceEditor::SetParameters(const wxString& params)
-{
- if ( !params )
- {
- // what can we do?
- return;
- }
-
- m_choices.Empty();
-
- wxStringTokenizer tk(params, _T(','));
- while ( tk.HasMoreTokens() )
- {
- m_choices.Add(tk.GetNextToken());
- }
-}
-
-// return the value in the text control
-wxString wxGridCellChoiceEditor::GetValue() const
-{
- return Combo()->GetValue();
-}
-
-#endif // wxUSE_COMBOBOX
-
-#if wxUSE_COMBOBOX
-
-// ----------------------------------------------------------------------------
-// wxGridCellEnumEditor
-// ----------------------------------------------------------------------------
-
-// A cell editor which displays an enum number as a textual equivalent. eg
-// data in cell is 0,1,2 ... n the cell could be displayed as
-// "John","Fred"..."Bob" in the combo choice box
-
-wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString& choices)
- :wxGridCellChoiceEditor()
-{
- m_index = -1;
-
- if (!choices.empty())
- SetParameters(choices);
-}
-
-wxGridCellEditor *wxGridCellEnumEditor::Clone() const
-{
- wxGridCellEnumEditor *editor = new wxGridCellEnumEditor();
- editor->m_index = m_index;
- return editor;
-}
-
-void wxGridCellEnumEditor::BeginEdit(int row, int col, wxGrid* grid)
-{
- wxASSERT_MSG(m_control,
- wxT("The wxGridCellEnumEditor must be Created first!"));
-
- wxGridTableBase *table = grid->GetTable();
-
- if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
- {
- m_index = table->GetValueAsLong(row, col);
- }
- else
- {
- wxString startValue = table->GetValue(row, col);
- if (startValue.IsNumber() && !startValue.empty())
- {
- startValue.ToLong(&m_index);
- }
- else
- {
- m_index = -1;
- }
- }
-
- Combo()->SetSelection(m_index);
- Combo()->SetInsertionPointEnd();
- Combo()->SetFocus();
-
-}
-
-bool wxGridCellEnumEditor::EndEdit(const wxString& WXUNUSED(oldval),
- wxString *newval)
-{
- long idx = Combo()->GetSelection();
- if ( idx == m_index )
- return false;
-
- m_index = idx;
-
- if ( newval )
- newval->Printf("%ld", m_index);
-
- return true;
-}
-
-void wxGridCellEnumEditor::ApplyEdit(int row, int col, wxGrid* grid)
-{
- wxGridTableBase * const table = grid->GetTable();
- if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )
- table->SetValueAsLong(row, col, m_index);
- else
- table->SetValue(row, col, wxString::Format("%ld", m_index));
-}
-
-#endif // wxUSE_COMBOBOX
-
-// ----------------------------------------------------------------------------
-// wxGridCellAutoWrapStringEditor
-// ----------------------------------------------------------------------------
-
-void
-wxGridCellAutoWrapStringEditor::Create(wxWindow* parent,
- wxWindowID id,
- wxEvtHandler* evtHandler)
-{
- wxGridCellTextEditor::DoCreate(parent, id, evtHandler,
- wxTE_MULTILINE | wxTE_RICH);
-}
-
-
-#endif // wxUSE_GRID
+///////////////////////////////////////////////////////////////////////////\r
+// Name: src/generic/grideditors.cpp\r
+// Purpose: wxGridCellEditorEvtHandler and wxGrid editors\r
+// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)\r
+// Modified by: Robin Dunn, Vadim Zeitlin, Santiago Palacios\r
+// Created: 1/08/1999\r
+// RCS-ID: $Id$\r
+// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)\r
+// Licence: wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+// For compilers that support precompilation, includes "wx/wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+ #pragma hdrstop\r
+#endif\r
+\r
+#if wxUSE_GRID\r
+\r
+#include "wx/grid.h"\r
+\r
+#ifndef WX_PRECOMP\r
+ #include "wx/utils.h"\r
+ #include "wx/dcclient.h"\r
+ #include "wx/settings.h"\r
+ #include "wx/log.h"\r
+ #include "wx/textctrl.h"\r
+ #include "wx/checkbox.h"\r
+ #include "wx/combobox.h"\r
+ #include "wx/valtext.h"\r
+ #include "wx/intl.h"\r
+ #include "wx/math.h"\r
+ #include "wx/listbox.h"\r
+#endif\r
+\r
+#include "wx/textfile.h"\r
+#include "wx/spinctrl.h"\r
+#include "wx/tokenzr.h"\r
+#include "wx/renderer.h"\r
+#include "wx/headerctrl.h"\r
+\r
+#include "wx/generic/gridsel.h"\r
+#include "wx/generic/grideditors.h"\r
+#include "wx/generic/private/grid.h"\r
+\r
+#if defined(__WXMOTIF__)\r
+ #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier)\r
+#else\r
+ #define WXUNUSED_MOTIF(identifier) identifier\r
+#endif\r
+\r
+#if defined(__WXGTK__)\r
+ #define WXUNUSED_GTK(identifier) WXUNUSED(identifier)\r
+#else\r
+ #define WXUNUSED_GTK(identifier) identifier\r
+#endif\r
+\r
+// Required for wxIs... functions\r
+#include <ctype.h>\r
+\r
+// ============================================================================\r
+// implementation\r
+// ============================================================================\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellEditorEvtHandler\r
+// ----------------------------------------------------------------------------\r
+\r
+void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event)\r
+{\r
+ // Don't disable the cell if we're just starting to edit it\r
+ if ( m_inSetFocus )\r
+ {\r
+ event.Skip();\r
+ return;\r
+ }\r
+\r
+ // accept changes\r
+ m_grid->DisableCellEditControl();\r
+\r
+ // notice that we must not skip the event here because the call above may\r
+ // delete the control which received the kill focus event in the first\r
+ // place and if we pretend not having processed the event, the search for a\r
+ // handler for it will continue using the now deleted object resulting in a\r
+ // crash\r
+}\r
+\r
+void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)\r
+{\r
+ switch ( event.GetKeyCode() )\r
+ {\r
+ case WXK_ESCAPE:\r
+ m_editor->Reset();\r
+ m_grid->DisableCellEditControl();\r
+ break;\r
+\r
+ case WXK_TAB:\r
+ m_grid->GetEventHandler()->ProcessEvent( event );\r
+ break;\r
+\r
+ case WXK_RETURN:\r
+ case WXK_NUMPAD_ENTER:\r
+ if (!m_grid->GetEventHandler()->ProcessEvent(event))\r
+ m_editor->HandleReturn(event);\r
+ break;\r
+\r
+ default:\r
+ event.Skip();\r
+ break;\r
+ }\r
+}\r
+\r
+void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)\r
+{\r
+ int row = m_grid->GetGridCursorRow();\r
+ int col = m_grid->GetGridCursorCol();\r
+ wxRect rect = m_grid->CellToRect( row, col );\r
+ int cw, ch;\r
+ m_grid->GetGridWindow()->GetClientSize( &cw, &ch );\r
+\r
+ // if cell width is smaller than grid client area, cell is wholly visible\r
+ bool wholeCellVisible = (rect.GetWidth() < cw);\r
+\r
+ switch ( event.GetKeyCode() )\r
+ {\r
+ case WXK_ESCAPE:\r
+ case WXK_TAB:\r
+ case WXK_RETURN:\r
+ case WXK_NUMPAD_ENTER:\r
+ break;\r
+\r
+ case WXK_HOME:\r
+ {\r
+ if ( wholeCellVisible )\r
+ {\r
+ // no special processing needed...\r
+ event.Skip();\r
+ break;\r
+ }\r
+\r
+ // do special processing for partly visible cell...\r
+\r
+ // get the widths of all cells previous to this one\r
+ int colXPos = 0;\r
+ for ( int i = 0; i < col; i++ )\r
+ {\r
+ colXPos += m_grid->GetColSize(i);\r
+ }\r
+\r
+ int xUnit = 1, yUnit = 1;\r
+ m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);\r
+ if (col != 0)\r
+ {\r
+ m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));\r
+ }\r
+ else\r
+ {\r
+ m_grid->Scroll(colXPos / xUnit, m_grid->GetScrollPos(wxVERTICAL));\r
+ }\r
+ event.Skip();\r
+ break;\r
+ }\r
+\r
+ case WXK_END:\r
+ {\r
+ if ( wholeCellVisible )\r
+ {\r
+ // no special processing needed...\r
+ event.Skip();\r
+ break;\r
+ }\r
+\r
+ // do special processing for partly visible cell...\r
+\r
+ int textWidth = 0;\r
+ wxString value = m_grid->GetCellValue(row, col);\r
+ if ( wxEmptyString != value )\r
+ {\r
+ // get width of cell CONTENTS (text)\r
+ int y;\r
+ wxFont font = m_grid->GetCellFont(row, col);\r
+ m_grid->GetTextExtent(value, &textWidth, &y, NULL, NULL, &font);\r
+\r
+ // try to RIGHT align the text by scrolling\r
+ int client_right = m_grid->GetGridWindow()->GetClientSize().GetWidth();\r
+\r
+ // (m_grid->GetScrollLineX()*2) is a factor for not scrolling to far,\r
+ // otherwise the last part of the cell content might be hidden below the scroll bar\r
+ // FIXME: maybe there is a more suitable correction?\r
+ textWidth -= (client_right - (m_grid->GetScrollLineX() * 2));\r
+ if ( textWidth < 0 )\r
+ {\r
+ textWidth = 0;\r
+ }\r
+ }\r
+\r
+ // get the widths of all cells previous to this one\r
+ int colXPos = 0;\r
+ for ( int i = 0; i < col; i++ )\r
+ {\r
+ colXPos += m_grid->GetColSize(i);\r
+ }\r
+\r
+ // and add the (modified) text width of the cell contents\r
+ // as we'd like to see the last part of the cell contents\r
+ colXPos += textWidth;\r
+\r
+ int xUnit = 1, yUnit = 1;\r
+ m_grid->GetScrollPixelsPerUnit(&xUnit, &yUnit);\r
+ m_grid->Scroll(colXPos / xUnit - 1, m_grid->GetScrollPos(wxVERTICAL));\r
+ event.Skip();\r
+ break;\r
+ }\r
+\r
+ default:\r
+ event.Skip();\r
+ break;\r
+ }\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+wxGridCellEditor::wxGridCellEditor()\r
+{\r
+ m_control = NULL;\r
+ m_attr = NULL;\r
+}\r
+\r
+wxGridCellEditor::~wxGridCellEditor()\r
+{\r
+ Destroy();\r
+}\r
+\r
+void wxGridCellEditor::Create(wxWindow* WXUNUSED(parent),\r
+ wxWindowID WXUNUSED(id),\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ if ( evtHandler )\r
+ m_control->PushEventHandler(evtHandler);\r
+}\r
+\r
+void wxGridCellEditor::PaintBackground(const wxRect& rectCell,\r
+ wxGridCellAttr *attr)\r
+{\r
+ // erase the background because we might not fill the cell\r
+ wxClientDC dc(m_control->GetParent());\r
+ wxGridWindow* gridWindow = wxDynamicCast(m_control->GetParent(), wxGridWindow);\r
+ if (gridWindow)\r
+ gridWindow->GetOwner()->PrepareDC(dc);\r
+\r
+ dc.SetPen(*wxTRANSPARENT_PEN);\r
+ dc.SetBrush(wxBrush(attr->GetBackgroundColour()));\r
+ dc.DrawRectangle(rectCell);\r
+\r
+ // redraw the control we just painted over\r
+ m_control->Refresh();\r
+}\r
+\r
+void wxGridCellEditor::Destroy()\r
+{\r
+ if (m_control)\r
+ {\r
+ m_control->PopEventHandler( true /* delete it*/ );\r
+\r
+ m_control->Destroy();\r
+ m_control = NULL;\r
+ }\r
+}\r
+\r
+void wxGridCellEditor::Show(bool show, wxGridCellAttr *attr)\r
+{\r
+ wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ m_control->Show(show);\r
+\r
+ if ( show )\r
+ {\r
+ // set the colours/fonts if we have any\r
+ if ( attr )\r
+ {\r
+ m_colFgOld = m_control->GetForegroundColour();\r
+ m_control->SetForegroundColour(attr->GetTextColour());\r
+\r
+ m_colBgOld = m_control->GetBackgroundColour();\r
+ m_control->SetBackgroundColour(attr->GetBackgroundColour());\r
+\r
+// Workaround for GTK+1 font setting problem on some platforms\r
+#if !defined(__WXGTK__) || defined(__WXGTK20__)\r
+ m_fontOld = m_control->GetFont();\r
+ m_control->SetFont(attr->GetFont());\r
+#endif\r
+\r
+ // can't do anything more in the base class version, the other\r
+ // attributes may only be used by the derived classes\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // restore the standard colours fonts\r
+ if ( m_colFgOld.Ok() )\r
+ {\r
+ m_control->SetForegroundColour(m_colFgOld);\r
+ m_colFgOld = wxNullColour;\r
+ }\r
+\r
+ if ( m_colBgOld.Ok() )\r
+ {\r
+ m_control->SetBackgroundColour(m_colBgOld);\r
+ m_colBgOld = wxNullColour;\r
+ }\r
+\r
+// Workaround for GTK+1 font setting problem on some platforms\r
+#if !defined(__WXGTK__) || defined(__WXGTK20__)\r
+ if ( m_fontOld.Ok() )\r
+ {\r
+ m_control->SetFont(m_fontOld);\r
+ m_fontOld = wxNullFont;\r
+ }\r
+#endif\r
+ }\r
+}\r
+\r
+void wxGridCellEditor::SetSize(const wxRect& rect)\r
+{\r
+ wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ m_control->SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);\r
+}\r
+\r
+void wxGridCellEditor::HandleReturn(wxKeyEvent& event)\r
+{\r
+ event.Skip();\r
+}\r
+\r
+bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)\r
+{\r
+ bool ctrl = event.ControlDown();\r
+ bool alt = event.AltDown();\r
+\r
+#ifdef __WXMAC__\r
+ // On the Mac the Alt key is more like shift and is used for entry of\r
+ // valid characters, so check for Ctrl and Meta instead.\r
+ alt = event.MetaDown();\r
+#endif\r
+\r
+ // Assume it's not a valid char if ctrl or alt is down, but if both are\r
+ // down then it may be because of an AltGr key combination, so let them\r
+ // through in that case.\r
+ if ((ctrl || alt) && !(ctrl && alt))\r
+ return false;\r
+\r
+#if wxUSE_UNICODE\r
+ // if the unicode key code is not really a unicode character (it may\r
+ // be a function key or etc., the platforms appear to always give us a\r
+ // small value in this case) then fallback to the ASCII key code but\r
+ // don't do anything for function keys or etc.\r
+ if ( event.GetUnicodeKey() > 127 && event.GetKeyCode() > 127 )\r
+ return false;\r
+#else\r
+ if ( event.GetKeyCode() > 255 )\r
+ return false;\r
+#endif\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellEditor::StartingKey(wxKeyEvent& event)\r
+{\r
+ event.Skip();\r
+}\r
+\r
+void wxGridCellEditor::StartingClick()\r
+{\r
+}\r
+\r
+#if wxUSE_TEXTCTRL\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellTextEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+wxGridCellTextEditor::wxGridCellTextEditor()\r
+{\r
+ m_maxChars = 0;\r
+}\r
+\r
+void wxGridCellTextEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ DoCreate(parent, id, evtHandler);\r
+}\r
+\r
+void wxGridCellTextEditor::DoCreate(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler,\r
+ long style)\r
+{\r
+ style |= wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxNO_BORDER;\r
+\r
+ m_control = new wxTextCtrl(parent, id, wxEmptyString,\r
+ wxDefaultPosition, wxDefaultSize,\r
+ style);\r
+\r
+ // set max length allowed in the textctrl, if the parameter was set\r
+ if ( m_maxChars != 0 )\r
+ {\r
+ Text()->SetMaxLength(m_maxChars);\r
+ }\r
+\r
+ wxGridCellEditor::Create(parent, id, evtHandler);\r
+}\r
+\r
+void wxGridCellTextEditor::PaintBackground(const wxRect& WXUNUSED(rectCell),\r
+ wxGridCellAttr * WXUNUSED(attr))\r
+{\r
+ // as we fill the entire client area,\r
+ // don't do anything here to minimize flicker\r
+}\r
+\r
+void wxGridCellTextEditor::SetSize(const wxRect& rectOrig)\r
+{\r
+ wxRect rect(rectOrig);\r
+\r
+ // Make the edit control large enough to allow for internal margins\r
+ //\r
+ // TODO: remove this if the text ctrl sizing is improved esp. for unix\r
+ //\r
+#if defined(__WXGTK__)\r
+ if (rect.x != 0)\r
+ {\r
+ rect.x += 1;\r
+ rect.y += 1;\r
+ rect.width -= 1;\r
+ rect.height -= 1;\r
+ }\r
+#elif defined(__WXMSW__)\r
+ if ( rect.x == 0 )\r
+ rect.x += 2;\r
+ else\r
+ rect.x += 3;\r
+\r
+ if ( rect.y == 0 )\r
+ rect.y += 2;\r
+ else\r
+ rect.y += 3;\r
+\r
+ rect.width -= 2;\r
+ rect.height -= 2;\r
+#else\r
+ int extra_x = ( rect.x > 2 ) ? 2 : 1;\r
+ int extra_y = ( rect.y > 2 ) ? 2 : 1;\r
+\r
+ #if defined(__WXMOTIF__)\r
+ extra_x *= 2;\r
+ extra_y *= 2;\r
+ #endif\r
+\r
+ rect.SetLeft( wxMax(0, rect.x - extra_x) );\r
+ rect.SetTop( wxMax(0, rect.y - extra_y) );\r
+ rect.SetRight( rect.GetRight() + 2 * extra_x );\r
+ rect.SetBottom( rect.GetBottom() + 2 * extra_y );\r
+#endif\r
+\r
+ wxGridCellEditor::SetSize(rect);\r
+}\r
+\r
+void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxASSERT_MSG(m_control, wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ m_value = grid->GetTable()->GetValue(row, col);\r
+\r
+ DoBeginEdit(m_value);\r
+}\r
+\r
+void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)\r
+{\r
+ Text()->SetValue(startValue);\r
+ Text()->SetInsertionPointEnd();\r
+ Text()->SetSelection(-1, -1);\r
+ Text()->SetFocus();\r
+}\r
+\r
+bool wxGridCellTextEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& WXUNUSED(oldval),\r
+ wxString *newval)\r
+{\r
+ wxCHECK_MSG( m_control, false,\r
+ "wxGridCellTextEditor must be created first!" );\r
+\r
+ const wxString value = Text()->GetValue();\r
+ if ( value == m_value )\r
+ return false;\r
+\r
+ m_value = value;\r
+\r
+ if ( newval )\r
+ *newval = m_value;\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellTextEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ grid->GetTable()->SetValue(row, col, m_value);\r
+ m_value.clear();\r
+}\r
+\r
+void wxGridCellTextEditor::Reset()\r
+{\r
+ wxASSERT_MSG( m_control, "wxGridCellTextEditor must be created first!" );\r
+\r
+ DoReset(m_value);\r
+}\r
+\r
+void wxGridCellTextEditor::DoReset(const wxString& startValue)\r
+{\r
+ Text()->SetValue(startValue);\r
+ Text()->SetInsertionPointEnd();\r
+}\r
+\r
+bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)\r
+{\r
+ return wxGridCellEditor::IsAcceptedKey(event);\r
+}\r
+\r
+void wxGridCellTextEditor::StartingKey(wxKeyEvent& event)\r
+{\r
+ // Since this is now happening in the EVT_CHAR event EmulateKeyPress is no\r
+ // longer an appropriate way to get the character into the text control.\r
+ // Do it ourselves instead. We know that if we get this far that we have\r
+ // a valid character, so not a whole lot of testing needs to be done.\r
+\r
+ wxTextCtrl* tc = Text();\r
+ wxChar ch;\r
+ long pos;\r
+\r
+#if wxUSE_UNICODE\r
+ ch = event.GetUnicodeKey();\r
+ if (ch <= 127)\r
+ ch = (wxChar)event.GetKeyCode();\r
+#else\r
+ ch = (wxChar)event.GetKeyCode();\r
+#endif\r
+\r
+ switch (ch)\r
+ {\r
+ case WXK_DELETE:\r
+ // delete the character at the cursor\r
+ pos = tc->GetInsertionPoint();\r
+ if (pos < tc->GetLastPosition())\r
+ tc->Remove(pos, pos + 1);\r
+ break;\r
+\r
+ case WXK_BACK:\r
+ // delete the character before the cursor\r
+ pos = tc->GetInsertionPoint();\r
+ if (pos > 0)\r
+ tc->Remove(pos - 1, pos);\r
+ break;\r
+\r
+ default:\r
+ tc->WriteText(ch);\r
+ break;\r
+ }\r
+}\r
+\r
+void wxGridCellTextEditor::HandleReturn( wxKeyEvent&\r
+ WXUNUSED_GTK(WXUNUSED_MOTIF(event)) )\r
+{\r
+#if defined(__WXMOTIF__) || defined(__WXGTK__)\r
+ // wxMotif needs a little extra help...\r
+ size_t pos = (size_t)( Text()->GetInsertionPoint() );\r
+ wxString s( Text()->GetValue() );\r
+ s = s.Left(pos) + wxT("\n") + s.Mid(pos);\r
+ Text()->SetValue(s);\r
+ Text()->SetInsertionPoint( pos );\r
+#else\r
+ // the other ports can handle a Return key press\r
+ //\r
+ event.Skip();\r
+#endif\r
+}\r
+\r
+void wxGridCellTextEditor::SetParameters(const wxString& params)\r
+{\r
+ if ( !params )\r
+ {\r
+ // reset to default\r
+ m_maxChars = 0;\r
+ }\r
+ else\r
+ {\r
+ long tmp;\r
+ if ( params.ToLong(&tmp) )\r
+ {\r
+ m_maxChars = (size_t)tmp;\r
+ }\r
+ else\r
+ {\r
+ wxLogDebug( _T("Invalid wxGridCellTextEditor parameter string '%s' ignored"), params.c_str() );\r
+ }\r
+ }\r
+}\r
+\r
+// return the value in the text control\r
+wxString wxGridCellTextEditor::GetValue() const\r
+{\r
+ return Text()->GetValue();\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellNumberEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)\r
+{\r
+ m_min = min;\r
+ m_max = max;\r
+}\r
+\r
+void wxGridCellNumberEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+#if wxUSE_SPINCTRL\r
+ if ( HasRange() )\r
+ {\r
+ // create a spin ctrl\r
+ m_control = new wxSpinCtrl(parent, wxID_ANY, wxEmptyString,\r
+ wxDefaultPosition, wxDefaultSize,\r
+ wxSP_ARROW_KEYS,\r
+ m_min, m_max);\r
+\r
+ wxGridCellEditor::Create(parent, id, evtHandler);\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ // just a text control\r
+ wxGridCellTextEditor::Create(parent, id, evtHandler);\r
+\r
+#if wxUSE_VALIDATORS\r
+ Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));\r
+#endif\r
+ }\r
+}\r
+\r
+void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ // first get the value\r
+ wxGridTableBase *table = grid->GetTable();\r
+ if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
+ {\r
+ m_value = table->GetValueAsLong(row, col);\r
+ }\r
+ else\r
+ {\r
+ m_value = 0;\r
+ wxString sValue = table->GetValue(row, col);\r
+ if (! sValue.ToLong(&m_value) && ! sValue.empty())\r
+ {\r
+ wxFAIL_MSG( _T("this cell doesn't have numeric value") );\r
+ return;\r
+ }\r
+ }\r
+\r
+#if wxUSE_SPINCTRL\r
+ if ( HasRange() )\r
+ {\r
+ Spin()->SetValue((int)m_value);\r
+ Spin()->SetFocus();\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ DoBeginEdit(GetString());\r
+ }\r
+}\r
+\r
+bool wxGridCellNumberEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& oldval, wxString *newval)\r
+{\r
+ long value = 0;\r
+ wxString text;\r
+\r
+#if wxUSE_SPINCTRL\r
+ if ( HasRange() )\r
+ {\r
+ value = Spin()->GetValue();\r
+ if ( value == m_value )\r
+ return false;\r
+\r
+ text.Printf(wxT("%ld"), value);\r
+ }\r
+ else // using unconstrained input\r
+#endif // wxUSE_SPINCTRL\r
+ {\r
+ text = Text()->GetValue();\r
+ if ( text.empty() )\r
+ {\r
+ if ( oldval.empty() )\r
+ return false;\r
+ }\r
+ else // non-empty text now (maybe 0)\r
+ {\r
+ if ( !text.ToLong(&value) )\r
+ return false;\r
+\r
+ // if value == m_value == 0 but old text was "" and new one is\r
+ // "0" something still did change\r
+ if ( value == m_value && (value || !oldval.empty()) )\r
+ return false;\r
+ }\r
+ }\r
+\r
+ m_value = value;\r
+\r
+ if ( newval )\r
+ *newval = text;\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellNumberEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxGridTableBase * const table = grid->GetTable();\r
+ if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
+ table->SetValueAsLong(row, col, m_value);\r
+ else\r
+ table->SetValue(row, col, wxString::Format("%ld", m_value));\r
+}\r
+\r
+void wxGridCellNumberEditor::Reset()\r
+{\r
+#if wxUSE_SPINCTRL\r
+ if ( HasRange() )\r
+ {\r
+ Spin()->SetValue((int)m_value);\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ DoReset(GetString());\r
+ }\r
+}\r
+\r
+bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event)\r
+{\r
+ if ( wxGridCellEditor::IsAcceptedKey(event) )\r
+ {\r
+ int keycode = event.GetKeyCode();\r
+ if ( (keycode < 128) &&\r
+ (wxIsdigit(keycode) || keycode == '+' || keycode == '-'))\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)\r
+{\r
+ int keycode = event.GetKeyCode();\r
+ if ( !HasRange() )\r
+ {\r
+ if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-')\r
+ {\r
+ wxGridCellTextEditor::StartingKey(event);\r
+\r
+ // skip Skip() below\r
+ return;\r
+ }\r
+ }\r
+#if wxUSE_SPINCTRL\r
+ else\r
+ {\r
+ if ( wxIsdigit(keycode) )\r
+ {\r
+ wxSpinCtrl* spin = (wxSpinCtrl*)m_control;\r
+ spin->SetValue(keycode - '0');\r
+ spin->SetSelection(1,1);\r
+ return;\r
+ }\r
+ }\r
+#endif\r
+\r
+ event.Skip();\r
+}\r
+\r
+void wxGridCellNumberEditor::SetParameters(const wxString& params)\r
+{\r
+ if ( !params )\r
+ {\r
+ // reset to default\r
+ m_min =\r
+ m_max = -1;\r
+ }\r
+ else\r
+ {\r
+ long tmp;\r
+ if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )\r
+ {\r
+ m_min = (int)tmp;\r
+\r
+ if ( params.AfterFirst(_T(',')).ToLong(&tmp) )\r
+ {\r
+ m_max = (int)tmp;\r
+\r
+ // skip the error message below\r
+ return;\r
+ }\r
+ }\r
+\r
+ wxLogDebug(_T("Invalid wxGridCellNumberEditor parameter string '%s' ignored"), params.c_str());\r
+ }\r
+}\r
+\r
+// return the value in the spin control if it is there (the text control otherwise)\r
+wxString wxGridCellNumberEditor::GetValue() const\r
+{\r
+ wxString s;\r
+\r
+#if wxUSE_SPINCTRL\r
+ if ( HasRange() )\r
+ {\r
+ long value = Spin()->GetValue();\r
+ s.Printf(wxT("%ld"), value);\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ s = Text()->GetValue();\r
+ }\r
+\r
+ return s;\r
+}\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellFloatEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+wxGridCellFloatEditor::wxGridCellFloatEditor(int width, int precision)\r
+{\r
+ m_width = width;\r
+ m_precision = precision;\r
+}\r
+\r
+void wxGridCellFloatEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ wxGridCellTextEditor::Create(parent, id, evtHandler);\r
+\r
+#if wxUSE_VALIDATORS\r
+ Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));\r
+#endif\r
+}\r
+\r
+void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ // first get the value\r
+ wxGridTableBase * const table = grid->GetTable();\r
+ if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )\r
+ {\r
+ m_value = table->GetValueAsDouble(row, col);\r
+ }\r
+ else\r
+ {\r
+ m_value = 0.0;\r
+\r
+ const wxString value = table->GetValue(row, col);\r
+ if ( !value.empty() )\r
+ {\r
+ if ( !value.ToDouble(&m_value) )\r
+ {\r
+ wxFAIL_MSG( _T("this cell doesn't have float value") );\r
+ return;\r
+ }\r
+ }\r
+ }\r
+\r
+ DoBeginEdit(GetString());\r
+}\r
+\r
+bool wxGridCellFloatEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& oldval, wxString *newval)\r
+{\r
+ const wxString text(Text()->GetValue());\r
+\r
+ double value;\r
+ if ( !text.empty() )\r
+ {\r
+ if ( !text.ToDouble(&value) )\r
+ return false;\r
+ }\r
+ else // new value is empty string\r
+ {\r
+ if ( oldval.empty() )\r
+ return false; // nothing changed\r
+\r
+ value = 0.;\r
+ }\r
+\r
+ // the test for empty strings ensures that we don't skip the value setting\r
+ // when "" is replaced by "0" or vice versa as "" numeric value is also 0.\r
+ if ( wxIsSameDouble(value, m_value) && !text.empty() && !oldval.empty() )\r
+ return false; // nothing changed\r
+\r
+ m_value = value;\r
+\r
+ if ( newval )\r
+ *newval = text;\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellFloatEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxGridTableBase * const table = grid->GetTable();\r
+\r
+ if ( table->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT) )\r
+ table->SetValueAsDouble(row, col, m_value);\r
+ else\r
+ table->SetValue(row, col, Text()->GetValue());\r
+}\r
+\r
+void wxGridCellFloatEditor::Reset()\r
+{\r
+ DoReset(GetString());\r
+}\r
+\r
+void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)\r
+{\r
+ int keycode = event.GetKeyCode();\r
+ char tmpbuf[2];\r
+ tmpbuf[0] = (char) keycode;\r
+ tmpbuf[1] = '\0';\r
+ wxString strbuf(tmpbuf, *wxConvCurrent);\r
+\r
+#if wxUSE_INTL\r
+ bool is_decimal_point = ( strbuf ==\r
+ wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) );\r
+#else\r
+ bool is_decimal_point = ( strbuf == _T(".") );\r
+#endif\r
+\r
+ if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'\r
+ || is_decimal_point )\r
+ {\r
+ wxGridCellTextEditor::StartingKey(event);\r
+\r
+ // skip Skip() below\r
+ return;\r
+ }\r
+\r
+ event.Skip();\r
+}\r
+\r
+void wxGridCellFloatEditor::SetParameters(const wxString& params)\r
+{\r
+ if ( !params )\r
+ {\r
+ // reset to default\r
+ m_width =\r
+ m_precision = -1;\r
+ }\r
+ else\r
+ {\r
+ long tmp;\r
+ if ( params.BeforeFirst(_T(',')).ToLong(&tmp) )\r
+ {\r
+ m_width = (int)tmp;\r
+\r
+ if ( params.AfterFirst(_T(',')).ToLong(&tmp) )\r
+ {\r
+ m_precision = (int)tmp;\r
+\r
+ // skip the error message below\r
+ return;\r
+ }\r
+ }\r
+\r
+ wxLogDebug(_T("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str());\r
+ }\r
+}\r
+\r
+wxString wxGridCellFloatEditor::GetString() const\r
+{\r
+ wxString fmt;\r
+ if ( m_precision == -1 && m_width != -1)\r
+ {\r
+ // default precision\r
+ fmt.Printf(_T("%%%d.f"), m_width);\r
+ }\r
+ else if ( m_precision != -1 && m_width == -1)\r
+ {\r
+ // default width\r
+ fmt.Printf(_T("%%.%df"), m_precision);\r
+ }\r
+ else if ( m_precision != -1 && m_width != -1 )\r
+ {\r
+ fmt.Printf(_T("%%%d.%df"), m_width, m_precision);\r
+ }\r
+ else\r
+ {\r
+ // default width/precision\r
+ fmt = _T("%f");\r
+ }\r
+\r
+ return wxString::Format(fmt, m_value);\r
+}\r
+\r
+bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)\r
+{\r
+ if ( wxGridCellEditor::IsAcceptedKey(event) )\r
+ {\r
+ const int keycode = event.GetKeyCode();\r
+ if ( isascii(keycode) )\r
+ {\r
+ char tmpbuf[2];\r
+ tmpbuf[0] = (char) keycode;\r
+ tmpbuf[1] = '\0';\r
+ wxString strbuf(tmpbuf, *wxConvCurrent);\r
+\r
+#if wxUSE_INTL\r
+ const wxString decimalPoint =\r
+ wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);\r
+#else\r
+ const wxString decimalPoint(_T('.'));\r
+#endif\r
+\r
+ // accept digits, 'e' as in '1e+6', also '-', '+', and '.'\r
+ if ( wxIsdigit(keycode) ||\r
+ tolower(keycode) == 'e' ||\r
+ keycode == decimalPoint ||\r
+ keycode == '+' ||\r
+ keycode == '-' )\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+#endif // wxUSE_TEXTCTRL\r
+\r
+#if wxUSE_CHECKBOX\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellBoolEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+// the default values for GetValue()\r
+wxString wxGridCellBoolEditor::ms_stringValues[2] = { _T(""), _T("1") };\r
+\r
+void wxGridCellBoolEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ m_control = new wxCheckBox(parent, id, wxEmptyString,\r
+ wxDefaultPosition, wxDefaultSize,\r
+ wxNO_BORDER);\r
+\r
+ wxGridCellEditor::Create(parent, id, evtHandler);\r
+}\r
+\r
+void wxGridCellBoolEditor::SetSize(const wxRect& r)\r
+{\r
+ bool resize = false;\r
+ wxSize size = m_control->GetSize();\r
+ wxCoord minSize = wxMin(r.width, r.height);\r
+\r
+ // check if the checkbox is not too big/small for this cell\r
+ wxSize sizeBest = m_control->GetBestSize();\r
+ if ( !(size == sizeBest) )\r
+ {\r
+ // reset to default size if it had been made smaller\r
+ size = sizeBest;\r
+\r
+ resize = true;\r
+ }\r
+\r
+ if ( size.x >= minSize || size.y >= minSize )\r
+ {\r
+ // leave 1 pixel margin\r
+ size.x = size.y = minSize - 2;\r
+\r
+ resize = true;\r
+ }\r
+\r
+ if ( resize )\r
+ {\r
+ m_control->SetSize(size);\r
+ }\r
+\r
+ // position it in the centre of the rectangle (TODO: support alignment?)\r
+\r
+#if defined(__WXGTK__) || defined (__WXMOTIF__)\r
+ // the checkbox without label still has some space to the right in wxGTK,\r
+ // so shift it to the right\r
+ size.x -= 8;\r
+#elif defined(__WXMSW__)\r
+ // here too, but in other way\r
+ size.x += 1;\r
+ size.y -= 2;\r
+#endif\r
+\r
+ int hAlign = wxALIGN_CENTRE;\r
+ int vAlign = wxALIGN_CENTRE;\r
+ if (GetCellAttr())\r
+ GetCellAttr()->GetAlignment(& hAlign, & vAlign);\r
+\r
+ int x = 0, y = 0;\r
+ if (hAlign == wxALIGN_LEFT)\r
+ {\r
+ x = r.x + 2;\r
+\r
+#ifdef __WXMSW__\r
+ x += 2;\r
+#endif\r
+\r
+ y = r.y + r.height / 2 - size.y / 2;\r
+ }\r
+ else if (hAlign == wxALIGN_RIGHT)\r
+ {\r
+ x = r.x + r.width - size.x - 2;\r
+ y = r.y + r.height / 2 - size.y / 2;\r
+ }\r
+ else if (hAlign == wxALIGN_CENTRE)\r
+ {\r
+ x = r.x + r.width / 2 - size.x / 2;\r
+ y = r.y + r.height / 2 - size.y / 2;\r
+ }\r
+\r
+ m_control->Move(x, y);\r
+}\r
+\r
+void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)\r
+{\r
+ m_control->Show(show);\r
+\r
+ if ( show )\r
+ {\r
+ wxColour colBg = attr ? attr->GetBackgroundColour() : *wxLIGHT_GREY;\r
+ CBox()->SetBackgroundColour(colBg);\r
+ }\r
+}\r
+\r
+void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxASSERT_MSG(m_control,\r
+ wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL))\r
+ {\r
+ m_value = grid->GetTable()->GetValueAsBool(row, col);\r
+ }\r
+ else\r
+ {\r
+ wxString cellval( grid->GetTable()->GetValue(row, col) );\r
+\r
+ if ( cellval == ms_stringValues[false] )\r
+ m_value = false;\r
+ else if ( cellval == ms_stringValues[true] )\r
+ m_value = true;\r
+ else\r
+ {\r
+ // do not try to be smart here and convert it to true or false\r
+ // because we'll still overwrite it with something different and\r
+ // this risks to be very surprising for the user code, let them\r
+ // know about it\r
+ wxFAIL_MSG( _T("invalid value for a cell with bool editor!") );\r
+ }\r
+ }\r
+\r
+ CBox()->SetValue(m_value);\r
+ CBox()->SetFocus();\r
+}\r
+\r
+bool wxGridCellBoolEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& WXUNUSED(oldval),\r
+ wxString *newval)\r
+{\r
+ bool value = CBox()->GetValue();\r
+ if ( value == m_value )\r
+ return false;\r
+\r
+ m_value = value;\r
+\r
+ if ( newval )\r
+ *newval = GetValue();\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellBoolEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxGridTableBase * const table = grid->GetTable();\r
+ if ( table->CanSetValueAs(row, col, wxGRID_VALUE_BOOL) )\r
+ table->SetValueAsBool(row, col, m_value);\r
+ else\r
+ table->SetValue(row, col, GetValue());\r
+}\r
+\r
+void wxGridCellBoolEditor::Reset()\r
+{\r
+ wxASSERT_MSG(m_control,\r
+ wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ CBox()->SetValue(m_value);\r
+}\r
+\r
+void wxGridCellBoolEditor::StartingClick()\r
+{\r
+ CBox()->SetValue(!CBox()->GetValue());\r
+}\r
+\r
+bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)\r
+{\r
+ if ( wxGridCellEditor::IsAcceptedKey(event) )\r
+ {\r
+ int keycode = event.GetKeyCode();\r
+ switch ( keycode )\r
+ {\r
+ case WXK_SPACE:\r
+ case '+':\r
+ case '-':\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event)\r
+{\r
+ int keycode = event.GetKeyCode();\r
+ switch ( keycode )\r
+ {\r
+ case WXK_SPACE:\r
+ CBox()->SetValue(!CBox()->GetValue());\r
+ break;\r
+\r
+ case '+':\r
+ CBox()->SetValue(true);\r
+ break;\r
+\r
+ case '-':\r
+ CBox()->SetValue(false);\r
+ break;\r
+ }\r
+}\r
+\r
+wxString wxGridCellBoolEditor::GetValue() const\r
+{\r
+ return ms_stringValues[CBox()->GetValue()];\r
+}\r
+\r
+/* static */ void\r
+wxGridCellBoolEditor::UseStringValues(const wxString& valueTrue,\r
+ const wxString& valueFalse)\r
+{\r
+ ms_stringValues[false] = valueFalse;\r
+ ms_stringValues[true] = valueTrue;\r
+}\r
+\r
+/* static */ bool\r
+wxGridCellBoolEditor::IsTrueValue(const wxString& value)\r
+{\r
+ return value == ms_stringValues[true];\r
+}\r
+\r
+#endif // wxUSE_CHECKBOX\r
+\r
+#if wxUSE_COMBOBOX\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellChoiceEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,\r
+ bool allowOthers)\r
+ : m_choices(choices),\r
+ m_allowOthers(allowOthers) { }\r
+\r
+wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,\r
+ const wxString choices[],\r
+ bool allowOthers)\r
+ : m_allowOthers(allowOthers)\r
+{\r
+ if ( count )\r
+ {\r
+ m_choices.Alloc(count);\r
+ for ( size_t n = 0; n < count; n++ )\r
+ {\r
+ m_choices.Add(choices[n]);\r
+ }\r
+ }\r
+}\r
+\r
+wxGridCellEditor *wxGridCellChoiceEditor::Clone() const\r
+{\r
+ wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;\r
+ editor->m_allowOthers = m_allowOthers;\r
+ editor->m_choices = m_choices;\r
+\r
+ return editor;\r
+}\r
+\r
+void wxGridCellChoiceEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ int style = wxTE_PROCESS_ENTER |\r
+ wxTE_PROCESS_TAB |\r
+ wxBORDER_NONE;\r
+\r
+ if ( !m_allowOthers )\r
+ style |= wxCB_READONLY;\r
+ m_control = new wxComboBox(parent, id, wxEmptyString,\r
+ wxDefaultPosition, wxDefaultSize,\r
+ m_choices,\r
+ style);\r
+\r
+ wxGridCellEditor::Create(parent, id, evtHandler);\r
+}\r
+\r
+void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,\r
+ wxGridCellAttr * attr)\r
+{\r
+ // as we fill the entire client area, don't do anything here to minimize\r
+ // flicker\r
+\r
+ // TODO: It doesn't actually fill the client area since the height of a\r
+ // combo always defaults to the standard. Until someone has time to\r
+ // figure out the right rectangle to paint, just do it the normal way.\r
+ wxGridCellEditor::PaintBackground(rectCell, attr);\r
+}\r
+\r
+void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxASSERT_MSG(m_control,\r
+ wxT("The wxGridCellEditor must be created first!"));\r
+\r
+ wxGridCellEditorEvtHandler* evtHandler = NULL;\r
+ if (m_control)\r
+ evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler);\r
+\r
+ // Don't immediately end if we get a kill focus event within BeginEdit\r
+ if (evtHandler)\r
+ evtHandler->SetInSetFocus(true);\r
+\r
+ m_value = grid->GetTable()->GetValue(row, col);\r
+\r
+ Reset(); // this updates combo box to correspond to m_value\r
+\r
+ Combo()->SetFocus();\r
+\r
+ if (evtHandler)\r
+ {\r
+ // When dropping down the menu, a kill focus event\r
+ // happens after this point, so we can't reset the flag yet.\r
+#if !defined(__WXGTK20__)\r
+ evtHandler->SetInSetFocus(false);\r
+#endif\r
+ }\r
+}\r
+\r
+bool wxGridCellChoiceEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& WXUNUSED(oldval),\r
+ wxString *newval)\r
+{\r
+ const wxString value = Combo()->GetValue();\r
+ if ( value == m_value )\r
+ return false;\r
+\r
+ m_value = value;\r
+\r
+ if ( newval )\r
+ *newval = value;\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellChoiceEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ grid->GetTable()->SetValue(row, col, m_value);\r
+}\r
+\r
+void wxGridCellChoiceEditor::Reset()\r
+{\r
+ if (m_allowOthers)\r
+ {\r
+ Combo()->SetValue(m_value);\r
+ Combo()->SetInsertionPointEnd();\r
+ }\r
+ else // the combobox is read-only\r
+ {\r
+ // find the right position, or default to the first if not found\r
+ int pos = Combo()->FindString(m_value);\r
+ if (pos == wxNOT_FOUND)\r
+ pos = 0;\r
+ Combo()->SetSelection(pos);\r
+ }\r
+}\r
+\r
+void wxGridCellChoiceEditor::SetParameters(const wxString& params)\r
+{\r
+ if ( !params )\r
+ {\r
+ // what can we do?\r
+ return;\r
+ }\r
+\r
+ m_choices.Empty();\r
+\r
+ wxStringTokenizer tk(params, _T(','));\r
+ while ( tk.HasMoreTokens() )\r
+ {\r
+ m_choices.Add(tk.GetNextToken());\r
+ }\r
+}\r
+\r
+// return the value in the text control\r
+wxString wxGridCellChoiceEditor::GetValue() const\r
+{\r
+ return Combo()->GetValue();\r
+}\r
+\r
+#endif // wxUSE_COMBOBOX\r
+\r
+#if wxUSE_COMBOBOX\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellEnumEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+// A cell editor which displays an enum number as a textual equivalent. eg\r
+// data in cell is 0,1,2 ... n the cell could be displayed as\r
+// "John","Fred"..."Bob" in the combo choice box\r
+\r
+wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString& choices)\r
+ :wxGridCellChoiceEditor()\r
+{\r
+ m_index = -1;\r
+\r
+ if (!choices.empty())\r
+ SetParameters(choices);\r
+}\r
+\r
+wxGridCellEditor *wxGridCellEnumEditor::Clone() const\r
+{\r
+ wxGridCellEnumEditor *editor = new wxGridCellEnumEditor();\r
+ editor->m_index = m_index;\r
+ return editor;\r
+}\r
+\r
+void wxGridCellEnumEditor::BeginEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxASSERT_MSG(m_control,\r
+ wxT("The wxGridCellEnumEditor must be Created first!"));\r
+\r
+ wxGridTableBase *table = grid->GetTable();\r
+\r
+ if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
+ {\r
+ m_index = table->GetValueAsLong(row, col);\r
+ }\r
+ else\r
+ {\r
+ wxString startValue = table->GetValue(row, col);\r
+ if (startValue.IsNumber() && !startValue.empty())\r
+ {\r
+ startValue.ToLong(&m_index);\r
+ }\r
+ else\r
+ {\r
+ m_index = -1;\r
+ }\r
+ }\r
+\r
+ Combo()->SetSelection(m_index);\r
+ Combo()->SetInsertionPointEnd();\r
+ Combo()->SetFocus();\r
+\r
+}\r
+\r
+bool wxGridCellEnumEditor::EndEdit(int WXUNUSED(row),\r
+ int WXUNUSED(col),\r
+ const wxGrid* WXUNUSED(grid),\r
+ const wxString& WXUNUSED(oldval),\r
+ wxString *newval)\r
+{\r
+ long idx = Combo()->GetSelection();\r
+ if ( idx == m_index )\r
+ return false;\r
+\r
+ m_index = idx;\r
+\r
+ if ( newval )\r
+ newval->Printf("%ld", m_index);\r
+\r
+ return true;\r
+}\r
+\r
+void wxGridCellEnumEditor::ApplyEdit(int row, int col, wxGrid* grid)\r
+{\r
+ wxGridTableBase * const table = grid->GetTable();\r
+ if ( table->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER) )\r
+ table->SetValueAsLong(row, col, m_index);\r
+ else\r
+ table->SetValue(row, col, wxString::Format("%ld", m_index));\r
+}\r
+\r
+#endif // wxUSE_COMBOBOX\r
+\r
+// ----------------------------------------------------------------------------\r
+// wxGridCellAutoWrapStringEditor\r
+// ----------------------------------------------------------------------------\r
+\r
+void\r
+wxGridCellAutoWrapStringEditor::Create(wxWindow* parent,\r
+ wxWindowID id,\r
+ wxEvtHandler* evtHandler)\r
+{\r
+ wxGridCellTextEditor::DoCreate(parent, id, evtHandler,\r
+ wxTE_MULTILINE | wxTE_RICH);\r
+}\r
+\r
+\r
+#endif // wxUSE_GRID\r