#include "wx/dynarray.h"
#include "wx/thread.h"
#include "wx/tracker.h"
+#include "wx/typeinfo.h"
+#include "wx/any.h"
#ifdef wxHAS_EVENT_BIND
#include "wx/meta/convertible.h"
#ifdef wxHAS_EVENT_BIND
-#include "wx/typeinfo.h"
-
// 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
return false;
}
+ // This is also used only internally by ProcessEvent() to check if it
+ // should process the event normally or only restrict the search for the
+ // event handler to this object itself.
+ bool ShouldProcessHereOnly() const { return m_processHereOnly; }
+
protected:
wxObject* m_eventObject;
wxEventType m_eventType;
// once for this event
bool m_wasProcessed;
+ // this flag is used by ProcessEventLocally() to prevent ProcessEvent()
+ // from doing its usual stuff and force it to just call TryHere() instead,
+ // see the comment there explaining why is this needed
+ bool m_processHereOnly;
+
protected:
wxEvent(const wxEvent&); // for implementing Clone()
wxEvent& operator=(const wxEvent&); // for derived classes operator=()
// it needs to access our m_propagationLevel
friend class WXDLLIMPEXP_FWD_BASE wxPropagateOnce;
+ // and this one needs to access our m_processHereOnly
+ friend class WXDLLIMPEXP_FWD_BASE wxEventProcessHereOnly;
+
+
DECLARE_ABSTRACT_CLASS(wxEvent)
};
wxDECLARE_NO_COPY_CLASS(wxPropagateOnce);
};
+// A helper used by ProcessEventLocally() to restrict the event processing
+// to this handler only.
+class WXDLLIMPEXP_BASE wxEventProcessHereOnly
+{
+public:
+ wxEventProcessHereOnly(wxEvent& event) : m_event(event)
+ {
+ // This would be unexpected and would also restore the wrong value in
+ // this class dtor so if even does happen legitimately we'd need to
+ // store the value in ctor and restore it in dtor.
+ wxASSERT_MSG( !m_event.m_processHereOnly,
+ "shouldn't be used twice for the same event" );
+
+ m_event.m_processHereOnly = true;
+ }
+
+ ~wxEventProcessHereOnly()
+ {
+ m_event.m_processHereOnly = false;
+ }
+
+private:
+ wxEvent& m_event;
+
+ wxDECLARE_NO_COPY_CLASS(wxEventProcessHereOnly);
+};
#if wxUSE_GUI
// make sure our string member (which uses COW, aka refcounting) is not
// shared by other wxString instances:
SetString(GetString().c_str());
+
+#if wxUSE_ANY && (!defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7))
+ m_payload = event.m_payload;
+#endif
}
virtual wxEvent *Clone() const
{
- wxThreadEvent* ev = new wxThreadEvent(*this);
-
- // make sure our string member (which uses COW, aka refcounting) is not
- // shared by other wxString instances:
- ev->SetString(GetString().c_str());
- return ev;
+ return new wxThreadEvent(*this);
}
// this is important to avoid that calling wxEventLoopBase::YieldFor thread events
virtual wxEventCategory GetEventCategory() const
{ return wxEVT_CATEGORY_THREAD; }
+#if wxUSE_ANY && (!defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7))
+ template<typename T>
+ void SetPayload(const T& payload)
+ {
+ m_payload = payload;
+ }
+
+ template<typename T>
+ T GetPayload() const
+ {
+ return m_payload.As<T>();
+ }
+
+protected:
+ wxAny m_payload;
+#endif // wxUSE_ANY && (!defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7))
+
private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxThreadEvent)
};
bool SafelyProcessEvent(wxEvent& event);
// NOTE: uses ProcessEvent()
+ // This method tries to process the event in this event handler, including
+ // any preprocessing done by TryBefore() and all the handlers chained to
+ // it, but excluding the post-processing done in TryAfter().
+ //
+ // It is meant to be called from ProcessEvent() only and is not virtual,
+ // additional event handlers can be hooked into the normal event processing
+ // logic using TryBefore() and TryAfter() hooks.
+ //
+ // You can also call it yourself to forward an event to another handler but
+ // without propagating it upwards if it's unhandled (this is usually
+ // unwanted when forwarding as the original handler would already do it if
+ // needed normally).
+ bool ProcessEventLocally(wxEvent& event);
+
// Schedule the given event to be processed later. It takes ownership of
// the event pointer, i.e. it will be deleted later. This is safe to call
// from multiple threads although you still need to ensure that wxString
void OnSinkDestroyed( wxEvtHandler *sink );
- // The method tries to process the event in this event handler.
- //
- // It is meant to be called from ProcessEvent() only and is not virtual,
- // additional event handlers can be hooked into the normal event processing
- // logic using TryBefore() and TryAfter() hooks.
- bool ProcessEventHere(wxEvent& event);
-
-
private:
void DoBind(int winid,
int lastId,
// validators.
virtual bool TryBefore(wxEvent& event);
+ // this one is not a hook but just a helper which looks up the handler in
+ // this object itself called from ProcessEventLocally() and normally
+ // shouldn't be called directly as doing it would ignore any chained event
+ // handlers
+ bool TryHere(wxEvent& event);
+
// this one is called after failing to find the event handle in our own
// table to give a chance to the other windows to process it
//
// pass the event to wxTheApp instance, called from TryAfter()
bool DoTryApp(wxEvent& event);
+ // try to process events in all handlers chained to this one
+ bool DoTryChain(wxEvent& event);
+
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
};
#ifdef 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) \
+ #define wxBIND_OR_CONNECT_HACK(win, evt, handler, func, obj) \
win->Bind(evt, &func, obj)
#else // 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) \
+ #define wxBIND_OR_CONNECT_HACK(win, evt, handler, func, obj) \
win->Connect(evt, handler(func), NULL, obj)
#endif // wxHAS_EVENT_BIND