]> git.saurik.com Git - wxWidgets.git/blob - src/common/any.cpp
Correct bug in the wxSpinCtrlGeneric sub-controls resizing.
[wxWidgets.git] / src / common / any.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/any.cpp
3 // Purpose: wxAny class, container for any type
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: 07/05/2009
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/any.h"
20
21 #if wxUSE_ANY
22
23 #ifndef WX_PRECOMP
24 #include "wx/math.h"
25 #include "wx/crt.h"
26 #endif
27
28 #include "wx/vector.h"
29 #include "wx/module.h"
30 #include "wx/hashmap.h"
31 #include "wx/hashset.h"
32
33 using namespace wxPrivate;
34
35 #if wxUSE_VARIANT
36
37 //-------------------------------------------------------------------------
38 // wxAnyValueTypeGlobals
39 //-------------------------------------------------------------------------
40
41 WX_DECLARE_HASH_MAP(wxAnyValueType*,
42 wxVariantDataFactory,
43 wxPointerHash,
44 wxPointerEqual,
45 wxAnyTypeToVariantDataFactoryMap);
46
47 //
48 // Helper class to manage global variables related to type conversion
49 // between wxAny and wxVariant.
50 //
51 class wxAnyValueTypeGlobals
52 {
53 public:
54 wxAnyValueTypeGlobals()
55 {
56 }
57 ~wxAnyValueTypeGlobals()
58 {
59 m_anyToVariant.clear();
60 }
61
62 void PreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
63 {
64 m_anyToVariantRegs.push_back(reg);
65 }
66
67 // Find wxVariantData factory function for given value type,
68 // (or compatible, if possible)
69 wxVariantDataFactory FindVariantDataFactory(const wxAnyValueType* type_)
70 {
71 // Ideally we'd have the hash map of type 'const wxAnyValueType*',
72 // but WX_DECLARE_HASH_MAP() has some trouble with it.
73 wxAnyValueType* type = const_cast<wxAnyValueType*>(type_);
74
75 wxAnyTypeToVariantDataFactoryMap& anyToVariant = m_anyToVariant;
76 wxAnyTypeToVariantDataFactoryMap::const_iterator it;
77 it = anyToVariant.find(type);
78 if ( it != anyToVariant.end() )
79 return it->second;
80
81 // Not found, handle pre-registrations
82 size_t i = m_anyToVariantRegs.size();
83 while ( i > 0 )
84 {
85 i--;
86 wxAnyToVariantRegistration* reg = m_anyToVariantRegs[i];
87 wxAnyValueType* assocType = reg->GetAssociatedType();
88 if ( assocType )
89 {
90 // Both variant data and wxAnyValueType have been
91 // now been properly initialized, so remove the
92 // pre-registration entry and move data to anyToVarian
93 // map.
94 anyToVariant[assocType] = reg->GetFactory();
95 m_anyToVariantRegs.erase( m_anyToVariantRegs.begin() + i );
96 }
97 }
98
99 // Then try again
100 it = anyToVariant.find(type);
101 if ( it != anyToVariant.end() )
102 return it->second;
103
104 // Finally, attempt to find a compatible type
105 for ( it = anyToVariant.begin(); it != anyToVariant.end(); it++ )
106 {
107 if ( type->IsSameType(it->first) )
108 {
109 wxVariantDataFactory f = it->second;
110 anyToVariant[type] = f;
111 return f;
112 }
113 }
114
115 // Nothing found
116 return NULL;
117 }
118
119 private:
120 wxAnyTypeToVariantDataFactoryMap m_anyToVariant;
121 wxVector<wxAnyToVariantRegistration*> m_anyToVariantRegs;
122 };
123
124 static wxAnyValueTypeGlobals* g_wxAnyValueTypeGlobals = NULL;
125
126
127 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplVariantData)
128
129 void wxPreRegisterAnyToVariant(wxAnyToVariantRegistration* reg)
130 {
131 if ( !g_wxAnyValueTypeGlobals )
132 g_wxAnyValueTypeGlobals = new wxAnyValueTypeGlobals();
133 g_wxAnyValueTypeGlobals->PreRegisterAnyToVariant(reg);
134 }
135
136 bool wxConvertAnyToVariant(const wxAny& any, wxVariant* variant)
137 {
138 if ( any.IsNull() )
139 {
140 variant->MakeNull();
141 return true;
142 }
143
144 // (signed) integer is a special case, because there is only one type
145 // in wxAny, and two ("long" and "longlong") in wxVariant. For better
146 // backwards compatibility, convert all values that fit in "long",
147 // and others to "longlong".
148 if ( wxANY_CHECK_TYPE(any, signed int) )
149 {
150 #ifdef wxLongLong_t
151 wxLongLong_t ll = 0;
152 if ( any.GetAs(&ll) )
153 {
154 // NB: Do not use LONG_MAX here. Explicitly using 32-bit
155 // integer constraint yields more consistent behavior across
156 // builds.
157 if ( ll > wxINT32_MAX || ll < wxINT32_MIN )
158 *variant = wxLongLong(ll);
159 else
160 *variant = (long) wxLongLong(ll).GetLo();
161 }
162 else
163 {
164 return false;
165 }
166 #else
167 long l;
168 if ( any.GetAs(&l) )
169 *variant = l;
170 else
171 return false;
172 #endif
173 return true;
174 }
175
176 // Find matching factory function
177 wxVariantDataFactory f =
178 g_wxAnyValueTypeGlobals->FindVariantDataFactory(any.GetType());
179
180 wxVariantData* data = NULL;
181
182 if ( f )
183 {
184 data = f(any);
185 }
186 else
187 {
188 // Check if wxAny wrapped wxVariantData*
189 if ( !any.GetAs(&data) )
190 {
191 // Ok, one last chance: while unlikely, it is possible that the
192 // wxAny actually contains wxVariant.
193 if ( wxANY_CHECK_TYPE(any, wxVariant) )
194 *variant = wxANY_AS(any, wxVariant);
195 return false;
196 }
197
198 // Wrapper's GetValue() does not increase reference
199 // count, se have to do it before the data gets passed
200 // to a new variant.
201 data->IncRef();
202 }
203
204 variant->SetData(data);
205 return true;
206 }
207
208 //
209 // This class is to make sure that wxAnyValueType instances
210 // etc. get freed correctly. We must use a separate wxAnyValueTypeGlobals
211 // because wxModule itself is instantiated too late.
212 //
213 class wxAnyValueTypeGlobalsManager : public wxModule
214 {
215 DECLARE_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager)
216 public:
217 wxAnyValueTypeGlobalsManager() : wxModule() { }
218 virtual ~wxAnyValueTypeGlobalsManager() { }
219
220 virtual bool OnInit()
221 {
222 return true;
223 }
224 virtual void OnExit()
225 {
226 wxDELETE(g_wxAnyValueTypeGlobals);
227 }
228 private:
229 };
230
231 IMPLEMENT_DYNAMIC_CLASS(wxAnyValueTypeGlobalsManager, wxModule)
232
233 #endif // wxUSE_VARIANT
234
235
236 //-------------------------------------------------------------------------
237 // Dynamic conversion member functions
238 //-------------------------------------------------------------------------
239
240 //
241 // Define integer minimum and maximum as helpers
242 #ifdef wxLongLong_t
243 #define UseIntMin (wxINT64_MIN)
244 #define UseIntMax (wxINT64_MAX)
245 #define UseUintMax (wxUINT64_MAX)
246 #else
247 #define UseIntMin (LONG_MIN)
248 #define UseIntMax (LONG_MAX)
249 #define UseUintMax (ULONG_MAX)
250 #endif
251
252 namespace
253 {
254
255 const double UseIntMinF = static_cast<double>(UseIntMin);
256 const double UseIntMaxF = static_cast<double>(UseIntMax);
257 const double UseUintMaxF = static_cast<double>(UseUintMax);
258
259 } // anonymous namespace
260
261 bool wxAnyValueTypeImplInt::ConvertValue(const wxAnyValueBuffer& src,
262 wxAnyValueType* dstType,
263 wxAnyValueBuffer& dst) const
264 {
265 wxAnyBaseIntType value = GetValue(src);
266 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
267 {
268 #ifdef wxLongLong_t
269 wxLongLong ll(value);
270 wxString s = ll.ToString();
271 #else
272 wxString s = wxString::Format(wxS("%ld"), (long)value);
273 #endif
274 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
275 }
276 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
277 {
278 if ( value < 0 )
279 return false;
280 wxAnyBaseUintType ul = (wxAnyBaseUintType) value;
281 wxAnyValueTypeImplUint::SetValue(ul, dst);
282 }
283 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
284 {
285 double value2 = static_cast<double>(value);
286 wxAnyValueTypeImplDouble::SetValue(value2, dst);
287 }
288 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
289 {
290 bool value2 = value ? true : false;
291 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
292 }
293 else
294 return false;
295
296 return true;
297 }
298
299 bool wxAnyValueTypeImplUint::ConvertValue(const wxAnyValueBuffer& src,
300 wxAnyValueType* dstType,
301 wxAnyValueBuffer& dst) const
302 {
303 wxAnyBaseUintType value = GetValue(src);
304 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
305 {
306 #ifdef wxLongLong_t
307 wxULongLong ull(value);
308 wxString s = ull.ToString();
309 #else
310 wxString s = wxString::Format(wxS("%lu"), (long)value);
311 #endif
312 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
313 }
314 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
315 {
316 if ( value > UseIntMax )
317 return false;
318 wxAnyBaseIntType l = (wxAnyBaseIntType) value;
319 wxAnyValueTypeImplInt::SetValue(l, dst);
320 }
321 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
322 {
323 #ifndef __VISUALC6__
324 double value2 = static_cast<double>(value);
325 #else
326 // VC6 doesn't implement conversion from unsigned __int64 to double
327 wxAnyBaseIntType value0 = static_cast<wxAnyBaseIntType>(value);
328 double value2 = static_cast<double>(value0);
329 #endif
330 wxAnyValueTypeImplDouble::SetValue(value2, dst);
331 }
332 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
333 {
334 bool value2 = value ? true : false;
335 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
336 }
337 else
338 return false;
339
340 return true;
341 }
342
343 // Convert wxString to destination wxAny value type
344 bool wxAnyConvertString(const wxString& value,
345 wxAnyValueType* dstType,
346 wxAnyValueBuffer& dst)
347 {
348 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
349 {
350 wxAnyValueTypeImpl<wxString>::SetValue(value, dst);
351 }
352 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
353 {
354 wxAnyBaseIntType value2;
355 #ifdef wxLongLong_t
356 if ( !value.ToLongLong(&value2) )
357 #else
358 if ( !value.ToLong(&value2) )
359 #endif
360 return false;
361 wxAnyValueTypeImplInt::SetValue(value2, dst);
362 }
363 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
364 {
365 wxAnyBaseUintType value2;
366 #ifdef wxLongLong_t
367 if ( !value.ToULongLong(&value2) )
368 #else
369 if ( !value.ToULong(&value2) )
370 #endif
371 return false;
372 wxAnyValueTypeImplUint::SetValue(value2, dst);
373 }
374 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, double) )
375 {
376 double value2;
377 if ( !value.ToDouble(&value2) )
378 return false;
379 wxAnyValueTypeImplDouble::SetValue(value2, dst);
380 }
381 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, bool) )
382 {
383 bool value2;
384 wxString s(value);
385 s.MakeLower();
386 if ( s == wxS("true") ||
387 s == wxS("yes") ||
388 s == wxS('1') )
389 value2 = true;
390 else if ( s == wxS("false") ||
391 s == wxS("no") ||
392 s == wxS('0') )
393 value2 = false;
394 else
395 return false;
396
397 wxAnyValueTypeImpl<bool>::SetValue(value2, dst);
398 }
399 else
400 return false;
401
402 return true;
403 }
404
405 bool wxAnyValueTypeImpl<bool>::ConvertValue(const wxAnyValueBuffer& src,
406 wxAnyValueType* dstType,
407 wxAnyValueBuffer& dst) const
408 {
409 bool value = GetValue(src);
410 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
411 {
412 wxAnyBaseIntType value2 = static_cast<wxAnyBaseIntType>(value);
413 wxAnyValueTypeImplInt::SetValue(value2, dst);
414 }
415 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
416 {
417 wxAnyBaseIntType value2 = static_cast<wxAnyBaseUintType>(value);
418 wxAnyValueTypeImplUint::SetValue(value2, dst);
419 }
420 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
421 {
422 wxString s;
423 if ( value )
424 s = wxS("true");
425 else
426 s = wxS("false");
427 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
428 }
429 else
430 return false;
431
432 return true;
433 }
434
435 bool wxAnyValueTypeImplDouble::ConvertValue(const wxAnyValueBuffer& src,
436 wxAnyValueType* dstType,
437 wxAnyValueBuffer& dst) const
438 {
439 double value = GetValue(src);
440 if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseIntType) )
441 {
442 if ( value < UseIntMinF || value > UseIntMaxF )
443 return false;
444 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
445 wxAnyValueTypeImplUint::SetValue(ul, dst);
446 }
447 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxAnyBaseUintType) )
448 {
449 if ( value < 0.0 || value > UseUintMaxF )
450 return false;
451 wxAnyBaseUintType ul = static_cast<wxAnyBaseUintType>(value);
452 wxAnyValueTypeImplUint::SetValue(ul, dst);
453 }
454 else if ( wxANY_VALUE_TYPE_CHECK_TYPE(dstType, wxString) )
455 {
456 wxString s = wxString::Format(wxS("%.14g"), value);
457 wxAnyValueTypeImpl<wxString>::SetValue(s, dst);
458 }
459 else
460 return false;
461
462 return true;
463 }
464
465 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplInt)
466 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplUint)
467 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<bool>)
468 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplDouble)
469
470 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplwxString)
471 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstCharPtr)
472 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImplConstWchar_tPtr)
473
474 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxDateTime>)
475 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxObject*>)
476 //WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxArrayString>)
477
478 //-------------------------------------------------------------------------
479 // wxAnyNullValueType implementation
480 //-------------------------------------------------------------------------
481
482 class wxAnyNullValue
483 {
484 private:
485 void* m_dummy;
486 };
487
488 template <>
489 class wxAnyValueTypeImpl<wxAnyNullValue> : public wxAnyValueType
490 {
491 WX_DECLARE_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
492 public:
493 // Dummy implementations
494 virtual void DeleteValue(wxAnyValueBuffer& buf) const
495 {
496 wxUnusedVar(buf);
497 }
498
499 virtual void CopyBuffer(const wxAnyValueBuffer& src,
500 wxAnyValueBuffer& dst) const
501 {
502 wxUnusedVar(src);
503 wxUnusedVar(dst);
504 }
505
506 virtual bool ConvertValue(const wxAnyValueBuffer& src,
507 wxAnyValueType* dstType,
508 wxAnyValueBuffer& dst) const
509 {
510 wxUnusedVar(src);
511 wxUnusedVar(dstType);
512 wxUnusedVar(dst);
513 return false;
514 }
515
516 private:
517 };
518
519 WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<wxAnyNullValue>)
520
521 wxAnyValueType* wxAnyNullValueType =
522 wxAnyValueTypeImpl<wxAnyNullValue>::GetInstance();
523
524 #endif // wxUSE_ANY