diff --git a/include/wx/event.h b/include/wx/event.h index 8bea624513..ed6a8017f2 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -27,6 +27,10 @@ #include "wx/thread.h" #include "wx/tracker.h" +#if !wxEVENTS_COMPATIBILITY_2_8 + #include "wx/meta/convertible.h" +#endif + // ---------------------------------------------------------------------------- // forward declarations // ---------------------------------------------------------------------------- @@ -131,20 +135,20 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType(); // a nested typedef: #define wxDEFINE_EVENT( name, type ) \ - const wxTypedEventType< type > name( wxNewEventType() ); + const wxEventTypeTag< type > name( wxNewEventType() ); #define wxDECLARE_EXPORTED_EVENT( expdecl, name, type ) \ - extern const expdecl wxTypedEventType< type > name; + extern const expdecl wxEventTypeTag< type > name; // Define/Declare a templatized event type and initialize it with a // predefined event type. (Only used for wxEVT_SPIN_XXX for backward // compatibility) #define wxDEFINE_EVENT_ALIAS( name, type, value ) \ - const wxTypedEventType< type > name( value ); + const wxEventTypeTag< type > name( value ); #define wxDECLARE_EXPORTED_EVENT_ALIAS( expdecl, name, type ) \ - extern const expdecl wxTypedEventType< type > name; + extern const expdecl wxEventTypeTag< type > name; // Declare a local (not exported) templatized event type: @@ -162,13 +166,18 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType(); #if !wxEVENTS_COMPATIBILITY_2_8 -template -class wxTypedEventType +// The tag is a type associated to the event type (which is an integer itself, +// in spite of its name) value. It exists in order to be used as a template +// parameter and provide a mapping between the event type values and their +// corresponding wxEvent-derived classes. +template +class wxEventTypeTag { public: - typedef Event CorrespondingEvent; + // The class of wxEvent-derived class carried by the events of this type. + typedef T EventClass; - wxTypedEventType(wxEventType type) { m_type = type; } + wxEventTypeTag(wxEventType type) { m_type = type; } // Return a wxEventType reference for the initialization of the static // event tables. See wxEventTableEntry::m_eventType for a more thorough @@ -201,18 +210,24 @@ public: virtual ~wxEventFunctor(); // Invoke the actual event handler: - virtual void operator()(wxEvtHandler *, wxEvent &) = 0; + virtual void operator()(wxEvtHandler *, wxEvent&) = 0; // this function tests whether this functor is matched, for the purpose of // finding it in an event table in Disconnect(), by the given func virtual bool Matches(const wxEventFunctor& func) const = 0; - virtual wxEvtHandler *GetHandler() const { return NULL; } + // these functions are used for functors comparison in Matches() + virtual void *GetHandler() const { return GetEvtHandler(); } + virtual wxEventFunction GetMethod() const { return NULL; } - virtual wxObjectEventFunction GetMethod() const { return NULL; } + // this one is also used elsewhere in the code and should be overridden to + // return non-NULL if we are indeed associated with an wxEvtHandler + virtual wxEvtHandler *GetEvtHandler() const { return NULL; } }; -// A plain method functor +// A plain method functor: notice that it is used even with the new events as +// it is reused as a specialization of wxEventFunctorMethod for legacy untyped +// event types class WXDLLIMPEXP_BASE wxObjectEventFunctor : public wxEventFunctor { public: @@ -229,22 +244,26 @@ public: (realHandler->*m_method)(event); } - virtual bool Matches(const wxEventFunctor& other) const + virtual bool Matches(const wxEventFunctor& func) const { - wxEvtHandler * const handler = other.GetHandler(); + void * const handler = func.GetHandler(); + if ( handler && GetHandler() != handler ) + return false; - return (m_handler == handler || !handler) && - (m_method == other.GetMethod()); + const wxEventFunction method = GetMethod(); + return !method || GetMethod() == method; } - virtual wxEvtHandler *GetHandler() const { return m_handler; } - virtual wxObjectEventFunction GetMethod() const { return m_method; } + virtual wxEvtHandler *GetEvtHandler() const { return m_handler; } + virtual wxEventFunction GetMethod() const { return m_method; } private: wxEvtHandler *m_handler; wxObjectEventFunction m_method; }; +#if wxEVENTS_COMPATIBILITY_2_8 + // Create a functor for the legacy events: handler can be NULL and its default // value is used by the event table macros @@ -257,224 +276,234 @@ wxNewEventFunctor(const wxEventType& WXUNUSED(evtType), } inline wxObjectEventFunctor -wxConstructEventFunctor(const wxEventType& WXUNUSED(evtType), +wxMakeEventFunctor(const wxEventType& WXUNUSED(evtType), wxObjectEventFunction method, wxEvtHandler *handler) { return wxObjectEventFunctor(method, handler); } -#if !wxEVENTS_COMPATIBILITY_2_8 +#else // !wxEVENTS_COMPATIBILITY_2_8 -template +// functor forwarding the event to anything callable (function, static method, +// generalized functor...) +template class wxEventFunctorFunction : public wxEventFunctor { public: - wxEventFunctorFunction(void (*handler)(typename EventType::CorrespondingEvent &)) + typedef typename EventTag::EventClass EventArg; + + wxEventFunctorFunction(Functor handler) { m_handler = handler; } virtual void operator()(wxEvtHandler *WXUNUSED(handler), wxEvent& event) { - // Protect against wrong event i.e. wxMouseEvent evt(wxEVT_PAINT): - wxASSERT( dynamic_cast< typename EventType::CorrespondingEvent * >( &event ) != NULL ); - - // Will throw a std::bad_cast exception in release build: - ( *m_handler )( dynamic_cast< typename EventType::CorrespondingEvent & >( event )); + m_handler(static_cast(event)); } - virtual bool Matches( const wxEventFunctor &right ) const + virtual bool Matches(const wxEventFunctor& WXUNUSED(func)) const { - wxEventFunctorFunction const &other = dynamic_cast< wxEventFunctorFunction const & >( right ); - - return m_handler == other.m_handler || other.m_handler == NULL; + // we have no way to compare arbitrary functors so just consider them + // to be equal: this means that disconnecting a functor will always + // find the last functor connected which in turn implies that it's + // probably a bad idea to connect more than one functor if you plan to + // disconnect them but this limitation doesn't seem very important in + // practice + return true; } private: - void ( *m_handler )( typename EventType::CorrespondingEvent & ); + Functor m_handler; }; +// helper class defining operations different for method functors using an +// object of wxEvtHandler-derived class as handler and the others +namespace wxPrivate +{ -template -class wxEventFunctorMethod : public wxEventFunctor +template struct HandlerImpl; + +// specialization for handlers deriving from wxEvtHandler +template +struct HandlerImpl +{ + static bool IsEvtHandler() + { return true; } + static T *ConvertFromEvtHandler(wxEvtHandler *p) + { return static_cast(p); } + static wxEvtHandler *ConvertToEvtHandler(T *p) + { return p; } + static wxEventFunction ConvertToEvtFunction(void (T::*f)(A&)) + { return reinterpret_cast(f); } +}; + +// specialization for handlers not deriving from wxEvtHandler +template +struct HandlerImpl +{ + static bool IsEvtHandler() + { return false; } + static T *ConvertFromEvtHandler(wxEvtHandler *) + { return NULL; } + static wxEvtHandler *ConvertToEvtHandler(T *) + { return NULL; } + static wxEventFunction ConvertToEvtFunction(void (T::*)(A&)) + { return NULL; } +}; + +} // namespace wxPrivate + +// functor forwarding the event to a method of the given object +// +// notice that the object class may be different from the class in which the +// method is defined but it must be convertible to this class +template +class wxEventFunctorMethod + : public wxEventFunctor, + private wxPrivate::HandlerImpl + < + Class, + typename EventTag::EventClass, + wxConvertibleTo::value + > { public: - wxEventFunctorMethod( void ( Class::*method )( typename EventType::CorrespondingEvent & ), - Derived *handler ) + typedef typename EventTag::EventClass EventArg; + + wxEventFunctorMethod(void (Class::*method)(EventArg&), ObjClass *handler) { + wxASSERT_MSG( handler || IsEvtHandler(), + "handlers defined in non-wxEvtHandler-derived classes " + "must be connected with a valid sink object" ); + m_handler = handler; m_method = method; } - virtual void operator () ( wxEvtHandler *handler, wxEvent &event ) + virtual void operator()(wxEvtHandler *handler, wxEvent& event) { - // Compile-time type check 1: This requires Derived to derive from or - // be of the same type as Class - Class *realHandler = m_handler; - - if( m_handler == NULL ) + Class * realHandler = m_handler; + if ( !realHandler ) { - // Verify that the handler does indeed derive from the class - // containing the handler method - wxASSERT( dynamic_cast< Class * >( handler) != NULL ); + realHandler = ConvertFromEvtHandler(handler); - realHandler = dynamic_cast< Class * >( handler ); + // this is not supposed to happen but check for it nevertheless + wxCHECK_RET( realHandler, "invalid event handler" ); } - // Protect against wrong event i.e. wxMouseEvent evt(wxEVT_PAINT): - wxASSERT( dynamic_cast< typename EventType::CorrespondingEvent * >( &event ) != NULL ); - - // Will throw a std::bad_cast exception in release build: - ( realHandler->*m_method )( dynamic_cast< typename EventType::CorrespondingEvent & >( event )); + (realHandler->*m_method)(static_cast(event)); } - virtual bool Matches( const wxEventFunctor &right ) const + virtual bool Matches(const wxEventFunctor& func) const { - wxEventFunctorMethod const &other = dynamic_cast< wxEventFunctorMethod const & >( right ); + void * const handler = func.GetHandler(); + if ( handler && GetHandler() != handler ) + return false; - return (( m_handler == other.m_handler || other.m_handler == NULL ) && - ( m_method == other.m_method || other.m_method == NULL )); + const wxEventFunction method = GetMethod(); + return !method || GetMethod() == method; } - virtual wxEvtHandler *GetHandler() const + virtual void *GetHandler() const { - // This makes sure Derived derives from wxEvtHandler (it is still - // possible and even ok if Class does not derive from wxEvtHandler. In - // this case Derived would end up using multiple inheritance: class - // Derived : public wxEvtHandler, public Class { } where Class contains - // the method to call, but wxEvtHandler contains the wxTrackable and - // code for weak ref support return m_handler; } - virtual wxObjectEventFunction GetMethod() const + virtual wxEventFunction GetMethod() const { - return reinterpret_cast(m_method); + return ConvertToEvtFunction(m_method); + } + + virtual wxEvtHandler *GetEvtHandler() const + { + return ConvertToEvtHandler(m_handler); } private: - Derived *m_handler; - void (Class::*m_method)(typename EventType::CorrespondingEvent&); + ObjClass *m_handler; + void (Class::*m_method)(EventArg&); }; - -template -class wxEventFunctorAdapter : public wxEventFunctor +// partial specialization for legacy event types +template +class wxEventFunctorMethod + : public wxObjectEventFunctor { public: - wxEventFunctorAdapter( Functor &functor ) + wxEventFunctorMethod(wxObjectEventFunction method, ObjClass *handler) + : wxObjectEventFunctor(method, handler) { - m_functor = functor; } - - virtual void operator () ( wxEvtHandler *WXUNUSED( handler ), wxEvent &event ) - { - // Protect against wrong event i.e. wxMouseEvent evt(wxEVT_PAINT): - wxASSERT( dynamic_cast< typename EventType::CorrespondingEvent * >( &event ) != NULL ); - - // Will throw a std::bad_cast exception in release build: - m_functor( dynamic_cast< typename EventType::CorrespondingEvent & >( event )); - } - - virtual bool Matches( const wxEventFunctor &right ) const - { - wxEventFunctorAdapter const &other = dynamic_cast< wxEventFunctorAdapter const & >( right ); - - return m_functor == other.m_functor; - } - -private: - Functor m_functor; }; -// -// Create functors for the templatized events (needed in wxEvtHandler::Connect): -// - -// Create a functor for functions: - -template -inline wxEventFunctorFunction * -wxNewEventFunctor(const EventType &, - void (*function)(typename EventType::CorrespondingEvent&)) -{ - return new wxEventFunctorFunction(function); -} - -// Create a functor for methods: - -template -inline wxEventFunctorMethod * -wxNewEventFunctor(const EventType &, - void (Class::*method)(typename EventType::CorrespondingEvent&)) -{ - return new wxEventFunctorMethod(method, NULL); -} - -template -inline wxEventFunctorMethod * -wxNewEventFunctor(const EventType &, - void (Class::*method)(typename EventType::CorrespondingEvent &), - Derived *handler ) -{ - return new wxEventFunctorMethod(method, handler); -} - -// Create a functor for arbitrary functors (like boost::function): -template -inline wxEventFunctorAdapter * -wxNewEventFunctor(const EventType &, - Functor& functor ) -{ - return new wxEventFunctorAdapter(functor); -} // -// Construct functors for the templatized events (needed in wxEvtHandler::Disconnect): -// +// Create functors for the templatized events, either allocated on the heap for +// wxNewXXX() variants (this is needed in wxEvtHandler::Connect() to store them +// in dynamic event table) or just by returning them as temporary objects (this +// is enough for Disconnect() and we allocate unnecessary heap allocation like +// this) -// Construct a functor for functions: -template -inline wxEventFunctorFunction -wxConstructEventFunctor(const EventType &, - void (*function)(typename EventType::CorrespondingEvent&)) +// Create functors wrapping other functors (including functions): +template +inline wxEventFunctorFunction * +wxNewEventFunctor(const EventTag&, Functor func) { - return wxEventFunctorFunction(function); + return new wxEventFunctorFunction(func); } -// Construct a functor for methods: - -template -inline wxEventFunctorMethod -wxConstructEventFunctor(const EventType &, - void (Class::*method)(typename EventType::CorrespondingEvent&)) +template +inline wxEventFunctorFunction +wxMakeEventFunctor(const EventTag&, Functor func) { - return wxEventFunctorMethod(method, NULL); + return wxEventFunctorFunction(func); } -template -inline wxEventFunctorMethod -wxConstructEventFunctor(const EventType &, - void (Class::*method)(typename EventType::CorrespondingEvent&), - Derived *handler) + +// Create functors for methods: +template + +inline wxEventFunctorMethod * +wxNewEventFunctor(const EventTag&, + void (Class::*method)(EventArg&), + ObjClass *handler) { - return wxEventFunctorMethod(method, handler); + return new wxEventFunctorMethod(method, handler); } -// Construct a functor for arbitrary functors (like boost:function): - -template -inline wxEventFunctorAdapter -wxConstructEventFunctor(const EventType &, - Functor& functor) +template + +inline wxEventFunctorMethod +wxMakeEventFunctor(const EventTag&, + void (Class::*method)(EventArg&), + ObjClass *handler) { - return wxEventFunctorAdapter(functor); + return wxEventFunctorMethod(method, handler); +} + +// Special case for the wxNewEventFunctor() calls used inside the event table +// macros: they don't specify the handler so ObjClass can't be deduced +template +inline wxEventFunctorMethod * +wxNewEventFunctor(const EventTag&, void (Class::*method)(EventArg&)) +{ + return new wxEventFunctorMethod(method, NULL); +} + +template + +inline wxEventFunctorMethod +wxMakeEventFunctor(const EventTag&, void (Class::*method)(EventArg&)) +{ + return wxEventFunctorMethod(method, NULL); } #endif // !wxEVENTS_COMPATIBILITY_2_8 + // many, but not all, standard event types // some generic events @@ -1016,7 +1045,7 @@ class WXDLLIMPEXP_CORE wxScrollWinEvent : public wxEvent public: wxScrollWinEvent(wxEventType commandType = wxEVT_NULL, int pos = 0, int orient = 0); - wxScrollWinEvent(const wxScrollWinEvent & event) : wxEvent(event) + wxScrollWinEvent(const wxScrollWinEvent& event) : wxEvent(event) { m_commandInt = event.m_commandInt; m_extraLong = event.m_extraLong; } @@ -1260,7 +1289,7 @@ public: m_x(x), m_y(y), m_cursor() { } - wxSetCursorEvent(const wxSetCursorEvent & event) + wxSetCursorEvent(const wxSetCursorEvent& event) : wxEvent(event), m_x(event.m_x), m_y(event.m_y), @@ -1403,7 +1432,7 @@ public: : wxEvent(winid, wxEVT_SIZE), m_size(sz) { } - wxSizeEvent(const wxSizeEvent & event) + wxSizeEvent(const wxSizeEvent& event) : wxEvent(event), m_size(event.m_size), m_rect(event.m_rect) { } @@ -1658,7 +1687,7 @@ public: wxMenuEvent(wxEventType type = wxEVT_NULL, int winid = 0, wxMenu* menu = NULL) : wxEvent(winid, type) { m_menuId = winid; m_menu = menu; } - wxMenuEvent(const wxMenuEvent & event) + wxMenuEvent(const wxMenuEvent& event) : wxEvent(event) { m_menuId = event.m_menuId; m_menu = event.m_menu; } @@ -1696,7 +1725,7 @@ public: m_veto(false), // should be false by default m_canVeto(true) {} - wxCloseEvent(const wxCloseEvent & event) + wxCloseEvent(const wxCloseEvent& event) : wxEvent(event), m_loggingOff(event.m_loggingOff), m_veto(event.m_veto), @@ -1746,7 +1775,7 @@ public: wxShowEvent(int winid = 0, bool show = false) : wxEvent(winid, wxEVT_SHOW) { m_show = show; } - wxShowEvent(const wxShowEvent & event) + wxShowEvent(const wxShowEvent& event) : wxEvent(event) { m_show = event.m_show; } @@ -1778,7 +1807,7 @@ public: wxIconizeEvent(int winid = 0, bool iconized = true) : wxEvent(winid, wxEVT_ICONIZE) { m_iconized = iconized; } - wxIconizeEvent(const wxIconizeEvent & event) + wxIconizeEvent(const wxIconizeEvent& event) : wxEvent(event) { m_iconized = event.m_iconized; } @@ -1860,7 +1889,7 @@ public: m_joyStick(joystick) { } - wxJoystickEvent(const wxJoystickEvent & event) + wxJoystickEvent(const wxJoystickEvent& event) : wxEvent(event), m_pos(event.m_pos), m_zPosition(event.m_zPosition), @@ -1995,7 +2024,7 @@ public: m_setText = m_setChecked = false; } - wxUpdateUIEvent(const wxUpdateUIEvent & event) + wxUpdateUIEvent(const wxUpdateUIEvent& event) : wxCommandEvent(event), m_checked(event.m_checked), m_enabled(event.m_enabled), @@ -2191,7 +2220,7 @@ public: : wxEvent(winid, wxEVT_QUERY_NEW_PALETTE), m_paletteRealized(false) { } - wxQueryNewPaletteEvent(const wxQueryNewPaletteEvent & event) + wxQueryNewPaletteEvent(const wxQueryNewPaletteEvent& event) : wxEvent(event), m_paletteRealized(event.m_paletteRealized) { } @@ -2337,7 +2366,7 @@ public: m_pos(pt), m_origin(GuessOrigin(origin)) { } - wxHelpEvent(const wxHelpEvent & event) + wxHelpEvent(const wxHelpEvent& event) : wxCommandEvent(event), m_pos(event.m_pos), m_target(event.m_target), @@ -2395,7 +2424,7 @@ public: wxWindowID winid = 0) : wxCommandEvent(type, winid) { } - wxClipboardTextEvent(const wxClipboardTextEvent & event) + wxClipboardTextEvent(const wxClipboardTextEvent& event) : wxCommandEvent(event) { } @@ -2422,7 +2451,7 @@ public: : wxCommandEvent(type, winid), m_pos(pt) { } - wxContextMenuEvent(const wxContextMenuEvent & event) + wxContextMenuEvent(const wxContextMenuEvent& event) : wxCommandEvent(event), m_pos(event.m_pos) { } @@ -2468,7 +2497,7 @@ public: : wxEvent(0, wxEVT_IDLE), m_requestMore(false) { } - wxIdleEvent(const wxIdleEvent & event) + wxIdleEvent(const wxIdleEvent& event) : wxEvent(event), m_requestMore(event.m_requestMore) { } @@ -2534,7 +2563,7 @@ struct WXDLLIMPEXP_BASE wxEventTableEntryBase // being initialized (a temporary instance is created and then this // constructor is called). - const_cast< wxEventTableEntryBase & >( entry ).m_fn = NULL; + const_cast( entry ).m_fn = NULL; } ~wxEventTableEntryBase() @@ -2554,7 +2583,7 @@ struct WXDLLIMPEXP_BASE wxEventTableEntryBase wxObject* m_callbackUserData; private: - wxEventTableEntryBase &operator = ( const wxEventTableEntryBase & ); + DECLARE_NO_ASSIGN_CLASS(wxEventTableEntryBase) }; // an entry from a static event table @@ -2575,7 +2604,7 @@ struct WXDLLIMPEXP_BASE wxEventTableEntry : public wxEventTableEntryBase const int& m_eventType; private: - wxEventTableEntry &operator = ( const wxEventTableEntry & ); + DECLARE_NO_ASSIGN_CLASS(wxEventTableEntry) }; // an entry used in dynamic event table managed by wxEvtHandler::Connect() @@ -2593,7 +2622,7 @@ struct WXDLLIMPEXP_BASE wxDynamicEventTableEntry : public wxEventTableEntryBase int m_eventType; private: - wxDynamicEventTableEntry &operator = ( const wxDynamicEventTableEntry & ); + DECLARE_NO_ASSIGN_CLASS(wxDynamicEventTableEntry) }; // ---------------------------------------------------------------------------- @@ -2634,7 +2663,7 @@ public: // Handle the given event, in other words search the event table hash // and call self->ProcessEvent() if a match was found. - bool HandleEvent(wxEvent &event, wxEvtHandler *self); + bool HandleEvent(wxEvent& event, wxEvtHandler *self); // Clear table void Clear(); @@ -2745,6 +2774,15 @@ public: // Connecting and disconnecting // ---------------------------- + // These functions are used for old, untyped, event handlers and don't + // check that the type of the function passed to them actually matches the + // type of the event. They also only allow connecting events to methods of + // wxEvtHandler-derived classes. + // + // The template Connect() methods below are safer and allow connecting + // events to arbitrary functions or functors -- but require compiler + // support for templates. + // Dynamic association of a member function handler with the event handler, // winid and event type void Connect(int winid, @@ -2754,9 +2792,9 @@ public: wxObject *userData = NULL, wxEvtHandler *eventSink = NULL) { - wxObjectEventFunctor *functor = wxNewEventFunctor( eventType, func, eventSink ); - - Subscribe( winid, lastId, eventType, functor, userData ); + DoConnect(winid, lastId, eventType, + wxNewEventFunctor(eventType, func, eventSink), + userData); } // Convenience function: take just one id @@ -2781,9 +2819,9 @@ public: wxObject *userData = NULL, wxEvtHandler *eventSink = NULL) { - wxObjectEventFunctor functor = wxConstructEventFunctor( eventType, func, eventSink ); - - return Unsubscribe( winid, lastId, eventType, functor, userData ); + return DoDisconnect(winid, lastId, eventType, + wxMakeEventFunctor(eventType, func, eventSink), + userData ); } bool Disconnect(int winid = wxID_ANY, @@ -2798,305 +2836,258 @@ public: wxObject *userData = NULL, wxEvtHandler *eventSink = NULL) { return Disconnect(wxID_ANY, eventType, func, userData, eventSink); } + #if !wxEVENTS_COMPATIBILITY_2_8 - // - // Connect a method to an event: - // + // Event handling in functions (including generalized functors): - template - void Connect( int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { - wxEventFunctorMethod< EventType, Class, Class > *functor = - wxNewEventFunctor( eventType, func, static_cast< Class * const >( this )); - - Subscribe( winid, lastId, eventType, functor, userData ); - } - - template - void Connect( int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { Connect( winid, wxID_ANY, eventType, func, userData ); } - - template - void Connect( const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { Connect( wxID_ANY, wxID_ANY, eventType, func, userData ); } - - template - void Connect( int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { - wxEventFunctorMethod< EventType, Class, Derived > *functor = - wxNewEventFunctor( eventType, func, eventSink ); - - Subscribe( winid, lastId, eventType, functor, userData ); - } - - template - void Connect( int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { Connect( winid, wxID_ANY, eventType, func, userData, eventSink ); } - - template - void Connect( const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { Connect( wxID_ANY, wxID_ANY, eventType, func, userData, eventSink ); } - - template - static void Connect( Sender *sender, - int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { - wxEventFunctorMethod< EventType, Class, Derived > *functor = - wxNewEventFunctor( eventType, func, eventSink ); - - sender->Subscribe( winid, lastId, eventType, functor, userData ); - } - - template - static void Connect( Sender *sender, - int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { Connect( sender, winid, wxID_ANY, eventType, func, userData, eventSink ); } - - template - static void Connect( Sender *sender, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { Connect( sender, wxID_ANY, wxID_ANY, eventType, func, userData, eventSink ); } - - // - // Connect a function to an event: - // - template + template void Connect(int winid, int lastId, - const EventType &eventType, - void (*func)(typename EventType::CorrespondingEvent&), - wxObject* userData = NULL) + const EventTag& eventType, + Functor func) { - wxEventFunctorFunction< EventType > *functor = wxNewEventFunctor( eventType, func ); - - Subscribe( winid, lastId, eventType, functor, userData ); + DoConnect(winid, lastId, eventType, + wxNewEventFunctor(eventType, func)); } - template - void Connect( int winid, - const EventType &eventType, - void ( *func )( typename EventType::CorrespondingEvent & ), - wxObject* userData = NULL ) - { Connect( winid, wxID_ANY, eventType, func, userData ); } + template + void Connect(int winid, const EventTag& eventType, Functor func) + { Connect(winid, wxID_ANY, eventType, func); } - template - void Connect( const EventType &eventType, - void ( *func )( typename EventType::CorrespondingEvent & ), - wxObject* userData = NULL ) - { Connect( wxID_ANY, wxID_ANY, eventType, func, userData ); } + template + void Connect(const EventTag& eventType, Functor func) + { Connect(wxID_ANY, eventType, func); } - // - // Connect an arbitrary functor to an event: - // - template - void Connect( int winid, - int lastId, - const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) + template + bool Disconnect(int winid, + int lastId, + const EventTag& eventType, + Functor func) { - wxEventFunctorAdapter< EventType, Functor > *adapter = - wxNewEventFunctor( eventType, functor ); - - Subscribe( winid, lastId, eventType, adapter, userData ); - } - template - void Connect( int winid, - const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) - { Connect( winid, wxID_ANY, eventType, functor, userData ); } - - template - void Connect( const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) - { Connect( wxID_ANY, wxID_ANY, eventType, functor, userData ); } - - // - // Disconnect a function from an event: - // - - template - bool Disconnect( int winid, - int lastId, - const EventType &eventType, - void ( *func )( typename EventType::CorrespondingEvent & ), - wxObject* userData = NULL ) - { - wxEventFunctorFunction< EventType > functor = wxConstructEventFunctor( eventType, func ); - - return Unsubscribe( winid, lastId, eventType, functor, userData ); + return DoDisconnect(winid, lastId, eventType, + wxMakeEventFunctor(eventType, func)); } - template - bool Disconnect( int winid, - const EventType &eventType, - void ( *func )( typename EventType::CorrespondingEvent & ), - wxObject* userData = NULL ) - { return Disconnect( winid, wxID_ANY, eventType, func, userData ); } + template + bool Disconnect(int winid, const EventTag& eventType, Functor func) + { return Disconnect(winid, wxID_ANY, eventType, func); } - template - bool Disconnect( const EventType &eventType, - void ( *func )( typename EventType::CorrespondingEvent & ), - wxObject* userData = NULL ) - { return Disconnect( wxID_ANY, wxID_ANY, eventType, func, userData ); } + template + bool Disconnect(const EventTag& eventType, Functor func) + { return Disconnect(wxID_ANY, eventType, func); } + + + // Event handling in class methods: the object handling the event (i.e. + // this object itself by default or eventSink if specified) must be + // convertible to this class. // - // Disconnect a method from an event: - // + // Notice that we need to have separate overloads for the versions with and + // without eventSink because in the latter case we must check that this + // object itself derives from Class while in the former this is not + // necessarily true - template - bool Disconnect( int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { - wxEventFunctorMethod< EventType, Class, Class > functor = - wxConstructEventFunctor( eventType, func, static_cast< Class * const >( this )); + // Methods connecting/disconnecting event to this object itself - return Unsubscribe( winid, lastId, eventType, functor, userData ); - } - - template - bool Disconnect( int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { return Disconnect( winid, wxID_ANY, eventType, func, userData ); } - - template - bool Disconnect( const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL ) - { return Disconnect( wxID_ANY, wxID_ANY, eventType, func, userData ); } - - template - bool Disconnect( int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { - wxEventFunctorMethod< EventType, Class, Derived > functor = - wxConstructEventFunctor( eventType, func, eventSink ); - - return Unsubscribe( winid, lastId, eventType, functor, userData ); - } - - template - bool Disconnect( int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { return Disconnect( winid, wxID_ANY, eventType, func, userData, eventSink ); } - - template - bool Disconnect( const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { return Disconnect( wxID_ANY, wxID_ANY, eventType, func, userData, eventSink ); } - - template - static bool Disconnect( Sender *sender, - int winid, - int lastId, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) + template + void Connect(int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) { - wxEventFunctorMethod< EventType, Class, Derived > functor = - wxConstructEventFunctor( eventType, func, eventSink ); - - return sender->Unsubscribe( winid, lastId, eventType, functor, userData ); + DoConnect(winid, lastId, eventType, + wxNewEventFunctor(eventType, func, static_cast(this)), + userData); } - template - static bool Disconnect( Sender *sender, - int winid, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { return Disconnect( sender, winid, wxID_ANY, eventType, func, userData, eventSink ); } + template + void Connect(int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) + { Connect(winid, wxID_ANY, eventType, func, userData); } - template - static bool Disconnect( Sender *sender, - const EventType &eventType, - void ( Class::*func )( typename EventType::CorrespondingEvent & ), - wxObject *userData = NULL, - Derived *eventSink = NULL ) - { return Disconnect( sender, wxID_ANY, wxID_ANY, eventType, func, userData, eventSink ); } + template + void Connect(const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) + { Connect(wxID_ANY, eventType, func, userData); } - // - // Disconnect an arbitrary functor from an event: - // - template - bool Disconnect( int winid, - int lastId, - const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) + template + bool Disconnect(int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) { - wxEventFunctorAdapter< EventType, Functor > adapter = - wxConstructEventFunctor( eventType, functor ); - - return Unsubscribe( winid, lastId, eventType, adapter, userData ); + return DoDisconnect(winid, lastId, eventType, + wxMakeEventFunctor(eventType, func, + static_cast(this)), + userData); } - template - bool Disconnect( int winid, - const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) - { return Disconnect( winid, wxID_ANY, eventType, functor, userData ); } + template + bool Disconnect(int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) + { return Disconnect(winid, wxID_ANY, eventType, func, userData); } - template - bool Disconnect( const EventType &eventType, - Functor &functor, - wxObject* userData = NULL) - { return Disconnect( wxID_ANY, wxID_ANY, eventType, functor, userData ); } + template + bool Disconnect(const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL) + { return Disconnect(wxID_ANY, eventType, func, userData); } + + // Methods connecting/disconnecting event to another object + + template + + void Connect(int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { + DoConnect(winid, lastId, eventType, + wxNewEventFunctor(eventType, func, eventSink), + userData); + } + + template + + void Connect(int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { Connect(winid, wxID_ANY, eventType, func, userData, eventSink); } + + template + + void Connect(const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { Connect(wxID_ANY, eventType, func, userData, eventSink); } + + + template + + bool Disconnect(int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { + return DoDisconnect(winid, lastId, eventType, + wxMakeEventFunctor(eventType, func, eventSink), + userData); + } + + template + + bool Disconnect(int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { return Disconnect(winid, wxID_ANY, eventType, func, + userData, eventSink); } + + template + + bool Disconnect(const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData, + ObjClass *eventSink) + { return Disconnect(wxID_ANY, eventType, func, userData, eventSink); } + + + + // Static version of Connect() which allows to specify the event source and + // event handler in a more symmetric way + template + static void Connect(ObjSource *eventSrc, + int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + eventSrc->Connect(winid, lastId, eventType, func, userData, eventSink); + } + + template + static void Connect(ObjSource *eventSrc, + int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + Connect(eventSrc, winid, wxID_ANY, eventType, func, userData, eventSink); + } + + template + static void Connect(ObjSource *eventSrc, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + Connect(eventSrc, wxID_ANY, eventType, func, userData, eventSink); + } + + + template + static bool Disconnect(ObjSource *eventSrc, + int winid, + int lastId, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + return eventSrc->Disconnect(winid, lastId, eventType, func, + userData, eventSink); + } + + template + static bool Disconnect(ObjSource *eventSrc, + int winid, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + return Disconnect(eventSrc, winid, wxID_ANY, eventType, func, + userData, eventSink); + } + + template + static bool Disconnect(ObjSource *eventSrc, + const EventTag& eventType, + void (Class::*func)(EventArg&), + wxObject *userData = NULL, + ObjClass *eventSink = NULL) + { + return Disconnect(eventSrc, wxID_ANY, eventType, func, + userData, eventSink); + } #endif // !wxEVENTS_COMPATIBILITY_2_8 @@ -3140,17 +3131,17 @@ public: private: - void Subscribe(int winid, + void DoConnect(int winid, int lastId, wxEventType eventType, wxEventFunctor *func, - wxObject* userData); + wxObject* userData = NULL); - bool Unsubscribe(int winid, - int lastId, - wxEventType eventType, - const wxEventFunctor &func, - wxObject *userData); + bool DoDisconnect(int winid, + int lastId, + wxEventType eventType, + const wxEventFunctor& func, + wxObject *userData = NULL); static const wxEventTableEntry sm_eventTableEntries[]; diff --git a/include/wx/msw/chkconf.h b/include/wx/msw/chkconf.h index 356cb0160b..d1d30c7c24 100644 --- a/include/wx/msw/chkconf.h +++ b/include/wx/msw/chkconf.h @@ -406,7 +406,7 @@ Windows. */ #if !wxEVENTS_COMPATIBILITY_2_8 -# if !wxCHECK_VISUALC_VERSION(8) +# if !wxCHECK_VISUALC_VERSION(7) # undef wxEVENTS_COMPATIBILITY_2_8 # define wxEVENTS_COMPATIBILITY_2_8 1 # endif diff --git a/src/common/event.cpp b/src/common/event.cpp index 85951a1b3e..6a878fd460 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -1065,7 +1065,7 @@ wxEvtHandler::~wxEvtHandler() // Remove ourselves from sink destructor notifications // (this has usually been done, in wxTrackable destructor) - wxEvtHandler *eventSink = entry->m_fn->GetHandler(); + wxEvtHandler *eventSink = entry->m_fn->GetEvtHandler(); if ( eventSink ) { wxEventConnectionRef * const @@ -1408,10 +1408,11 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event) return false; } -void wxEvtHandler::Subscribe( int id, int lastId, - wxEventType eventType, - wxEventFunctor *func, - wxObject *userData ) +void wxEvtHandler::DoConnect(int id, + int lastId, + wxEventType eventType, + wxEventFunctor *func, + wxObject *userData) { wxDynamicEventTableEntry *entry = new wxDynamicEventTableEntry(eventType, id, lastId, func, userData); @@ -1423,7 +1424,7 @@ void wxEvtHandler::Subscribe( int id, int lastId, m_dynamicEvents->Insert( (wxObject*) entry ); // Make sure we get to know when a sink is destroyed - wxEvtHandler *eventSink = func->GetHandler(); + wxEvtHandler *eventSink = func->GetEvtHandler(); if ( eventSink && eventSink != this ) { wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink); @@ -1435,17 +1436,17 @@ void wxEvtHandler::Subscribe( int id, int lastId, } bool -wxEvtHandler::Unsubscribe(int id, - int lastId, - wxEventType eventType, - const wxEventFunctor& func, - wxObject *userData) +wxEvtHandler::DoDisconnect(int id, + int lastId, + wxEventType eventType, + const wxEventFunctor& func, + wxObject *userData) { if (!m_dynamicEvents) return false; // Remove connection from tracker node (wxEventConnectionRef) - wxEvtHandler *eventSink = func.GetHandler(); + wxEvtHandler *eventSink = func.GetEvtHandler(); if ( eventSink && eventSink != this ) { wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink); @@ -1490,7 +1491,7 @@ bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event ) if ( event.GetEventType() == entry->m_eventType ) { - wxEvtHandler *handler = entry->m_fn->GetHandler(); + wxEvtHandler *handler = entry->m_fn->GetEvtHandler(); if ( !handler ) handler = this; if ( ProcessEventIfMatchesId(*entry, handler, event) ) @@ -1571,7 +1572,7 @@ void wxEvtHandler::OnSinkDestroyed( wxEvtHandler *sink ) wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData(); node_nxt = node->GetNext(); - if ( entry->m_fn->GetHandler() == sink ) + if ( entry->m_fn->GetEvtHandler() == sink ) { delete entry->m_callbackUserData; m_dynamicEvents->Erase( node ); diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index d19a1fde30..137fe3e6e2 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -17,38 +17,11 @@ #pragma hdrstop #endif -#ifndef WX_PRECOMP -#endif // WX_PRECOMP - #include "wx/event.h" - -// -------------------------------------------------------------------------- -// test class -// -------------------------------------------------------------------------- - -class EvtHandlerTestCase : public CppUnit::TestCase -{ -public: - EvtHandlerTestCase() {} - -private: - CPPUNIT_TEST_SUITE( EvtHandlerTestCase ); - CPPUNIT_TEST( TestConnectCompilation ); - CPPUNIT_TEST( TestEventFunctorCompare ); - CPPUNIT_TEST_SUITE_END(); - - void TestConnectCompilation(); - void TestEventFunctorCompare(); - - DECLARE_NO_COPY_CLASS(EvtHandlerTestCase) -}; - -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase ); - -// also include in it's own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" ); +// ---------------------------------------------------------------------------- +// test events and their handlers +// ---------------------------------------------------------------------------- const wxEventType EVT_LEGACY = wxNewEventType(); @@ -93,44 +66,145 @@ void GlobalOnMyEvent(MyEvent&) g_called.function = true; } -class MyFunctor -{ -public: - void operator()(MyEvent &) { g_called.functor = true; } +void GlobalOnAnotherEvent(AnotherEvent&); - bool operator==(const MyFunctor &) const { return true; } +void GlobalOnIdle(wxIdleEvent&) +{ + g_called.function = true; +} + +struct MyFunctor +{ + void operator()(MyEvent &) { g_called.functor = true; } +}; + +struct IdleFunctor +{ + void operator()(wxIdleEvent &) { g_called.functor = true; } }; class MyHandler : public wxEvtHandler { public: - void OnMyEvent(MyEvent&) { g_called.method = true; } - static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; } + static void StaticOnAnotherEvent(AnotherEvent &); + static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; } - void OnEvent(wxEvent &) { } - void OnAnotherEvent(AnotherEvent&) { } + void OnMyEvent(MyEvent&) { g_called.method = true; } + void OnEvent(wxEvent&) { g_called.method = true; } + void OnAnotherEvent(AnotherEvent&); + void OnIdle(wxIdleEvent&) { g_called.method = true; } }; +// we can also handle events in classes not deriving from wxEvtHandler +struct MySink +{ + void OnMyEvent(MyEvent&) { g_called.method = true; } + void OnIdle(wxIdleEvent&) { g_called.method = true; } +}; + +// also test event table compilation +class MyClassWithEventTable : public wxEvtHandler +{ +public: + void OnMyEvent(MyEvent&) { g_called.method = true; } + void OnEvent(wxEvent&) { g_called.method = true; } + void OnAnotherEvent(AnotherEvent&); + void OnIdle(wxIdleEvent&) { g_called.method = true; } + +private: + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler) + EVT_IDLE(MyClassWithEventTable::OnIdle) + + // this shouldn't compile: + //EVT_IDLE(MyClassWithEventTable::OnAnotherEvent) +END_EVENT_TABLE() + } // anonymous namespace -void EvtHandlerTestCase::TestConnectCompilation() -{ - // Test that connecting the 'legacy' events still compiles: +// -------------------------------------------------------------------------- +// test class +// -------------------------------------------------------------------------- + +class EvtHandlerTestCase : public CppUnit::TestCase +{ +public: + EvtHandlerTestCase() {} + +private: + CPPUNIT_TEST_SUITE( EvtHandlerTestCase ); + CPPUNIT_TEST( BuiltinConnect ); + CPPUNIT_TEST( LegacyConnect ); +#if !wxEVENTS_COMPATIBILITY_2_8 + CPPUNIT_TEST( ConnectFunction ); + CPPUNIT_TEST( ConnectStaticMethod ); + CPPUNIT_TEST( ConnectFunctor ); + CPPUNIT_TEST( ConnectMethod ); + CPPUNIT_TEST( ConnectMethodWithSink ); + CPPUNIT_TEST( ConnectNonHandler ); + CPPUNIT_TEST( StaticConnect ); + CPPUNIT_TEST( InvalidConnect ); +#endif // !wxEVENTS_COMPATIBILITY_2_8 + CPPUNIT_TEST_SUITE_END(); + + void BuiltinConnect(); + void LegacyConnect(); +#if !wxEVENTS_COMPATIBILITY_2_8 + void ConnectFunction(); + void ConnectStaticMethod(); + void ConnectFunctor(); + void ConnectMethod(); + void ConnectMethodWithSink(); + void ConnectNonHandler(); + void StaticConnect(); + void InvalidConnect(); +#endif // !wxEVENTS_COMPATIBILITY_2_8 + + + // these member variables exceptionally don't use "m_" prefix because + // they're used so many times MyHandler handler; MyEvent e; - handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + DECLARE_NO_COPY_CLASS(EvtHandlerTestCase) +}; - handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); - handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); +// register in the unnamed registry so that these tests are run by default +CPPUNIT_TEST_SUITE_REGISTRATION( EvtHandlerTestCase ); +// also include in it's own registry so that these tests can be run alone +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtHandlerTestCase, "EvtHandlerTestCase" ); +void EvtHandlerTestCase::BuiltinConnect() +{ + handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle)); + handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle)); + handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler); + handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), NULL, &handler); + +#if !wxEVENTS_COMPATIBILITY_2_8 + handler.Connect(wxEVT_IDLE, GlobalOnIdle); + handler.Disconnect(wxEVT_IDLE, GlobalOnIdle); + + IdleFunctor f; + handler.Connect(wxEVT_IDLE, f); + handler.Disconnect(wxEVT_IDLE, f); + + handler.Connect(wxEVT_IDLE, &MyHandler::OnIdle); + handler.Disconnect(wxEVT_IDLE, &MyHandler::OnIdle); + + handler.Connect(wxEVT_IDLE, &MyHandler::StaticOnIdle); + handler.Disconnect(wxEVT_IDLE, &MyHandler::StaticOnIdle); +#endif // !wxEVENTS_COMPATIBILITY_2_8 +} + +void EvtHandlerTestCase::LegacyConnect() +{ handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); @@ -139,38 +213,99 @@ void EvtHandlerTestCase::TestConnectCompilation() handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent ); - // Call (and therefore instantiate) all Connect() variants to detect template - // errors: + + handler.Connect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Connect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Connect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + + handler.Disconnect( EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Disconnect( 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); + handler.Disconnect( 0, 0, EVT_LEGACY, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler ); +} #if !wxEVENTS_COMPATIBILITY_2_8 + +void EvtHandlerTestCase::ConnectFunction() +{ + // function tests + handler.Connect( EVT_MYEVENT, GlobalOnMyEvent ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.function ); + handler.Disconnect( EVT_MYEVENT, GlobalOnMyEvent ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.function ); // check that it was disconnected + + handler.Connect( 0, EVT_MYEVENT, GlobalOnMyEvent ); + handler.Disconnect( 0, EVT_MYEVENT, GlobalOnMyEvent ); + + handler.Connect( 0, 0, EVT_MYEVENT, GlobalOnMyEvent ); + handler.Disconnect( 0, 0, EVT_MYEVENT, GlobalOnMyEvent ); +} + +void EvtHandlerTestCase::ConnectStaticMethod() +{ + // static method tests (this is same as functions but still test it just in + // case we hit some strange compiler bugs) handler.Connect( EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); g_called.Reset(); handler.ProcessEvent(e); CPPUNIT_ASSERT( g_called.smethod ); handler.Disconnect( EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); - g_called.Reset(); handler.ProcessEvent(e); - CPPUNIT_ASSERT( !g_called.smethod ); // check that it was disconnected + CPPUNIT_ASSERT( !g_called.smethod ); handler.Connect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::StaticOnMyEvent ); +} +void EvtHandlerTestCase::ConnectFunctor() +{ + // generalized functor tests + MyFunctor functor; + handler.Connect( EVT_MYEVENT, functor ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.functor ); + handler.Disconnect( EVT_MYEVENT, functor ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.functor ); + handler.Connect( 0, EVT_MYEVENT, functor ); + handler.Disconnect( 0, EVT_MYEVENT, functor ); + + handler.Connect( 0, 0, EVT_MYEVENT, functor ); + handler.Disconnect( 0, 0, EVT_MYEVENT, functor ); +} + +void EvtHandlerTestCase::ConnectMethod() +{ + // class method tests handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent ); - handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); - handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); - + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.method ); handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.method ); + + handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); + + handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent ); +} - - +void EvtHandlerTestCase::ConnectMethodWithSink() +{ handler.Connect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); handler.Connect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); handler.Connect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); @@ -178,8 +313,25 @@ void EvtHandlerTestCase::TestConnectCompilation() handler.Disconnect( EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); handler.Disconnect( 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); handler.Disconnect( 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); +} +void EvtHandlerTestCase::ConnectNonHandler() +{ + // class method tests for class not derived from wxEvtHandler + MySink sink; + handler.Connect( EVT_MYEVENT, &MySink::OnMyEvent, NULL, &sink ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( g_called.method ); + handler.Disconnect( EVT_MYEVENT, &MySink::OnMyEvent, NULL, &sink ); + g_called.Reset(); + handler.ProcessEvent(e); + CPPUNIT_ASSERT( !g_called.method ); +} + +void EvtHandlerTestCase::StaticConnect() +{ wxEvtHandler::Connect( &handler, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); wxEvtHandler::Connect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); wxEvtHandler::Connect( &handler, 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); @@ -187,43 +339,17 @@ void EvtHandlerTestCase::TestConnectCompilation() wxEvtHandler::Disconnect( &handler, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); wxEvtHandler::Disconnect( &handler, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); wxEvtHandler::Disconnect( &handler, 0, 0, EVT_MYEVENT, &MyHandler::OnMyEvent, NULL, &handler ); +} - - - MyFunctor functor; - - handler.Connect( EVT_MYEVENT, functor ); - handler.Connect( 0, EVT_MYEVENT, functor ); - handler.Connect( 0, 0, EVT_MYEVENT, functor ); - - handler.Disconnect( EVT_MYEVENT, functor ); - handler.Disconnect( 0, EVT_MYEVENT, functor ); - handler.Disconnect( 0, 0, EVT_MYEVENT, functor ); - +void EvtHandlerTestCase::InvalidConnect() +{ // these calls shouldn't compile but we unfortunately can't check this // automatically, you need to uncomment them manually and test that // compilation does indeed fail - //handler.Connect(EVT_MYEVENT, &MyHandler::OnAnotherEvent, NULL, &handler); + //handler.Connect(EVT_MYEVENT, GlobalOnAnotherEvent); + //IdleFunctor f; handler.Connect(EVT_MYEVENT, f); + //handler.Connect(EVT_MYEVENT, &MyHandler::StaticOnAnotherEvent); + //handler.Connect(EVT_MYEVENT, &MyHandler::OnAnotherEvent); +} + #endif // !wxEVENTS_COMPATIBILITY_2_8 -} - -void EvtHandlerTestCase::TestEventFunctorCompare() -{ -//#if !wxEVENTS_COMPATIBILITY_2_8 -// MyHandler handler1; -// wxEventFunctor *connectFunctor = wxNewEventFunctor( EVT_MYEVENT, &MyHandler::OnMyEvent, &handler1 ); -// wxEventFunctor *disconnectFunctor = wxNewEventFunctor( EVT_MYEVENT, &MyHandler::OnMyEvent, &handler1 ); -// wxEventFunctor *nullFunctor = wxNewEventFunctor( EVT_MYEVENT, &MyHandler::OnMyEvent ); -// -// CPPUNIT_ASSERT( connectFunctor->Matches( *disconnectFunctor )); -// CPPUNIT_ASSERT( disconnectFunctor->Matches( *connectFunctor )); -// -// CPPUNIT_ASSERT( connectFunctor->Matches( *nullFunctor )); -// CPPUNIT_ASSERT( nullFunctor->Matches( *connectFunctor )); -// -// CPPUNIT_ASSERT( disconnectFunctor->Matches( *nullFunctor )); -// CPPUNIT_ASSERT( nullFunctor->Matches( *disconnectFunctor )); -//#endif -} - -