mirror of https://github.com/PCSX2/pcsx2.git
Maybe better console log behavior when dragging scrollbars; move some code out of ConsoleLogger.cpp into new files to reduce clutter and mammoth file size.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2271 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
97332663c2
commit
740777ec1e
|
@ -364,7 +364,8 @@
|
|||
<Unit filename="../gui/MainFrame.h" />
|
||||
<Unit filename="../gui/MainMenuClicks.cpp" />
|
||||
<Unit filename="../gui/MemoryCardFile.cpp" />
|
||||
<Unit filename="../gui/Panels/AudioPanel.cpp" />
|
||||
<Unit filename="../gui/MessageBoxes.cpp" />
|
||||
<Unit filename="../gui/Panels/AudioPanel.cpp" />
|
||||
<Unit filename="../gui/Panels/BaseConfigPanel.h" />
|
||||
<Unit filename="../gui/Panels/BiosSelectorPanel.cpp" />
|
||||
<Unit filename="../gui/Panels/ConfigurationPanels.h" />
|
||||
|
@ -456,8 +457,10 @@
|
|||
<Unit filename="../gui/Resources/EmbeddedImage.h" />
|
||||
<Unit filename="../gui/Saveslots.cpp" />
|
||||
<Unit filename="../gui/i18n.cpp" />
|
||||
<Unit filename="../gui/i18n.cpp" />
|
||||
<Unit filename="../gui/i18n.h" />
|
||||
<Unit filename="../ps2/BiosTools.cpp" />
|
||||
<Unit filename="../gui/pxLogTextCtrl.cpp" />
|
||||
<Unit filename="../ps2/BiosTools.cpp" />
|
||||
<Unit filename="../ps2/BiosTools.h" />
|
||||
<Unit filename="../ps2/GIFpath.cpp" />
|
||||
<Unit filename="../ps2/Iop/IopHwRead.cpp" />
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <wx/textfile.h>
|
||||
|
||||
#ifdef __WXMSW__
|
||||
# include <wx/msw/wrapwin.h> // needed for OutputDebugStirng
|
||||
# include <wx/msw/wrapwin.h> // needed for OutputDebugString
|
||||
#endif
|
||||
|
||||
BEGIN_DECLARE_EVENT_TYPES()
|
||||
|
@ -39,7 +39,7 @@ DEFINE_EVENT_TYPE(wxEVT_SetTitleText)
|
|||
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
|
||||
DEFINE_EVENT_TYPE(wxEVT_FlushQueue)
|
||||
|
||||
// C++ requires abstract destructors to exist, even thought hey're abstract.
|
||||
// C++ requires abstract destructors to exist, even though they're abstract.
|
||||
PipeRedirectionBase::~PipeRedirectionBase() throw() {}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -236,101 +236,6 @@ enum MenuIDs_t
|
|||
MenuID_FontSize_Huge,
|
||||
};
|
||||
|
||||
void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
if( obj == NULL ) return;
|
||||
pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
|
||||
|
||||
// WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
|
||||
// are always displayed as the last line of the log window). Unfortunately this also
|
||||
// makes logging very slow, so we only send the message for status changes, so that the
|
||||
// log aligns itself nicely when we pause emulation or when errors occur.
|
||||
|
||||
::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
mframe->m_win32_StupidRefreshTricks = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
if( obj == NULL ) return;
|
||||
pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
|
||||
|
||||
// WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
|
||||
// are always displayed as the last line of the log window). Unfortunately this also
|
||||
// makes logging very slow, so we only send the message for status changes, so that the
|
||||
// log aligns itself nicely when we pause emulation or when errors occur.
|
||||
|
||||
::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
mframe->m_win32_StupidRefreshTricks = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent )
|
||||
: wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2
|
||||
)
|
||||
|
||||
, m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) )
|
||||
, m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener<PluginEventType> ( this, OnCorePluginStatusChanged ) )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
m_win32_StupidRefreshTricks = 0;
|
||||
m_win32_LinesPerScroll = 10;
|
||||
#endif
|
||||
m_FreezeWrites = false;
|
||||
|
||||
Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) );
|
||||
Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) );
|
||||
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) );
|
||||
}
|
||||
|
||||
|
||||
void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// Windows has retarded console window update patterns. This helps smarten them up.
|
||||
int ctrly = GetSize().y;
|
||||
int fonty;
|
||||
GetTextExtent( L"blaH yeah", NULL, &fonty );
|
||||
m_win32_LinesPerScroll = (int)((ctrly * 0.72) / fonty);
|
||||
#endif
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt)
|
||||
{
|
||||
//Console.Warning( "Thumb Tracking!!!" );
|
||||
m_FreezeWrites = true;
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt)
|
||||
{
|
||||
//Console.Warning( "Thumb Releasing!!!" );
|
||||
m_FreezeWrites = false;
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::DoFlushUpdate()
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts
|
||||
// clearing old history:
|
||||
::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff);
|
||||
|
||||
if( ++m_win32_StupidRefreshTricks > m_win32_LinesPerScroll )
|
||||
{
|
||||
m_win32_StupidRefreshTricks = 0;
|
||||
::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, AppConfig::ConsoleLogOptions& options )
|
||||
: wxFrame(parent, wxID_ANY, title)
|
||||
|
@ -672,7 +577,7 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt )
|
|||
ScopedLock locker( m_QueueLock );
|
||||
|
||||
m_pendingFlushMsg = false;
|
||||
if( m_TextCtrl.HasWriteLock() ) return;
|
||||
//if( m_TextCtrl.HasWriteLock() ) return;
|
||||
|
||||
if( m_CurQueuePos != 0 )
|
||||
{
|
||||
|
@ -691,8 +596,6 @@ void ConsoleLogFrame::OnFlushEvent( wxCommandEvent& evt )
|
|||
}
|
||||
|
||||
DoFlushQueue();
|
||||
m_TextCtrl.DoFlushUpdate();
|
||||
|
||||
//m_TextCtrl.Thaw();
|
||||
}
|
||||
|
||||
|
@ -758,9 +661,7 @@ void ConsoleLogFrame::DoFlushQueue()
|
|||
m_TextCtrl.WriteText( &m_QueueBuffer[m_QueueColorSection[i].startpoint] );
|
||||
}
|
||||
|
||||
// Some reports on Windows7 have corrupted cursor when using insertPoint (or
|
||||
// +1 / -1 ). This works better for some reason:
|
||||
m_TextCtrl.SetInsertionPointEnd(); //( insertPoint );
|
||||
m_TextCtrl.ConcludeIssue( m_pendingFlushes );
|
||||
|
||||
m_QueueColorSection.Clear();
|
||||
m_CurQueuePos = 0;
|
||||
|
@ -930,188 +831,3 @@ void Pcsx2App::DisableWindowLogging() const
|
|||
Console_SetActiveHandler( (emuLog!=NULL) ? (IConsoleWriter&)ConsoleWriter_File : (IConsoleWriter&)ConsoleWriter_Buffered );
|
||||
Threading::Sleep( 5 );
|
||||
}
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
|
||||
DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
|
||||
|
||||
using namespace Threading;
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
|
||||
{
|
||||
if( IsDevBuild && !wxThread::IsMain() )
|
||||
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||
|
||||
// fixme: If the emulator is currently active and is running in fullscreen mode, then we
|
||||
// need to either:
|
||||
// 1) Exit fullscreen mode before issuing the popup.
|
||||
// 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it.
|
||||
//
|
||||
// And in either case the emulation should be paused/suspended for the user.
|
||||
|
||||
return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and
|
||||
// uses fixed-width (modern) fonts.
|
||||
static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags )
|
||||
{
|
||||
if( IsDevBuild && !wxThread::IsMain() )
|
||||
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||
|
||||
return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
|
||||
}
|
||||
|
||||
class pxMessageBoxEvent : public wxEvent
|
||||
{
|
||||
protected:
|
||||
MsgboxEventResult& m_Instdata;
|
||||
wxString m_Title;
|
||||
wxString m_Content;
|
||||
long m_Flags;
|
||||
|
||||
public:
|
||||
pxMessageBoxEvent()
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( *(MsgboxEventResult*)NULL )
|
||||
, m_Title()
|
||||
, m_Content()
|
||||
{
|
||||
m_Flags = 0;
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags )
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( instdata )
|
||||
, m_Title( title )
|
||||
, m_Content( content )
|
||||
{
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( const pxMessageBoxEvent& event )
|
||||
: wxEvent( event )
|
||||
, m_Instdata( event.m_Instdata )
|
||||
, m_Title( event.m_Title )
|
||||
, m_Content( event.m_Content )
|
||||
{
|
||||
m_Flags = event.m_Flags;
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
void DoTheDialog()
|
||||
{
|
||||
int result;
|
||||
|
||||
if( m_id == pxEVT_MSGBOX )
|
||||
result = pxMessageDialog( m_Content, m_Title, m_Flags );
|
||||
else
|
||||
result = pxCallstackDialog( m_Content, m_Title, m_Flags );
|
||||
m_Instdata.result = result;
|
||||
m_Instdata.WaitForMe.Post();
|
||||
}
|
||||
|
||||
virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||
|
||||
private:
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
|
||||
|
||||
namespace Msgbox
|
||||
{
|
||||
// parameters:
|
||||
// flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
|
||||
//
|
||||
static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
|
||||
{
|
||||
// must pass the message to the main gui thread, and then stall this thread, to avoid
|
||||
// threaded chaos where our thread keeps running while the popup is awaiting input.
|
||||
|
||||
MsgboxEventResult instdat;
|
||||
pxMessageBoxEvent tevt( instdat, title, content, flags );
|
||||
wxGetApp().AddPendingEvent( tevt );
|
||||
instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
|
||||
return instdat.result;
|
||||
}
|
||||
|
||||
void OnEvent( pxMessageBoxEvent& evt )
|
||||
{
|
||||
evt.DoTheDialog();
|
||||
}
|
||||
|
||||
// Pops up an alert Dialog Box with a singular "OK" button.
|
||||
// Always returns false.
|
||||
bool Alert( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxOK;
|
||||
if( wxThread::IsMain() )
|
||||
pxMessageDialog( text, caption, icon );
|
||||
else
|
||||
ThreadedMessageBox( text, caption, icon );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
|
||||
// true if OK, false if cancel.
|
||||
bool OkCancel( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxOK | wxCANCEL;
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return wxID_OK == pxMessageDialog( text, caption, icon );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxID_OK == ThreadedMessageBox( text, caption, icon );
|
||||
}
|
||||
}
|
||||
|
||||
bool YesNo( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxYES_NO;
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return wxID_YES == pxMessageDialog( text, caption, icon );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxID_YES == ThreadedMessageBox( text, caption, icon );
|
||||
}
|
||||
}
|
||||
|
||||
// [TODO] : This should probably be a fancier looking dialog box with the stacktrace
|
||||
// displayed inside a wxTextCtrl.
|
||||
static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons )
|
||||
{
|
||||
buttons |= wxICON_STOP;
|
||||
|
||||
wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt );
|
||||
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return pxCallstackDialog( text, caption, buttons );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
|
||||
}
|
||||
}
|
||||
|
||||
int Assertion( const wxString& text, const wxString& stacktrace )
|
||||
{
|
||||
return CallStack( text, stacktrace,
|
||||
L"\nDo you want to stop the program?"
|
||||
L"\nOr press [Cancel] to suppress further assertions.",
|
||||
L"PCSX2 Assertion Failure",
|
||||
wxYES_NO | wxCANCEL
|
||||
);
|
||||
}
|
||||
|
||||
void Except( const Exception::BaseException& src )
|
||||
{
|
||||
CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ protected:
|
|||
|
||||
#ifdef __WXMSW__
|
||||
int m_win32_StupidRefreshTricks;
|
||||
int m_win32_LinesPerPage;
|
||||
int m_win32_LinesPerScroll;
|
||||
#endif
|
||||
bool m_FreezeWrites;
|
||||
|
@ -105,7 +106,9 @@ public:
|
|||
pxLogTextCtrl(wxWindow* parent);
|
||||
|
||||
bool HasWriteLock() const { return m_FreezeWrites; }
|
||||
void DoFlushUpdate();
|
||||
void ConcludeIssue( int lines );
|
||||
|
||||
virtual void WriteText(const wxString& text);
|
||||
|
||||
protected:
|
||||
virtual void OnThumbTrack(wxScrollWinEvent& event);
|
||||
|
@ -114,7 +117,6 @@ protected:
|
|||
|
||||
static void __evt_fastcall OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt );
|
||||
static void __evt_fastcall OnCorePluginStatusChanged( void* obj, PluginEventType& evt );
|
||||
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "App.h"
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEVT_MSGBOX );
|
||||
DEFINE_EVENT_TYPE( pxEVT_CallStackBox );
|
||||
|
||||
using namespace Threading;
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
static int pxMessageDialog( const wxString& content, const wxString& caption, long flags )
|
||||
{
|
||||
if( IsDevBuild && !wxThread::IsMain() )
|
||||
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||
|
||||
// fixme: If the emulator is currently active and is running in fullscreen mode, then we
|
||||
// need to either:
|
||||
// 1) Exit fullscreen mode before issuing the popup.
|
||||
// 2) Issue the popup with wxSTAY_ON_TOP specified so that the user will see it.
|
||||
//
|
||||
// And in either case the emulation should be paused/suspended for the user.
|
||||
|
||||
return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
// fixme: this function should use a custom dialog box that has a wxTextCtrl for the callstack, and
|
||||
// uses fixed-width (modern) fonts.
|
||||
static int pxCallstackDialog( const wxString& content, const wxString& caption, long flags )
|
||||
{
|
||||
if( IsDevBuild && !wxThread::IsMain() )
|
||||
throw Exception::InvalidOperation( "Function must be called by the main GUI thread only." );
|
||||
|
||||
return wxMessageDialog( NULL, content, caption, flags ).ShowModal();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// pxMessageBoxEvent
|
||||
// --------------------------------------------------------------------------------------
|
||||
class pxMessageBoxEvent : public wxEvent
|
||||
{
|
||||
protected:
|
||||
MsgboxEventResult& m_Instdata;
|
||||
wxString m_Title;
|
||||
wxString m_Content;
|
||||
long m_Flags;
|
||||
|
||||
public:
|
||||
pxMessageBoxEvent()
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( *(MsgboxEventResult*)NULL )
|
||||
, m_Title()
|
||||
, m_Content()
|
||||
{
|
||||
m_Flags = 0;
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( MsgboxEventResult& instdata, const wxString& title, const wxString& content, long flags )
|
||||
: wxEvent( 0, pxEVT_MSGBOX )
|
||||
, m_Instdata( instdata )
|
||||
, m_Title( title )
|
||||
, m_Content( content )
|
||||
{
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
||||
pxMessageBoxEvent( const pxMessageBoxEvent& event )
|
||||
: wxEvent( event )
|
||||
, m_Instdata( event.m_Instdata )
|
||||
, m_Title( event.m_Title )
|
||||
, m_Content( event.m_Content )
|
||||
{
|
||||
m_Flags = event.m_Flags;
|
||||
}
|
||||
|
||||
// Thread Safety: Must be called from the GUI thread ONLY.
|
||||
void DoTheDialog()
|
||||
{
|
||||
int result;
|
||||
|
||||
if( m_id == pxEVT_MSGBOX )
|
||||
result = pxMessageDialog( m_Content, m_Title, m_Flags );
|
||||
else
|
||||
result = pxCallstackDialog( m_Content, m_Title, m_Flags );
|
||||
m_Instdata.result = result;
|
||||
m_Instdata.WaitForMe.Post();
|
||||
}
|
||||
|
||||
virtual wxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||
|
||||
private:
|
||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( pxMessageBoxEvent, wxEvent )
|
||||
|
||||
namespace Msgbox
|
||||
{
|
||||
// parameters:
|
||||
// flags - messagebox type flags, such as wxOK, wxCANCEL, etc.
|
||||
//
|
||||
static int ThreadedMessageBox( const wxString& content, const wxString& title, long flags, int boxType=pxEVT_MSGBOX )
|
||||
{
|
||||
// must pass the message to the main gui thread, and then stall this thread, to avoid
|
||||
// threaded chaos where our thread keeps running while the popup is awaiting input.
|
||||
|
||||
MsgboxEventResult instdat;
|
||||
pxMessageBoxEvent tevt( instdat, title, content, flags );
|
||||
wxGetApp().AddPendingEvent( tevt );
|
||||
instdat.WaitForMe.WaitNoCancel(); // Important! disable cancellation since we're using local stack vars.
|
||||
return instdat.result;
|
||||
}
|
||||
|
||||
void OnEvent( pxMessageBoxEvent& evt )
|
||||
{
|
||||
evt.DoTheDialog();
|
||||
}
|
||||
|
||||
// Pops up an alert Dialog Box with a singular "OK" button.
|
||||
// Always returns false.
|
||||
bool Alert( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxOK;
|
||||
if( wxThread::IsMain() )
|
||||
pxMessageDialog( text, caption, icon );
|
||||
else
|
||||
ThreadedMessageBox( text, caption, icon );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry,
|
||||
// true if OK, false if cancel.
|
||||
bool OkCancel( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxOK | wxCANCEL;
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return wxID_OK == pxMessageDialog( text, caption, icon );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxID_OK == ThreadedMessageBox( text, caption, icon );
|
||||
}
|
||||
}
|
||||
|
||||
bool YesNo( const wxString& text, const wxString& caption, int icon )
|
||||
{
|
||||
icon |= wxYES_NO;
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return wxID_YES == pxMessageDialog( text, caption, icon );
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxID_YES == ThreadedMessageBox( text, caption, icon );
|
||||
}
|
||||
}
|
||||
|
||||
// [TODO] : This should probably be a fancier looking dialog box with the stacktrace
|
||||
// displayed inside a wxTextCtrl.
|
||||
static int CallStack( const wxString& errormsg, const wxString& stacktrace, const wxString& prompt, const wxString& caption, int buttons )
|
||||
{
|
||||
buttons |= wxICON_STOP;
|
||||
|
||||
wxString text( errormsg + L"\n\n" + stacktrace + L"\n" + prompt );
|
||||
|
||||
if( wxThread::IsMain() )
|
||||
{
|
||||
return pxCallstackDialog( text, caption, buttons );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ThreadedMessageBox( text, caption, buttons, pxEVT_CallStackBox );
|
||||
}
|
||||
}
|
||||
|
||||
int Assertion( const wxString& text, const wxString& stacktrace )
|
||||
{
|
||||
return CallStack( text, stacktrace,
|
||||
L"\nDo you want to stop the program?"
|
||||
L"\nOr press [Cancel] to suppress further assertions.",
|
||||
L"PCSX2 Assertion Failure",
|
||||
wxYES_NO | wxCANCEL
|
||||
);
|
||||
}
|
||||
|
||||
void Except( const Exception::BaseException& src )
|
||||
{
|
||||
CallStack( src.FormatDisplayMessage(), src.FormatDiagnosticMessage(), wxEmptyString, L"PCSX2 Unhandled Exception", wxOK );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "App.h"
|
||||
#include "ConsoleLogger.h"
|
||||
|
||||
#ifdef __WXMSW__
|
||||
# include <wx/msw/wrapwin.h> // needed for windows-specific rich text messages to make scrolling not lame
|
||||
#endif
|
||||
|
||||
void __evt_fastcall pxLogTextCtrl::OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
if( obj == NULL ) return;
|
||||
pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
|
||||
|
||||
// See ConcludeIssue for details on WM_VSCROLL
|
||||
|
||||
if( mframe->HasWriteLock() ) return;
|
||||
::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
mframe->m_win32_StupidRefreshTricks = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void __evt_fastcall pxLogTextCtrl::OnCorePluginStatusChanged( void* obj, PluginEventType& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
if( obj == NULL ) return;
|
||||
pxLogTextCtrl* mframe = (pxLogTextCtrl*)obj;
|
||||
|
||||
// See ConcludeIssue for details on WM_VSCROLL
|
||||
|
||||
if( mframe->HasWriteLock() ) return;
|
||||
::SendMessage((HWND)mframe->GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
mframe->m_win32_StupidRefreshTricks = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
pxLogTextCtrl::pxLogTextCtrl( wxWindow* parent )
|
||||
: wxTextCtrl( parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH2
|
||||
)
|
||||
|
||||
, m_Listener_CoreThreadStatus ( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener ( this, OnCoreThreadStatusChanged ) )
|
||||
, m_Listener_CorePluginStatus ( wxGetApp().Source_CorePluginStatus(), EventListener<PluginEventType> ( this, OnCorePluginStatusChanged ) )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
m_win32_StupidRefreshTricks = 0;
|
||||
m_win32_LinesPerScroll = 10;
|
||||
#endif
|
||||
m_FreezeWrites = false;
|
||||
|
||||
Connect( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbTrack) );
|
||||
Connect( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(pxLogTextCtrl::OnThumbRelease) );
|
||||
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler(pxLogTextCtrl::OnResize) );
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::WriteText(const wxString& text)
|
||||
{
|
||||
// Don't need the update message -- saves some overhead.
|
||||
DoWriteText( text, SetValue_SelectionOnly );
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// Windows has retarded console window update patterns. This helps smarten them up.
|
||||
int ctrly = GetSize().y;
|
||||
int fonty;
|
||||
GetTextExtent( L"blaH yeah", NULL, &fonty );
|
||||
m_win32_LinesPerPage = (ctrly / fonty) + 1;
|
||||
m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.72;
|
||||
#endif
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
bool m_IsPaused = false;
|
||||
|
||||
void pxLogTextCtrl::OnThumbTrack(wxScrollWinEvent& evt)
|
||||
{
|
||||
//Console.Warning( "Thumb Tracking!!!" );
|
||||
m_FreezeWrites = true;
|
||||
if( !m_IsPaused )
|
||||
m_IsPaused = CoreThread.Pause();
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::OnThumbRelease(wxScrollWinEvent& evt)
|
||||
{
|
||||
//Console.Warning( "Thumb Releasing!!!" );
|
||||
m_FreezeWrites = false;
|
||||
if( m_IsPaused )
|
||||
{
|
||||
CoreThread.Resume();
|
||||
m_IsPaused = false;
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void pxLogTextCtrl::ConcludeIssue( int lines )
|
||||
{
|
||||
if( HasWriteLock() ) return;
|
||||
SetInsertionPointEnd();
|
||||
|
||||
#ifdef __WXMSW__
|
||||
|
||||
// EM_LINESCROLL avoids weird errors when the buffer reaches "max" and starts
|
||||
// clearing old history:
|
||||
::SendMessage((HWND)GetHWND(), EM_LINESCROLL, 0, 0xfffffff);
|
||||
|
||||
// WM_VSCROLL makes the scrolling 'smooth' (such that the last line of the log contents
|
||||
// are always displayed as the last line of the log window). Unfortunately this also
|
||||
// makes logging very slow, so we only send the message for status changes, so that the
|
||||
// log aligns itself nicely when we pause emulation or when errors occur.
|
||||
|
||||
m_win32_StupidRefreshTricks += lines;
|
||||
m_win32_StupidRefreshTricks %= m_win32_LinesPerPage;
|
||||
if( m_win32_StupidRefreshTricks > m_win32_LinesPerScroll )
|
||||
{
|
||||
m_win32_StupidRefreshTricks = 0;
|
||||
::SendMessage((HWND)GetHWND(), WM_VSCROLL, SB_BOTTOM, (LPARAM)NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1808,10 +1808,18 @@
|
|||
RelativePath="..\..\gui\MemoryCardFile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\MessageBoxes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\Plugins.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\pxLogTextCtrl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\RecentIsoList.cpp"
|
||||
>
|
||||
|
@ -1879,41 +1887,7 @@
|
|||
<Filter
|
||||
Name="Resources"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\gui\Resources\ButtonIcon_Camera.png"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
<File
|
||||
RelativePath="..\..\gui\Resources\AppIcon16.png"
|
||||
>
|
||||
<FileConfiguration
|
||||
|
@ -2049,6 +2023,40 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\Resources\ButtonIcon_Camera.png"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Devel|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""$(InputDir)\bin2cpp.cmd" $(InputFileName)
"
|
||||
Outputs=""$(InputDir)\$(InputName).h"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\gui\Resources\ConfigIcon_Cpu.png"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue