]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/event.cpp
Reorganize wxCollapsiblePane event and layout code under GTK+
[wxWidgets.git] / src / common / event.cpp
index 9eb05a0bbfa01d36e65345fcd315e6c4a61adce9..85951a1b3eb7c32e2681cd44e117f3c053748a0a 100644 (file)
@@ -38,6 +38,7 @@
         #include "wx/window.h"
         #include "wx/control.h"
         #include "wx/dc.h"
+        #include "wx/spinbutt.h"
         #include "wx/textctrl.h"
         #include "wx/validate.h"
     #endif // wxUSE_GUI
@@ -232,6 +233,21 @@ wxDEFINE_EVENT( wxEVT_SCROLL_THUMBTRACK, wxScrollEvent )
 wxDEFINE_EVENT( wxEVT_SCROLL_THUMBRELEASE, wxScrollEvent )
 wxDEFINE_EVENT( wxEVT_SCROLL_CHANGED, wxScrollEvent )
 
+// Due to a bug in older wx versions, wxSpinEvents were being sent with type of
+// wxEVT_SCROLL_LINEUP, wxEVT_SCROLL_LINEDOWN and wxEVT_SCROLL_THUMBTRACK. But
+// with the type-safe events in place, these event types are associated with
+// wxScrollEvent. To allow handling of spin events, new event types have been
+// defined in spinbutt.h/spinnbuttcmn.cpp. To maintain backward compatibility
+// the spin event types are being initialized with the scroll event types.
+
+#if wxUSE_SPINBTN
+
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_UP,   wxSpinEvent, wxEVT_SCROLL_LINEUP )
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_DOWN, wxSpinEvent, wxEVT_SCROLL_LINEDOWN )
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN,      wxSpinEvent, wxEVT_SCROLL_THUMBTRACK )
+
+#endif // wxUSE_SPINBTN
+
 // Scroll events from wxWindow
 wxDEFINE_EVENT( wxEVT_SCROLLWIN_TOP, wxScrollWinEvent )
 wxDEFINE_EVENT( wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEvent )
@@ -352,6 +368,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType )
     m_callbackUserData = NULL;
     m_isCommandEvent = false;
     m_propagationLevel = wxEVENT_PROPAGATE_NONE;
+    m_wasProcessed = false;
 }
 
 wxEvent::wxEvent(const wxEvent& src)
@@ -364,6 +381,7 @@ wxEvent::wxEvent(const wxEvent& src)
     , m_propagationLevel(src.m_propagationLevel)
     , m_skipped(src.m_skipped)
     , m_isCommandEvent(src.m_isCommandEvent)
+    , m_wasProcessed(false)
 {
 }
 
@@ -380,6 +398,8 @@ wxEvent& wxEvent::operator=(const wxEvent& src)
     m_skipped = src.m_skipped;
     m_isCommandEvent = src.m_isCommandEvent;
 
+    // don't change m_wasProcessed
+
     return *this;
 }
 
@@ -895,11 +915,9 @@ bool wxEventHashTable::HandleEvent(wxEvent &event, wxEvtHandler *self)
         const size_t count = eventEntryTable.GetCount();
         for (size_t n = 0; n < count; n++)
         {
-            if ( wxEvtHandler::
-                    ProcessEventIfMatches(*eventEntryTable[n], self, event) )
-            {
+            const wxEventTableEntry& entry = *eventEntryTable[n];
+            if ( wxEvtHandler::ProcessEventIfMatchesId(entry, self, event) )
                 return true;
-            }
         }
     }
 
@@ -1034,12 +1052,7 @@ wxEvtHandler::wxEvtHandler()
 
 wxEvtHandler::~wxEvtHandler()
 {
-    // Takes itself out of the list of handlers
-    if (m_previousHandler)
-        m_previousHandler->m_nextHandler = m_nextHandler;
-
-    if (m_nextHandler)
-        m_nextHandler->m_previousHandler = m_previousHandler;
+    Unlink();
 
     if (m_dynamicEvents)
     {
@@ -1101,6 +1114,26 @@ wxEvtHandler::~wxEvtHandler()
         delete m_clientObject;
 }
 
+void wxEvtHandler::Unlink()
+{
+    // this event handler must take itself out of the chain of handlers:
+
+    if (m_previousHandler)
+        m_previousHandler->SetNextHandler(m_nextHandler);
+
+    if (m_nextHandler)
+        m_nextHandler->SetPreviousHandler(m_previousHandler);
+
+    m_nextHandler = NULL;
+    m_previousHandler = NULL;
+}
+
+bool wxEvtHandler::IsUnlinked() const
+{
+    return m_previousHandler == NULL &&
+           m_nextHandler == NULL;
+}
+
 #if wxUSE_THREADS
 
 bool wxEvtHandler::ProcessThreadEvent(const wxEvent& event)
@@ -1198,9 +1231,9 @@ void wxEvtHandler::ProcessPendingEvents()
  * Event table stuff
  */
 /* static */ bool
-wxEvtHandler::ProcessEventIfMatches(const wxEventTableEntryBase& entry,
-                                    wxEvtHandler *handler,
-                                    wxEvent& event)
+wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
+                                      wxEvtHandler *handler,
+                                      wxEvent& event)
 {
     int tableId1 = entry.m_id,
         tableId2 = entry.m_lastId;
@@ -1265,22 +1298,35 @@ bool wxEvtHandler::TryParent(wxEvent& event)
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
     // allow the application to hook into event processing
-    if ( wxTheApp )
+    //
+    // note that we should only do it if we're the first event handler called
+    // to avoid calling FilterEvent() multiple times as the event goes through
+    // the event handler chain and possibly upwards the window hierarchy
+    if ( !event.WasProcessed() )
     {
-        int rc = wxTheApp->FilterEvent(event);
-        if ( rc != -1 )
+        if ( wxTheApp )
         {
-            wxASSERT_MSG( rc == 1 || rc == 0,
-                          _T("unexpected wxApp::FilterEvent return value") );
+            int rc = wxTheApp->FilterEvent(event);
+            if ( rc != -1 )
+            {
+                wxASSERT_MSG( rc == 1 || rc == 0,
+                              "unexpected wxApp::FilterEvent return value" );
 
-            return rc != 0;
+                return rc != 0;
+            }
+            //else: proceed normally
         }
-        //else: proceed normally
     }
 
     if ( ProcessEventHere(event) )
         return true;
 
+    // pass the event to the next handler, notice that we shouldn't call
+    // TryParent() even if it doesn't handle the event as the last handler in
+    // the chain will do it
+    if ( GetNextHandler() )
+        return GetNextHandler()->ProcessEvent(event);
+
     // propagate the event upwards the window chain and/or to the application
     // object if it wasn't processed at this level
     return TryParent(event);
@@ -1288,25 +1334,21 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
 
 bool wxEvtHandler::ProcessEventHere(wxEvent& event)
 {
-    // An event handler can be enabled or disabled
-    if ( GetEvtHandlerEnabled() )
-    {
-        // if we have a validator, it has higher priority than our own event
-        // table
-        if ( TryValidator(event) )
-            return true;
+    // If the event handler is disabled it doesn't process any events
+    if ( !GetEvtHandlerEnabled() )
+        return false;
 
-        // Handle per-instance dynamic event tables first
-        if ( m_dynamicEvents && SearchDynamicEventTable(event) )
-            return true;
+    // If we have a validator, it has higher priority than our own event
+    // handlers
+    if ( TryValidator(event) )
+        return true;
 
-        // Then static per-class event tables
-        if ( GetEventHashTable().HandleEvent(event, this) )
-            return true;
-    }
+    // Handle per-instance dynamic event tables first
+    if ( m_dynamicEvents && SearchDynamicEventTable(event) )
+        return true;
 
-    // Try going down the event handler chain
-    if ( GetNextHandler() && GetNextHandler()->ProcessEventHere(event) )
+    // Then static per-class event tables
+    if ( GetEventHashTable().HandleEvent(event, this) )
         return true;
 
     // We don't have a handler for this event.
@@ -1358,7 +1400,7 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
         const wxEventTableEntry& entry = table.entries[i];
         if ( eventType == entry.m_eventType )
         {
-            if ( ProcessEventIfMatches(entry, this, event) )
+            if ( ProcessEventIfMatchesId(entry, this, event) )
                 return true;
         }
     }
@@ -1419,7 +1461,7 @@ wxEvtHandler::Unsubscribe(int id,
         if ((entry->m_id == id) &&
             ((entry->m_lastId == lastId) || (lastId == wxID_ANY)) &&
             ((entry->m_eventType == eventType) || (eventType == wxEVT_NULL)) &&
-            (*entry->m_fn == func) &&
+            entry->m_fn->Matches(func) &&
             ((entry->m_callbackUserData == userData) || !userData))
         {
             delete entry->m_callbackUserData;
@@ -1446,10 +1488,12 @@ bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
         // call Disconnect() invalidating the current node
         node = node->GetNext();
 
-        if ((event.GetEventType() == entry->m_eventType) && (entry->m_fn != 0))
+        if ( event.GetEventType() == entry->m_eventType )
         {
-            wxEvtHandler *handler = entry->m_fn->GetHandler() ? entry->m_fn->GetHandler() : this;
-            if ( ProcessEventIfMatches(*entry, handler, event) )
+            wxEvtHandler *handler = entry->m_fn->GetHandler();
+            if ( !handler )
+               handler = this;
+            if ( ProcessEventIfMatchesId(*entry, handler, event) )
                 return true;
         }
     }