]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/event.h
fixed wxVector<T> to work with non-POD types again; added optimization to keep using...
[wxWidgets.git] / include / wx / event.h
index ffea5e3562f68ce87b5215c226891bcca8c5f96b..55e8cf5f31a42690cfc28c3647b6c8bb1164e0ff 100644 (file)
 #endif
 
 #include "wx/dynarray.h"
+#include "wx/thread.h"
+#include "wx/tracker.h"
 
 // ----------------------------------------------------------------------------
 // forward declarations
 // ----------------------------------------------------------------------------
 
 class WXDLLIMPEXP_FWD_BASE wxList;
-#if wxUSE_THREADS
-    class WXDLLIMPEXP_FWD_BASE wxCriticalSection;
-#endif
 #if wxUSE_GUI
     class WXDLLIMPEXP_FWD_CORE wxDC;
     class WXDLLIMPEXP_FWD_CORE wxMenu;
@@ -40,6 +39,7 @@ class WXDLLIMPEXP_FWD_BASE wxList;
 #endif // wxUSE_GUI
 
 class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
+class wxEventConnectionRef;
 
 // ----------------------------------------------------------------------------
 // Event types
@@ -53,47 +53,6 @@ typedef int wxEventType;
 // handler only a function with proper parameter list can be given.
 #define wxStaticCastEvent(type, val) wx_static_cast(type, val)
 
-// in previous versions of wxWidgets the event types used to be constants
-// which created difficulties with custom/user event types definition
-//
-// starting from wxWidgets 2.4 the event types are now dynamically assigned
-// using wxNewEventType() which solves this problem, however at price of
-// several incompatibilities:
-//
-//  a) event table macros declaration changed, it now uses wxEventTableEntry
-//     ctor instead of initialisation from an agregate - the macro
-//     DECLARE_EVENT_TABLE_ENTRY may be used to write code which can compile
-//     with all versions of wxWidgets
-//
-//  b) event types can't be used as switch() cases as they're not really
-//     constant any more - there is no magic solution here, you just have to
-//     change the switch()es to if()s
-//
-// if these are real problems for you, define WXWIN_COMPATIBILITY_EVENT_TYPES
-// as 1 to get 100% old behaviour, however you won't be able to use the
-// libraries using the new dynamic event type allocation in such case, so avoid
-// it if possible.
-#ifndef WXWIN_COMPATIBILITY_EVENT_TYPES
-    #define WXWIN_COMPATIBILITY_EVENT_TYPES 0
-#endif
-
-#if WXWIN_COMPATIBILITY_EVENT_TYPES
-
-#define DECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj) \
-    { type, winid, idLast, fn, obj }
-
-#define BEGIN_DECLARE_EVENT_TYPES() enum {
-#define END_DECLARE_EVENT_TYPES() };
-#define DECLARE_EVENT_TYPE(name, value) name = wxEVT_FIRST + value,
-#define DECLARE_LOCAL_EVENT_TYPE(name, value) name = wxEVT_USER_FIRST + value,
-#define DECLARE_EXPORTED_EVENT_TYPE(expdecl, name, value) \
-    DECLARE_LOCAL_EVENT_TYPE(name, value)
-#define DEFINE_EVENT_TYPE(name)
-#define DEFINE_LOCAL_EVENT_TYPE(name)
-
-
-#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
-
 #define DECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj) \
     wxEventTableEntry(type, winid, idLast, fn, obj)
 
@@ -111,21 +70,12 @@ typedef int wxEventType;
 // generate a new unique event type
 extern WXDLLIMPEXP_BASE wxEventType wxNewEventType();
 
-#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
-
 BEGIN_DECLARE_EVENT_TYPES()
-
-#if WXWIN_COMPATIBILITY_EVENT_TYPES
-    wxEVT_NULL = 0,
-    wxEVT_FIRST = 10000,
-    wxEVT_USER_FIRST = wxEVT_FIRST + 2000,
-#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
     // it is important to still have these as constants to avoid
     // initialization order related problems
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_NULL, 0)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_FIRST, 10000)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_BASE, wxEVT_USER_FIRST, wxEVT_FIRST + 2000)
-#endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES
 
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_BUTTON_CLICKED, 1)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_CHECKBOX_CLICKED, 2)
@@ -133,13 +83,6 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED, 4)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 5)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 6)
-    // now they are in wx/textctrl.h
-#if WXWIN_COMPATIBILITY_EVENT_TYPES
-    DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED, 7)
-    DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER, 8)
-    DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL, 13)
-    DECLARE_EVENT_TYPE(wxEVT_COMMAND_TEXT_MAXLEN, 14)
-#endif // WXWIN_COMPATIBILITY_EVENT_TYPES
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED, 9)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED, 10)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED, 11)
@@ -312,9 +255,7 @@ END_DECLARE_EVENT_TYPES()
 // wx/textctrl.h in all ports [yet], so declare it here as well
 //
 // still, any new code using it should include wx/textctrl.h explicitly
-#if !WXWIN_COMPATIBILITY_EVENT_TYPES
-    extern const wxEventType WXDLLIMPEXP_CORE wxEVT_COMMAND_TEXT_UPDATED;
-#endif
+extern const wxEventType WXDLLIMPEXP_CORE wxEVT_COMMAND_TEXT_UPDATED;
 
 // the predefined constants for the number of times we propagate event
 // upwards window child-parent chain
@@ -838,7 +779,7 @@ public:
 
     virtual wxEvent *Clone() const { return new wxMouseEvent(*this); }
 
-    wxMouseEvent& operator=(const wxMouseEvent& event) { Assign(event); return *this; }
+    wxMouseEvent& operator=(const wxMouseEvent& event) { if (&event != this) Assign(event); return *this; }
 
 public:
     wxCoord m_x, m_y;
@@ -994,33 +935,30 @@ public:
     // Get Y position
     wxCoord GetY() const { return m_y; }
 
-#if WXWIN_COMPATIBILITY_2_6
-    // deprecated, Use GetKeyCode instead.
-    wxDEPRECATED( long KeyCode() const );
-#endif // WXWIN_COMPATIBILITY_2_6
-
     virtual wxEvent *Clone() const { return new wxKeyEvent(*this); }
 
     // we do need to copy wxKeyEvent sometimes (in wxTreeCtrl code, for
     // example)
     wxKeyEvent& operator=(const wxKeyEvent& evt)
     {
-        m_x = evt.m_x;
-        m_y = evt.m_y;
-
-        m_keyCode = evt.m_keyCode;
-
-        m_controlDown = evt.m_controlDown;
-        m_shiftDown = evt.m_shiftDown;
-        m_altDown = evt.m_altDown;
-        m_metaDown = evt.m_metaDown;
-        m_scanCode = evt.m_scanCode;
-        m_rawCode = evt.m_rawCode;
-        m_rawFlags = evt.m_rawFlags;
+        if (&evt != this)
+        {
+            m_x = evt.m_x;
+            m_y = evt.m_y;
+
+            m_keyCode = evt.m_keyCode;
+
+            m_controlDown = evt.m_controlDown;
+            m_shiftDown = evt.m_shiftDown;
+            m_altDown = evt.m_altDown;
+            m_metaDown = evt.m_metaDown;
+            m_scanCode = evt.m_scanCode;
+            m_rawCode = evt.m_rawCode;
+            m_rawFlags = evt.m_rawFlags;
 #if wxUSE_UNICODE
-        m_uniChar = evt.m_uniChar;
+            m_uniChar = evt.m_uniChar;
 #endif
-
+        }
         return *this;
     }
 
@@ -2169,25 +2107,6 @@ private:
 // as a wxObject method even though it can only be a wxEvtHandler one
 typedef void (wxObject::*wxObjectEventFunction)(wxEvent&);
 
-// we can't have ctors nor base struct in backwards compatibility mode or
-// otherwise we won't be able to initialize the objects with an agregate, so
-// we have to keep both versions
-#if WXWIN_COMPATIBILITY_EVENT_TYPES
-
-struct WXDLLIMPEXP_BASE wxEventTableEntry
-{
-    // For some reason, this can't be wxEventType, or VC++ complains.
-    int m_eventType;            // main event type
-    int m_id;                   // control/menu/toolbar id
-    int m_lastId;               // used for ranges of ids
-    wxObjectEventFunction m_fn; // function to call: not wxEventFunction,
-                                // because of dependency problems
-
-    wxObject* m_callbackUserData;
-};
-
-#else // !WXWIN_COMPATIBILITY_EVENT_TYPES
-
 // struct containing the members common to static and dynamic event tables
 // entries
 struct WXDLLIMPEXP_BASE wxEventTableEntryBase
@@ -2267,8 +2186,6 @@ struct WXDLLIMPEXP_BASE wxDynamicEventTableEntry : public wxEventTableEntryBase
     DECLARE_NO_COPY_CLASS(wxDynamicEventTableEntry)
 };
 
-#endif // !WXWIN_COMPATIBILITY_EVENT_TYPES
-
 // ----------------------------------------------------------------------------
 // wxEventTable: an array of event entries terminated with {0, 0, 0, 0, 0}
 // ----------------------------------------------------------------------------
@@ -2346,7 +2263,7 @@ protected:
 // wxEvtHandler: the base class for all objects handling wxWidgets events
 // ----------------------------------------------------------------------------
 
-class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject
+class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject, public wxTrackable
 {
 public:
     wxEvtHandler();
@@ -2444,12 +2361,9 @@ public:
     virtual bool SearchEventTable(wxEventTable& table, wxEvent& event);
     bool SearchDynamicEventTable( wxEvent& event );
 
-#if wxUSE_THREADS
-    void ClearEventLocker();
-#endif // wxUSE_THREADS
-
     // Avoid problems at exit by cleaning up static hash table gracefully
     void ClearEventHashTable() { GetEventHashTable().Clear(); }
+    void OnSinkDestroyed( wxEvtHandler *sink );
 
 private:
     static const wxEventTableEntry sm_eventTableEntries[];
@@ -2487,18 +2401,9 @@ protected:
     wxList*             m_pendingEvents;
 
 #if wxUSE_THREADS
-#if defined (__VISAGECPP__)
-    const wxCriticalSection& Lock() const { return m_eventsLocker; }
-    wxCriticalSection& Lock() { return m_eventsLocker; }
-
-    wxCriticalSection   m_eventsLocker;
-#  else
-    const wxCriticalSection& Lock() const { return *m_eventsLocker; }
-    wxCriticalSection& Lock() { return *m_eventsLocker; }
-
-    wxCriticalSection*  m_eventsLocker;
-#  endif
-#endif
+    // critical section protecting m_pendingEvents
+    wxCriticalSection m_pendingEventsLock;
+#endif // wxUSE_THREADS
 
     // Is event handler enabled?
     bool                m_enabled;
@@ -2525,10 +2430,62 @@ protected:
     virtual void DoSetClientData( void *data );
     virtual void *DoGetClientData() const;
 
+    // Search tracker objects for event connection with this sink
+    wxEventConnectionRef *FindRefInTrackerList(wxEvtHandler *eventSink);
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
 };
 
+// ----------------------------------------------------------------------------
+// wxEventConnectionRef represents all connections between two event handlers
+// and enables automatic disconnect when an event handler sink goes out of
+// scope. Each connection/disconnect increases/decreases ref count, and
+// when it reaches zero the node goes out of scope.
+// ----------------------------------------------------------------------------
+
+class wxEventConnectionRef : public wxTrackerNode
+{
+public:
+    wxEventConnectionRef() : m_src(NULL), m_sink(NULL), m_refCount(0) { }
+    wxEventConnectionRef(wxEvtHandler *src, wxEvtHandler *sink)
+        : m_src(src), m_sink(sink), m_refCount(1)
+    {
+        m_sink->AddNode(this);
+    }
+
+    // The sink is being destroyed
+    virtual void OnObjectDestroy( )
+    {
+        if ( m_src )
+            m_src->OnSinkDestroyed( m_sink );
+        delete this;
+    }
+
+    virtual wxEventConnectionRef *ToEventConnection() { return this; }
+
+    void IncRef() { m_refCount++; }
+    void DecRef()
+    {
+        if ( !--m_refCount )
+        {
+            // The sink holds the only external pointer to this object
+            if ( m_sink )
+                m_sink->RemoveNode(this);
+            delete this;
+        }
+    }
+
+private:
+    wxEvtHandler *m_src,
+                 *m_sink;
+    int m_refCount;
+
+    friend class wxEvtHandler;
+
+    DECLARE_NO_ASSIGN_CLASS(wxEventConnectionRef)
+};
+
 // Post a message to the given eventhandler which will be processed during the
 // next event loop iteration
 inline void wxPostEvent(wxEvtHandler *dest, const wxEvent& event)
@@ -3093,8 +3050,9 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
 // Global data
 // ----------------------------------------------------------------------------
 
-// for pending event processing - notice that there is intentionally no
-// WXDLLEXPORT here
+// list containing event handlers with pending events for them
+//
+// notice that each event handler should occur at most once in this list
 extern WXDLLIMPEXP_BASE wxList *wxPendingEvents;
 #if wxUSE_THREADS
     extern WXDLLIMPEXP_BASE wxCriticalSection *wxPendingEventsLocker;