Small bugfixes to settings handling at startup, fixed a memleak when opening multiple dialog boxes, and some other minor interface code cleanups.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2079 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-10-25 22:33:23 +00:00
parent eae4643a40
commit 581e8a30a7
16 changed files with 217 additions and 115 deletions

View File

@ -203,6 +203,10 @@
RelativePath="..\..\src\Utilities\Console.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\EventSource.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\Exceptions.cpp"
>
@ -429,6 +433,10 @@
RelativePath="..\..\include\Utilities\EventSource.h"
>
</File>
<File
RelativePath="..\..\include\Utilities\EventSource.inl"
>
</File>
<File
RelativePath="..\..\include\Utilities\Exceptions.h"
>

View File

@ -78,7 +78,7 @@ public:
protected:
typedef typename ListenerList::const_iterator ConstIterator;
ListenerList m_listeners;
ListenerList m_listeners;
// This is a cached copy of the listener list used to handle standard dispatching, which
// allows for self-modification of the EventSource's listener list by the listeners.
@ -112,10 +112,6 @@ public:
return m_listeners.begin();
}
// Checks for duplicates before adding the event.
virtual inline void Add( const ListenerType& listener );
virtual inline void RemoveObject( const void* object );
void Add( void* objhandle, typename ListenerType::FuncType* fnptr )
{
Add( ListenerType( objhandle, fnptr ) );
@ -126,43 +122,17 @@ public:
Remove( ListenerType( objhandle, fnptr ) );
}
void Dispatch( EvtType& evt )
{
if( !m_cache_valid )
{
m_cache_copy = m_listeners;
m_cache_valid = true;
}
_DispatchRaw( m_cache_copy.begin(), m_cache_copy.end(), evt );
}
// Checks for duplicates before adding the event.
virtual void Add( const ListenerType& listener );
virtual void RemoveObject( const void* object );
void Dispatch( EvtType& evt );
protected:
__forceinline void _DispatchRaw( ConstIterator iter, const ConstIterator& iend, EvtType& evt )
{
while( iter != iend )
{
try
{
iter->OnEvent( iter->object, evt );
}
catch( Exception::RuntimeError& ex )
{
Console.Error( L"Ignoring runtime error thrown from event listener: " + ex.FormatDiagnosticMessage() );
}
catch( Exception::BaseException& ex )
{
if( IsDevBuild ) throw;
Console.Error( L"Ignoring non-runtime BaseException thrown from event listener: " + ex.FormatDiagnosticMessage() );
}
++iter;
}
}
inline void _DispatchRaw( ConstIterator iter, const ConstIterator& iend, EvtType& evt );
};
// --------------------------------------------------------------------------------------
// EventListenerBinding< typename EvtType ?
// EventListenerBinding< typename EvtType >
// --------------------------------------------------------------------------------------
// Encapsulated event listener binding, provides the "benefits" of object unwinding.
//
@ -215,44 +185,9 @@ typedef EventSource<wxCommandEvent> CmdEvt_Source;
typedef EventListener<wxCommandEvent> CmdEvt_Listener;
typedef EventListenerBinding<wxCommandEvent> CmdEvt_ListenerBinding;
// Checks for duplicates before adding the event.
template< typename EvtType >
void EventSource<EvtType>::Add( const ListenerType& listener )
{
if( !pxAssertDev( listener.OnEvent != NULL, "NULL listener callback function." ) ) return;
Handle iter = m_listeners.begin();
while( iter != m_listeners.end() )
{
if( *iter == listener ) return;
++iter;
}
AddFast( listener );
}
template< typename EvtType >
class PredicatesAreTheThingsOfNightmares
{
typedef EventListener< EvtType > ListenerType;
protected:
const void* const m_object_match;
public:
PredicatesAreTheThingsOfNightmares( const void* objmatch ) : m_object_match( objmatch ) { }
bool operator()( const ListenerType& src ) const
{
return src.object == m_object_match;
}
};
// removes all listeners which reference the given object. Use for assuring object deletion.
template< typename EvtType >
void EventSource<EvtType>::RemoveObject( const void* object )
{
m_cache_valid = false;
m_listeners.remove_if( PredicatesAreTheThingsOfNightmares<EvtType>( object ) );
}
#define EventSource_ImplementType( tname ) \
template void EventSource<tname>::Add(const EventSource<tname>::ListenerType &listener); \
template void EventSource<tname>::RemoveObject(const void* object); \
template void EventSource<tname>::Add(const EventSource<tname>::ListenerType &listener); \
template void EventSource<tname>::Dispatch(tname& evt); \
template void EventSource<tname>::_DispatchRaw( EventSource<tname>::ConstIterator iter, const EventSource<tname>::ConstIterator& iend, tname& evt );

View File

@ -0,0 +1,90 @@
/* 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/>.
*/
#pragma once
// Checks for duplicates before adding the event.
template< typename EvtType >
void EventSource<EvtType>::Add( const ListenerType& listener )
{
if( !pxAssertDev( listener.OnEvent != NULL, "NULL listener callback function." ) ) return;
Handle iter = m_listeners.begin();
while( iter != m_listeners.end() )
{
if( *iter == listener ) return;
++iter;
}
AddFast( listener );
}
template< typename EvtType >
class PredicatesAreTheThingsOfNightmares
{
typedef EventListener< EvtType > ListenerType;
protected:
const void* const m_object_match;
public:
PredicatesAreTheThingsOfNightmares( const void* objmatch ) : m_object_match( objmatch ) { }
bool operator()( const ListenerType& src ) const
{
return src.object == m_object_match;
}
};
// removes all listeners which reference the given object. Use for assuring object deletion.
template< typename EvtType >
void EventSource<EvtType>::RemoveObject( const void* object )
{
m_cache_valid = false;
m_listeners.remove_if( PredicatesAreTheThingsOfNightmares<EvtType>( object ) );
}
template< typename EvtType >
__forceinline void EventSource<EvtType>::_DispatchRaw( ConstIterator iter, const ConstIterator& iend, EvtType& evt )
{
while( iter != iend )
{
try
{
iter->OnEvent( iter->object, evt );
}
catch( Exception::RuntimeError& ex )
{
Console.Error( L"Ignoring runtime error thrown from event listener: " + ex.FormatDiagnosticMessage() );
}
catch( Exception::BaseException& ex )
{
if( IsDevBuild ) throw;
Console.Error( L"Ignoring non-runtime BaseException thrown from event listener: " + ex.FormatDiagnosticMessage() );
}
++iter;
}
}
template< typename EvtType >
void EventSource<EvtType>::Dispatch( EvtType& evt )
{
if( !m_cache_valid )
{
m_cache_copy = m_listeners;
m_cache_valid = true;
}
_DispatchRaw( m_cache_copy.begin(), m_cache_copy.end(), evt );
}

View File

@ -0,0 +1,23 @@
/* 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 "EventSource.h"
#include "EventSource.inl"
#include <wx/event.h>
EventSource_ImplementType( wxCommandEvent );
EventSource_ImplementType( int );

View File

@ -28,6 +28,9 @@
#include "CDVD/CDVD.h"
#include "System/PageFaultSource.h"
#include "Utilities/EventSource.inl"
EventSource_ImplementType( PageFaultInfo );
SrcType_PageFault Source_PageFault;
#if _MSC_VER

View File

@ -531,6 +531,11 @@ DECLARE_APP(Pcsx2App)
#define sMainFrame \
if( MainEmuFrame* __frame_ = GetMainFramePtr() ) (*__frame_)
// Use this within the scope of a wxWindow (wxDialog or wxFrame). If the window has a valid menu
// bar, the command will run, otherwise it will be silently ignored. :)
#define sMenuBar \
if( wxMenuBar* __menubar_ = GetMenuBar() ) (*__menubar_)
// --------------------------------------------------------------------------------------
// External App-related Globals and Shortcuts

View File

@ -520,7 +520,7 @@ void RelocateLogfile()
if( (emuLog != NULL) && (emuLogName != newlogname) )
{
Console.Status( "\nRelocating Logfile...\n\tFrom: %s\n\tTo : %s\n", emuLogName.c_str(), newlogname.c_str() );
Console.Status( wxsFormat(L"\nRelocating Logfile...\n\tFrom: %s\n\tTo : %s\n", emuLogName.c_str(), newlogname.c_str()) );
wxGetApp().DisableDiskLogging();
fclose( emuLog );

View File

@ -447,6 +447,6 @@ struct CrtDebugBreak
}
};
//CrtDebugBreak breakAt( 8890 );
//CrtDebugBreak breakAt( 7586 );
#endif

View File

@ -39,6 +39,10 @@ DEFINE_EVENT_TYPE( pxEVT_LoadPluginsComplete );
DEFINE_EVENT_TYPE( pxEVT_CoreThreadStatus );
DEFINE_EVENT_TYPE( pxEVT_FreezeThreadFinished );
#include "Utilities/EventSource.inl"
EventSource_ImplementType( IniInterface );
EventSource_ImplementType( AppEventType );
bool UseAdminMode = false;
wxDirName SettingsFolder;
bool UseDefaultSettingsFolder = true;

View File

@ -168,8 +168,6 @@ void FirstTimeWizard::OnPageChanging( wxWizardEvent& evt )
evt.Veto();
return;
}
m_panel_PluginSel.ReloadSettings();
m_panel_BiosSel.ReloadSettings();
}
}
}

View File

@ -55,7 +55,7 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent ) :
void Dialogs::ImportSettingsDialog::OnImport_Click( wxCommandEvent& /* evt */ )
{
AppConfig_OnChangedSettingsFolder( false ); // ... and import existing settings
AppConfig_OnChangedSettingsFolder( false ); // ... and import existing settings
g_Conf->Folders.Bios.Mkdir();
EndModal( wxID_OK );
}

View File

@ -70,8 +70,7 @@ void MainEmuFrame::UpdateIsoSrcSelection()
jNO_DEFAULT
}
GetMenuBar()->Check( cdsrc, true );
sMenuBar.Check( cdsrc, true );
m_statusbar.SetStatusText( CDVD_SourceLabels[g_Conf->CdvdSource], 1 );
}
@ -86,7 +85,7 @@ void MainEmuFrame::UpdateIsoSrcFile()
label.Printf( L"%s -> %s", _("Iso"),
exists ? g_Conf->CurrentIso.c_str() : _("Empty")
);
GetMenuBar()->SetLabel( MenuId_Src_Iso, label );
sMenuBar.SetLabel( MenuId_Src_Iso, label );
}
void MainEmuFrame::LoadSaveRecentIsoList( IniInterface& conf )
@ -321,13 +320,13 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
// Initial menubar setup. This needs to be done first so that the menu bar's visible size
// can be factored into the window size (which ends up being background+status+menus)
m_menubar.Append( &m_menuBoot, _("Boot") );
m_menubar.Append( &m_menuEmu, _("Emulation") );
m_menubar.Append( &m_menuConfig, _("Config") );
m_menubar.Append( &m_menuVideo, _("Video") );
m_menubar.Append( &m_menuAudio, _("Audio") );
m_menubar.Append( &m_menuMisc, _("Misc") );
m_menubar.Append( &m_menuDebug, _("Debug") );
m_menubar.Append( &m_menuBoot, _("&Boot") );
m_menubar.Append( &m_menuEmu, _("&System") );
m_menubar.Append( &m_menuConfig, _("&Config") );
m_menubar.Append( &m_menuVideo, _("&Video") );
m_menubar.Append( &m_menuAudio, _("&Audio") );
m_menubar.Append( &m_menuMisc, _("&Misc") );
m_menubar.Append( &m_menuDebug, _("&Debug") );
SetMenuBar( &m_menubar );
// ------------------------------------------------------------------------
@ -407,8 +406,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
_("Closing PCSX2 may be hazardous to your health"));
// ------------------------------------------------------------------------
m_menuEmu.Append(MenuId_Sys_SuspendResume, _("Suspend"),
_("Stops emulation dead in its tracks") )->Enable( SysHasValidState() );
m_menuEmu.Append(MenuId_Sys_SuspendResume, _("Suspend") )->Enable( SysHasValidState() );
m_menuEmu.AppendSeparator();
@ -428,7 +426,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
// ------------------------------------------------------------------------
m_menuConfig.Append(MenuId_Config_Settings, _("General Settings") );
m_menuConfig.Append(MenuId_Config_Settings, _("General &Settings") );
m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_PAD, _("PAD"), &m_menuPad );
@ -517,20 +515,44 @@ void MainEmuFrame::ReloadRecentLists()
void MainEmuFrame::ApplyCoreStatus()
{
bool valstate = SysHasValidState();
wxMenuBar& menubar( *GetMenuBar() );
if( !pxAssertMsg( &menubar!=NULL, "Mainframe menu bar is NULL!" ) ) return;
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, SysHasValidState() );
GetMenuBar()->Enable( MenuId_Sys_Reset, SysHasValidState() || (g_plugins!=NULL) );
wxMenuItem& susres( *menubar.FindItem( MenuId_Sys_SuspendResume ) );
if( !pxAssertMsg( &susres!=NULL, "Suspend/Resume Menubar Item is NULL!" ) ) return;
GetMenuBar()->SetLabel( MenuId_Sys_SuspendResume, CoreThread.IsOpen() ? _("Suspend") : _("Resume") );
if( SysHasValidState() )
{
susres.Enable();
if( CoreThread.IsOpen() )
{
susres.SetHelp( _("Safely pauses emulation and preserves the PS2 state.") );
susres.SetText( _("Suspend") );
}
else
{
susres.SetHelp( _("Resumes the suspended emulation state.") );
susres.SetText( _("Resume") );
}
}
else
{
susres.Enable( false );
susres.SetHelp( _("No emulation state is active; cannot suspend or resume.") );
}
menubar.Enable( MenuId_Sys_Reset, SysHasValidState() || (g_plugins!=NULL) );
}
void MainEmuFrame::ApplySettings()
{
GetMenuBar()->Check( MenuId_SkipBiosToggle, g_Conf->EmuOptions.SkipBiosSplash );
wxMenuBar& menubar( *GetMenuBar() );
if( !pxAssertMsg( &menubar!=NULL, "Mainframe menu bar is NULL!" ) ) return;
GetMenuBar()->Check( MenuId_Config_Multitap0Toggle, g_Conf->EmuOptions.MultitapPort0_Enabled );
GetMenuBar()->Check( MenuId_Config_Multitap1Toggle, g_Conf->EmuOptions.MultitapPort1_Enabled );
menubar.Check( MenuId_SkipBiosToggle, g_Conf->EmuOptions.SkipBiosSplash );
menubar.Check( MenuId_Config_Multitap0Toggle, g_Conf->EmuOptions.MultitapPort0_Enabled );
menubar.Check( MenuId_Config_Multitap1Toggle, g_Conf->EmuOptions.MultitapPort1_Enabled );
if( m_RecentIsoList )
{

View File

@ -186,17 +186,16 @@ void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event)
{
if( !SysHasValidState() ) return;
// Note: We manually update the menu here, even though it'll be updated again
// when the thread "officially" suspends or resumes (via listener callback), because
// the callback is tied to the actual thread status
if( CoreThread.Suspend() )
GetMenuBar()->SetLabel( MenuId_Sys_SuspendResume, _("Resume") );
else
if( !CoreThread.Suspend() )
{
sApp.SysExecute();
GetMenuBar()->SetLabel( MenuId_Sys_SuspendResume, _("Suspend") );
}
// Disable the menu item. The state of the menu is indeterminate until the core thread
// has responded (it updates status after the plugins are loaded and emulation has
// engaged successfully).
GetMenuBar()->Enable( MenuId_Sys_SuspendResume, false );
}
void MainEmuFrame::Menu_SysReset_Click(wxCommandEvent &event)

View File

@ -14,6 +14,7 @@
*/
#include "PrecompiledHeader.h"
#include "App.h"
#include "ConfigurationPanels.h"
#include "Utilities/ScopedPtr.h"
@ -27,6 +28,7 @@ using namespace wxHelpers;
// ------------------------------------------------------------------------
Panels::BaseSelectorPanel::BaseSelectorPanel( wxWindow& parent, int idealWidth ) :
BaseApplicableConfigPanel( &parent, idealWidth )
, m_ReloadSettingsBinding( wxGetApp().Source_SettingsApplied(), EventListener<int>( this, OnAppliedSettings ) )
{
Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler(PluginSelectorPanel::OnFolderChanged), NULL, this );
}
@ -61,6 +63,11 @@ void Panels::BaseSelectorPanel::OnFolderChanged( wxFileDirPickerEvent& evt )
OnShown();
}
void Panels::BaseSelectorPanel::OnAppliedSettings( void* me, int& )
{
if( me == NULL ) return;
((BaseSelectorPanel*)me)->ReloadSettings();
}
// ----------------------------------------------------------------------------
Panels::BiosSelectorPanel::BiosSelectorPanel( wxWindow& parent, int idealWidth ) :

View File

@ -31,6 +31,7 @@
#include "wxHelpers.h"
#include "Utilities/SafeArray.h"
#include "Utilities/Threading.h"
#include "Utilities/EventSource.h"
class wxListBox;
@ -336,9 +337,10 @@ namespace Panels
class BaseSelectorPanel: public BaseApplicableConfigPanel
{
protected:
EventListenerBinding<int> m_ReloadSettingsBinding;
public:
virtual ~BaseSelectorPanel();
virtual ~BaseSelectorPanel() throw();
BaseSelectorPanel( wxWindow& parent, int idealWidth );
virtual bool Show( bool visible=true );
@ -349,6 +351,9 @@ namespace Panels
protected:
virtual void DoRefresh()=0;
virtual bool ValidateEnumerationStatus()=0;
virtual void ReloadSettings()=0;
static void __evt_fastcall OnAppliedSettings( void* me, int& whatever );
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -363,12 +368,13 @@ namespace Panels
public:
BiosSelectorPanel( wxWindow& parent, int idealWidth );
virtual ~BiosSelectorPanel();
void ReloadSettings();
protected:
virtual void Apply();
virtual void DoRefresh();
virtual bool ValidateEnumerationStatus();
virtual void ReloadSettings();
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -468,7 +474,6 @@ namespace Panels
void CancelRefresh(); // used from destructor, stays non-virtual
void Apply();
void ReloadSettings();
protected:
void OnConfigure_Clicked( wxCommandEvent& evt );
@ -476,11 +481,14 @@ namespace Panels
virtual void OnProgress( wxCommandEvent& evt );
virtual void OnEnumComplete( wxCommandEvent& evt );
virtual void ReloadSettings();
virtual void DoRefresh();
virtual bool ValidateEnumerationStatus();
int FileCount() const { return m_FileList->Count(); }
const wxString& GetFilename( int i ) const { return (*m_FileList)[i]; }
friend class EnumThread;
};
}

View File

@ -272,7 +272,7 @@ wxDialogWithHelpers::wxDialogWithHelpers( wxWindow* parent, int id, const wxStr
++m_DialogIdents[GetId()];
if( hasContextHelp )
wxHelpProvider::Set( new wxSimpleHelpProvider() );
delete wxHelpProvider::Set( new wxSimpleHelpProvider() );
// Note: currently the Close (X) button doesn't appear to work in dialogs. Docs indicate
// that it should, so I presume the problem is in wxWidgets and that (hopefully!) an updated