From 68b7121b9264631532e9daea6e500db5d0f07ac7 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 27 Apr 2010 13:18:29 +0000 Subject: [PATCH] ... and the missing file might help. Woops. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2912 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Utilities/pxEvents.h | 381 ++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 common/include/Utilities/pxEvents.h diff --git a/common/include/Utilities/pxEvents.h b/common/include/Utilities/pxEvents.h new file mode 100644 index 000000000..7880f3481 --- /dev/null +++ b/common/include/Utilities/pxEvents.h @@ -0,0 +1,381 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2009 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +BEGIN_DECLARE_EVENT_TYPES() + DECLARE_EVENT_TYPE( pxEvt_StartIdleEventTimer, -1 ) + DECLARE_EVENT_TYPE( pxEvt_DeleteObject, -1 ) + DECLARE_EVENT_TYPE( pxEvt_DeleteThread, -1 ) + DECLARE_EVENT_TYPE( pxEvt_InvokeAction, -1 ) + DECLARE_EVENT_TYPE( pxEvt_SynchronousCommand, -1 ) +END_DECLARE_EVENT_TYPES() + +// -------------------------------------------------------------------------------------- +// SynchronousActionState +// -------------------------------------------------------------------------------------- +class SynchronousActionState +{ + DeclareNoncopyableObject( SynchronousActionState ); + +protected: + bool m_posted; + Threading::Semaphore m_sema; + ScopedPtr m_exception; + +public: + sptr return_value; + + SynchronousActionState() + { + m_posted = false; + return_value = 0; + } + + virtual ~SynchronousActionState() throw() {} + + void SetException( const BaseException& ex ) + { + m_exception = ex.Clone(); + } + + void SetException( BaseException* ex ) + { + m_exception = ex; + } + + Threading::Semaphore& GetSemaphore() { return m_sema; } + const Threading::Semaphore& GetSemaphore() const { return m_sema; } + + void RethrowException() const + { + if( m_exception ) m_exception->Rethrow(); + } + + int WaitForResult() + { + m_sema.WaitNoCancel(); + RethrowException(); + return return_value; + } + + void PostResult( int res ) + { + return_value = res; + PostResult(); + } + + void ClearResult() + { + m_posted = false; + } + + void PostResult() + { + if( m_posted ) return; + m_posted = true; + m_sema.Post(); + } +}; + + +// -------------------------------------------------------------------------------------- +// pxSimpleEvent - non-abstract implementation of wxEvent +// -------------------------------------------------------------------------------------- +// Why? I mean, why is wxEvent abstract? Over-designed OO is such a bad habit. And while +// I'm on my high horse (and it's so very high!), why use 'private'? Ever? Seriously, it +// sucks. Stop using it, people. +// +class pxSimpleEvent : public wxEvent +{ + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSimpleEvent) + +public: + pxSimpleEvent( int evtid=0 ) + : wxEvent(0, evtid) + { } + + pxSimpleEvent( wxWindowID winId, int evtid ) + : wxEvent(winId, evtid) + { } + + virtual wxEvent *Clone() const { return new pxSimpleEvent(*this); } +}; + +// -------------------------------------------------------------------------------------- +// pxInvokeActionEvent +// -------------------------------------------------------------------------------------- +class pxInvokeActionEvent : public wxEvent, public virtual IActionInvocation +{ + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxInvokeActionEvent) + +protected: + SynchronousActionState* m_state; + +public: + virtual ~pxInvokeActionEvent() throw() { } + virtual pxInvokeActionEvent *Clone() const { return new pxInvokeActionEvent(*this); } + + explicit pxInvokeActionEvent( SynchronousActionState* sema=NULL, int msgtype=pxEvt_InvokeAction ); + explicit pxInvokeActionEvent( SynchronousActionState& sema, int msgtype=pxEvt_InvokeAction ); + pxInvokeActionEvent( const pxInvokeActionEvent& src ); + + Threading::Semaphore* GetSemaphore() const { return m_state ? &m_state->GetSemaphore() : NULL; } + + const SynchronousActionState* GetSyncState() const { return m_state; } + SynchronousActionState* GetSyncState() { return m_state; } + + void SetSyncState( SynchronousActionState* obj ) { m_state = obj; } + void SetSyncState( SynchronousActionState& obj ) { m_state = &obj; } + + virtual void SetException( BaseException* ex ); + void SetException( const BaseException& ex ); + + virtual void InvokeAction(); + +protected: + virtual void _DoInvoke() {}; +}; + + +// -------------------------------------------------------------------------------------- +// pxExceptionEvent +// -------------------------------------------------------------------------------------- +class pxExceptionEvent : public pxInvokeActionEvent +{ + typedef pxInvokeActionEvent _parent; + +protected: + BaseException* m_except; + +public: + pxExceptionEvent( BaseException* ex=NULL ) + { + m_except = ex; + } + + pxExceptionEvent( const BaseException& ex ); + + virtual ~pxExceptionEvent() throw() { } + virtual pxExceptionEvent *Clone() const { return new pxExceptionEvent(*this); } + +protected: + void _DoInvoke(); +}; + +// -------------------------------------------------------------------------------------- +// pxSynchronousCommandEvent +// -------------------------------------------------------------------------------------- + +class pxSynchronousCommandEvent : public wxCommandEvent +{ + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSynchronousCommandEvent) + +protected: + SynchronousActionState* m_sync; + wxEventType m_realEvent; + +public: + virtual ~pxSynchronousCommandEvent() throw() { } + virtual pxSynchronousCommandEvent *Clone() const { return new pxSynchronousCommandEvent(*this); } + + pxSynchronousCommandEvent(SynchronousActionState* sema=NULL, wxEventType commandType = wxEVT_NULL, int winid = 0); + pxSynchronousCommandEvent(SynchronousActionState& sema, wxEventType commandType = wxEVT_NULL, int winid = 0); + + pxSynchronousCommandEvent(SynchronousActionState* sema, const wxCommandEvent& evt); + pxSynchronousCommandEvent(SynchronousActionState& sema, const wxCommandEvent& evt); + + pxSynchronousCommandEvent(const pxSynchronousCommandEvent& src); + + Threading::Semaphore* GetSemaphore() { return m_sync ? &m_sync->GetSemaphore() : NULL; } + wxEventType GetRealEventType() const { return m_realEvent; } + + void SetException( BaseException* ex ); + void SetException( const BaseException& ex ); +}; + +// -------------------------------------------------------------------------------------- +// BaseMessageBoxEvent +// -------------------------------------------------------------------------------------- +class BaseMessageBoxEvent : public pxInvokeActionEvent +{ + typedef pxInvokeActionEvent _parent; + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent) + +protected: + wxString m_Content; + +public: + virtual ~BaseMessageBoxEvent() throw() { } + virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); } + + explicit BaseMessageBoxEvent( const wxString& content=wxEmptyString, SynchronousActionState* instdata=NULL ); + BaseMessageBoxEvent( const wxString& content, SynchronousActionState& instdata ); + BaseMessageBoxEvent( const BaseMessageBoxEvent& event ); + +protected: + virtual void _DoInvoke(); + virtual int _DoDialog() const; +}; + +// -------------------------------------------------------------------------------------- +// MsgButtons +// -------------------------------------------------------------------------------------- +class MsgButtons +{ +protected: + BITFIELD32() + bool + m_OK :1, + m_Cancel :1, + m_Yes :1, + m_No :1, + m_AllowToAll:1, + m_Apply :1, + m_Abort :1, + m_Retry :1, + m_Ignore :1, + m_Reset :1, + m_Close :1; + BITFIELD_END + + wxString m_CustomLabel; + +public: + MsgButtons() { bitset = 0; } + + MsgButtons& OK() { m_OK = true; return *this; } + MsgButtons& Cancel() { m_Cancel = true; return *this; } + MsgButtons& Apply() { m_Apply = true; return *this; } + MsgButtons& Yes() { m_Yes = true; return *this; } + MsgButtons& No() { m_No = true; return *this; } + MsgButtons& ToAll() { m_AllowToAll = true; return *this; } + + MsgButtons& Abort() { m_Abort = true; return *this; } + MsgButtons& Retry() { m_Retry = true; return *this; } + MsgButtons& Ignore() { m_Ignore = true; return *this; } + MsgButtons& Reset() { m_Reset = true; return *this; } + MsgButtons& Close() { m_Close = true; return *this; } + + MsgButtons& Custom( const wxString& label) + { + m_CustomLabel = label; + return *this; + } + + MsgButtons& OKCancel() { m_OK = m_Cancel = true; return *this; } + MsgButtons& YesNo() { m_Yes = m_No = true; return *this; } + + bool HasOK() const { return m_OK; } + bool HasCancel() const { return m_Cancel; } + bool HasApply() const { return m_Apply; } + bool HasYes() const { return m_Yes; } + bool HasNo() const { return m_No; } + bool AllowsToAll() const{ return m_AllowToAll; } + + bool HasAbort() const { return m_Abort; } + bool HasRetry() const { return m_Retry; } + bool HasIgnore() const { return m_Ignore; } + bool HasReset() const { return m_Reset; } + bool HasClose() const { return m_Close; } + + bool HasCustom() const { return !m_CustomLabel.IsEmpty(); } + const wxString& GetCustomLabel() const { return m_CustomLabel; } + + bool Allows( wxWindowID id ) const; + void SetBestFocus( wxWindow* dialog ) const; + void SetBestFocus( wxWindow& dialog ) const; + + bool operator ==( const MsgButtons& right ) const + { + return OpEqu( bitset ); + } + + bool operator !=( const MsgButtons& right ) const + { + return !OpEqu( bitset ); + } +}; + +// -------------------------------------------------------------------------------------- +// pxMessageBoxEvent +// -------------------------------------------------------------------------------------- +// This event type is used to transfer message boxes to the main UI thread, and return the +// result of the box. It's the only way a message box can be issued from non-main threads +// with complete safety in wx2.8. +// +// For simplicity sake this message box only supports two basic designs. The main design +// is a generic message box with confirmation buttons of your choosing. Additionally you +// can specify a "scrollableContent" text string, which is added into a read-only richtext +// control similar to the console logs and such. +// +// Future consideration: If wxWidgets 3.0 has improved thread safety, then it should probably +// be reasonable for it to work with a more flexable model where the dialog can be created +// on a child thread, passed to the main thread, where ShowModal() is run (keeping the nested +// message pumps on the main thread where they belong). But so far this is not possible, +// because of various subtle issues in wx2.8 design. +// +class pxMessageBoxEvent : public BaseMessageBoxEvent +{ + typedef BaseMessageBoxEvent _parent; + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent) + +protected: + wxString m_Title; + MsgButtons m_Buttons; + +public: + virtual ~pxMessageBoxEvent() throw() { } + virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); } + + pxMessageBoxEvent() {} + pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons, SynchronousActionState& instdata ); + pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons, SynchronousActionState* instdata=NULL ); + pxMessageBoxEvent( const pxMessageBoxEvent& event ); + +protected: + int _DoDialog() const; +}; + +// -------------------------------------------------------------------------------------- +// pxAssertionEvent +// -------------------------------------------------------------------------------------- +class pxAssertionEvent : public BaseMessageBoxEvent +{ + typedef BaseMessageBoxEvent _parent; + DECLARE_DYNAMIC_CLASS_NO_ASSIGN( pxAssertionEvent ) + +protected: + wxString m_Stacktrace; + +public: + virtual ~pxAssertionEvent() throw() { } + virtual pxAssertionEvent *Clone() const { return new pxAssertionEvent(*this); } + + pxAssertionEvent( const wxString& content=wxEmptyString, const wxString& trace=wxEmptyString, SynchronousActionState* instdata=NULL ); + pxAssertionEvent( const wxString& content, const wxString& trace, SynchronousActionState& instdata ); + pxAssertionEvent( const pxAssertionEvent& event ); + + pxAssertionEvent& SetStacktrace( const wxString& trace ); + +protected: + int _DoDialog() const; +}; + + +typedef void (wxEvtHandler::*pxSyncronousEventFunction)(pxSynchronousCommandEvent&); + +#define pxSynchronousEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxSyncronousEventFunction, &func )