]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/event.cpp
Show OLE errors using wxLogDebug() in wxAutomationObject.
[wxWidgets.git] / src / common / event.cpp
index 2a4ff7954eb41a67415195d9141421743cbcb563..b6c0144752529d3bc6fae6a13971db34c6030464 100644 (file)
@@ -126,7 +126,7 @@ const wxEventTableEntry wxEvtHandler::sm_eventTableEntries[] =
 // the memory leaks when using it, however this breaks re-initializing the
 // library (i.e. repeated calls to wxInitialize/wxUninitialize) because the
 // event tables won't be rebuilt the next time, so disable this by default
-#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING
+#if wxUSE_MEMORY_TRACING
 
 class wxEventTableEntryModule: public wxModule
 {
@@ -140,7 +140,7 @@ public:
 
 IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule)
 
-#endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING
+#endif // wxUSE_MEMORY_TRACING
 
 // ----------------------------------------------------------------------------
 // global variables
@@ -177,6 +177,8 @@ wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_ENTER, wxCommandEvent );
 wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEvent );
 wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, wxCommandEvent );
 wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_DROPDOWN, wxCommandEvent);
+wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_CLOSEUP, wxCommandEvent);
 
 // Mouse event types
 wxDEFINE_EVENT( wxEVT_LEFT_DOWN, wxMouseEvent );
@@ -364,6 +366,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType)
     m_isCommandEvent = false;
     m_propagationLevel = wxEVENT_PROPAGATE_NONE;
     m_wasProcessed = false;
+    m_processHereOnly = false;
 }
 
 wxEvent::wxEvent(const wxEvent& src)
@@ -377,6 +380,7 @@ wxEvent::wxEvent(const wxEvent& src)
     , m_skipped(src.m_skipped)
     , m_isCommandEvent(src.m_isCommandEvent)
     , m_wasProcessed(false)
+    , m_processHereOnly(false)
 {
 }
 
@@ -393,7 +397,7 @@ wxEvent& wxEvent::operator=(const wxEvent& src)
     m_skipped = src.m_skipped;
     m_isCommandEvent = src.m_isCommandEvent;
 
-    // don't change m_wasProcessed
+    // don't change m_wasProcessed nor m_processHereOnly
 
     return *this;
 }
@@ -701,34 +705,6 @@ bool wxMouseEvent::Button(int but) const
     }
 }
 
-bool wxMouseEvent::ButtonIsDown(int but) const
-{
-    switch (but)
-    {
-        default:
-            wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonIsDown"));
-            // fall through
-
-        case wxMOUSE_BTN_ANY:
-            return LeftIsDown() || MiddleIsDown() || RightIsDown() || Aux1Down() || Aux2Down();
-
-        case wxMOUSE_BTN_LEFT:
-            return LeftIsDown();
-
-        case wxMOUSE_BTN_MIDDLE:
-            return MiddleIsDown();
-
-        case wxMOUSE_BTN_RIGHT:
-            return RightIsDown();
-
-        case wxMOUSE_BTN_AUX1:
-            return Aux1IsDown();
-
-        case wxMOUSE_BTN_AUX2:
-            return Aux2IsDown();
-    }
-}
-
 int wxMouseEvent::GetButton() const
 {
     for ( int i = 1; i < wxMOUSE_BTN_MAX; i++ )
@@ -778,6 +754,46 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt)
 #endif
 }
 
+bool wxKeyEvent::IsKeyInCategory(int category) const
+{
+    switch ( GetKeyCode() )
+    {
+        case WXK_LEFT:
+        case WXK_RIGHT:
+        case WXK_UP:
+        case WXK_DOWN:
+        case WXK_NUMPAD_LEFT:
+        case WXK_NUMPAD_RIGHT:
+        case WXK_NUMPAD_UP:
+        case WXK_NUMPAD_DOWN:
+            return (category & WXK_CATEGORY_ARROW) != 0;
+
+        case WXK_PAGEDOWN:
+        case WXK_END:
+        case WXK_NUMPAD_PAGEUP:
+        case WXK_NUMPAD_PAGEDOWN:
+            return (category & WXK_CATEGORY_PAGING) != 0;
+
+        case WXK_HOME:
+        case WXK_PAGEUP:
+        case WXK_NUMPAD_HOME:
+        case WXK_NUMPAD_END:
+            return (category & WXK_CATEGORY_JUMP) != 0;
+
+        case WXK_TAB:
+        case WXK_NUMPAD_TAB:
+            return (category & WXK_CATEGORY_TAB) != 0;
+
+        case WXK_BACK:
+        case WXK_DELETE:
+        case WXK_NUMPAD_DELETE:
+            return (category & WXK_CATEGORY_CUT) != 0;
+
+        default:
+            return false;
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxWindowCreateEvent
 // ----------------------------------------------------------------------------
@@ -876,7 +892,7 @@ void wxEventHashTable::Clear()
     m_size = 0;
 }
 
-#if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING
+#if wxUSE_MEMORY_TRACING
 
 // Clear all tables
 void wxEventHashTable::ClearAll()
@@ -889,7 +905,7 @@ void wxEventHashTable::ClearAll()
     }
 }
 
-#endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING
+#endif // wxUSE_MEMORY_TRACING
 
 bool wxEventHashTable::HandleEvent(wxEvent &event, wxEvtHandler *self)
 {
@@ -1305,7 +1321,7 @@ bool wxEvtHandler::DoTryApp(wxEvent& event)
 
 bool wxEvtHandler::TryBefore(wxEvent& event)
 {
-#ifdef WXWIN_COMPATIBILITY_2_8
+#if WXWIN_COMPATIBILITY_2_8
     // call the old virtual function to keep the code overriding it working
     return TryValidator(event);
 #else
@@ -1316,7 +1332,19 @@ bool wxEvtHandler::TryBefore(wxEvent& event)
 
 bool wxEvtHandler::TryAfter(wxEvent& event)
 {
-#ifdef WXWIN_COMPATIBILITY_2_8
+    // We only want to pass the window to the application object once even if
+    // there are several chained handlers. Ensure that this is what happens by
+    // only calling DoTryApp() if there is no next handler (which would do it).
+    //
+    // Notice that, unlike simply calling TryAfter() on the last handler in the
+    // chain only from ProcessEvent(), this also works with wxWindow object in
+    // the middle of the chain: its overridden TryAfter() will still be called
+    // and propagate the event upwards the window hierarchy even if it's not
+    // the last one in the chain (which, admittedly, shouldn't happen often).
+    if ( GetNextHandler() )
+        return GetNextHandler()->TryAfter(event);
+
+#if WXWIN_COMPATIBILITY_2_8
     // as above, call the old virtual function for compatibility
     return TryParent(event);
 #else
@@ -1326,11 +1354,12 @@ bool wxEvtHandler::TryAfter(wxEvent& event)
 
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
-    // allow the application to hook into event processing
+    // The very first thing we do is to allow the application to hook into
+    // event processing in order to globally pre-process all events.
     //
-    // note that we should only do it if we're the first event handler called
+    // 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
+    // the event handler chain and possibly upwards the window hierarchy.
     if ( !event.WasProcessed() )
     {
         if ( wxTheApp )
@@ -1347,30 +1376,80 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
         }
     }
 
-    if ( ProcessEventHere(event) )
+    // Short circuit the event processing logic if we're requested to process
+    // this event in this handler only, see DoTryChain() for more details.
+    if ( event.ShouldProcessHereOnly() )
+        return TryHere(event);
+
+
+    // Try to process the event in this handler itself.
+    if ( ProcessEventLocally(event) )
+        return true;
+
+    // If we still didn't find a handler, propagate the event upwards the
+    // window chain and/or to the application object.
+    if ( TryAfter(event) )
         return true;
 
-    // pass the event to the next handler, notice that we shouldn't call
-    // TryAfter() 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 TryAfter(event);
+    // No handler found anywhere, bail out.
+    return false;
 }
 
-bool wxEvtHandler::ProcessEventHere(wxEvent& event)
+bool wxEvtHandler::ProcessEventLocally(wxEvent& event)
+{
+    // First try the hooks which should be called before our own handlers
+    if ( TryBefore(event) )
+        return true;
+
+    // Then try this handler itself, notice that we should not call
+    // ProcessEvent() on this one as we're already called from it, which
+    // explains why we do it here and not in DoTryChain()
+    if ( TryHere(event) )
+        return true;
+
+    // Finally try the event handlers chained to this one,
+    if ( DoTryChain(event) )
+        return true;
+
+    // And return false to indicate that we didn't find any handler at this
+    // level.
+    return false;
+}
+
+bool wxEvtHandler::DoTryChain(wxEvent& event)
+{
+    for ( wxEvtHandler *h = GetNextHandler(); h; h = h->GetNextHandler() )
+    {
+        // We need to process this event at the level of this handler only
+        // right now, the pre-/post-processing was either already done by
+        // ProcessEvent() from which we were called or will be done by it when
+        // we return.
+        //
+        // However we must call ProcessEvent() and not TryHere() because the
+        // existing code (including some in wxWidgets itself) expects the
+        // overridden ProcessEvent() in its custom event handlers pushed on a
+        // window to be called.
+        //
+        // So we must call ProcessEvent() but it must not do what it usually
+        // does. To resolve this paradox we pass a special "process here only"
+        // flag to ProcessEvent() via the event object itself. This ensures
+        // that if our own, base class, version is called, it will just call
+        // TryHere() and won't do anything else, just as we want it to.
+        wxEventProcessHereOnly processHereOnly(event);
+        if ( h->ProcessEvent(event) )
+            return true;
+    }
+
+    return false;
+}
+
+bool wxEvtHandler::TryHere(wxEvent& event)
 {
     // If the event handler is disabled it doesn't process any events
     if ( !GetEvtHandlerEnabled() )
         return false;
 
-    // Try the hooks which should be called before our own handlers
-    if ( TryBefore(event) )
-        return true;
-
     // Handle per-instance dynamic event tables first
     if ( m_dynamicEvents && SearchDynamicEventTable(event) )
         return true;
@@ -1441,11 +1520,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);
@@ -1469,11 +1548,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;
@@ -1495,7 +1574,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;