1 ///////////////////////////////////////////////////////////////////////////// 2 // Name: wx/clntdata.h 3 // Purpose: A mixin class for holding a wxClientData or void pointer 4 // Author: Robin Dunn 5 // Modified by: 6 // Created: 9-Oct-2001 7 // RCS-ID: $Id: clntdata.h 36973 2006-01-18 16:45:41Z JS $ 8 // Copyright: (c) wxWidgets team 9 // Licence: wxWindows licence 10 ///////////////////////////////////////////////////////////////////////////// 11 12 #ifndef _WX_CLNTDATAH__ 13 #define _WX_CLNTDATAH__ 14 15 #include "wx/defs.h" 16 #include "wx/string.h" 17 #include "wx/hashmap.h" 18 19 typedef int (*wxShadowObjectMethod)(void*, void*); 20 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( 21 wxShadowObjectMethod, 22 wxShadowObjectMethods, 23 class WXDLLIMPEXP_BASE 24 ); 25 WX_DECLARE_STRING_HASH_MAP_WITH_DECL( 26 void *, 27 wxShadowObjectFields, 28 class WXDLLIMPEXP_BASE 29 ); 30 31 class WXDLLIMPEXP_BASE wxShadowObject 32 { 33 public: wxShadowObject()34 wxShadowObject() { } 35 AddMethod(const wxString & name,wxShadowObjectMethod method)36 void AddMethod( const wxString &name, wxShadowObjectMethod method ) 37 { 38 wxShadowObjectMethods::iterator it = m_methods.find( name ); 39 if (it == m_methods.end()) 40 m_methods[ name ] = method; 41 else 42 it->second = method; 43 } 44 InvokeMethod(const wxString & name,void * window,void * param,int * returnValue)45 bool InvokeMethod( const wxString &name, void* window, void* param, int* returnValue ) 46 { 47 wxShadowObjectMethods::iterator it = m_methods.find( name ); 48 if (it == m_methods.end()) 49 return false; 50 wxShadowObjectMethod method = it->second; 51 int ret = (*method)(window, param); 52 if (returnValue) 53 *returnValue = ret; 54 return true; 55 } 56 57 void AddField( const wxString &name, void* initialValue = NULL ) 58 { 59 wxShadowObjectFields::iterator it = m_fields.find( name ); 60 if (it == m_fields.end()) 61 m_fields[ name ] = initialValue; 62 else 63 it->second = initialValue; 64 } 65 SetField(const wxString & name,void * value)66 void SetField( const wxString &name, void* value ) 67 { 68 wxShadowObjectFields::iterator it = m_fields.find( name ); 69 if (it == m_fields.end()) 70 return; 71 it->second = value; 72 } 73 74 void* GetField( const wxString &name, void *defaultValue = NULL ) 75 { 76 wxShadowObjectFields::iterator it = m_fields.find( name ); 77 if (it == m_fields.end()) 78 return defaultValue; 79 return it->second; 80 } 81 82 private: 83 wxShadowObjectMethods m_methods; 84 wxShadowObjectFields m_fields; 85 }; 86 87 88 // ---------------------------------------------------------------------------- 89 90 // what kind of client data do we have? 91 enum wxClientDataType 92 { 93 wxClientData_None, // we don't know yet because we don't have it at all 94 wxClientData_Object, // our client data is typed and we own it 95 wxClientData_Void // client data is untyped and we don't own it 96 }; 97 98 class WXDLLIMPEXP_BASE wxClientData 99 { 100 public: wxClientData()101 wxClientData() { } ~wxClientData()102 virtual ~wxClientData() { } 103 }; 104 105 class WXDLLIMPEXP_BASE wxStringClientData : public wxClientData 106 { 107 public: wxStringClientData()108 wxStringClientData() : m_data() { } wxStringClientData(const wxString & data)109 wxStringClientData( const wxString &data ) : m_data(data) { } SetData(const wxString & data)110 void SetData( const wxString &data ) { m_data = data; } GetData()111 const wxString& GetData() const { return m_data; } 112 113 private: 114 wxString m_data; 115 }; 116 117 // This class is a mixin that provides storage and management of "client 118 // data." The client data stored can either be a pointer to a wxClientData 119 // object in which case it is managed by the container (i.e. it will delete 120 // the data when it's destroyed) or an untyped pointer which won't be deleted 121 // by the container - but not both of them 122 // 123 // NOTE: This functionality is currently duplicated in wxEvtHandler in order 124 // to avoid having more than one vtable in that class hierarchy. 125 126 class WXDLLIMPEXP_BASE wxClientDataContainer 127 { 128 public: 129 wxClientDataContainer(); 130 virtual ~wxClientDataContainer(); 131 SetClientObject(wxClientData * data)132 void SetClientObject( wxClientData *data ) { DoSetClientObject(data); } GetClientObject()133 wxClientData *GetClientObject() const { return DoGetClientObject(); } 134 SetClientData(void * data)135 void SetClientData( void *data ) { DoSetClientData(data); } GetClientData()136 void *GetClientData() const { return DoGetClientData(); } 137 138 protected: 139 // The user data: either an object which will be deleted by the container 140 // when it's deleted or some raw pointer which we do nothing with. Only 141 // one type of data can be used with the given window, i.e. you cannot set 142 // the void data and then associate the container with wxClientData or vice 143 // versa. 144 union 145 { 146 wxClientData *m_clientObject; 147 void *m_clientData; 148 }; 149 150 // client data accessors 151 virtual void DoSetClientObject( wxClientData *data ); 152 virtual wxClientData *DoGetClientObject() const; 153 154 virtual void DoSetClientData( void *data ); 155 virtual void *DoGetClientData() const; 156 157 // what kind of data do we have? 158 wxClientDataType m_clientDataType; 159 160 }; 161 162 #include "wx/vector.h" 163 164 struct WXDLLIMPEXP_BASE wxClientDataDictionaryPair 165 { wxClientDataDictionaryPairwxClientDataDictionaryPair166 wxClientDataDictionaryPair( size_t idx ) : index( idx ), data( 0 ) { } 167 168 size_t index; 169 wxClientData* data; 170 }; 171 172 _WX_DECLARE_VECTOR( 173 wxClientDataDictionaryPair, 174 wxClientDataDictionaryPairVector, 175 WXDLLIMPEXP_BASE 176 ); 177 178 // this class is used internally to maintain the association between items 179 // of (some subclasses of) wxControlWithItems and their client data 180 // NOTE: this class does not keep track of whether it contains 181 // wxClientData or void*. The client must ensure that 182 // it does not contain a mix of the two, and that 183 // DestroyData is called if it contains wxClientData 184 class WXDLLIMPEXP_BASE wxClientDataDictionary 185 { 186 public: wxClientDataDictionary()187 wxClientDataDictionary() {} 188 189 // deletes all the data DestroyData()190 void DestroyData() 191 { 192 for( size_t i = 0, end = m_vec.size(); i != end; ++i ) 193 delete m_vec[i].data; 194 m_vec.clear(); 195 } 196 197 // if data for the given index is not present, add it, 198 // if it is present, delete the old data and replace it with 199 // the new one Set(size_t index,wxClientData * data,bool doDelete)200 void Set( size_t index, wxClientData* data, bool doDelete ) 201 { 202 size_t ptr = Find( index ); 203 204 if( !data ) 205 { 206 if( ptr == m_vec.size() ) return; 207 if( doDelete ) 208 delete m_vec[ptr].data; 209 m_vec.erase( ptr ); 210 } 211 else 212 { 213 if( ptr == m_vec.size() ) 214 { 215 m_vec.push_back( wxClientDataDictionaryPair( index ) ); 216 ptr = m_vec.size() - 1; 217 } 218 219 if( doDelete ) 220 delete m_vec[ptr].data; 221 m_vec[ptr].data = data; 222 } 223 } 224 225 // get the data associated with the given index, 226 // return 0 if not found Get(size_t index)227 wxClientData* Get( size_t index ) const 228 { 229 size_t it = Find( index ); 230 if( it == m_vec.size() ) return 0; 231 return (wxClientData*)m_vec[it].data; // const cast 232 } 233 234 // delete the data associated with the given index 235 // it also decreases by one the indices of all the elements 236 // with an index greater than the given index Delete(size_t index,bool doDelete)237 void Delete( size_t index, bool doDelete ) 238 { 239 size_t todel = m_vec.size(); 240 241 for( size_t i = 0, end = m_vec.size(); i != end; ++i ) 242 { 243 if( m_vec[i].index == index ) 244 todel = i; 245 else if( m_vec[i].index > index ) 246 --(m_vec[i].index); 247 } 248 249 if( todel != m_vec.size() ) 250 { 251 if( doDelete ) 252 delete m_vec[todel].data; 253 m_vec.erase( todel ); 254 } 255 } 256 private: 257 // returns MyVec.size() if not found Find(size_t index)258 size_t Find( size_t index ) const 259 { 260 for( size_t i = 0, end = m_vec.size(); i != end; ++i ) 261 { 262 if( m_vec[i].index == index ) 263 return i; 264 } 265 266 return m_vec.size(); 267 } 268 269 wxClientDataDictionaryPairVector m_vec; 270 }; 271 272 #endif // _WX_CLNTDATAH__ 273 274