]>
Commit | Line | Data |
---|---|---|
e1d3601a PC |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: wx/variantbase.h | |
3 | // Purpose: wxVariantBase class, a minimal version of wxVariant used by XTI | |
4 | // Author: Julian Smart | |
5 | // Modified by: Francesco Montorsi | |
6 | // Created: 10/09/98 | |
e1d3601a PC |
7 | // Copyright: (c) Julian Smart |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_VARIANTBASE_H_ | |
12 | #define _WX_VARIANTBASE_H_ | |
13 | ||
14 | #include "wx/defs.h" | |
15 | ||
16 | #if wxUSE_VARIANT | |
17 | ||
18 | #include "wx/string.h" | |
19 | #include "wx/arrstr.h" | |
20 | #include "wx/cpp.h" | |
21 | #include <typeinfo> | |
22 | ||
23 | #if wxUSE_DATETIME | |
24 | #include "wx/datetime.h" | |
25 | #endif // wxUSE_DATETIME | |
26 | ||
27 | #include "wx/iosfwrap.h" | |
28 | ||
29 | class wxTypeInfo; | |
30 | class wxObject; | |
31 | class wxClassInfo; | |
32 | ||
33 | /* | |
34 | * wxVariantData stores the actual data in a wxVariant object, | |
35 | * to allow it to store any type of data. | |
36 | * Derive from this to provide custom data handling. | |
37 | * | |
38 | * NB: To prevent addition of extra vtbl pointer to wxVariantData, | |
39 | * we don't multiple-inherit from wxObjectRefData. Instead, | |
40 | * we simply replicate the wxObject ref-counting scheme. | |
41 | * | |
42 | * NB: When you construct a wxVariantData, it will have refcount | |
43 | * of one. Refcount will not be further increased when | |
44 | * it is passed to wxVariant. This simulates old common | |
45 | * scenario where wxVariant took ownership of wxVariantData | |
46 | * passed to it. | |
47 | * If you create wxVariantData for other reasons than passing | |
48 | * it to wxVariant, technically you are not required to call | |
49 | * DecRef() before deleting it. | |
50 | * | |
51 | * TODO: in order to replace wxPropertyValue, we would need | |
52 | * to consider adding constructors that take pointers to C++ variables, | |
53 | * or removing that functionality from the wxProperty library. | |
54 | * Essentially wxPropertyValue takes on some of the wxValidator functionality | |
55 | * by storing pointers and not just actual values, allowing update of C++ data | |
56 | * to be handled automatically. Perhaps there's another way of doing this without | |
57 | * overloading wxVariant with unnecessary functionality. | |
58 | */ | |
59 | ||
60 | class WXDLLIMPEXP_BASE wxVariantData | |
61 | { | |
62 | friend class wxVariantBase; | |
63 | ||
64 | public: | |
65 | wxVariantData() | |
66 | : m_count(1) | |
67 | { } | |
68 | ||
69 | #if wxUSE_STD_IOSTREAM | |
70 | virtual bool Write(wxSTD ostream& WXUNUSED(str)) const { return false; } | |
71 | virtual bool Read(wxSTD istream& WXUNUSED(str)) { return false; } | |
72 | #endif | |
73 | virtual bool Write(wxString& WXUNUSED(str)) const { return false; } | |
74 | virtual bool Read(wxString& WXUNUSED(str)) { return false; } | |
75 | ||
76 | // Override these to provide common functionality | |
77 | virtual bool Eq(wxVariantData& data) const = 0; | |
78 | ||
79 | // What type is it? Return a string name. | |
80 | virtual wxString GetType() const = 0; | |
81 | ||
82 | // returns the type info of the content | |
83 | virtual const wxTypeInfo* GetTypeInfo() const = 0; | |
84 | ||
85 | // If it based on wxObject return the ClassInfo. | |
86 | virtual wxClassInfo* GetValueClassInfo() { return NULL; } | |
87 | ||
88 | int GetRefCount() const | |
89 | { return m_count; } | |
90 | void IncRef() | |
91 | { m_count++; } | |
92 | void DecRef() | |
93 | { | |
94 | if ( --m_count == 0 ) | |
95 | delete this; | |
96 | } | |
97 | ||
98 | protected: | |
99 | // Protected dtor should make some incompatible code | |
100 | // break more louder. That is, they should do data->DecRef() | |
101 | // instead of delete data. | |
102 | virtual ~wxVariantData() {} | |
103 | ||
104 | private: | |
105 | int m_count; | |
106 | }; | |
107 | ||
108 | template<typename T> class wxVariantDataT : public wxVariantData | |
109 | { | |
110 | public: | |
111 | wxVariantDataT(const T& d) : m_data(d) {} | |
112 | virtual ~wxVariantDataT() {} | |
113 | ||
114 | // get a ref to the stored data | |
115 | T & Get() { return m_data; } | |
116 | ||
117 | // get a const ref to the stored data | |
118 | const T & Get() const { return m_data; } | |
119 | ||
120 | // set the data | |
121 | void Set(const T& d) { m_data = d; } | |
122 | ||
123 | // Override these to provide common functionality | |
124 | virtual bool Eq(wxVariantData& WXUNUSED(data)) const | |
125 | { return false; /* FIXME!! */ } | |
126 | ||
127 | // What type is it? Return a string name. | |
128 | virtual wxString GetType() const | |
129 | { return GetTypeInfo()->GetTypeName(); } | |
130 | ||
131 | // return a heap allocated duplicate | |
132 | //virtual wxVariantData* Clone() const { return new wxVariantDataT<T>( Get() ); } | |
133 | ||
134 | // returns the type info of the contentc | |
135 | virtual const wxTypeInfo* GetTypeInfo() const { return wxGetTypeInfo( (T*) NULL ); } | |
136 | ||
137 | private: | |
138 | T m_data; | |
139 | }; | |
140 | ||
141 | ||
142 | /* | |
143 | * wxVariantBase can store any kind of data, but has some basic types | |
144 | * built in. | |
145 | */ | |
146 | ||
147 | class WXDLLIMPEXP_BASE wxVariantBase | |
148 | { | |
149 | public: | |
150 | wxVariantBase(); | |
151 | wxVariantBase(const wxVariantBase& variant); | |
152 | wxVariantBase(wxVariantData* data, const wxString& name = wxEmptyString); | |
153 | ||
154 | template<typename T> | |
155 | wxVariantBase(const T& data, const wxString& name = wxEmptyString) : | |
156 | m_data(new wxVariantDataT<T>(data)), m_name(name) {} | |
157 | ||
158 | virtual ~wxVariantBase(); | |
159 | ||
160 | // generic assignment | |
161 | void operator= (const wxVariantBase& variant); | |
162 | ||
163 | // Assignment using data, e.g. | |
164 | // myVariant = new wxStringVariantData("hello"); | |
165 | void operator= (wxVariantData* variantData); | |
166 | ||
167 | bool operator== (const wxVariantBase& variant) const; | |
168 | bool operator!= (const wxVariantBase& variant) const; | |
169 | ||
170 | // Sets/gets name | |
171 | inline void SetName(const wxString& name) { m_name = name; } | |
172 | inline const wxString& GetName() const { return m_name; } | |
173 | ||
174 | // Tests whether there is data | |
175 | bool IsNull() const; | |
176 | ||
177 | // FIXME: used by wxVariantBase code but is nice wording... | |
178 | bool IsEmpty() const { return IsNull(); } | |
179 | ||
180 | // For compatibility with wxWidgets <= 2.6, this doesn't increase | |
181 | // reference count. | |
182 | wxVariantData* GetData() const { return m_data; } | |
183 | void SetData(wxVariantData* data) ; | |
184 | ||
185 | // make a 'clone' of the object | |
186 | void Ref(const wxVariantBase& clone); | |
187 | ||
188 | // destroy a reference | |
189 | void UnRef(); | |
190 | ||
191 | // Make NULL (i.e. delete the data) | |
192 | void MakeNull(); | |
193 | ||
194 | // write contents to a string (e.g. for debugging) | |
195 | wxString MakeString() const; | |
196 | ||
197 | // Delete data and name | |
198 | void Clear(); | |
199 | ||
200 | // Returns a string representing the type of the variant, | |
201 | // e.g. "string", "bool", "stringlist", "list", "double", "long" | |
202 | wxString GetType() const; | |
203 | ||
204 | bool IsType(const wxString& type) const; | |
205 | bool IsValueKindOf(const wxClassInfo* type) const; | |
206 | ||
207 | // FIXME wxXTI methods: | |
208 | ||
209 | // get the typeinfo of the stored object | |
210 | const wxTypeInfo* GetTypeInfo() const | |
211 | { | |
212 | if (!m_data) | |
213 | return NULL; | |
214 | return m_data->GetTypeInfo(); | |
215 | } | |
216 | ||
217 | // get a ref to the stored data | |
218 | template<typename T> T& Get(wxTEMPLATED_MEMBER_FIX(T)) | |
219 | { | |
220 | wxVariantDataT<T> *dataptr = | |
221 | wx_dynamic_cast(wxVariantDataT<T>*, m_data); | |
222 | wxASSERT_MSG( dataptr, | |
223 | wxString::Format(wxT("Cast to %s not possible"), typeid(T).name()) ); | |
224 | return dataptr->Get(); | |
225 | } | |
226 | ||
227 | // get a const ref to the stored data | |
228 | template<typename T> const T& Get(wxTEMPLATED_MEMBER_FIX(T)) const | |
229 | { | |
230 | const wxVariantDataT<T> *dataptr = | |
231 | wx_dynamic_cast(const wxVariantDataT<T>*, m_data); | |
232 | wxASSERT_MSG( dataptr, | |
233 | wxString::Format(wxT("Cast to %s not possible"), typeid(T).name()) ); | |
234 | return dataptr->Get(); | |
235 | } | |
236 | ||
237 | template<typename T> bool HasData(wxTEMPLATED_MEMBER_FIX(T)) const | |
238 | { | |
239 | const wxVariantDataT<T> *dataptr = | |
240 | wx_dynamic_cast(const wxVariantDataT<T>*, m_data); | |
241 | return dataptr != NULL; | |
242 | } | |
243 | ||
244 | // returns this value as string | |
245 | wxString GetAsString() const; | |
246 | ||
247 | // gets the stored data casted to a wxObject*, | |
248 | // returning NULL if cast is not possible | |
249 | wxObject* GetAsObject(); | |
250 | ||
251 | protected: | |
252 | wxVariantData* m_data; | |
253 | wxString m_name; | |
254 | }; | |
255 | ||
256 | #include "wx/dynarray.h" | |
257 | WX_DECLARE_OBJARRAY_WITH_DECL(wxVariantBase, wxVariantBaseArray, class WXDLLIMPEXP_BASE); | |
258 | ||
259 | ||
260 | // templated streaming, every type must have their specialization for these methods | |
261 | ||
262 | template<typename T> | |
263 | void wxStringReadValue( const wxString &s, T &data ); | |
264 | ||
265 | template<typename T> | |
266 | void wxStringWriteValue( wxString &s, const T &data); | |
267 | ||
268 | template<typename T> | |
269 | void wxToStringConverter( const wxVariantBase &v, wxString &s wxTEMPLATED_FUNCTION_FIX(T)) \ | |
270 | { wxStringWriteValue( s, v.wxTEMPLATED_MEMBER_CALL(Get, T) ); } | |
271 | ||
272 | template<typename T> | |
273 | void wxFromStringConverter( const wxString &s, wxVariantBase &v wxTEMPLATED_FUNCTION_FIX(T)) \ | |
274 | { T d; wxStringReadValue( s, d ); v = wxVariantBase(d); } | |
275 | ||
276 | ||
277 | #endif // wxUSE_VARIANT | |
278 | #endif // _WX_VARIANTBASE_H_ |