From f646e8b11ce6477c3d36105970f4fbd9c53a18cf Mon Sep 17 00:00:00 2001 From: Frode Roxrud Gill Date: Sun, 13 Mar 2022 17:05:12 +0100 Subject: [PATCH] Allow cloning client data stored in wxGrid attributes etc Add wxSharedClientDataContainer class storing ref-counted client data and use it instead of plain wxClientDataContainer in wxGridCellAttr, wxGridCellEditor and wxGridCellRenderer classes. This allows to keep the same client data associated with many grid cells without having to make many copies of it. --- include/wx/clntdata.h | 36 +++++++++ include/wx/generic/grid.h | 39 ++++++++-- include/wx/generic/gridctrl.h | 90 ++++++++++++++++++---- include/wx/generic/grideditors.h | 128 +++++++++++++++++++++++-------- interface/wx/clntdata.h | 52 ++++++++++++- interface/wx/grid.h | 6 +- src/common/clntdata.cpp | 29 +++++++ src/generic/grid.cpp | 11 +++ src/generic/gridctrl.cpp | 49 ++++-------- src/generic/grideditors.cpp | 84 ++++++-------------- tests/controls/gridtest.cpp | 15 ++++ 11 files changed, 387 insertions(+), 152 deletions(-) diff --git a/include/wx/clntdata.h b/include/wx/clntdata.h index 0619ff3b6a..a6899cab5b 100644 --- a/include/wx/clntdata.h +++ b/include/wx/clntdata.h @@ -14,6 +14,7 @@ #include "wx/defs.h" #include "wx/string.h" #include "wx/hashmap.h" +#include "wx/sharedptr.h" typedef int (*wxShadowObjectMethod)(void*, void*); WX_DECLARE_STRING_HASH_MAP_WITH_DECL( @@ -158,5 +159,40 @@ protected: }; +// This class is a replacement for wxClientDataContainer, and unlike +// wxClientDataContainer the wxSharedClientDataContainer client data is +// copiable, so it can be copied when objects containing it are cloned. +// Like wxClientDataContainer, wxSharedClientDataContainer is a mixin +// that provides storage and management of "client data.". The client data +// is reference counted and managed by the container. +// +// NOTE: If your class has a clone function and needs to store client data, +// use wxSharedClientDataContainer and not wxClientDataContainer! + +class WXDLLIMPEXP_BASE wxSharedClientDataContainer +{ +public: + // Provide the same functions as in wxClientDataContainer, so that objects + // using it and this class could be used in exactly the same way. + void SetClientObject(wxClientData *data); + wxClientData *GetClientObject() const; + void SetClientData(void *data); + void *GetClientData() const; + +protected: + bool HasClientDataContainer() const { return m_data.get() != NULL; } + wxSharedPtr GetClientDataContainer() const { return m_data; } + void SetClientDataContainer(wxSharedPtr data) { m_data = data; } + +private: + // Helper function that will create m_data if it is currently NULL + wxClientDataContainer *GetValidClientData(); + + // m_data is shared, not deep copied, when cloned. If you make changes to + // the data in one instance of your class, you change it for all cloned + // instances! + wxSharedPtr m_data; +}; + #endif // _WX_CLNTDATAH__ diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 9b821d2237..1473973a46 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -138,11 +138,14 @@ class wxGridDirectionOperations; // class is not documented and is not public at all // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxGridCellWorker : public wxClientDataContainer, public wxRefCounter +class WXDLLIMPEXP_CORE wxGridCellWorker : public wxSharedClientDataContainer, + public wxRefCounter { public: wxGridCellWorker() { } + wxGridCellWorker(const wxGridCellWorker& other); + // interpret renderer parameters: arbitrary string whose interpretation is // left to the derived classes virtual void SetParameters(const wxString& params); @@ -169,6 +172,16 @@ private: class WXDLLIMPEXP_CORE wxGridCellRenderer : public wxGridCellWorker { public: + wxGridCellRenderer() + : wxGridCellWorker() + { + } + + wxGridCellRenderer(const wxGridCellRenderer& other) + : wxGridCellWorker(other) + { + } + // 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. @@ -376,7 +389,14 @@ private: class WXDLLIMPEXP_CORE wxGridCellEditor : public wxGridCellWorker { public: - wxGridCellEditor(); + wxGridCellEditor() + : wxGridCellWorker(), + m_control(NULL), + m_attr(NULL) + { + } + + wxGridCellEditor(const wxGridCellEditor& other); bool IsCreated() const { return m_control != NULL; } @@ -524,8 +544,6 @@ protected: // suppress the stupid gcc warning about the class having private dtor and // no friends friend class wxGridCellEditorDummyFriend; - - wxDECLARE_NO_COPY_CLASS(wxGridCellEditor); }; // Smart pointer to wxGridCellEditor, calling DecRef() on it automatically. @@ -535,6 +553,16 @@ typedef wxObjectDataPtr wxGridCellEditorPtr; class wxGridCellActivatableEditor : public wxGridCellEditor { public: + wxGridCellActivatableEditor() + : wxGridCellEditor() + { + } + + wxGridCellActivatableEditor(const wxGridCellActivatableEditor& other) + : wxGridCellEditor(other) + { + } + // In this class these methods must be overridden. virtual wxGridActivationResult TryActivate(int row, int col, wxGrid* grid, @@ -705,7 +733,8 @@ private: // class may be returned by wxGridTable::GetAttr(). // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxGridCellAttr : public wxClientDataContainer, public wxRefCounter +class WXDLLIMPEXP_CORE wxGridCellAttr : public wxSharedClientDataContainer, + public wxRefCounter { public: enum wxAttrKind diff --git a/include/wx/generic/gridctrl.h b/include/wx/generic/gridctrl.h index 42f67cf383..71112fb94f 100644 --- a/include/wx/generic/gridctrl.h +++ b/include/wx/generic/gridctrl.h @@ -23,6 +23,16 @@ class WXDLLIMPEXP_ADV wxGridCellStringRenderer : public wxGridCellRenderer { public: + wxGridCellStringRenderer() + : wxGridCellRenderer() + { + } + + wxGridCellStringRenderer(const wxGridCellStringRenderer& other) + : wxGridCellRenderer(other) + { + } + // draw the string virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -38,7 +48,7 @@ public: int row, int col) wxOVERRIDE; virtual wxGridCellRenderer *Clone() const wxOVERRIDE - { return new wxGridCellStringRenderer; } + { return new wxGridCellStringRenderer(*this); } protected: // calc the string extent for given string/font @@ -53,11 +63,19 @@ class WXDLLIMPEXP_ADV wxGridCellNumberRenderer : public wxGridCellStringRenderer public: explicit wxGridCellNumberRenderer(long minValue = LONG_MIN, long maxValue = LONG_MAX) - : m_minValue(minValue), + : wxGridCellStringRenderer(), + m_minValue(minValue), m_maxValue(maxValue) { } + wxGridCellNumberRenderer(const wxGridCellNumberRenderer& other) + : wxGridCellStringRenderer(other), + m_minValue(other.m_minValue), + m_maxValue(other.m_maxValue) + { + } + // draw the string right aligned virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -79,7 +97,7 @@ public: virtual void SetParameters(const wxString& params) wxOVERRIDE; virtual wxGridCellRenderer *Clone() const wxOVERRIDE - { return new wxGridCellNumberRenderer(m_minValue, m_maxValue); } + { return new wxGridCellNumberRenderer(*this); } protected: wxString GetString(const wxGrid& grid, int row, int col); @@ -95,6 +113,15 @@ public: int precision = -1, int format = wxGRID_FLOAT_FORMAT_DEFAULT); + wxGridCellFloatRenderer(const wxGridCellFloatRenderer& other) + : wxGridCellStringRenderer(other), + m_width(other.m_width), + m_precision(other.m_precision), + m_style(other.m_style), + m_format(other.m_format) + { + } + // get/change formatting parameters int GetWidth() const { return m_width; } void SetWidth(int width) { m_width = width; m_format.clear(); } @@ -120,7 +147,8 @@ public: // with format being one of f|e|g|E|F|G virtual void SetParameters(const wxString& params) wxOVERRIDE; - virtual wxGridCellRenderer *Clone() const wxOVERRIDE; + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { return new wxGridCellFloatRenderer(*this); } protected: wxString GetString(const wxGrid& grid, int row, int col); @@ -138,6 +166,16 @@ private: class WXDLLIMPEXP_ADV wxGridCellBoolRenderer : public wxGridCellRenderer { public: + wxGridCellBoolRenderer() + : wxGridCellRenderer() + { + } + + wxGridCellBoolRenderer(const wxGridCellBoolRenderer& other) + : wxGridCellRenderer(other) + { + } + // draw a check mark or nothing virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -157,7 +195,7 @@ public: wxDC& dc) wxOVERRIDE; virtual wxGridCellRenderer *Clone() const wxOVERRIDE - { return new wxGridCellBoolRenderer; } + { return new wxGridCellBoolRenderer(*this); } }; @@ -174,7 +212,8 @@ public: explicit wxGridCellDateRenderer(const wxString& outformat = wxString()); wxGridCellDateRenderer(const wxGridCellDateRenderer& other) - : m_oformat(other.m_oformat), + : wxGridCellStringRenderer(other), + m_oformat(other.m_oformat), m_tz(other.m_tz) { } @@ -196,7 +235,8 @@ public: wxGridCellAttr& attr, wxDC& dc) wxOVERRIDE; - virtual wxGridCellRenderer *Clone() const wxOVERRIDE; + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { return new wxGridCellDateRenderer(*this); } // output strptime()-like format string virtual void SetParameters(const wxString& params) wxOVERRIDE; @@ -226,7 +266,8 @@ public: { } - virtual wxGridCellRenderer *Clone() const wxOVERRIDE; + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { return new wxGridCellDateTimeRenderer(*this); } protected: virtual void @@ -242,7 +283,9 @@ protected: class WXDLLIMPEXP_ADV wxGridCellChoiceRenderer : public wxGridCellStringRenderer { public: - wxGridCellChoiceRenderer() { } + wxGridCellChoiceRenderer( const wxString& choices = wxEmptyString ); + + wxGridCellChoiceRenderer(const wxGridCellChoiceRenderer& other); virtual wxSize GetMaxBestSize(wxGrid& grid, wxGridCellAttr& attr, @@ -257,10 +300,6 @@ public: } protected: - wxGridCellChoiceRenderer(const wxGridCellChoiceRenderer& other) - : m_choices(other.m_choices) - { - } wxArrayString m_choices; }; @@ -270,7 +309,15 @@ protected: class WXDLLIMPEXP_ADV wxGridCellEnumRenderer : public wxGridCellChoiceRenderer { public: - wxGridCellEnumRenderer( const wxString& choices = wxEmptyString ); + wxGridCellEnumRenderer( const wxString& choices = wxEmptyString ) + : wxGridCellChoiceRenderer(choices) + { + } + + wxGridCellEnumRenderer(const wxGridCellEnumRenderer& other) + : wxGridCellChoiceRenderer(other) + { + } // draw the string right aligned virtual void Draw(wxGrid& grid, @@ -285,7 +332,8 @@ public: wxDC& dc, int row, int col) wxOVERRIDE; - virtual wxGridCellRenderer *Clone() const wxOVERRIDE; + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { return new wxGridCellEnumRenderer(*this); } protected: wxString GetString(const wxGrid& grid, int row, int col); @@ -295,7 +343,15 @@ protected: class WXDLLIMPEXP_ADV wxGridCellAutoWrapStringRenderer : public wxGridCellStringRenderer { public: - wxGridCellAutoWrapStringRenderer() : wxGridCellStringRenderer() { } + wxGridCellAutoWrapStringRenderer() + : wxGridCellStringRenderer() + { + } + + wxGridCellAutoWrapStringRenderer(const wxGridCellAutoWrapStringRenderer& other) + : wxGridCellStringRenderer(other) + { + } virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, @@ -322,7 +378,7 @@ public: int height) wxOVERRIDE; virtual wxGridCellRenderer *Clone() const wxOVERRIDE - { return new wxGridCellAutoWrapStringRenderer; } + { return new wxGridCellAutoWrapStringRenderer(*this); } private: wxArrayString GetTextLines( wxGrid& grid, diff --git a/include/wx/generic/grideditors.h b/include/wx/generic/grideditors.h index 025c9faff7..86979c1f41 100644 --- a/include/wx/generic/grideditors.h +++ b/include/wx/generic/grideditors.h @@ -55,7 +55,13 @@ private: class WXDLLIMPEXP_ADV wxGridCellTextEditor : public wxGridCellEditor { public: - explicit wxGridCellTextEditor(size_t maxChars = 0); + explicit wxGridCellTextEditor(size_t maxChars = 0) + : wxGridCellEditor(), + m_maxChars(maxChars) + { + } + + wxGridCellTextEditor(const wxGridCellTextEditor& other); virtual void Create(wxWindow* parent, wxWindowID id, @@ -78,7 +84,8 @@ public: virtual void SetValidator(const wxValidator& validator); #endif - virtual wxGridCellEditor *Clone() const wxOVERRIDE; + virtual wxGridCellEditor *Clone() const wxOVERRIDE + { return new wxGridCellTextEditor(*this); } // added GetValue so we can get the value which is in the control virtual wxString GetValue() const wxOVERRIDE; @@ -98,8 +105,6 @@ private: wxScopedPtr m_validator; #endif wxString m_value; - - wxDECLARE_NO_COPY_CLASS(wxGridCellTextEditor); }; // the editor for numeric (long) data @@ -108,7 +113,20 @@ 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); + wxGridCellNumberEditor(int min = -1, int max = -1) + : wxGridCellTextEditor(), + m_min(min), + m_max(max) + { + } + + wxGridCellNumberEditor(const wxGridCellNumberEditor& other) + : wxGridCellTextEditor(other), + m_min(other.m_min), + m_max(other.m_max), + m_value(other.m_value) + { + } virtual void Create(wxWindow* parent, wxWindowID id, @@ -129,7 +147,7 @@ public: virtual void SetParameters(const wxString& params) wxOVERRIDE; virtual wxGridCellEditor *Clone() const wxOVERRIDE - { return new wxGridCellNumberEditor(m_min, m_max); } + { return new wxGridCellNumberEditor(*this); } // added GetValue so we can get the value which is in the control virtual wxString GetValue() const wxOVERRIDE; @@ -158,8 +176,6 @@ private: m_max; long m_value; - - wxDECLARE_NO_COPY_CLASS(wxGridCellNumberEditor); }; @@ -193,7 +209,23 @@ class WXDLLIMPEXP_ADV wxGridCellFloatEditor : public wxGridCellTextEditor public: wxGridCellFloatEditor(int width = -1, int precision = -1, - int format = wxGRID_FLOAT_FORMAT_DEFAULT); + int format = wxGRID_FLOAT_FORMAT_DEFAULT) + : wxGridCellTextEditor(), + m_width(width), + m_precision(precision), + m_style(format) + { + } + + wxGridCellFloatEditor(const wxGridCellFloatEditor& other) + : wxGridCellTextEditor(other), + m_width(other.m_width), + m_precision(other.m_precision), + m_value(other.m_value), + m_style(other.m_style), + m_format(other.m_format) + { + } virtual void Create(wxWindow* parent, wxWindowID id, @@ -209,7 +241,7 @@ public: virtual void StartingKey(wxKeyEvent& event) wxOVERRIDE; virtual wxGridCellEditor *Clone() const wxOVERRIDE - { return new wxGridCellFloatEditor(m_width, m_precision); } + { return new wxGridCellFloatEditor(*this); } // parameters string format is "width[,precision[,format]]" // format to choose between f|e|g|E|G (f is used by default) @@ -226,8 +258,6 @@ private: int m_style; wxString m_format; - - wxDECLARE_NO_COPY_CLASS(wxGridCellFloatEditor); }; #endif // wxUSE_TEXTCTRL @@ -238,7 +268,16 @@ private: class WXDLLIMPEXP_ADV wxGridCellBoolEditor : public wxGridCellEditor { public: - wxGridCellBoolEditor() { } + wxGridCellBoolEditor() + : wxGridCellEditor() + { + } + + wxGridCellBoolEditor(const wxGridCellBoolEditor& other) + : wxGridCellEditor(other), + m_value(other.m_value) + { + } virtual wxGridActivationResult TryActivate(int row, int col, wxGrid* grid, @@ -263,7 +302,7 @@ public: virtual void StartingKey(wxKeyEvent& event) wxOVERRIDE; virtual wxGridCellEditor *Clone() const wxOVERRIDE - { return new wxGridCellBoolEditor; } + { return new wxGridCellBoolEditor(*this); } // added GetValue so we can get the value which is in the control, see // also UseStringValues() @@ -294,8 +333,6 @@ private: bool m_value; static wxString ms_stringValues[2]; - - wxDECLARE_NO_COPY_CLASS(wxGridCellBoolEditor); }; #endif // wxUSE_CHECKBOX @@ -311,7 +348,20 @@ public: const wxString choices[] = NULL, bool allowOthers = false); wxGridCellChoiceEditor(const wxArrayString& choices, - bool allowOthers = false); + bool allowOthers = false) + : wxGridCellEditor(), + m_choices(choices), + m_allowOthers(allowOthers) + { + } + + wxGridCellChoiceEditor(const wxGridCellChoiceEditor& other) + : wxGridCellEditor(other), + m_value(other.m_value), + m_choices(other.m_choices), + m_allowOthers(other.m_allowOthers) + { + } virtual void Create(wxWindow* parent, wxWindowID id, @@ -329,7 +379,8 @@ public: // parameters string format is "item1[,item2[...,itemN]]" virtual void SetParameters(const wxString& params) wxOVERRIDE; - virtual wxGridCellEditor *Clone() const wxOVERRIDE; + virtual wxGridCellEditor *Clone() const wxOVERRIDE + { return new wxGridCellChoiceEditor(*this); } // added GetValue so we can get the value which is in the control virtual wxString GetValue() const wxOVERRIDE; @@ -342,8 +393,6 @@ protected: wxString m_value; wxArrayString m_choices; bool m_allowOthers; - - wxDECLARE_NO_COPY_CLASS(wxGridCellChoiceEditor); }; #endif // wxUSE_COMBOBOX @@ -354,9 +403,17 @@ class WXDLLIMPEXP_ADV wxGridCellEnumEditor : public wxGridCellChoiceEditor { public: wxGridCellEnumEditor( const wxString& choices = wxEmptyString ); + + wxGridCellEnumEditor(const wxGridCellEnumEditor& other) + : wxGridCellChoiceEditor(other), + m_index(other.m_index) + { + } + virtual ~wxGridCellEnumEditor() {} - virtual wxGridCellEditor* Clone() const wxOVERRIDE; + virtual wxGridCellEditor* Clone() const wxOVERRIDE + { return new wxGridCellEnumEditor(*this); } virtual void BeginEdit(int row, int col, wxGrid* grid) wxOVERRIDE; virtual bool EndEdit(int row, int col, const wxGrid* grid, @@ -365,8 +422,6 @@ public: private: long m_index; - - wxDECLARE_NO_COPY_CLASS(wxGridCellEnumEditor); }; #endif // wxUSE_COMBOBOX @@ -374,15 +429,22 @@ private: class WXDLLIMPEXP_ADV wxGridCellAutoWrapStringEditor : public wxGridCellTextEditor { public: - wxGridCellAutoWrapStringEditor() : wxGridCellTextEditor() { } + wxGridCellAutoWrapStringEditor() + : wxGridCellTextEditor() + { + } + + wxGridCellAutoWrapStringEditor(const wxGridCellAutoWrapStringEditor& other) + : wxGridCellTextEditor(other) + { + } + virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) wxOVERRIDE; virtual wxGridCellEditor *Clone() const wxOVERRIDE - { return new wxGridCellAutoWrapStringEditor; } - - wxDECLARE_NO_COPY_CLASS(wxGridCellAutoWrapStringEditor); + { return new wxGridCellAutoWrapStringEditor(*this); } }; #if wxUSE_DATEPICKCTRL @@ -392,6 +454,13 @@ class WXDLLIMPEXP_ADV wxGridCellDateEditor : public wxGridCellEditor public: explicit wxGridCellDateEditor(const wxString& format = wxString()); + wxGridCellDateEditor(const wxGridCellDateEditor& other) + : wxGridCellEditor(other), + m_value(other.m_value), + m_format(other.m_format) + { + } + virtual void SetParameters(const wxString& params) wxOVERRIDE; virtual void Create(wxWindow* parent, @@ -407,7 +476,8 @@ public: virtual void Reset() wxOVERRIDE; - virtual wxGridCellEditor *Clone() const wxOVERRIDE; + virtual wxGridCellEditor *Clone() const wxOVERRIDE + { return new wxGridCellDateEditor(*this); } virtual wxString GetValue() const wxOVERRIDE; @@ -417,8 +487,6 @@ protected: private: wxDateTime m_value; wxString m_format; - - wxDECLARE_NO_COPY_CLASS(wxGridCellDateEditor); }; #endif // wxUSE_DATEPICKCTRL diff --git a/interface/wx/clntdata.h b/interface/wx/clntdata.h index b0df901a9c..cfe7d9a9d1 100644 --- a/interface/wx/clntdata.h +++ b/interface/wx/clntdata.h @@ -21,7 +21,7 @@ @library{wxbase} @category{containers} - @see wxEvtHandler, wxClientData + @see wxSharedClientDataContainer, wxEvtHandler, wxClientData */ class wxClientDataContainer { @@ -59,6 +59,56 @@ public: +/** + @class wxSharedClientDataContainer + + This class is a replacement for @ref wxClientDataContainer, and unlike + wxClientDataContainer the wxSharedClientDataContainer client data is + copiable, so it can be copied when objects containing it are cloned. + Like wxClientDataContainer, wxSharedClientDataContainer is a mixin + that provides storage and management of "client data.". The client data + is reference counted and managed by the container. As the client data + is a shared object, changing the client data used by any object changes + it for all other objects, too. + + @note If your class has a Clone function and needs to store client data, + use wxSharedClientDataContainer and not wxClientDataContainer! + + @library{wxbase} + @category{containers} + + @see wxClientDataContainer, wxClientData + @since 3.1.7 +*/ +class wxSharedClientDataContainer +{ +public: + // Provide the same functions as in wxClientDataContainer, so that objects + // using it and this class could be used in exactly the same way. + + /** + Get the untyped client data. + */ + void* GetClientData() const; + + /** + Get a pointer to the client data object. + */ + wxClientData* GetClientObject() const; + + /** + Set the untyped client data. + */ + void SetClientData(void* data); + + /** + Set the client data object. Any previous object will be deleted. + */ + void SetClientObject(wxClientData* data); +}; + + + /** @class wxClientData diff --git a/interface/wx/grid.h b/interface/wx/grid.h index 604d9494f8..dd3840aaf7 100644 --- a/interface/wx/grid.h +++ b/interface/wx/grid.h @@ -28,7 +28,7 @@ wxGridCellFloatRenderer, wxGridCellNumberRenderer, wxGridCellStringRenderer */ -class wxGridCellRenderer : public wxClientDataContainer, public wxRefCounter +class wxGridCellRenderer : public wxSharedClientDataContainer, public wxRefCounter { public: wxGridCellRenderer(); @@ -571,7 +571,7 @@ public: wxGridCellFloatEditor, wxGridCellNumberEditor, wxGridCellTextEditor, wxGridCellDateEditor */ -class wxGridCellEditor : public wxClientDataContainer, public wxRefCounter +class wxGridCellEditor : public wxSharedClientDataContainer, public wxRefCounter { public: /** @@ -1217,7 +1217,7 @@ public: @library{wxcore} @category{grid} */ -class wxGridCellAttr : public wxClientDataContainer, public wxRefCounter +class wxGridCellAttr : public wxSharedClientDataContainer, public wxRefCounter { public: /** diff --git a/src/common/clntdata.cpp b/src/common/clntdata.cpp index 9a66e116cc..2caad76c70 100644 --- a/src/common/clntdata.cpp +++ b/src/common/clntdata.cpp @@ -72,6 +72,35 @@ void *wxClientDataContainer::DoGetClientData() const } +void wxSharedClientDataContainer::SetClientObject(wxClientData *data) +{ + GetValidClientData()->SetClientObject(data); +} + +wxClientData *wxSharedClientDataContainer::GetClientObject() const +{ + return HasClientDataContainer() ? GetClientDataContainer()->GetClientObject() : NULL; +} + +void wxSharedClientDataContainer::SetClientData(void *data) +{ + GetValidClientData()->SetClientData(data); +} + +void *wxSharedClientDataContainer::GetClientData() const +{ + return HasClientDataContainer() ? GetClientDataContainer()->GetClientData() : NULL; +} + +wxClientDataContainer *wxSharedClientDataContainer::GetValidClientData() +{ + if ( !HasClientDataContainer() ) + { + m_data = new wxClientDataContainer; + } + return m_data.get(); +} + // ---------------------------------------------------------------------------- diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index cf548ab76e..02ad59fd83 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -253,6 +253,11 @@ int wxGridColumnOperations::GetFirstLine(const wxGrid *grid, wxGridWindow *gridW // wxGridCellRenderer and wxGridCellEditor managing ref counting // ---------------------------------------------------------------------------- +wxGridCellWorker::wxGridCellWorker(const wxGridCellWorker& other) +{ + SetClientDataContainer(other.GetClientDataContainer()); +} + void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params)) { // nothing to do @@ -445,6 +450,8 @@ wxGridCellAttr *wxGridCellAttr::Clone() const m_editor->IncRef(); } + attr->SetClientDataContainer(GetClientDataContainer()); + if ( IsReadOnly() ) attr->SetReadOnly(); @@ -485,6 +492,10 @@ void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom) m_editor = mergefrom->m_editor; m_editor->IncRef(); } + if ( !HasClientDataContainer() && mergefrom->HasClientDataContainer() ) + { + SetClientDataContainer(mergefrom->GetClientDataContainer()); + } if ( !HasReadWriteMode() && mergefrom->HasReadWriteMode() ) SetReadOnly(mergefrom->IsReadOnly()); diff --git a/src/generic/gridctrl.cpp b/src/generic/gridctrl.cpp index 4c526f81b5..cac2baf413 100644 --- a/src/generic/gridctrl.cpp +++ b/src/generic/gridctrl.cpp @@ -158,6 +158,7 @@ using namespace wxGridPrivate; // Enables a grid cell to display a formatted date wxGridCellDateRenderer::wxGridCellDateRenderer(const wxString& outformat) + : wxGridCellStringRenderer() { if ( outformat.empty() ) { @@ -170,11 +171,6 @@ wxGridCellDateRenderer::wxGridCellDateRenderer(const wxString& outformat) m_tz = wxDateTime::Local; } -wxGridCellRenderer *wxGridCellDateRenderer::Clone() const -{ - return new wxGridCellDateRenderer(*this); -} - wxString wxGridCellDateRenderer::GetString(const wxGrid& grid, int row, int col) { wxString text; @@ -256,11 +252,6 @@ wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(const wxString& outformat { } -wxGridCellRenderer *wxGridCellDateTimeRenderer::Clone() const -{ - return new wxGridCellDateTimeRenderer(*this); -} - void wxGridCellDateTimeRenderer::GetDateParseParams(DateParseParams& params) const { @@ -273,6 +264,19 @@ wxGridCellDateTimeRenderer::GetDateParseParams(DateParseParams& params) const // wxGridCellChoiceRenderer // ---------------------------------------------------------------------------- +wxGridCellChoiceRenderer::wxGridCellChoiceRenderer(const wxString& choices) + : wxGridCellStringRenderer() +{ + if (!choices.empty()) + SetParameters(choices); +} + +wxGridCellChoiceRenderer::wxGridCellChoiceRenderer(const wxGridCellChoiceRenderer& other) + : wxGridCellStringRenderer(other), + m_choices(other.m_choices) +{ +} + wxSize wxGridCellChoiceRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid), wxGridCellAttr& attr, wxDC& dc) @@ -308,19 +312,6 @@ void wxGridCellChoiceRenderer::SetParameters(const wxString& params) // eg data in cell is 0,1,2 ... n the cell could be rendered as "John","Fred"..."Bob" -wxGridCellEnumRenderer::wxGridCellEnumRenderer(const wxString& choices) -{ - if (!choices.empty()) - SetParameters(choices); -} - -wxGridCellRenderer *wxGridCellEnumRenderer::Clone() const -{ - wxGridCellEnumRenderer *renderer = new wxGridCellEnumRenderer; - renderer->m_choices = m_choices; - return renderer; -} - wxString wxGridCellEnumRenderer::GetString(const wxGrid& grid, int row, int col) { wxGridTableBase *table = grid.GetTable(); @@ -809,23 +800,13 @@ void wxGridCellNumberRenderer::SetParameters(const wxString& params) wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision, int format) + : wxGridCellStringRenderer() { SetWidth(width); SetPrecision(precision); SetFormat(format); } -wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const -{ - wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer; - renderer->m_width = m_width; - renderer->m_precision = m_precision; - renderer->m_style = m_style; - renderer->m_format = m_format; - - return renderer; -} - wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col) { wxGridTableBase *table = grid.GetTable(); diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp index 96832ee9de..e122b44238 100644 --- a/src/generic/grideditors.cpp +++ b/src/generic/grideditors.cpp @@ -228,10 +228,14 @@ void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event) // wxGridCellEditor // ---------------------------------------------------------------------------- -wxGridCellEditor::wxGridCellEditor() +wxGridCellEditor::wxGridCellEditor(const wxGridCellEditor& other) + : wxGridCellWorker(other), + m_control(other.m_control), + m_colFgOld(other.m_colFgOld), + m_colBgOld(other.m_colBgOld), + m_fontOld(other.m_fontOld) { - m_control = NULL; - m_attr = NULL; + m_attr = other.m_attr ? other.m_attr->Clone() : NULL; } wxGridCellEditor::~wxGridCellEditor() @@ -434,9 +438,17 @@ void wxGridCellEditor::StartingClick() // wxGridCellTextEditor // ---------------------------------------------------------------------------- -wxGridCellTextEditor::wxGridCellTextEditor(size_t maxChars) +wxGridCellTextEditor::wxGridCellTextEditor(const wxGridCellTextEditor& other) + : wxGridCellEditor(other), + m_maxChars(other.m_maxChars), + m_value(other.m_value) { - m_maxChars = maxChars; +#if wxUSE_VALIDATORS + if ( other.m_validator ) + { + SetValidator(*other.m_validator); + } +#endif } void wxGridCellTextEditor::Create(wxWindow* parent, @@ -669,18 +681,6 @@ void wxGridCellTextEditor::SetValidator(const wxValidator& validator) } #endif -wxGridCellEditor *wxGridCellTextEditor::Clone() const -{ - wxGridCellTextEditor* editor = new wxGridCellTextEditor(m_maxChars); -#if wxUSE_VALIDATORS - if ( m_validator ) - { - editor->SetValidator(*m_validator); - } -#endif - return editor; -} - // return the value in the text control wxString wxGridCellTextEditor::GetValue() const { @@ -691,12 +691,6 @@ wxString wxGridCellTextEditor::GetValue() const // wxGridCellNumberEditor // ---------------------------------------------------------------------------- -wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max) -{ - m_min = min; - m_max = max; -} - void wxGridCellNumberEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) @@ -964,15 +958,6 @@ wxString wxGridCellNumberEditor::GetValue() const // wxGridCellFloatEditor // ---------------------------------------------------------------------------- -wxGridCellFloatEditor::wxGridCellFloatEditor(int width, - int precision, - int format) -{ - m_width = width; - m_precision = precision; - m_style = format; -} - void wxGridCellFloatEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) @@ -1486,15 +1471,11 @@ void wxGridCellBoolEditor::SetGridFromValue(int row, int col, wxGrid* grid) cons // 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) + : wxGridCellEditor(), + m_allowOthers(allowOthers) { if ( count ) { @@ -1506,15 +1487,6 @@ wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count, } } -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) @@ -1684,21 +1656,13 @@ void wxGridCellChoiceEditor::OnComboCloseUp(wxCommandEvent& WXUNUSED(evt)) // "John","Fred"..."Bob" in the combo choice box wxGridCellEnumEditor::wxGridCellEnumEditor(const wxString& choices) - :wxGridCellChoiceEditor() + : wxGridCellChoiceEditor(), + m_index(-1) { - 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, @@ -1846,6 +1810,7 @@ struct wxGridCellDateEditorKeyHandler #endif // __WXGTK__ wxGridCellDateEditor::wxGridCellDateEditor(const wxString& format) + : wxGridCellEditor() { SetParameters(format); } @@ -1957,11 +1922,6 @@ void wxGridCellDateEditor::Reset() m_value = DatePicker()->GetValue(); } -wxGridCellEditor *wxGridCellDateEditor::Clone() const -{ - return new wxGridCellDateEditor(m_format); -} - wxString wxGridCellDateEditor::GetValue() const { wxASSERT_MSG(m_control, "The wxGridCellDateEditor must be created first!"); diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index 001491eff9..ad2cefd914 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -1729,6 +1729,21 @@ TEST_CASE_METHOD(GridTestCase, "Grid::CellAttribute", "[attr][cell][grid]") CHECK_ATTR_COUNT( 0 ); } + SECTION("Cloning") + { + CHECK_ATTR_COUNT( 0 ); + + m_grid->GetOrCreateCellAttrPtr(0, 0) + ->SetClientObject(new wxStringClientData("test")); + CHECK_ATTR_COUNT( 1 ); + + m_grid->SetAttr(0, 1, m_grid->GetOrCreateCellAttrPtr(0, 0)->Clone()); + CHECK_ATTR_COUNT( 2 ); + + wxClientData* const + data = m_grid->GetOrCreateCellAttrPtr(0, 1)->GetClientObject(); + CHECK( static_cast(data)->GetData() == "test" ); + } // Fill the grid with attributes for next sections.