#define wxGRID_VALUE_BOOL _T("bool")
#define wxGRID_VALUE_NUMBER _T("long")
#define wxGRID_VALUE_FLOAT _T("double")
+#define wxGRID_VALUE_CHOICE _T("choice")
#define wxGRID_VALUE_TEXT wxGRID_VALUE_STRING
#define wxGRID_VALUE_LONG wxGRID_VALUE_NUMBER
#define wxSafeDecRef(p) if ( p ) (p)->DecRef()
// ----------------------------------------------------------------------------
-// wxGridCellRenderer: this class is responsible for actually drawing the cell
-// in the grid. You may pass it to the wxGridCellAttr (below) to change the
-// format of one given cell or to wxGrid::SetDefaultRenderer() to change the
-// view of all cells. This is an ABC, you will normally use one of the
-// predefined derived classes or derive your own class from it.
+// wxGridCellWorker: common base class for wxGridCellRenderer and
+// wxGridCellEditor
+//
+// NB: this is more an implementation convenience than a design issue, so this
+// class is not documented and is not public at all
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxGridCellRenderer
+class WXDLLEXPORT wxGridCellWorker
{
public:
- wxGridCellRenderer() { m_nRef = 1; }
+ wxGridCellWorker() { m_nRef = 1; }
// this class is ref counted: it is created with ref count of 1, so
// calling DecRef() once will delete it. Calling IncRef() allows to lock
void IncRef() { m_nRef++; }
void DecRef() { if ( !--m_nRef ) delete this; }
+ // interpret renderer parameters: arbitrary string whose interpretatin is
+ // left to the derived classes
+ virtual void SetParameters(const wxString& params);
+
+protected:
+ // virtual dtor for any base class - private because only DecRef() can
+ // delete us
+ virtual ~wxGridCellWorker();
+
+private:
+ size_t m_nRef;
+
+ // suppress the stupid gcc warning about the class having private dtor and
+ // no friends
+ friend class wxGridCellWorkerDummyFriend;
+};
+
+// ----------------------------------------------------------------------------
+// wxGridCellRenderer: this class is responsible for actually drawing the cell
+// in the grid. You may pass it to the wxGridCellAttr (below) to change the
+// format of one given cell or to wxGrid::SetDefaultRenderer() to change the
+// view of all cells. This is an ABC, you will normally use one of the
+// predefined derived classes or derive your own class from it.
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGridCellRenderer : public wxGridCellWorker
+{
+public:
// draw the given cell on the provided DC inside the given rectangle
// using the style specified by the attribute and the default or selected
// state corresponding to the isSelected value.
wxDC& dc,
int row, int col) = 0;
- // interpret renderer parameters: arbitrary string whose interpretatin is
- // left to the derived classes
- virtual void SetParameters(const wxString& params);
-
// create a new object which is the copy of this one
virtual wxGridCellRenderer *Clone() const = 0;
-
-protected:
- // virtual dtor for any base class - private because only DecRef() can
- // delete us
- virtual ~wxGridCellRenderer();
-
-private:
- size_t m_nRef;
-
- // suppress the stupid gcc warning about the class having private dtor and
- // no friends
- friend class wxGridCellRendererDummyFriend;
};
// the default renderer for the cells containing string data
// even for the entire grid.
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxGridCellEditor
+class WXDLLEXPORT wxGridCellEditor : public wxGridCellWorker
{
public:
wxGridCellEditor();
- // this class is ref counted: it is created with ref count of 1, so
- // calling DecRef() once will delete it. Calling IncRef() allows to lock
- // it until the matching DecRef() is called
- void IncRef() { m_nRef++; }
- void DecRef() { if ( !--m_nRef ) delete this; }
-
bool IsCreated() { return m_control != NULL; }
// Creates the actual edit control
// Final cleanup
virtual void Destroy();
+ // create a new object which is the copy of this one
+ virtual wxGridCellEditor *Clone() const = 0;
+
protected:
// the dtor is private because only DecRef() can delete us
virtual ~wxGridCellEditor();
- // the ref count - when it goes to 0, we die
- size_t m_nRef;
-
// the control we show on screen
wxControl* m_control;
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; }
+
protected:
wxTextCtrl *Text() const { return (wxTextCtrl *)m_control; }
void DoReset(const wxString& startValue);
private:
+ size_t m_maxChars; // max number of chars allowed
wxString m_startValue;
};
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); }
+
protected:
wxSpinCtrl *Spin() const { return (wxSpinCtrl *)m_control; }
virtual void Reset();
virtual void StartingKey(wxKeyEvent& event);
+ virtual wxGridCellEditor *Clone() const
+ { return new wxGridCellFloatEditor; }
+
protected:
// string representation of m_valueOld
wxString GetString() const
virtual void Reset();
virtual void StartingClick();
+ virtual wxGridCellEditor *Clone() const
+ { return new wxGridCellBoolEditor; }
+
protected:
wxCheckBox *CBox() const { return (wxCheckBox *)m_control; }
{
public:
// if !allowOthers, user can't type a string not in choices array
- wxGridCellChoiceEditor(size_t count, const wxChar* choices[],
+ wxGridCellChoiceEditor(size_t count = 0,
+ const wxChar* choices[] = NULL,
bool allowOthers = FALSE);
virtual void Create(wxWindow* parent,
virtual void Reset();
+ // parameters string format is "item1[,item2[...,itemN]]"
+ virtual void SetParameters(const wxString& params);
+
+ virtual wxGridCellEditor *Clone() const;
+
protected:
wxComboBox *Combo() const { return (wxComboBox *)m_control; }
#include "wx/textfile.h"
#include "wx/spinctrl.h"
+#include "wx/tokenzr.h"
#include "wx/grid.h"
void RegisterDataType(const wxString& typeName,
wxGridCellRenderer* renderer,
wxGridCellEditor* editor);
+
+ // find one of already registered data types
+ int FindRegisteredDataType(const wxString& typeName);
+
+ // try to FindRegisteredDataType(), if this fails and typeName is one of
+ // standard typenames, register it and return its index
int FindDataType(const wxString& typeName);
+
+ // try to FindDataType(), if it fails see if it is not one of already
+ // registered data types with some params in which case clone the
+ // registered data type and set params for it
+ int FindOrCloneDataType(const wxString& typeName);
+
wxGridCellRenderer* GetRenderer(int index);
wxGridCellEditor* GetEditor(int index);
wxGridCellEditor::wxGridCellEditor()
{
m_control = NULL;
-
- m_nRef = 1;
}
wxGridCellTextEditor::wxGridCellTextEditor()
{
+ m_maxChars = 0;
}
void wxGridCellTextEditor::Create(wxWindow* parent,
#endif
);
+ // TODO: use m_maxChars
+
wxGridCellEditor::Create(parent, id, evtHandler);
}
#endif
}
+void wxGridCellTextEditor::SetParameters(const wxString& params)
+{
+ if ( !params )
+ {
+ // reset to default
+ m_maxChars = 0;
+ }
+ else
+ {
+ long tmp;
+ if ( !params.ToLong(&tmp) )
+ {
+ wxLogDebug(_T("Invalid wxGridCellTextEditor parameter string "
+ "'%s' ignored"), params.c_str());
+ }
+ else
+ {
+ m_maxChars = (size_t)tmp;
+ }
+ }
+}
+
// ----------------------------------------------------------------------------
// wxGridCellNumberEditor
// ----------------------------------------------------------------------------
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());
+ }
+}
+
// ----------------------------------------------------------------------------
// wxGridCellFloatEditor
// ----------------------------------------------------------------------------
bool allowOthers)
: m_allowOthers(allowOthers)
{
- m_choices.Alloc(count);
- for ( size_t n = 0; n < count; n++ )
+ if ( count )
{
- m_choices.Add(choices[n]);
+ 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)
Combo()->SetInsertionPointEnd();
}
+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());
+ }
+}
+
// ----------------------------------------------------------------------------
// wxGridCellEditorEvtHandler
// ----------------------------------------------------------------------------
}
}
+// ----------------------------------------------------------------------------
+// wxGridCellWorker is an (almost) empty common base class for
+// wxGridCellRenderer and wxGridCellEditor managing ref counting
+// ----------------------------------------------------------------------------
+
+void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params))
+{
+ // nothing to do
+}
+
+wxGridCellWorker::~wxGridCellWorker()
+{
+}
+
// ============================================================================
// renderer classes
// ============================================================================
dc.DrawRectangle(rect);
}
-void wxGridCellRenderer::SetParameters(const wxString& WXUNUSED(params))
-{
- // nothing to do
-}
-
-wxGridCellRenderer::~wxGridCellRenderer()
-{
-}
-
// ----------------------------------------------------------------------------
// wxGridCellStringRenderer
// ----------------------------------------------------------------------------
wxGridDataTypeInfo* info = new wxGridDataTypeInfo(typeName, renderer, editor);
// is it already registered?
- int loc = FindDataType(typeName);
+ int loc = FindRegisteredDataType(typeName);
if ( loc != wxNOT_FOUND )
{
delete m_typeinfo[loc];
}
}
+int wxGridTypeRegistry::FindRegisteredDataType(const wxString& typeName)
+{
+ size_t count = m_typeinfo.GetCount();
+ for ( size_t i = 0; i < count; i++ )
+ {
+ if ( typeName == m_typeinfo[i]->m_typeName )
+ {
+ return i;
+ }
+ }
+
+ return wxNOT_FOUND;
+}
+
int wxGridTypeRegistry::FindDataType(const wxString& typeName)
{
- int found = -1;
+ int index = FindRegisteredDataType(typeName);
+ if ( index == wxNOT_FOUND )
+ {
+ // check whether this is one of the standard ones, in which case
+ // register it "on the fly"
+ if ( typeName == wxGRID_VALUE_STRING )
+ {
+ RegisterDataType(wxGRID_VALUE_STRING,
+ new wxGridCellStringRenderer,
+ new wxGridCellTextEditor);
+ }
+ else if ( typeName == wxGRID_VALUE_BOOL )
+ {
+ RegisterDataType(wxGRID_VALUE_BOOL,
+ new wxGridCellBoolRenderer,
+ new wxGridCellBoolEditor);
+ }
+ else if ( typeName == wxGRID_VALUE_NUMBER )
+ {
+ RegisterDataType(wxGRID_VALUE_NUMBER,
+ new wxGridCellNumberRenderer,
+ new wxGridCellNumberEditor);
+ }
+ else if ( typeName == wxGRID_VALUE_FLOAT )
+ {
+ RegisterDataType(wxGRID_VALUE_FLOAT,
+ new wxGridCellFloatRenderer,
+ new wxGridCellFloatEditor);
+ }
+ else if ( typeName == wxGRID_VALUE_CHOICE )
+ {
+ RegisterDataType(wxGRID_VALUE_CHOICE,
+ new wxGridCellStringRenderer,
+ new wxGridCellChoiceEditor);
+ }
+ else
+ {
+ return wxNOT_FOUND;
+ }
- for (size_t i=0; i<m_typeinfo.Count(); i++) {
- if (typeName == m_typeinfo[i]->m_typeName) {
- found = i;
- break;
+ // we get here only if just added the entry for this type, so return
+ // the last index
+ index = m_typeinfo.GetCount() - 1;
+ }
+
+ return index;
+}
+
+int wxGridTypeRegistry::FindOrCloneDataType(const wxString& typeName)
+{
+ int index = FindDataType(typeName);
+ if ( index == wxNOT_FOUND )
+ {
+ // the first part of the typename is the "real" type, anything after ':'
+ // are the parameters for the renderer
+ index = FindDataType(typeName.BeforeFirst(_T(':')));
+ if ( index == wxNOT_FOUND )
+ {
+ return wxNOT_FOUND;
}
+
+ wxGridCellRenderer *renderer = GetRenderer(index);
+ wxGridCellRenderer *rendererOld = renderer;
+ renderer = renderer->Clone();
+ rendererOld->DecRef();
+
+ wxGridCellEditor *editor = GetEditor(index);
+ wxGridCellEditor *editorOld = editor;
+ editor = editor->Clone();
+ editorOld->DecRef();
+
+ // do it even if there are no parameters to reset them to defaults
+ wxString params = typeName.AfterFirst(_T(':'));
+ renderer->SetParameters(params);
+ editor->SetParameters(params);
+
+ // register the new typename
+ renderer->IncRef();
+ editor->IncRef();
+ RegisterDataType(typeName, renderer, editor);
+
+ // we just registered it, it's the last one
+ index = m_typeinfo.GetCount() - 1;
}
- return found;
+ return index;
}
wxGridCellRenderer* wxGridTypeRegistry::GetRenderer(int index)
m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
- // data type registration: register all standard data types
- // TODO: may be allow the app to selectively disable some of them?
+ // create the type registry
m_typeRegistry = new wxGridTypeRegistry;
- RegisterDataType(wxGRID_VALUE_STRING,
- new wxGridCellStringRenderer,
- new wxGridCellTextEditor);
- RegisterDataType(wxGRID_VALUE_BOOL,
- new wxGridCellBoolRenderer,
- new wxGridCellBoolEditor);
- RegisterDataType(wxGRID_VALUE_NUMBER,
- new wxGridCellNumberRenderer,
- new wxGridCellNumberEditor);
- RegisterDataType(wxGRID_VALUE_FLOAT,
- new wxGridCellFloatRenderer,
- new wxGridCellFloatEditor);
// subwindow components that make up the wxGrid
m_cornerLabelWin = new wxGridCornerLabelWindow( this,
wxGridCellEditor*
wxGrid::GetDefaultEditorForType(const wxString& typeName) const
{
- int index = m_typeRegistry->FindDataType(typeName);
+ int index = m_typeRegistry->FindOrCloneDataType(typeName);
if ( index == wxNOT_FOUND )
{
wxFAIL_MSG(wxT("Unknown data type name"));
wxGridCellRenderer*
wxGrid::GetDefaultRendererForType(const wxString& typeName) const
{
- // first try to find an exact match
- wxGridCellRenderer *renderer;
- int index = m_typeRegistry->FindDataType(typeName);
+ int index = m_typeRegistry->FindOrCloneDataType(typeName);
if ( index == wxNOT_FOUND )
{
- // then try to construct a renderer from the base name and parameters
- // following it
-
- // the first part of the typename is the "real" type, anything after ':'
- // are the parameters for the renderer
- index = m_typeRegistry->FindDataType(typeName.BeforeFirst(_T(':')));
- if ( index == wxNOT_FOUND )
- {
- wxFAIL_MSG(wxT("Unknown data type name"));
-
- return NULL;
- }
-
- renderer = m_typeRegistry->GetRenderer(index);
- wxGridCellRenderer *rendererOld = renderer;
- renderer = renderer->Clone();
- rendererOld->DecRef();
-
- // do it even if there are no parameters to reset them to defaults
- renderer->SetParameters(typeName.AfterFirst(_T(':')));
+ wxFAIL_MSG(wxT("Unknown data type name"));
- // register the new typename
- m_typeRegistry->RegisterDataType(typeName, renderer, NULL);
- }
- else
- {
- renderer = m_typeRegistry->GetRenderer(index);
+ return NULL;
}
- return renderer;
+ return m_typeRegistry->GetRenderer(index);
}