X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/88a9f974b8d98b194174270c575cc6cb9b2b5bd3..04f109ec63bb2522e520ce9239828e8ee41cd61c:/include/wx/clntdata.h diff --git a/include/wx/clntdata.h b/include/wx/clntdata.h index e91f2391b2..33fae4c104 100644 --- a/include/wx/clntdata.h +++ b/include/wx/clntdata.h @@ -5,18 +5,85 @@ // Modified by: // Created: 9-Oct-2001 // RCS-ID: $Id$ -// Copyright: (c) wxWindows team +// Copyright: (c) wxWidgets team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_CLNTDATAH__ #define _WX_CLNTDATAH__ -#ifdef __GNUG__ - #pragma interface "event.h" -#endif - #include "wx/defs.h" +#include "wx/string.h" +#include "wx/hashmap.h" + +typedef int (*wxShadowObjectMethod)(void*, void*); +WX_DECLARE_STRING_HASH_MAP_WITH_DECL( + wxShadowObjectMethod, + wxShadowObjectMethods, + class WXDLLIMPEXP_BASE +); +WX_DECLARE_STRING_HASH_MAP_WITH_DECL( + void *, + wxShadowObjectFields, + class WXDLLIMPEXP_BASE +); + +class WXDLLIMPEXP_BASE wxShadowObject +{ +public: + wxShadowObject() { } + + void AddMethod( const wxString &name, wxShadowObjectMethod method ) + { + wxShadowObjectMethods::iterator it = m_methods.find( name ); + if (it == m_methods.end()) + m_methods[ name ] = method; + else + it->second = method; + } + + bool InvokeMethod( const wxString &name, void* window, void* param, int* returnValue ) + { + wxShadowObjectMethods::iterator it = m_methods.find( name ); + if (it == m_methods.end()) + return false; + wxShadowObjectMethod method = it->second; + int ret = (*method)(window, param); + if (returnValue) + *returnValue = ret; + return true; + } + + void AddField( const wxString &name, void* initialValue = NULL ) + { + wxShadowObjectFields::iterator it = m_fields.find( name ); + if (it == m_fields.end()) + m_fields[ name ] = initialValue; + else + it->second = initialValue; + } + + void SetField( const wxString &name, void* value ) + { + wxShadowObjectFields::iterator it = m_fields.find( name ); + if (it == m_fields.end()) + return; + it->second = value; + } + + void* GetField( const wxString &name, void *defaultValue = NULL ) + { + wxShadowObjectFields::iterator it = m_fields.find( name ); + if (it == m_fields.end()) + return defaultValue; + return it->second; + } + +private: + wxShadowObjectMethods m_methods; + wxShadowObjectFields m_fields; +}; + // ---------------------------------------------------------------------------- @@ -28,17 +95,17 @@ enum wxClientDataType wxClientData_Void // client data is untyped and we don't own it }; -class WXDLLEXPORT wxClientData +class WXDLLIMPEXP_BASE wxClientData { public: wxClientData() { } virtual ~wxClientData() { } }; -class WXDLLEXPORT wxStringClientData : public wxClientData +class WXDLLIMPEXP_BASE wxStringClientData : public wxClientData { public: - wxStringClientData() { } + wxStringClientData() : m_data() { } wxStringClientData( const wxString &data ) : m_data(data) { } void SetData( const wxString &data ) { m_data = data; } const wxString& GetData() const { return m_data; } @@ -47,17 +114,21 @@ private: wxString m_data; }; +// This class is a mixin that provides storage and management of "client +// data." The client data stored can either be a pointer to a wxClientData +// object in which case it is managed by the container (i.e. it will delete +// the data when it's destroyed) or an untyped pointer which won't be deleted +// by the container - but not both of them +// +// NOTE: This functionality is currently duplicated in wxEvtHandler in order +// to avoid having more than one vtable in that class hierarchy. -class WXDLLEXPORT wxClientDataContainer +class WXDLLIMPEXP_BASE wxClientDataContainer { public: wxClientDataContainer(); - ~wxClientDataContainer(); + virtual ~wxClientDataContainer(); - // each window may have associated client data: either a pointer to - // wxClientData object in which case it is managed by the window (i.e. - // it will delete the data when it's destroyed) or an untyped pointer - // which won't be deleted by the window - but not both of them void SetClientObject( wxClientData *data ) { DoSetClientObject(data); } wxClientData *GetClientObject() const { return DoGetClientObject(); } @@ -65,11 +136,11 @@ public: void *GetClientData() const { return DoGetClientData(); } protected: - // user data associated with the window: either an object which will be - // deleted by the window when it's deleted or some raw pointer which we do - // nothing with - only one type of data can be used with the given window - // (i.e. you cannot set the void data and then associate the window with - // wxClientData or vice versa) + // The user data: either an object which will be deleted by the container + // when it's deleted or some raw pointer which we do nothing with. Only + // one type of data can be used with the given window, i.e. you cannot set + // the void data and then associate the container with wxClientData or vice + // versa. union { wxClientData *m_clientObject; @@ -88,6 +159,115 @@ protected: }; -// ---------------------------------------------------------------------------- -#endif +#include "wx/vector.h" + +struct WXDLLIMPEXP_BASE wxClientDataDictionaryPair +{ + wxClientDataDictionaryPair( size_t idx ) : index( idx ), data( 0 ) { } + + size_t index; + wxClientData* data; +}; + +_WX_DECLARE_VECTOR( + wxClientDataDictionaryPair, + wxClientDataDictionaryPairVector, + WXDLLIMPEXP_BASE +); + +// this class is used internally to maintain the association between items +// of (some subclasses of) wxControlWithItems and their client data +// NOTE: this class does not keep track of whether it contains +// wxClientData or void*. The client must ensure that +// it does not contain a mix of the two, and that +// DestroyData is called if it contains wxClientData +class WXDLLIMPEXP_BASE wxClientDataDictionary +{ +public: + wxClientDataDictionary() {} + + // deletes all the data + void DestroyData() + { + for( size_t i = 0, end = m_vec.size(); i != end; ++i ) + delete m_vec[i].data; + m_vec.clear(); + } + + // if data for the given index is not present, add it, + // if it is present, delete the old data and replace it with + // the new one + void Set( size_t index, wxClientData* data, bool doDelete ) + { + size_t ptr = Find( index ); + + if( !data ) + { + if( ptr == m_vec.size() ) return; + if( doDelete ) + delete m_vec[ptr].data; + m_vec.erase( ptr ); + } + else + { + if( ptr == m_vec.size() ) + { + m_vec.push_back( wxClientDataDictionaryPair( index ) ); + ptr = m_vec.size() - 1; + } + + if( doDelete ) + delete m_vec[ptr].data; + m_vec[ptr].data = data; + } + } + + // get the data associated with the given index, + // return 0 if not found + wxClientData* Get( size_t index ) const + { + size_t it = Find( index ); + if( it == m_vec.size() ) return 0; + return (wxClientData*)m_vec[it].data; // const cast + } + + // delete the data associated with the given index + // it also decreases by one the indices of all the elements + // with an index greater than the given index + void Delete( size_t index, bool doDelete ) + { + size_t todel = m_vec.size(); + + for( size_t i = 0, end = m_vec.size(); i != end; ++i ) + { + if( m_vec[i].index == index ) + todel = i; + else if( m_vec[i].index > index ) + --(m_vec[i].index); + } + + if( todel != m_vec.size() ) + { + if( doDelete ) + delete m_vec[todel].data; + m_vec.erase( todel ); + } + } +private: + // returns MyVec.size() if not found + size_t Find( size_t index ) const + { + for( size_t i = 0, end = m_vec.size(); i != end; ++i ) + { + if( m_vec[i].index == index ) + return i; + } + + return m_vec.size(); + } + + wxClientDataDictionaryPairVector m_vec; +}; + +#endif // _WX_CLNTDATAH__