/src/wxwidgets/include/wx/clntdata.h
Line | Count | Source |
1 | | ///////////////////////////////////////////////////////////////////////////// |
2 | | // Name: wx/clntdata.h |
3 | | // Purpose: A mixin class for holding a wxClientData or void pointer |
4 | | // Author: Robin Dunn |
5 | | // Created: 9-Oct-2001 |
6 | | // Copyright: (c) wxWidgets team |
7 | | // Licence: wxWindows licence |
8 | | ///////////////////////////////////////////////////////////////////////////// |
9 | | |
10 | | #ifndef _WX_CLNTDATAH__ |
11 | | #define _WX_CLNTDATAH__ |
12 | | |
13 | | #include "wx/defs.h" |
14 | | #include "wx/string.h" |
15 | | #include "wx/object.h" |
16 | | |
17 | | #include <unordered_map> |
18 | | |
19 | | typedef int (*wxShadowObjectMethod)(void*, void*); |
20 | | |
21 | | using wxShadowObjectMethods = std::unordered_map<wxString, wxShadowObjectMethod>; |
22 | | using wxShadowObjectFields = std::unordered_map<wxString, void*>; |
23 | | |
24 | | class WXDLLIMPEXP_BASE wxShadowObject |
25 | | { |
26 | | public: |
27 | | wxShadowObject() = default; |
28 | | |
29 | | void AddMethod( const wxString &name, wxShadowObjectMethod method ) |
30 | 0 | { |
31 | 0 | const auto it = m_methods.find( name ); |
32 | 0 | if (it == m_methods.end()) |
33 | 0 | m_methods[ name ] = method; |
34 | 0 | else |
35 | 0 | it->second = method; |
36 | 0 | } |
37 | | |
38 | | bool InvokeMethod( const wxString &name, void* window, void* param, int* returnValue ) |
39 | 0 | { |
40 | 0 | const auto it = m_methods.find( name ); |
41 | 0 | if (it == m_methods.end()) |
42 | 0 | return false; |
43 | 0 | wxShadowObjectMethod method = it->second; |
44 | 0 | const int ret = (*method)(window, param); |
45 | 0 | if (returnValue) |
46 | 0 | *returnValue = ret; |
47 | 0 | return true; |
48 | 0 | } |
49 | | |
50 | | void AddField( const wxString &name, void* initialValue = nullptr ) |
51 | 0 | { |
52 | 0 | const auto it = m_fields.find( name ); |
53 | 0 | if (it == m_fields.end()) |
54 | 0 | m_fields[ name ] = initialValue; |
55 | 0 | else |
56 | 0 | it->second = initialValue; |
57 | 0 | } |
58 | | |
59 | | void SetField( const wxString &name, void* value ) |
60 | 0 | { |
61 | 0 | const auto it = m_fields.find( name ); |
62 | 0 | if (it == m_fields.end()) |
63 | 0 | return; |
64 | 0 | it->second = value; |
65 | 0 | } |
66 | | |
67 | | void* GetField( const wxString &name, void *defaultValue = nullptr ) |
68 | 0 | { |
69 | 0 | const auto it = m_fields.find( name ); |
70 | 0 | if (it == m_fields.end()) |
71 | 0 | return defaultValue; |
72 | 0 | return it->second; |
73 | 0 | } |
74 | | |
75 | | private: |
76 | | wxShadowObjectMethods m_methods; |
77 | | wxShadowObjectFields m_fields; |
78 | | }; |
79 | | |
80 | | |
81 | | // ---------------------------------------------------------------------------- |
82 | | |
83 | | // what kind of client data do we have? |
84 | | enum wxClientDataType |
85 | | { |
86 | | wxClientData_None, // we don't know yet because we don't have it at all |
87 | | wxClientData_Object, // our client data is typed and we own it |
88 | | wxClientData_Void // client data is untyped and we don't own it |
89 | | }; |
90 | | |
91 | | class WXDLLIMPEXP_BASE wxClientData |
92 | | { |
93 | | public: |
94 | | wxClientData() = default; |
95 | | virtual ~wxClientData() = default; |
96 | | }; |
97 | | |
98 | | class WXDLLIMPEXP_BASE wxStringClientData : public wxClientData |
99 | | { |
100 | | public: |
101 | 0 | wxStringClientData() : m_data() { } |
102 | 0 | wxStringClientData( const wxString &data ) : m_data(data) { } |
103 | 0 | void SetData( const wxString &data ) { m_data = data; } |
104 | 0 | const wxString& GetData() const { return m_data; } |
105 | | |
106 | | private: |
107 | | wxString m_data; |
108 | | }; |
109 | | |
110 | | // This class is a mixin that provides storage and management of "client |
111 | | // data." The client data stored can either be a pointer to a wxClientData |
112 | | // object in which case it is managed by the container (i.e. it will delete |
113 | | // the data when it's destroyed) or an untyped pointer which won't be deleted |
114 | | // by the container - but not both of them |
115 | | // |
116 | | // NOTE: This functionality is currently duplicated in wxEvtHandler in order |
117 | | // to avoid having more than one vtable in that class hierarchy. |
118 | | |
119 | | class WXDLLIMPEXP_BASE wxClientDataContainer |
120 | | { |
121 | | public: |
122 | | wxClientDataContainer(); |
123 | | virtual ~wxClientDataContainer(); |
124 | | |
125 | 0 | void SetClientObject( wxClientData *data ) { DoSetClientObject(data); } |
126 | 0 | wxClientData *GetClientObject() const { return DoGetClientObject(); } |
127 | | |
128 | 0 | void SetClientData( void *data ) { DoSetClientData(data); } |
129 | 0 | void *GetClientData() const { return DoGetClientData(); } |
130 | | |
131 | | protected: |
132 | | // The user data: either an object which will be deleted by the container |
133 | | // when it's deleted or some raw pointer which we do nothing with. Only |
134 | | // one type of data can be used with the given window, i.e. you cannot set |
135 | | // the void data and then associate the container with wxClientData or vice |
136 | | // versa. |
137 | | union |
138 | | { |
139 | | wxClientData *m_clientObject; |
140 | | void *m_clientData; |
141 | | }; |
142 | | |
143 | | // client data accessors |
144 | | virtual void DoSetClientObject( wxClientData *data ); |
145 | | virtual wxClientData *DoGetClientObject() const; |
146 | | |
147 | | virtual void DoSetClientData( void *data ); |
148 | | virtual void *DoGetClientData() const; |
149 | | |
150 | | // what kind of data do we have? |
151 | | wxClientDataType m_clientDataType; |
152 | | |
153 | | }; |
154 | | |
155 | | // This class is a replacement for wxClientDataContainer, and unlike |
156 | | // wxClientDataContainer the wxSharedClientDataContainer client data is |
157 | | // copiable, so it can be copied when objects containing it are cloned. |
158 | | // Like wxClientDataContainer, wxSharedClientDataContainer is a mixin |
159 | | // that provides storage and management of "client data.". The client data |
160 | | // is reference counted and managed by the container. |
161 | | // |
162 | | // NOTE: If your class has a clone function and needs to store client data, |
163 | | // use wxSharedClientDataContainer and not wxClientDataContainer! |
164 | | |
165 | | class WXDLLIMPEXP_BASE wxSharedClientDataContainer |
166 | | { |
167 | | public: |
168 | | // Provide the same functions as in wxClientDataContainer, so that objects |
169 | | // using it and this class could be used in exactly the same way. |
170 | | void SetClientObject(wxClientData *data); |
171 | | wxClientData *GetClientObject() const; |
172 | | void SetClientData(void *data); |
173 | | void *GetClientData() const; |
174 | | |
175 | | protected: |
176 | 0 | bool HasClientDataContainer() const { return m_data.get() != nullptr; } |
177 | | void CopyClientDataContainer(const wxSharedClientDataContainer& other) |
178 | 0 | { |
179 | 0 | m_data = other.m_data; |
180 | 0 | } |
181 | | |
182 | | private: |
183 | | class wxRefCountedClientDataContainer : public wxClientDataContainer, |
184 | | public wxRefCounter |
185 | | { |
186 | | }; |
187 | | |
188 | | // Helper function that will create m_data if it is currently null |
189 | | wxClientDataContainer *GetValidClientData(); |
190 | | |
191 | | // m_data is shared, not deep copied, when cloned. If you make changes to |
192 | | // the data in one instance of your class, you change it for all cloned |
193 | | // instances! |
194 | | wxObjectDataPtr<wxRefCountedClientDataContainer> m_data; |
195 | | }; |
196 | | |
197 | | #endif // _WX_CLNTDATAH__ |
198 | | |