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:
Jake.Stine 2009-11-28 17:16:10 +00:00
parent 97332663c2
commit 740777ec1e
6 changed files with 401 additions and 327 deletions

View File

@ -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" />

View File

@ -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 );
}
}

View File

@ -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 );
};
// --------------------------------------------------------------------------------------

205
pcsx2/gui/MessageBoxes.cpp Normal file
View File

@ -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 );
}
}

140
pcsx2/gui/pxLogTextCtrl.cpp Normal file
View File

@ -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
}

View File

@ -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="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(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="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\gui\Resources\ConfigIcon_Cpu.png"
>