]> git.saurik.com Git - wxWidgets.git/commitdiff
improvements to wxEventFunctor classes; use wxHAS_EVENT_BIND instead of wxEVENTS_COMP...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 2 May 2009 12:52:54 +0000 (12:52 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 2 May 2009 12:52:54 +0000 (12:52 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60470 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

17 files changed:
configure.in
include/wx/event.h
include/wx/features.h
include/wx/motif/setup0.h
include/wx/msw/chkconf.h
include/wx/msw/setup0.h
include/wx/msw/wince/setup.h
include/wx/os2/setup0.h
include/wx/osx/setup0.h
include/wx/palmos/setup0.h
include/wx/setup_inc.h
include/wx/univ/setup0.h
samples/event/event.cpp
setup.h.in
src/common/appbase.cpp
src/common/event.cpp
tests/events/evthandler.cpp

index 7cffd8152f5075c98a1a6becc4e83c7128e172a5..61cf02e185ed98708e4cbdaade9a5abccb64bac2 100644 (file)
@@ -682,13 +682,6 @@ WX_ARG_ENABLE_PARAM(universal_binary, [[  --enable-universal_binary  create Mac
 WX_ARG_ENABLE(compat26,      [  --enable-compat26       enable wxWidgets 2.6 compatibility], WXWIN_COMPATIBILITY_2_6)
 WX_ARG_DISABLE(compat28,     [  --disable-compat28      disable wxWidgets 2.8 compatibility], WXWIN_COMPATIBILITY_2_8)
 
-dnl currently we don't provide a switch for disabling it as it shouldn't be
-dnl necessary to do it unless the compiler doesn't support the new events and
-dnl this should be tested for by configure itself (but also isn't done yet
-dnl because there are no known examples of such compilers among the currently
-dnl supported ones)
-AC_DEFINE(wxEVENTS_COMPATIBILITY_2_8, 0)
-
 WX_ARG_DISABLE(rpath,        [  --disable-rpath         disable use of rpath for uninstalled builds], wxUSE_RPATH)
 
 WX_ARG_ENABLE(objc_uniquifying,[  --enable-objc_uniquifying enable Objective-C class name uniquifying], wxUSE_OBJC_UNIQUIFYING)
index d3bcc5b2751fd4db4d956e2a48a8895fe7c85ee8..b116e3e8c6dfb0e23da814c4f391de9f010a30a0 100644 (file)
@@ -27,7 +27,7 @@
 #include "wx/thread.h"
 #include "wx/tracker.h"
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     #include "wx/meta/convertible.h"
 #endif
 
@@ -101,7 +101,7 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType();
 
 // New macros to create templatized event types:
 
-#if wxEVENTS_COMPATIBILITY_2_8
+#ifndef wxHAS_EVENT_BIND
 
     // Define/Declare a wxEventType-based event type:
 
@@ -126,7 +126,8 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType();
     #define wxDECLARE_EVENT( name, type ) \
         wxDECLARE_EXPORTED_EVENT( wxEMPTY_PARAMETER_VALUE, name, type )
 
-#else
+#else // wxHAS_EVENT_BIND
+
     // Define/Declare a templatized event type with the corresponding event as
     // a nested typedef:
 
@@ -151,16 +152,15 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType();
     #define wxDECLARE_EVENT( name, type ) \
         wxDECLARE_EXPORTED_EVENT( wxEMPTY_PARAMETER_VALUE, name, type )
 
-#endif
+#endif // wxHAS_EVENT_BIND
 
 // Try to cast the given event handler to the correct handler type:
 
 #define wxEVENT_HANDLER_CAST( functype, func ) \
     ( wxObjectEventFunction )( wxEventFunction )wxStaticCastEvent( functype, &func )
 
-// Template which associates the correct event object with the event type
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
 
 // 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
@@ -184,7 +184,7 @@ private:
     wxEventType m_type;
 };
 
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
 // These are needed for the functor definitions
 typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
@@ -199,6 +199,15 @@ typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
 typedef wxEventFunction wxObjectEventFunction;
 
 
+// wxEventFunctorClassInfo is used as a unique identifier for wxEventFunctor-
+// derived classes; it is more light weight than wxClassInfo and can be used in
+// template classes
+typedef void (*wxEventFunctorClassInfo)();
+
+// this macro must be used in wxEventFunctor-derived classes
+#define wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( classInfoName ) \
+    static void classInfoName() {}
+
 // The event functor which is stored in the static and dynamic event tables:
 class WXDLLIMPEXP_BASE wxEventFunctor
 {
@@ -209,54 +218,74 @@ public:
     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;
+    // finding it in an event table in Unbind(), by the given functor:
+    virtual bool IsMatching(const wxEventFunctor& functor) const = 0;
 
-    // these functions are used for functors comparison in Matches()
-    virtual void *GetHandler() const { return GetEvtHandler(); }
-    virtual wxEventFunction GetMethod() const { return NULL; }
+    // Test whether the given class info is the same as from this functor. This
+    // allows us in IsMatching to safely downcast the given wxEventFunctor without
+    // the usage of dynamic_cast<>().
+    virtual bool IsSameClass(wxEventFunctorClassInfo classInfo) const = 0;
 
-    // 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; }
+    // If the functor holds an wxEvtHandler, then get access to it and track
+    // its lifetime with wxEventConnectionRef:
+    virtual wxEvtHandler *GetEvtHandler() const
+        { return NULL; }
+
+    // This is only used to maintain backward compatibility in
+    // wxAppConsoleBase::CallEventHandler and ensures that an overwritten
+    // wxAppConsoleBase::HandleEvent is still called for functors which hold an
+    // wxEventFunction:
+    virtual wxEventFunction GetEvtMethod() const
+        { return NULL; }
 };
 
-// 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
+// A plain method functor for the untyped legacy event types:
 class WXDLLIMPEXP_BASE wxObjectEventFunctor : public wxEventFunctor
 {
 public:
     wxObjectEventFunctor(wxObjectEventFunction method, wxEvtHandler *handler)
+        : m_handler( handler ), m_method( method )
+        { }
+
+    virtual void operator()(wxEvtHandler *handler, wxEvent& event)
     {
-        m_handler = handler;
-        m_method = method;
-    }
+        wxEvtHandler * const realHandler = m_handler ? m_handler : handler;
 
-    virtual void operator()(wxEvtHandler *handler, wxEvent& event);
+        (realHandler->*m_method)(event);
+    }
 
-    virtual bool Matches(const wxEventFunctor& func) const
+    virtual bool IsMatching(const wxEventFunctor& functor) const
     {
-        void * const handler = func.GetHandler();
-        if ( handler && GetHandler() != handler )
-            return false;
+        if ( functor.IsSameClass( sm_classInfo ))
+        {
+            const wxObjectEventFunctor &other =
+                static_cast< const wxObjectEventFunctor & >( functor );
 
-        const wxEventFunction method = GetMethod();
+            // FIXME-VC6: amazing but true: replacing "method == NULL" here
+            // with "!method" makes VC6 crash with an ICE in DLL build (only!)
 
-        // FIXME-VC6: amazing but true: replacing "method == NULL" here with
-        //            "!method" makes VC6 crash with an ICE in DLL build (only!)
-        return method == NULL || GetMethod() == method;
+            return ( m_method == other.m_method || other.m_method == NULL ) &&
+                   ( m_handler == other.m_handler || other.m_handler == NULL );
+        }
+        else
+            return false;
     }
 
-    virtual wxEvtHandler *GetEvtHandler() const { return m_handler; }
-    virtual wxEventFunction GetMethod() const { return m_method; }
+    virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
+        { return sm_classInfo == otherClassInfo; }
+
+    virtual wxEvtHandler *GetEvtHandler() const
+        { return m_handler; }
+
+    virtual wxEventFunction GetEvtMethod() const
+        { return m_method; }
 
 private:
     wxEvtHandler *m_handler;
     wxEventFunction m_method;
-};
 
-#if wxEVENTS_COMPATIBILITY_2_8
+    wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
+};
 
 // Create a functor for the legacy events: used by Connect()
 inline wxObjectEventFunctor *
@@ -283,40 +312,7 @@ wxMakeEventFunctor(const wxEventType& WXUNUSED(evtType),
     return wxObjectEventFunctor(method, handler);
 }
 
-#else // !wxEVENTS_COMPATIBILITY_2_8
-
-// functor forwarding the event to anything callable (function, static method,
-// generalized functor...)
-template <typename EventTag, typename Functor>
-class wxEventFunctorFunction : public wxEventFunctor
-{
-public:
-    typedef typename EventTag::EventClass EventArg;
-
-    wxEventFunctorFunction(Functor handler)
-    {
-        m_handler = handler;
-    }
-
-    virtual void operator()(wxEvtHandler *WXUNUSED(handler), wxEvent& event)
-    {
-        m_handler(static_cast<EventArg&>(event));
-    }
-
-    virtual bool Matches(const wxEventFunctor& WXUNUSED(func)) const
-    {
-        // 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:
-    Functor m_handler;
-};
+#ifdef wxHAS_EVENT_BIND
 
 namespace wxPrivate
 {
@@ -356,7 +352,7 @@ struct HandlerImpl<T, A, true>
         { return static_cast<T *>(p); }
     static wxEvtHandler *ConvertToEvtHandler(T *p)
         { return p; }
-    static wxEventFunction ConvertToEvtFunction(void (T::*f)(A&))
+    static wxEventFunction ConvertToEvtMethod(void (T::*f)(A&))
         { return static_cast<wxEventFunction>(
                     reinterpret_cast<void (T::*)(wxEvent&)>(f)); }
 };
@@ -371,7 +367,7 @@ struct HandlerImpl<T, A, false>
         { return NULL; }
     static wxEvtHandler *ConvertToEvtHandler(T *)
         { return NULL; }
-    static wxEventFunction ConvertToEvtFunction(void (T::*)(A&))
+    static wxEventFunction ConvertToEvtMethod(void (T::*)(A&))
         { return NULL; }
 };
 
@@ -406,6 +402,7 @@ public:
 
 
     wxEventFunctorMethod(void (Class::*method)(EventArg&), EventHandler *handler)
+        : m_handler( handler ), m_method( method )
     {
         wxASSERT_MSG( handler || this->IsEvtHandler(),
                       "handlers defined in non-wxEvtHandler-derived classes "
@@ -415,9 +412,6 @@ public:
         // you're trying to use is not compatible with (i.e. is not the same as
         // or a base class of) the real event class used for this event type
         CheckHandlerArgument(static_cast<EventClass *>(NULL));
-
-        m_handler = handler;
-        m_method =  method;
     }
 
     virtual void operator()(wxEvtHandler *handler, wxEvent& event)
@@ -437,60 +431,179 @@ public:
         (realHandler->*m_method)(static_cast<EventArg&>(event));
     }
 
-    virtual bool Matches(const wxEventFunctor& func) const
+    virtual bool IsMatching(const wxEventFunctor& functor) const
     {
-        void * const handler = func.GetHandler();
-        if ( handler && GetHandler() != handler )
+        if ( !functor.IsSameClass(sm_classInfo) )
             return false;
 
-        const wxEventFunction method = GetMethod();
-        return !method || GetMethod() == method;
+        typedef wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>
+            ThisFunctor;
+
+        // the cast is valid because IsSameClass() returned true above
+        const ThisFunctor& other = static_cast<const ThisFunctor &>(functor);
+
+        return (m_method == other.m_method || other.m_method == NULL) &&
+               (m_handler == other.m_handler || other.m_handler == NULL);
     }
 
-    virtual void *GetHandler() const
+    virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
+        { return sm_classInfo == otherClassInfo; }
+
+    virtual wxEvtHandler *GetEvtHandler() const
+        { return this->ConvertToEvtHandler(m_handler); }
+
+    virtual wxEventFunction GetEvtMethod() const
+        { return this->ConvertToEvtMethod(m_method); }
+
+private:
+    EventHandler *m_handler;
+    void (Class::*m_method)(EventArg&);
+
+    wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
+};
+
+
+// functor forwarding the event to function (function, static method)
+template <typename EventTag, typename EventArg>
+class wxEventFunctorFunction : public wxEventFunctor
+{
+private:
+    static void CheckHandlerArgument(EventArg *) { }
+
+public:
+    // the event class associated with the given event tag
+    typedef typename wxPrivate::EventClassOf<EventTag>::type EventClass;
+
+    wxEventFunctorFunction( void ( *handler )( EventArg & ))
+        : m_handler( handler )
     {
-        return m_handler;
+        // if you get an error here it means that the signature of the handler
+        // you're trying to use is not compatible with (i.e. is not the same as
+        // or a base class of) the real event class used for this event type
+        CheckHandlerArgument(static_cast<EventClass *>(NULL));
     }
 
-    virtual wxEventFunction GetMethod() const
+    virtual void operator()(wxEvtHandler *WXUNUSED(handler), wxEvent& event)
     {
-        return this->ConvertToEvtFunction(m_method);
+        // If you get an error here like "must use .* or ->* to call
+        // pointer-to-member function" then you probably tried to call
+        // Bind/Unbind with a method pointer but without a handler pointer or
+        // NULL as a handler e.g.:
+        // Unbind( wxEVT_XXX, &EventHandler::method );
+        // or
+        // Unbind( wxEVT_XXX, &EventHandler::method, NULL )
+        m_handler(static_cast<EventArg&>(event));
     }
 
-    virtual wxEvtHandler *GetEvtHandler() const
+    virtual bool IsMatching(const wxEventFunctor &functor) const
     {
-        return this->ConvertToEvtHandler(m_handler);
+        if ( !functor.IsSameClass(sm_classInfo) )
+            return false;
+
+        typedef wxEventFunctorFunction<EventTag, EventArg> ThisFunctor;
+
+        const ThisFunctor& other = static_cast<const ThisFunctor&>( functor );
+
+        return m_handler == other.m_handler;
     }
 
+    virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
+        { return sm_classInfo == otherClassInfo; }
+
 private:
-    EventHandler *m_handler;
-    void (Class::*m_method)(EventArg&);
+    void (*m_handler)(EventArg&);
+
+    wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
 };
 
 
+template <typename EventTag, typename Functor>
+class wxEventFunctorFunctor : public wxEventFunctor
+{
+public:
+    typedef typename EventTag::EventClass EventArg;
+
+    wxEventFunctorFunctor(Functor& handler)
+        : m_handler(handler), m_handlerAddr(&handler)
+        { }
+
+    virtual void operator()(wxEvtHandler *WXUNUSED(handler), wxEvent& event)
+    {
+        // If you get an error here like "must use '.*' or '->*' to call
+        // pointer-to-member function" then you probably tried to call
+        // Bind/Unbind with a method pointer but without a handler pointer or
+        // NULL as a handler e.g.:
+        // Unbind( wxEVT_XXX, &EventHandler::method );
+        // or
+        // Unbind( wxEVT_XXX, &EventHandler::method, NULL )
+        m_handler(static_cast<EventArg&>(event));
+    }
+
+    virtual bool IsMatching(const wxEventFunctor &functor) const
+    {
+        if ( !functor.IsSameClass(sm_classInfo) )
+            return false;
+
+        typedef wxEventFunctorFunctor<EventTag, Functor> FunctorThis;
+
+        const FunctorThis& other = static_cast<const FunctorThis&>(functor);
+
+        // The only reliable/portable way to compare two functors is by
+        // identity:
+        return m_handlerAddr == other.m_handlerAddr;
+    }
+
+    virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
+        { return sm_classInfo == otherClassInfo; }
+
+private:
+    // Store a copy of the functor to prevent using/calling an already
+    // destroyed instance:
+    Functor m_handler;
+
+    // Use the address of the original functor for comparison in IsMatching:
+    const void *m_handlerAddr;
+
+    wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
+};
+
 // Create functors for the templatized events, either allocated on the heap for
 // wxNewXXX() variants (this is needed in wxEvtHandler::Bind<>() to store them
-// in dynamic event table) or just by returning them as temporary objects (this
+// in dynamic event table) or just by returning them as temporary objects (this
 // is enough for Unbind<>() and we avoid unnecessary heap allocation like this).
 
 
-// Create functors wrapping other functors (including functions):
-template <typename EventTag, typename Functor>
-inline wxEventFunctorFunction<EventTag, Functor> *
-wxNewEventFunctor(const EventTag&, Functor func)
+// Create functors wrapping functions:
+template <typename EventTag, typename EventArg>
+inline wxEventFunctorFunction<EventTag, EventArg> *
+wxNewEventFunctor(const EventTag&, void (*func)(EventArg &))
 {
-    return new wxEventFunctorFunction<EventTag, Functor>(func);
+    return new wxEventFunctorFunction<EventTag, EventArg>(func);
 }
 
+template <typename EventTag, typename EventArg>
+inline wxEventFunctorFunction<EventTag, EventArg>
+wxMakeEventFunctor(const EventTag&, void (*func)(EventArg &))
+{
+    return wxEventFunctorFunction<EventTag, EventArg>(func);
+}
+
+// Create functors wrapping other functors:
 template <typename EventTag, typename Functor>
-inline wxEventFunctorFunction<EventTag, Functor>
-wxMakeEventFunctor(const EventTag&, Functor func)
+inline wxEventFunctorFunctor<EventTag, Functor> *
+wxNewEventFunctor(const EventTag&, Functor &func)
 {
-    return wxEventFunctorFunction<EventTag, Functor>(func);
+    return new wxEventFunctorFunctor<EventTag, Functor>(func);
 }
 
+template <typename EventTag, typename Functor>
+inline wxEventFunctorFunctor<EventTag, Functor>
+wxMakeEventFunctor(const EventTag&, Functor &func)
+{
+    return wxEventFunctorFunctor<EventTag, Functor>(func);
+}
 
-// Create functors for methods:
+// Create functors wrapping methods:
 template
   <typename EventTag, typename Class, typename EventArg, typename EventHandler>
 inline wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler> *
@@ -524,7 +637,7 @@ wxNewEventTableFunctor(const EventTag&, void (Class::*method)(EventArg&))
                     method, NULL);
 }
 
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
 
 // many, but not all, standard event types
@@ -2871,7 +2984,7 @@ public:
                  wxObject *userData = NULL,
                  wxEvtHandler *eventSink = NULL)
     {
-        DoConnect(winid, lastId, eventType,
+        DoBind(winid, lastId, eventType,
                   wxNewEventFunctor(eventType, func, eventSink),
                   userData);
     }
@@ -2898,7 +3011,7 @@ public:
                     wxObject *userData = NULL,
                     wxEvtHandler *eventSink = NULL)
     {
-        return DoDisconnect(winid, lastId, eventType,
+        return DoUnbind(winid, lastId, eventType,
                             wxMakeEventFunctor(eventType, func, eventSink),
                             userData );
     }
@@ -2916,16 +3029,42 @@ public:
                     wxEvtHandler *eventSink = NULL)
         { return Disconnect(wxID_ANY, eventType, func, userData, eventSink); }
 
-#if !wxEVENTS_COMPATIBILITY_2_8
-    // Bind arbitrary functor (including just a function) to an event:
+#ifdef wxHAS_EVENT_BIND
+    // Bind functions to an event:
+    template <typename EventTag, typename EventArg>
+    void Bind(const EventTag& eventType,
+              void (*function)(EventArg &),
+              int winid = wxID_ANY,
+              int lastId = wxID_ANY,
+              wxObject *userData = NULL)
+    {
+        DoBind(winid, lastId, eventType,
+                  wxNewEventFunctor(eventType, function),
+                  userData);
+    }
+
+
+    template <typename EventTag, typename EventArg>
+    bool Unbind(const EventTag& eventType,
+                void (*function)(EventArg &),
+                int winid = wxID_ANY,
+                int lastId = wxID_ANY,
+                wxObject *userData = NULL)
+    {
+        return DoUnbind(winid, lastId, eventType,
+                            wxMakeEventFunctor(eventType, function),
+                            userData);
+    }
+
+    // Bind functors to an event:
     template <typename EventTag, typename Functor>
     void Bind(const EventTag& eventType,
-              Functor functor,
+              Functor &functor,
               int winid = wxID_ANY,
               int lastId = wxID_ANY,
               wxObject *userData = NULL)
     {
-        DoConnect(winid, lastId, eventType,
+        DoBind(winid, lastId, eventType,
                   wxNewEventFunctor(eventType, functor),
                   userData);
     }
@@ -2933,12 +3072,12 @@ public:
 
     template <typename EventTag, typename Functor>
     bool Unbind(const EventTag& eventType,
-                Functor functor,
+                Functor &functor,
                 int winid = wxID_ANY,
                 int lastId = wxID_ANY,
                 wxObject *userData = NULL)
     {
-        return DoDisconnect(winid, lastId, eventType,
+        return DoUnbind(winid, lastId, eventType,
                             wxMakeEventFunctor(eventType, functor),
                             userData);
     }
@@ -2955,7 +3094,7 @@ public:
               int lastId = wxID_ANY,
               wxObject *userData = NULL)
     {
-        DoConnect(winid, lastId, eventType,
+        DoBind(winid, lastId, eventType,
                   wxNewEventFunctor(eventType, method, handler),
                   userData);
     }
@@ -2968,11 +3107,11 @@ public:
                 int lastId = wxID_ANY,
                 wxObject *userData = NULL )
     {
-        return DoDisconnect(winid, lastId, eventType,
+        return DoUnbind(winid, lastId, eventType,
                             wxMakeEventFunctor(eventType, method, handler),
                             userData);
     }
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
     wxList* GetDynamicEventTable() const { return m_dynamicEvents ; }
 
@@ -3014,13 +3153,13 @@ public:
 
 
 private:
-    void DoConnect(int winid,
+    void DoBind(int winid,
                    int lastId,
                    wxEventType eventType,
                    wxEventFunctor *func,
                    wxObject* userData = NULL);
 
-    bool DoDisconnect(int winid,
+    bool DoUnbind(int winid,
                       int lastId,
                       wxEventType eventType,
                       const wxEventFunctor& func,
@@ -3155,13 +3294,6 @@ private:
     wxDECLARE_NO_ASSIGN_CLASS(wxEventConnectionRef);
 };
 
-inline void wxObjectEventFunctor::operator()(wxEvtHandler *handler, wxEvent& event)
-{
-    wxEvtHandler * const realHandler = m_handler ? m_handler : handler;
-
-    (realHandler->*m_method)(event);
-}
-
 // Post a message to the given event handler which will be processed during the
 // next event loop iteration.
 //
@@ -3771,17 +3903,17 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
 // (and not in a private header) because the base class must be visible from
 // other public headers, please do NOT use this in your code, it will be
 // removed from future wx versions without warning.
-#if wxEVENTS_COMPATIBILITY_2_8
+#ifndef wxHAS_EVENT_BIND
     #define wxBIND_OR_CONNECT_HACK_BASE_CLASS public wxEvtHandler,
     #define wxBIND_OR_CONNECT_HACK_ONLY_BASE_CLASS : public wxEvtHandler
     #define wxBIND_OR_CONNECT_HACK(w, evt, handler, func, obj) \
         win->Connect(evt, handler(func), NULL, obj)
-#else // wxEVENTS_COMPATIBILITY_2_8
+#else // wxHAS_EVENT_BIND
     #define wxBIND_OR_CONNECT_HACK_BASE_CLASS
     #define wxBIND_OR_CONNECT_HACK_ONLY_BASE_CLASS
     #define wxBIND_OR_CONNECT_HACK(w, evt, handler, func, obj) \
         win->Bind(evt, &func, obj)
-#endif // wxEVENTS_COMPATIBILITY_2_8/!wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
 #if wxUSE_GUI
 
index 22276fae0e2a0d4c1dce75b4b332872f0845b05b..ed27473c6f468a53a5ab11014e3cfe12b5c6ebdf 100644 (file)
     #define wxHAVE_RAW_BITMAP
 #endif
 
+/*
+   If this is defined, wxEvtHandler::Bind<>() is available (not all compilers
+   have the required template support for this and in particular under Windows
+   where only g++ and MSVC >= 7 currently support it, for the others it will be
+   undefined in wx/chkconf.h).
+ */
+#define wxHAS_EVENT_BIND
+
 #endif /*  _WX_FEATURES_H_ */
 
index f8ec92283a27ba3a241c6c095d130727bc9186c2..451b18c5380c2096c01a21c582d91881d2c33e4a 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index f855d59ab56b623ee81c9d92bed483dd9844af0a..db029d3d0ef4e206ad9de972ff78e430cba46918 100644 (file)
    Currently only recent MSVC compilers can build the new events code under
    Windows.
  */
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
 #   if !wxCHECK_VISUALC_VERSION(7)
-#       undef wxEVENTS_COMPATIBILITY_2_8
-#       define wxEVENTS_COMPATIBILITY_2_8 1
+#       undef wxHAS_EVENT_BIND
 #   endif
 #endif
 
index a598891110c3aa51c8fc9c7a176aef580c079464..a3471b7dc3a4890b6ae7f4f9af326b4d25770a54 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index 9ff4a0dccf88a2af44c0e927b60644e4df247ed8..300eecc4e9c2410c8902ff54931d08cb11f886b7 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index 2eebe1a1bb2b152cf18817e9279886df5630a996..04b27f059d67650316fc174d90a190d3ec62441a 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index d1a4b07b599dbf08b4f132bb4cd5da9214bd338c..ccf753d9fd1506448dacee9c2f8e4f65c9b1d7bf 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index f63d06e9df763ed5cf5e431abe6efdd40e8ab687..04917f436f03f9f8e31863e98c8bc0a4cb3cf273 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index 1112262abc9c0ad2dcb259257c89036d8465c095..4f21e8a492bfe5f60c2dff6c0bd0c92b82810891 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index e82d8e4c046a99d20e0e10a0520b3e88a4be32e3..3e8f5754a2372a6357276e21c74516a95170b4a9 100644 (file)
 // Recommended setting: 0 (please update your code)
 #define WXWIN_COMPATIBILITY_2_8 1
 
-// Use the 2.8-compatible events and Connect(): this is set to 0 by default as
-// the new events bring significant benefits in compile-time safety and
-// flexibility but can be disabled to somewhat reduce the compilation time and,
-// especially, to still allow building if the compiler template support is too
-// bad to compile the new code.
-//
-// Default is 0 but this is set to 1 automatically in wx/chkconf.h for the
-// compilers which can't build the new code (currently only g++ and MSVC >= 8
-// can)
-//
-// Recommended setting: 0
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
 // default system font is used for wxWindow::GetCharWidth/Height() instead of
 // the current font.
index 9c898852312c4db67246b1f39ad38cd12d2ee985..3cc8c01e55097537105e507504521f497999c9c3 100644 (file)
@@ -77,9 +77,9 @@ public:
 
     void OnQuit(wxCommandEvent& event);
     void OnAbout(wxCommandEvent& event);
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     void OnBind(wxCommandEvent& event);
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
     void OnConnect(wxCommandEvent& event);
     void OnDynamic(wxCommandEvent& event);
     void OnPushEventHandler(wxCommandEvent& event);
@@ -177,9 +177,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(Event_Quit,  MyFrame::OnQuit)
     EVT_MENU(Event_About, MyFrame::OnAbout)
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     EVT_MENU(Event_Bind, MyFrame::OnBind)
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
     EVT_MENU(Event_Connect, MyFrame::OnConnect)
 
     EVT_MENU(Event_Custom, MyFrame::OnFireCustom)
@@ -257,10 +257,10 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
     menuFile->Append(Event_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
 
     wxMenu *menuEvent = new wxMenu;
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     menuEvent->AppendCheckItem(Event_Bind, "&Bind\tCtrl-B",
                                "Bind or unbind a dynamic event handler");
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
     menuEvent->AppendCheckItem(Event_Connect, _T("&Connect\tCtrl-C"),
                      _T("Connect or disconnect the dynamic event handler"));
     menuEvent->Append(Event_Dynamic, _T("&Dynamic event\tCtrl-D"),
@@ -352,7 +352,7 @@ void MyFrame::OnDynamic(wxCommandEvent& event)
     );
 }
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
 
 void MyFrame::OnBind(wxCommandEvent& event)
 {
@@ -379,7 +379,7 @@ void MyFrame::OnBind(wxCommandEvent& event)
     UpdateDynamicStatus(event.IsChecked());
 }
 
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
 void MyFrame::OnConnect(wxCommandEvent& event)
 {
index 2d7250e6a106f2389551daee4506d143a19fbeea..d9e18f346d71d4e565ddd1e6d2912b30bb45cf0c 100644 (file)
 
 #define WXWIN_COMPATIBILITY_2_8 0
 
-#define wxEVENTS_COMPATIBILITY_2_8 0
-
 #define wxDIALOG_UNIT_COMPATIBILITY   0
 
 
index a3caf25a2bc244763b5e9cc17d6e45f7ac8905d2..269be5b5751e507090d4f37ee705b82ac2ee9f3c 100644 (file)
@@ -503,7 +503,7 @@ void wxAppConsoleBase::CallEventHandler(wxEvtHandler *handler,
 {
     // If the functor holds a method then, for backward compatibility, call
     // HandleEvent():
-    wxEventFunction eventFunction = functor.GetMethod();
+    wxEventFunction eventFunction = functor.GetEvtMethod();
 
     if ( eventFunction )
         HandleEvent(handler, eventFunction, event);
index e093e352d4400225ad948350b053cd0d5cdc76d3..34ec269af161a4d5e5a2dfc76cd14efeb4896992 100644 (file)
@@ -1415,11 +1415,11 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
     return false;
 }
 
-void wxEvtHandler::DoConnect(int id,
-                             int lastId,
-                             wxEventType eventType,
-                             wxEventFunctor *func,
-                             wxObject *userData)
+void wxEvtHandler::DoBind(int id,
+                          int lastId,
+                          wxEventType eventType,
+                          wxEventFunctor *func,
+                          wxObject *userData)
 {
     wxDynamicEventTableEntry *entry =
         new wxDynamicEventTableEntry(eventType, id, lastId, func, userData);
@@ -1443,11 +1443,11 @@ void wxEvtHandler::DoConnect(int id,
 }
 
 bool
-wxEvtHandler::DoDisconnect(int id,
-                           int lastId,
-                           wxEventType eventType,
-                           const wxEventFunctor& func,
-                           wxObject *userData)
+wxEvtHandler::DoUnbind(int id,
+                       int lastId,
+                       wxEventType eventType,
+                       const wxEventFunctor& func,
+                       wxObject *userData)
 {
     if (!m_dynamicEvents)
         return false;
@@ -1469,7 +1469,7 @@ wxEvtHandler::DoDisconnect(int id,
         if ((entry->m_id == id) &&
             ((entry->m_lastId == lastId) || (lastId == wxID_ANY)) &&
             ((entry->m_eventType == eventType) || (eventType == wxEVT_NULL)) &&
-            entry->m_fn->Matches(func) &&
+            entry->m_fn->IsMatching(func) &&
             ((entry->m_callbackUserData == userData) || !userData))
         {
             delete entry->m_callbackUserData;
index f51360a2020522e3c95175e5367f4aa1f55eb42d..0f49b1a1791ba2ac8c8d7627e93622a350aee86c 100644 (file)
@@ -37,7 +37,7 @@ public:
 };
 
 typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&);
-#if wxEVENTS_COMPATIBILITY_2_8
+#ifndef wxHAS_EVENT_BIND
     #define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func)
 #else
     #define MyEventHandler(func) &func
@@ -75,6 +75,11 @@ void GlobalOnMyEvent(MyEvent&)
     g_called.function = true;
 }
 
+void GlobalOnEvent(wxEvent&)
+{
+    g_called.function = true;
+}
+
 void GlobalOnAnotherEvent(AnotherEvent&);
 
 void GlobalOnIdle(wxIdleEvent&)
@@ -130,7 +135,7 @@ BEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
     EVT_IDLE(MyClassWithEventTable::OnIdle)
 
     EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     EVT_MYEVENT(MyClassWithEventTable::OnEvent)
 #endif
 
@@ -155,28 +160,30 @@ private:
     CPPUNIT_TEST_SUITE( EvtHandlerTestCase );
         CPPUNIT_TEST( BuiltinConnect );
         CPPUNIT_TEST( LegacyConnect );
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
         CPPUNIT_TEST( BindFunction );
         CPPUNIT_TEST( BindStaticMethod );
         CPPUNIT_TEST( BindFunctor );
         CPPUNIT_TEST( BindMethod );
         CPPUNIT_TEST( BindMethodUsingBaseEvent );
+        CPPUNIT_TEST( BindFunctionUsingBaseEvent );
         CPPUNIT_TEST( BindNonHandler );
         CPPUNIT_TEST( InvalidBind );
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
     CPPUNIT_TEST_SUITE_END();
 
     void BuiltinConnect();
     void LegacyConnect();
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     void BindFunction();
     void BindStaticMethod();
     void BindFunctor();
     void BindMethod();
     void BindMethodUsingBaseEvent();
+    void BindFunctionUsingBaseEvent();
     void BindNonHandler();
     void InvalidBind();
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 
 
     // these member variables exceptionally don't use "m_" prefix because
@@ -206,7 +213,7 @@ void EvtHandlerTestCase::BuiltinConnect()
     handler.Connect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
     handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
     handler.Bind(wxEVT_IDLE, GlobalOnIdle);
     handler.Unbind(wxEVT_IDLE, GlobalOnIdle);
 
@@ -219,7 +226,7 @@ void EvtHandlerTestCase::BuiltinConnect()
 
     handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
     handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND
 }
 
 void EvtHandlerTestCase::LegacyConnect()
@@ -242,7 +249,7 @@ void EvtHandlerTestCase::LegacyConnect()
     handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, NULL, &handler );
 }
 
-#if !wxEVENTS_COMPATIBILITY_2_8
+#ifdef wxHAS_EVENT_BIND
 
 void EvtHandlerTestCase::BindFunction()
 {
@@ -345,6 +352,29 @@ void EvtHandlerTestCase::BindMethodUsingBaseEvent()
 }
 
 
+void EvtHandlerTestCase::BindFunctionUsingBaseEvent()
+{
+    // test connecting a function taking just wxEvent and not MyEvent: this
+    // should work too if we don't need any MyEvent-specific information in the
+    // handler
+    handler.Bind( MyEventType, GlobalOnEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( g_called.function );
+    handler.Unbind( MyEventType, GlobalOnEvent );
+    g_called.Reset();
+    handler.ProcessEvent(e);
+    CPPUNIT_ASSERT( !g_called.function );
+
+    handler.Bind( MyEventType, GlobalOnEvent, 0 );
+    handler.Unbind( MyEventType, GlobalOnEvent, 0 );
+
+    handler.Bind( MyEventType, GlobalOnEvent, 0, 0 );
+    handler.Unbind( MyEventType, GlobalOnEvent, 0, 0 );
+}
+
+
+
 void EvtHandlerTestCase::BindNonHandler()
 {
     // class method tests for class not derived from wxEvtHandler
@@ -402,4 +432,4 @@ void EvtHandlerTestCase::InvalidBind()
 #endif
 }
 
-#endif // !wxEVENTS_COMPATIBILITY_2_8
+#endif // wxHAS_EVENT_BIND