More work on memorycards, and general UI adjustments. Some things with the dialogs might be a bit broken-ish. Will finish this up properly soon. :)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3047 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-05-20 12:23:13 +00:00
parent d16754df41
commit f7a30c3291
30 changed files with 1252 additions and 354 deletions

View File

@ -211,6 +211,10 @@
RelativePath="..\..\src\Utilities\Exceptions.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\FastFormatString.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\HashTools.cpp"
>
@ -263,6 +267,10 @@
RelativePath="..\..\src\Utilities\pxStaticText.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\pxWindowTextWriter.cpp"
>
</File>
<File
RelativePath="..\..\src\Utilities\StringHelpers.cpp"
>

View File

@ -65,6 +65,9 @@ struct ParsedAssignmentString
ParsedAssignmentString( const wxString& src );
};
extern wxString FastFormatString_Ascii(const char* fmt, va_list argptr);
extern wxString FastFormatString_Unicode(const wxChar* fmt, va_list argptr);
//////////////////////////////////////////////////////////////////////////////////////////
// Custom internal sprintf functions, which are ASCII only (even in UNICODE builds)

View File

@ -455,6 +455,81 @@ protected:
virtual void OnNewLine();
};
// --------------------------------------------------------------------------------------
// pxWindowTextWriter
// --------------------------------------------------------------------------------------
class pxWindowTextWriter
{
protected:
wxDC& m_dc;
wxAlignment m_align;
wxPoint m_curpos;
int m_leading;
virtual void _DoWriteLn( const wxChar* msg );
void _DoWrite( const wxChar* msg );
public:
pxWindowTextWriter( wxDC& dc )
: m_dc( dc )
{
m_curpos = wxPoint();
m_align = wxALIGN_CENTER;
m_leading = 2;
OnFontChanged();
}
virtual ~pxWindowTextWriter() throw()
{
}
virtual void OnFontChanged();
pxWindowTextWriter& WriteLn();
pxWindowTextWriter& WriteLn( const wxChar* fmt, ... );
pxWindowTextWriter& SetFont( const wxFont& font );
pxWindowTextWriter& Align( const wxAlignment& align );
pxWindowTextWriter& SetLeading( int lead )
{
m_leading = lead;
return *this;
}
pxWindowTextWriter& SetWeight( int weight );
pxWindowTextWriter& SetStyle( int style );
pxWindowTextWriter& Normal();
pxWindowTextWriter& Bold()
{
return SetWeight(wxBOLD);
}
pxWindowTextWriter& Italic()
{
return SetStyle(wxITALIC);
}
pxWindowTextWriter& SetPos( const wxPoint& pos );
pxWindowTextWriter& MovePos( const wxSize& delta );
pxWindowTextWriter& SetPos( int xpos, int ypos )
{
return SetPos( wxPoint(xpos,ypos) );
}
pxWindowTextWriter& MovePos( int xdelta, int ydelta )
{
return MovePos( wxSize(xdelta, ydelta) );
}
pxWindowTextWriter& SetY( int ypos );
pxWindowTextWriter& MoveY( int ydelta );
};
// --------------------------------------------------------------------------------------
// MoreStockCursors
// --------------------------------------------------------------------------------------

View File

@ -281,141 +281,6 @@ const IConsoleWriter ConsoleWriter_wxError =
0, // instance-level indentation (should always be 0)
};
// Sanity check: truncate strings if they exceed 512k in length. Anything like that
// is either a bug or really horrible code that needs to be stopped before it causes
// system deadlock.
static const int MaxFormattedStringLength = 0x80000;
template< typename CharType >
class FormatBuffer : public Mutex
{
public:
bool& clearbit;
SafeArray<CharType> buffer;
wxMBConvUTF8 ConvUTF8;
FormatBuffer( bool& bit_to_clear_on_destruction )
: clearbit( bit_to_clear_on_destruction )
, buffer( 4096, wxsFormat( L"%s Format Buffer", (sizeof(CharType)==1) ? "Ascii" : "Unicode" ) )
{
}
virtual ~FormatBuffer() throw()
{
clearbit = true;
Wait(); // lock the mutex, just in case.
}
};
static bool ascii_buffer_is_deleted = false;
static bool unicode_buffer_is_deleted = false;
static FormatBuffer<char> ascii_buffer( ascii_buffer_is_deleted );
static FormatBuffer<wxChar> unicode_buffer( unicode_buffer_is_deleted );
static void format_that_ascii_mess( SafeArray<char>& buffer, const char* fmt, va_list argptr )
{
while( true )
{
int size = buffer.GetLength();
int len = vsnprintf(buffer.GetPtr(), size, fmt, argptr);
// some implementations of vsnprintf() don't NUL terminate
// the string if there is not enough space for it so
// always do it manually
buffer[size-1] = '\0';
if( size >= MaxFormattedStringLength ) break;
// vsnprintf() may return either -1 (traditional Unix behavior) or the
// total number of characters which would have been written if the
// buffer were large enough (newer standards such as Unix98)
if ( len < 0 )
len = size + (size/4);
if ( len < size ) break;
buffer.ExactAlloc( len + 1 );
};
// performing an assertion or log of a truncated string is unsafe, so let's not; even
// though it'd be kinda nice if we did.
}
static void format_that_unicode_mess( SafeArray<wxChar>& buffer, const wxChar* fmt, va_list argptr)
{
while( true )
{
int size = buffer.GetLength();
int len = wxVsnprintf(buffer.GetPtr(), size, fmt, argptr);
// some implementations of vsnprintf() don't NUL terminate
// the string if there is not enough space for it so
// always do it manually
buffer[size-1] = L'\0';
if( size >= MaxFormattedStringLength ) break;
// vsnprintf() may return either -1 (traditional Unix behavior) or the
// total number of characters which would have been written if the
// buffer were large enough (newer standards such as Unix98)
if ( len < 0 )
len = size + (size/4);
if ( len < size ) break;
buffer.ExactAlloc( len + 1 );
};
// performing an assertion or log of a truncated string is unsafe, so let's not; even
// though it'd be kinda nice if we did.
}
static wxString ascii_format_string(const char* fmt, va_list argptr)
{
if( ascii_buffer_is_deleted )
{
// This means that the program is shutting down and the C++ destructors are
// running, randomly deallocating static variables from existence. We handle it
// as gracefully as possible by allocating local vars to do our bidding (slow, but
// ultimately necessary!)
SafeArray<char> localbuf( 4096, L"Temporary Ascii Formatting Buffer" );
format_that_ascii_mess( localbuf, fmt, argptr );
return fromUTF8( localbuf.GetPtr() );
}
else
{
// This is normal operation. The static buffers are available for use, and we use
// them for sake of efficiency (fewer heap allocs, for sure!)
ScopedLock locker( ascii_buffer );
format_that_ascii_mess( ascii_buffer.buffer, fmt, argptr );
return fromUTF8( ascii_buffer.buffer.GetPtr() );
}
}
static wxString unicode_format_string(const wxChar* fmt, va_list argptr)
{
// See above for the explanation on the _is_deleted flags.
if( unicode_buffer_is_deleted )
{
SafeArray<wxChar> localbuf( 4096, L"Temporary Unicode Formatting Buffer" );
format_that_unicode_mess( localbuf, fmt, argptr );
return localbuf.GetPtr();
}
else
{
ScopedLock locker( unicode_buffer );
format_that_unicode_mess( unicode_buffer.buffer, fmt, argptr );
return unicode_buffer.buffer.GetPtr();
}
}
// =====================================================================================================
// IConsole Interfaces
// =====================================================================================================
@ -494,7 +359,7 @@ bool IConsoleWriter::Write( const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
DoWrite( ascii_format_string(fmt, args) );
DoWrite( FastFormatString_Ascii(fmt, args) );
va_end(args);
return false;
@ -507,7 +372,7 @@ bool IConsoleWriter::Write( ConsoleColors color, const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( color );
DoWrite( ascii_format_string(fmt, args) );
DoWrite( FastFormatString_Ascii(fmt, args) );
va_end(args);
return false;
@ -519,7 +384,7 @@ bool IConsoleWriter::WriteLn( const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
DoWriteLn( _addIndentation( ascii_format_string(fmt, args), conlog_Indent ) );
DoWriteLn( _addIndentation( FastFormatString_Ascii(fmt, args), conlog_Indent ) );
va_end(args);
return false;
@ -531,7 +396,7 @@ bool IConsoleWriter::WriteLn( ConsoleColors color, const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( color );
DoWriteLn( _addIndentation( ascii_format_string(fmt, args), conlog_Indent ) );
DoWriteLn( _addIndentation( FastFormatString_Ascii(fmt, args), conlog_Indent ) );
va_end(args);
return false;
@ -544,7 +409,7 @@ bool IConsoleWriter::Error( const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( Color_StrongRed );
DoWriteLn( _addIndentation( ascii_format_string(fmt, args) ) );
DoWriteLn( _addIndentation( FastFormatString_Ascii(fmt, args) ) );
va_end(args);
return false;
@ -557,7 +422,7 @@ bool IConsoleWriter::Warning( const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( Color_StrongOrange );
DoWriteLn( _addIndentation( ascii_format_string(fmt, args) ) );
DoWriteLn( _addIndentation( FastFormatString_Ascii(fmt, args) ) );
va_end(args);
return false;
@ -573,7 +438,7 @@ bool IConsoleWriter::Write( const wxChar* fmt, ... ) const
va_list args;
va_start(args,fmt);
DoWrite( unicode_format_string( fmt, args ) );
DoWrite( FastFormatString_Unicode( fmt, args ) );
va_end(args);
return false;
@ -586,7 +451,7 @@ bool IConsoleWriter::Write( ConsoleColors color, const wxChar* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( color );
DoWrite( unicode_format_string( fmt, args ) );
DoWrite( FastFormatString_Unicode( fmt, args ) );
va_end(args);
return false;
@ -598,7 +463,7 @@ bool IConsoleWriter::WriteLn( const wxChar* fmt, ... ) const
va_list args;
va_start(args,fmt);
DoWriteLn( _addIndentation( unicode_format_string( fmt, args ), conlog_Indent ) );
DoWriteLn( _addIndentation( FastFormatString_Unicode( fmt, args ), conlog_Indent ) );
va_end(args);
return false;
@ -611,7 +476,7 @@ bool IConsoleWriter::WriteLn( ConsoleColors color, const wxChar* fmt, ... ) cons
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( color );
DoWriteLn( _addIndentation( unicode_format_string( fmt, args ), conlog_Indent ) );
DoWriteLn( _addIndentation( FastFormatString_Unicode( fmt, args ), conlog_Indent ) );
va_end(args);
return false;
@ -624,7 +489,7 @@ bool IConsoleWriter::Error( const wxChar* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( Color_StrongRed );
DoWriteLn( _addIndentation( unicode_format_string( fmt, args ) ) );
DoWriteLn( _addIndentation( FastFormatString_Unicode( fmt, args ) ) );
va_end(args);
return false;
@ -637,7 +502,7 @@ bool IConsoleWriter::Warning( const wxChar* fmt, ... ) const
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( Color_StrongOrange );
DoWriteLn( _addIndentation( unicode_format_string( fmt, args ) ) );
DoWriteLn( _addIndentation( FastFormatString_Unicode( fmt, args ) ) );
va_end(args);
return false;
@ -653,7 +518,7 @@ bool IConsoleWriter::WriteFromStdout( const char* fmt, ... ) const
va_list args;
va_start(args,fmt);
DoWrite( ascii_format_string(fmt, args) );
DoWrite( FastFormatString_Ascii(fmt, args) );
va_end(args);
return false;
@ -666,7 +531,7 @@ bool IConsoleWriter::WriteFromStdout( ConsoleColors color, const char* fmt, ...
va_list args;
va_start(args,fmt);
ConsoleColorScope cs( color );
DoWrite( ascii_format_string(fmt, args) );
DoWrite( FastFormatString_Ascii(fmt, args) );
va_end(args);
return false;

View File

@ -0,0 +1,163 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 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 "Threading.h"
using namespace Threading;
// Sanity check: truncate strings if they exceed 512k in length. Anything like that
// is either a bug or really horrible code that needs to be stopped before it causes
// system deadlock.
static const int MaxFormattedStringLength = 0x80000;
// --------------------------------------------------------------------------------------
// FormatBuffer
// --------------------------------------------------------------------------------------
// This helper class provides a "safe" way for us to check if the global handles for the
// string format buffer have been initialized or destructed by the C++ global heap manager.
// (C++ has no way to enforce init/destruct order on complex globals, thus the convoluted
// use of booleans to check the status of the type initializers).
//
template< typename CharType >
class FormatBuffer : public Mutex
{
public:
bool& clearbit;
SafeArray<CharType> buffer;
wxMBConvUTF8 ConvUTF8;
FormatBuffer( bool& bit_to_clear_on_destruction )
: clearbit( bit_to_clear_on_destruction )
, buffer( 4096, wxsFormat( L"%s Format Buffer", (sizeof(CharType)==1) ? "Ascii" : "Unicode" ) )
{
bit_to_clear_on_destruction = false;
}
virtual ~FormatBuffer() throw()
{
clearbit = true;
Wait(); // lock the mutex, just in case.
}
};
// Assume the buffer is 'deleted' -- technically it's never existed on startup,
// but "deleted" is well enough.
static bool ascii_buffer_is_deleted = true;
static bool unicode_buffer_is_deleted = true;
static FormatBuffer<char> ascii_buffer( ascii_buffer_is_deleted );
static FormatBuffer<wxChar> unicode_buffer( unicode_buffer_is_deleted );
static void format_that_ascii_mess( SafeArray<char>& buffer, const char* fmt, va_list argptr )
{
while( true )
{
int size = buffer.GetLength();
int len = vsnprintf(buffer.GetPtr(), size, fmt, argptr);
// some implementations of vsnprintf() don't NUL terminate
// the string if there is not enough space for it so
// always do it manually
buffer[size-1] = '\0';
if( size >= MaxFormattedStringLength ) break;
// vsnprintf() may return either -1 (traditional Unix behavior) or the
// total number of characters which would have been written if the
// buffer were large enough (newer standards such as Unix98)
if ( len < 0 )
len = size + (size/4);
if ( len < size ) break;
buffer.ExactAlloc( len + 1 );
};
// performing an assertion or log of a truncated string is unsafe, so let's not; even
// though it'd be kinda nice if we did.
}
static void format_that_unicode_mess( SafeArray<wxChar>& buffer, const wxChar* fmt, va_list argptr)
{
while( true )
{
int size = buffer.GetLength();
int len = wxVsnprintf(buffer.GetPtr(), size, fmt, argptr);
// some implementations of vsnprintf() don't NUL terminate
// the string if there is not enough space for it so
// always do it manually
buffer[size-1] = L'\0';
if( size >= MaxFormattedStringLength ) break;
// vsnprintf() may return either -1 (traditional Unix behavior) or the
// total number of characters which would have been written if the
// buffer were large enough (newer standards such as Unix98)
if ( len < 0 )
len = size + (size/4);
if ( len < size ) break;
buffer.ExactAlloc( len + 1 );
};
// performing an assertion or log of a truncated string is unsafe, so let's not; even
// though it'd be kinda nice if we did.
}
wxString FastFormatString_Ascii(const char* fmt, va_list argptr)
{
if( ascii_buffer_is_deleted )
{
// This means that the program is shutting down and the C++ destructors are
// running, randomly deallocating static variables from existence. We handle it
// as gracefully as possible by allocating local vars to do our bidding (slow, but
// ultimately necessary!)
SafeArray<char> localbuf( 4096, L"Temporary Ascii Formatting Buffer" );
format_that_ascii_mess( localbuf, fmt, argptr );
return fromUTF8( localbuf.GetPtr() );
}
else
{
// This is normal operation. The static buffers are available for use, and we use
// them for sake of efficiency (fewer heap allocs, for sure!)
ScopedLock locker( ascii_buffer );
format_that_ascii_mess( ascii_buffer.buffer, fmt, argptr );
return fromUTF8( ascii_buffer.buffer.GetPtr() );
}
}
wxString FastFormatString_Unicode(const wxChar* fmt, va_list argptr)
{
// See above for the explanation on the _is_deleted flags.
if( unicode_buffer_is_deleted )
{
SafeArray<wxChar> localbuf( 4096, L"Temporary Unicode Formatting Buffer" );
format_that_unicode_mess( localbuf, fmt, argptr );
return localbuf.GetPtr();
}
else
{
ScopedLock locker( unicode_buffer );
format_that_unicode_mess( unicode_buffer.buffer, fmt, argptr );
return unicode_buffer.buffer.GetPtr();
}
}

View File

@ -0,0 +1,136 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 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 "wxGuiTools.h"
// --------------------------------------------------------------------------------------
// pxWindowTextWriter Implementations
// --------------------------------------------------------------------------------------
void pxWindowTextWriter::OnFontChanged()
{
}
pxWindowTextWriter& pxWindowTextWriter::SetWeight( int weight )
{
wxFont curfont( m_dc.GetFont() );
curfont.SetWeight( weight );
m_dc.SetFont( curfont );
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::SetStyle( int style )
{
wxFont curfont( m_dc.GetFont() );
curfont.SetStyle( style );
m_dc.SetFont( curfont );
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::Normal()
{
wxFont curfont( m_dc.GetFont() );
curfont.SetStyle( wxNORMAL );
curfont.SetWeight( wxNORMAL );
m_dc.SetFont( curfont );
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::SetPos( const wxPoint& pos )
{
m_curpos = pos;
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::MovePos( const wxSize& delta )
{
m_curpos += delta;
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::SetY( int ypos )
{
m_curpos.y = ypos;
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::MoveY( int ydelta )
{
m_curpos.y += ydelta;
return *this;
}
void pxWindowTextWriter::_DoWriteLn( const wxChar* msg )
{
pxAssume( msg );
int tWidth, tHeight;
m_dc.GetTextExtent( msg, &tWidth, &tHeight );
wxPoint dispos( m_curpos );
if( m_align & wxALIGN_CENTER_HORIZONTAL )
{
dispos.x = (m_dc.GetSize().GetWidth() - tWidth) / 2;
}
else if( m_align & wxALIGN_RIGHT )
{
dispos.x = m_dc.GetSize().GetWidth() - tWidth;
}
m_dc.DrawText( msg, dispos );
m_curpos.y += tHeight + m_leading;
}
// Splits incoming multi-line strings into pieces, and dispatches each line individually
// to the text writer.
void pxWindowTextWriter::_DoWrite( const wxChar* msg )
{
pxAssume( msg );
wxArrayString parts;
SplitString( parts, msg, L'\n' );
for( size_t i=0; i<parts.GetCount(); ++i )
_DoWriteLn( parts[i] );
}
pxWindowTextWriter& pxWindowTextWriter::SetFont( const wxFont& font )
{
m_dc.SetFont( font );
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::Align( const wxAlignment& align )
{
m_align = align;
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::WriteLn()
{
_DoWriteLn( L"" );
return *this;
}
pxWindowTextWriter& pxWindowTextWriter::WriteLn( const wxChar* fmt, ... )
{
va_list args;
va_start(args,fmt);
_DoWrite( FastFormatString_Unicode(fmt, args) );
va_end(args);
return *this;
}

View File

@ -639,7 +639,7 @@ DECLARE_APP(Pcsx2App)
template<typename DialogType>
void AppOpenDialog( wxWindow* parent=NULL )
{
if( wxWindow* window = wxFindWindowByName( DialogType::GetNameStatic() ) )
if( wxWindow* window = wxFindWindowByName( L"Dialog:" + DialogType::GetNameStatic() ) )
window->SetFocus();
else
(new DialogType( parent ))->Show();

View File

@ -50,7 +50,7 @@ ConfigOverrides OverrideOptions;
template<typename DialogType>
int AppOpenModalDialog( wxWindow* parent=NULL )
{
if( wxWindow* window = wxFindWindowByName( DialogType::GetNameStatic() ) )
if( wxWindow* window = wxFindWindowByName( L"Dialog:" + DialogType::GetNameStatic() ) )
{
window->SetFocus();
if( wxDialog* dialog = wxDynamicCast( window, wxDialog ) )

View File

@ -21,6 +21,12 @@
#include "AppCommon.h"
class BaseApplicableConfigPanel;
class BaseApplicableDialog;
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE( pxEvt_OnWindowCreated, -1 )
DECLARE_EVENT_TYPE( pxEvt_ApplySettings, -1 )
END_DECLARE_EVENT_TYPES()
namespace Exception
{
@ -109,6 +115,39 @@ public:
virtual ApplyStateStruct& GetApplyState() { return m_ApplyState; }
};
class BaseApplicableDialog
: public wxDialogWithHelpers
, public IApplyState
{
DECLARE_DYNAMIC_CLASS_NO_COPY(BaseApplicableDialog)
public:
BaseApplicableDialog() {}
virtual ~BaseApplicableDialog() throw();
// Must return the same thing as GetNameStatic; a name ideal for use in uniquely
// identifying dialogs. (this version is the 'instance' version, which is called
// by BaseConfigurationDialog to assign the wxWidgets dialog name, and for saving
// screenshots to disk)
virtual wxString GetDialogName() const;
protected:
void Init();
BaseApplicableDialog(wxWindow* parent, const wxString& title );
BaseApplicableDialog(wxWindow* parent, const wxString& title, wxOrientation sizerOrient );
void OnSettingsApplied( wxCommandEvent& evt );
void OnWindowCreated( wxCommandEvent& evt );
// Note: This method *will* be called automatically after a successful Apply, but will not
// be called after a failed Apply (canceled due to error).
virtual void AppStatusEvent_OnSettingsApplied() {}
virtual void AppStatusEvent_OnSettingsLoadSave( const AppSettingsEventInfo& ) {}
virtual void AppStatusEvent_OnExit() {}
};
// --------------------------------------------------------------------------------------
// BaseApplicableConfigPanel
// --------------------------------------------------------------------------------------
@ -119,7 +158,8 @@ public:
// static vars and assumes that only one ApplicableConfig system is available to the
// user at any time (ie, a singular modal dialog).
//
class BaseApplicableConfigPanel : public wxPanelWithHelpers
class BaseApplicableConfigPanel
: public wxPanelWithHelpers
{
protected:
int m_OwnerPage;

View File

@ -53,8 +53,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent )
wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN
)
{
SetName( GetNameStatic() );
static const wxString LabelAuthors = fromUTF8(
"Developers"
"\n\n"

View File

@ -28,6 +28,9 @@
#include <wx/filepicker.h>
#include <wx/listbook.h>
DEFINE_EVENT_TYPE( pxEvt_OnWindowCreated )
DEFINE_EVENT_TYPE( pxEvt_ApplySettings )
using namespace Panels;
// configure the orientation of the listbox based on the platform
@ -38,33 +41,63 @@ using namespace Panels;
static const int s_orient = wxBK_LEFT;
#endif
IMPLEMENT_DYNAMIC_CLASS(Dialogs::BaseApplicableDialog, wxDialogWithHelpers)
IMPLEMENT_DYNAMIC_CLASS(BaseApplicableDialog, wxDialogWithHelpers)
Dialogs::BaseApplicableDialog::BaseApplicableDialog( wxWindow* parent, const wxString& title )
BaseApplicableDialog::BaseApplicableDialog( wxWindow* parent, const wxString& title )
: wxDialogWithHelpers( parent, title, false )
{
Init();
}
Dialogs::BaseApplicableDialog::BaseApplicableDialog( wxWindow* parent, const wxString& title, wxOrientation sizerOrient )
BaseApplicableDialog::BaseApplicableDialog( wxWindow* parent, const wxString& title, wxOrientation sizerOrient )
: wxDialogWithHelpers( parent, title, sizerOrient )
{
Init();
}
Dialogs::BaseApplicableDialog::~BaseApplicableDialog() throw()
BaseApplicableDialog::~BaseApplicableDialog() throw()
{
m_ApplyState.DoCleanup();
}
Dialogs::BaseConfigurationDialog::BaseConfigurationDialog( wxWindow* parent, const wxString& title, wxImageList& bookicons, int idealWidth )
: _parent( parent, title, wxVERTICAL )
, m_listbook( *new wxListbook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, s_orient ) )
wxString BaseApplicableDialog::GetDialogName() const
{
m_idealWidth = idealWidth;
pxFailDev( "This class must implement GetDialogName!" );
return L"Unnamed";
}
m_listbook.SetImageList( &bookicons );
m_ApplyState.StartBook( &m_listbook );
*this += m_listbook | pxExpand.Border( wxLEFT | wxRIGHT, 2 );
void BaseApplicableDialog::Init()
{
Connect( pxEvt_OnWindowCreated, wxCommandEventHandler (BaseApplicableDialog::OnWindowCreated) );
Connect( pxEvt_ApplySettings, wxCommandEventHandler (BaseApplicableDialog::OnSettingsApplied) );
wxCommandEvent applyEvent( pxEvt_ApplySettings );
applyEvent.SetId( GetId() );
AddPendingEvent( applyEvent );
}
void BaseApplicableDialog::OnSettingsApplied( wxCommandEvent& evt )
{
evt.Skip();
if( evt.GetId() == GetId() ) AppStatusEvent_OnSettingsApplied();
}
void BaseApplicableDialog::OnWindowCreated( wxCommandEvent& evt )
{
evt.Skip();
if( evt.GetId() == GetId() ) SetName( L"Dialog:" + GetDialogName() );
}
// --------------------------------------------------------------------------------------
// BaseConfigurationDialog Implementations
// --------------------------------------------------------------------------------------
Dialogs::BaseConfigurationDialog::BaseConfigurationDialog( wxWindow* parent, const wxString& title, int idealWidth )
: _parent( parent, title, wxVERTICAL )
{
m_idealWidth = idealWidth;
m_listbook = NULL;
Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BaseConfigurationDialog::OnOk_Click ) );
Connect( wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BaseConfigurationDialog::OnCancel_Click ) );
@ -94,6 +127,19 @@ Dialogs::BaseConfigurationDialog::BaseConfigurationDialog( wxWindow* parent, con
ConnectSomethingChanged( DIRPICKER_CHANGED );
}
void Dialogs::BaseConfigurationDialog::AddListbook( wxSizer* sizer )
{
if( !sizer ) sizer = GetSizer();
sizer += m_listbook | pxExpand.Border( wxLEFT | wxRIGHT, 2 );
}
void Dialogs::BaseConfigurationDialog::CreateListbook( wxImageList& bookicons )
{
m_listbook = new wxListbook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, s_orient );
m_listbook->SetImageList( &bookicons );
m_ApplyState.StartBook( m_listbook );
}
void Dialogs::BaseConfigurationDialog::AddOkCancel( wxSizer* sizer )
{
_parent::AddOkCancel( sizer, true );
@ -131,7 +177,7 @@ void Dialogs::BaseConfigurationDialog::OnOk_Click( wxCommandEvent& evt )
if( m_ApplyState.ApplyAll() )
{
FindWindow( wxID_APPLY )->Disable();
GetConfSettingsTabName() = m_labels[m_listbook.GetSelection()];
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
AppSaveSettings();
evt.Skip();
}
@ -140,7 +186,7 @@ void Dialogs::BaseConfigurationDialog::OnOk_Click( wxCommandEvent& evt )
void Dialogs::BaseConfigurationDialog::OnCancel_Click( wxCommandEvent& evt )
{
evt.Skip();
GetConfSettingsTabName() = m_labels[m_listbook.GetSelection()];
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
}
void Dialogs::BaseConfigurationDialog::OnApply_Click( wxCommandEvent& evt )
@ -148,7 +194,7 @@ void Dialogs::BaseConfigurationDialog::OnApply_Click( wxCommandEvent& evt )
if( m_ApplyState.ApplyAll() )
FindWindow( wxID_APPLY )->Disable();
GetConfSettingsTabName() = m_labels[m_listbook.GetSelection()];
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
AppSaveSettings();
}
@ -164,8 +210,9 @@ void Dialogs::BaseConfigurationDialog::OnScreenshot_Click( wxCommandEvent& evt )
memDC.Blit( wxPoint(), dcsize, &dc, wxPoint() );
}
wxString pagename( m_listbook ? (L"_" + m_listbook->GetPageText( m_listbook->GetSelection() )) : wxString() );
wxString filenameDefault;
filenameDefault.Printf( L"pcsx2_settings_%s.png", m_listbook.GetPageText( m_listbook.GetSelection() ).c_str() );
filenameDefault.Printf( L"pcsx2_%s%s.png", GetDialogName().c_str(), pagename.c_str() );
filenameDefault.Replace( L"/", L"-" );
wxString filename( wxFileSelector( _("Save dialog screenshots to..."), g_Conf->Folders.Snapshots.ToString(),

View File

@ -23,6 +23,6 @@ void Dialogs::BaseConfigurationDialog::AddPage( const char* label, int iconid )
const wxString labelstr( fromUTF8( label ) );
const int curidx = m_labels.Add( labelstr );
m_ApplyState.SetCurrentPage( curidx );
m_listbook.AddPage( new T( &m_listbook ), wxGetTranslation( labelstr ),
m_listbook->AddPage( new T( m_listbook ), wxGetTranslation( labelstr ),
( labelstr == GetConfSettingsTabName() ), iconid );
}

View File

@ -30,8 +30,6 @@ using namespace pxSizerFlags;
Dialogs::BiosSelectorDialog::BiosSelectorDialog( wxWindow* parent )
: BaseApplicableDialog( parent, _("BIOS Selector"), wxVERTICAL )
{
SetName( GetNameStatic() );
m_idealWidth = 500;
m_selpan = new Panels::BiosSelectorPanel( this );

View File

@ -25,27 +25,13 @@
namespace Panels
{
class BaseSelectorPanel;
class MemoryCardListPanel;
class MemoryCardListPanel_Advanced;
class McdConfigPanel_Toggles;
class BaseMcdListPanel;
}
namespace Dialogs
{
class BaseApplicableDialog : public wxDialogWithHelpers, public IApplyState
{
DECLARE_DYNAMIC_CLASS_NO_COPY(BaseApplicableDialog)
public:
BaseApplicableDialog() {}
protected:
BaseApplicableDialog(wxWindow* parent, const wxString& title );
BaseApplicableDialog(wxWindow* parent, const wxString& title, wxOrientation sizerOrient );
public:
virtual ~BaseApplicableDialog() throw();
//ApplyStateStruct& GetApplyState() { return m_ApplyState; }
};
// --------------------------------------------------------------------------------------
// BaseConfigurationDialog
// --------------------------------------------------------------------------------------
@ -54,15 +40,17 @@ namespace Dialogs
typedef BaseApplicableDialog _parent;
protected:
wxListbook& m_listbook;
wxListbook* m_listbook;
wxArrayString m_labels;
public:
virtual ~BaseConfigurationDialog() throw();
BaseConfigurationDialog(wxWindow* parent, const wxString& title, wxImageList& bookicons, int idealWidth);
BaseConfigurationDialog(wxWindow* parent, const wxString& title, int idealWidth);
public:
void AddOkCancel( wxSizer* sizer=NULL );
void AddListbook( wxSizer* sizer=NULL );
void CreateListbook( wxImageList& bookicons );
template< typename T >
void AddPage( const char* label, int iconid );
@ -86,7 +74,8 @@ namespace Dialogs
public:
virtual ~SysConfigDialog() throw() {}
SysConfigDialog(wxWindow* parent=NULL);
static const wxChar* GetNameStatic() { return L"Dialog:CoreSettings"; }
static wxString GetNameStatic() { return L"CoreSettings"; }
wxString GetDialogName() const { return GetNameStatic(); }
protected:
virtual wxString& GetConfSettingsTabName() const { return g_Conf->SysSettingsTabName; }
@ -97,15 +86,16 @@ namespace Dialogs
// --------------------------------------------------------------------------------------
class McdConfigDialog : public BaseConfigurationDialog
{
typedef BaseApplicableDialog _parent;
typedef BaseConfigurationDialog _parent;
protected:
Panels::MemoryCardListPanel* m_panel_mcdlist;
Panels::BaseMcdListPanel* m_panel_mcdlist;
public:
virtual ~McdConfigDialog() throw() {}
McdConfigDialog(wxWindow* parent=NULL);
static const wxChar* GetNameStatic() { return L"Dialog:MemoryCardSettings"; }
static wxString GetNameStatic() { return L"McdConfig"; }
wxString GetDialogName() const { return GetNameStatic(); }
virtual bool Show( bool show=true );
virtual int ShowModal();
@ -124,7 +114,8 @@ namespace Dialogs
public:
virtual ~AppConfigDialog() throw() {}
AppConfigDialog(wxWindow* parent=NULL);
static const wxChar* GetNameStatic() { return L"Dialog:AppSettings"; }
static wxString GetNameStatic() { return L"AppSettings"; }
wxString GetDialogName() const { return GetNameStatic(); }
protected:
virtual wxString& GetConfSettingsTabName() const { return g_Conf->AppSettingsTabName; }
@ -144,7 +135,8 @@ namespace Dialogs
virtual ~BiosSelectorDialog() throw() {}
BiosSelectorDialog( wxWindow* parent=NULL );
static const wxChar* GetNameStatic() { return L"Dialog:BiosSelector"; }
static wxString GetNameStatic() { return L"BiosSelector"; }
wxString GetDialogName() const { return GetNameStatic(); }
virtual bool Show( bool show=true );
virtual int ShowModal();
@ -157,7 +149,7 @@ namespace Dialogs
// --------------------------------------------------------------------------------------
// CreateMemoryCardDialog
// --------------------------------------------------------------------------------------
class CreateMemoryCardDialog : public BaseApplicableDialog
class CreateMemoryCardDialog : public wxDialogWithHelpers
{
protected:
wxFilePickerCtrl* m_filepicker;
@ -171,8 +163,6 @@ namespace Dialogs
virtual ~CreateMemoryCardDialog() throw() {}
CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath=wxEmptyString );
static const wxChar* GetNameStatic() { return L"Dialog:CreateMemoryCard"; }
protected:
void OnOk_Click( wxCommandEvent& evt );
void OnDoubleClicked( wxCommandEvent& evt );

View File

@ -39,7 +39,7 @@ wxFilePickerCtrl* CreateMemoryCardFilePicker( wxWindow* parent, uint portidx, ui
) );*/
Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint port, uint slot, const wxString& filepath )
: BaseApplicableDialog( parent, _("Create a new MemoryCard..."), wxVERTICAL )
: wxDialogWithHelpers( parent, _("Create a new MemoryCard..."), wxVERTICAL )
{
m_idealWidth = 620;

View File

@ -24,8 +24,6 @@ using namespace Panels;
Dialogs::LogOptionsDialog::LogOptionsDialog( wxWindow* parent )
: BaseApplicableDialog( parent, _("Trace Logging"), wxVERTICAL )
{
SetName( GetNameStatic() );
m_idealWidth = 480;
*this += new LogOptionsPanel( this );

View File

@ -32,7 +32,8 @@ public:
LogOptionsDialog( wxWindow* parent=NULL );
virtual ~LogOptionsDialog() throw() { }
static const wxChar* GetNameStatic() { return L"Dialog:TraceLogSettings"; }
static wxString GetNameStatic() { return L"TraceLogSettings"; }
wxString GetDialogName() const { return GetNameStatic(); }
protected:
void OnOk_Click( wxCommandEvent& evt );

View File

@ -86,7 +86,8 @@ void Panels::McdConfigPanel_Toggles::AppStatusEvent_OnSettingsApplied()
#endif
}
Panels::McdConfigPanel_Standard::McdConfigPanel_Standard(wxWindow *parent) : _parent( parent )
Panels::McdConfigPanel_Standard::McdConfigPanel_Standard(wxWindow *parent)
: _parent( parent )
{
m_panel_cardinfo[0] = new MemoryCardInfoPanel( this, 0, 0 );
m_panel_cardinfo[1] = new MemoryCardInfoPanel( this, 1, 0 );
@ -139,29 +140,43 @@ using namespace Panels;
using namespace pxSizerFlags;
Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent )
: BaseConfigurationDialog( parent, _("MemoryCard Settings - PCSX2"), wxGetApp().GetImgList_Config(), 600 )
: BaseConfigurationDialog( parent, _("MemoryCard Manager"), 600 )
{
SetName( GetNameStatic() );
// [TODO] : Discover and use a good multitap port icon! Possibility might be a
// simple 3x memorycards icon, in cascading form.
// (for now everything defaults to the redundant memorycard icon)
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
if( false ) //g_Conf->McdAdvancedMode )
{
m_panel_mcdlist = new MemoryCardListPanel_Advanced( this );
AddPage<McdConfigPanel_Toggles> ( wxLt("Settings"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Standard> ( wxLt("Slots 1/2"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Multitap> ( wxLt("Multitap 1"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Multitap2> ( wxLt("Multitap 2"), cfgid.MemoryCard );
CreateListbook( wxGetApp().GetImgList_Config() );
MSW_ListView_SetIconSpacing( m_listbook, m_idealWidth );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
AddPage<McdConfigPanel_Toggles> ( wxLt("Settings"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Standard> ( wxLt("Slots 1/2"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Multitap> ( wxLt("Multitap 1"), cfgid.MemoryCard );
AddPage<McdConfigPanel_Multitap2> ( wxLt("Multitap 2"), cfgid.MemoryCard );
m_panel_mcdlist = new MemoryCardListPanel( this );
MSW_ListView_SetIconSpacing( m_listbook, m_idealWidth );
*this += StdPadding;
*this += new wxStaticLine( this ) | StdExpand();
*this += StdPadding;
*this += m_panel_mcdlist | StdExpand();
AddListbook();
*this += StdPadding;
*this += new wxStaticLine( this ) | StdExpand();
*this += StdPadding;
*this += m_panel_mcdlist | StdExpand();
}
else
{
m_panel_mcdlist = new MemoryCardListPanel_Simple( this );
*this += m_panel_mcdlist | StdExpand();
//*this += StdPadding;
*this += new wxStaticLine( this ) | StdExpand();
*this += StdPadding;
*this += new McdConfigPanel_Toggles( this ) | StdExpand();
}
AddOkCancel();
}

View File

@ -87,7 +87,8 @@ namespace Dialogs
AboutBoxDialog( wxWindow* parent=NULL );
virtual ~AboutBoxDialog() throw() {}
static const wxChar* GetNameStatic() { return L"Dialog:AboutBox"; }
static wxString GetNameStatic() { return L"AboutBox"; }
wxString GetDialogName() const { return GetNameStatic(); }
};

View File

@ -28,10 +28,9 @@
using namespace Panels;
Dialogs::SysConfigDialog::SysConfigDialog(wxWindow* parent)
: BaseConfigurationDialog( parent, _("PS2 Settings - PCSX2"), wxGetApp().GetImgList_Config(), 600 )
: BaseConfigurationDialog( parent, _("PS2 Settings - PCSX2"), 600 )
{
SetName( GetNameStatic() );
CreateListbook( wxGetApp().GetImgList_Config() );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
AddPage<CpuPanelEE> ( wxLt("EE/IOP"), cfgid.Cpu );
@ -43,14 +42,14 @@ Dialogs::SysConfigDialog::SysConfigDialog(wxWindow* parent)
MSW_ListView_SetIconSpacing( m_listbook, m_idealWidth );
AddListbook();
AddOkCancel();
}
Dialogs::AppConfigDialog::AppConfigDialog(wxWindow* parent)
: BaseConfigurationDialog( parent, _("Application Settings - PCSX2"), wxGetApp().GetImgList_Config(), 600 )
: BaseConfigurationDialog( parent, _("Application Settings - PCSX2"), 600 )
{
SetName( GetNameStatic() );
CreateListbook( wxGetApp().GetImgList_Config() );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
AddPage<GSWindowSettingsPanel> ( wxLt("GS Window"), cfgid.Paths );
@ -58,5 +57,6 @@ Dialogs::AppConfigDialog::AppConfigDialog(wxWindow* parent)
MSW_ListView_SetIconSpacing( m_listbook, GetClientSize().GetWidth() );
AddListbook();
AddOkCancel();
}

View File

@ -60,6 +60,13 @@ void MSW_ListView_SetIconSpacing( wxListbook& listbook, int width )
#endif
}
void MSW_ListView_SetIconSpacing( wxListbook* listbook, int width )
{
if( listbook == NULL ) return;
MSW_ListView_SetIconSpacing( *listbook, width );
}
#ifdef __WXMSW__
WXLRESULT GSPanel::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{

View File

@ -20,6 +20,7 @@ class wxListbook;
extern void MSW_SetWindowAfter( WXWidget hwnd, WXWidget hwndAfter );
extern void MSW_OutputDebugString( const wxString& text );
extern void MSW_ListView_SetIconSpacing( wxListbook& listbook, int width );
extern void MSW_ListView_SetIconSpacing( wxListbook* listbook, int width );
extern void pxDwm_Load();
extern void pxDwm_Unload();

View File

@ -167,12 +167,6 @@ void BaseApplicableConfigPanel::SetFocusToMe()
m_OwnerBook->SetSelection( m_OwnerPage );
}
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE( pxEvt_ApplySettings, -1 )
END_DECLARE_EVENT_TYPES()
DEFINE_EVENT_TYPE( pxEvt_ApplySettings )
void BaseApplicableConfigPanel::Init()
{
// We need to bind to an event that occurs *after* all window and child
@ -196,7 +190,6 @@ void BaseApplicableConfigPanel::Init()
AddPendingEvent( applyEvent );
}
//void BaseApplicableConfigPanel::OnCreateWindow( wxWindowCreateEvent& evt )
void BaseApplicableConfigPanel::OnSettingsApplied( wxCommandEvent& evt )
{
evt.Skip();

View File

@ -411,7 +411,7 @@ namespace Panels
virtual bool ValidateEnumerationStatus();
};
class MemoryCardListPanel;
class MemoryCardListPanel_Advanced;
class MemoryCardInfoPanel;
// --------------------------------------------------------------------------------------
@ -420,7 +420,7 @@ namespace Panels
class MemoryCardsPanel : public BaseApplicableConfigPanel
{
protected:
MemoryCardListPanel* m_panel_AllKnownCards;
MemoryCardListPanel_Advanced* m_panel_AllKnownCards;
MemoryCardInfoPanel* m_panel_cardinfo[2][4];
pxCheckBox* m_check_Ejection;
pxCheckBox* m_check_Multitap[2];

View File

@ -36,10 +36,17 @@ static bool IsMcdFormatted( wxFFile& fhand )
return memcmp( formatted_string, dest, fmtstrlen ) == 0;
}
static bool EnumerateMemoryCard( McdListItem& dest, const wxString& filename )
bool EnumerateMemoryCard( McdListItem& dest, const wxFileName& filename )
{
Console.WriteLn( filename.c_str() );
wxFFile mcdFile( filename );
dest.IsFormatted = false;
dest.IsEnabled = false;
dest.IsPresent = false;
const wxString fullpath( filename.GetFullPath() );
if( !filename.FileExists() ) return false;
Console.WriteLn( fullpath );
wxFFile mcdFile( fullpath );
if( !mcdFile.IsOpened() ) return false; // wx should log the error for us.
if( mcdFile.Length() < (1024*528) )
{
@ -47,10 +54,12 @@ static bool EnumerateMemoryCard( McdListItem& dest, const wxString& filename )
return false;
}
dest.IsPresent = true;
dest.IsEnabled = true;
dest.Filename = filename;
dest.SizeInMB = (uint)(mcdFile.Length() / (1024 * 528 * 2));
dest.IsFormatted = IsMcdFormatted( mcdFile );
wxFileName(filename).GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
filename.GetTimes( NULL, &dest.DateModified, &dest.DateCreated );
return true;
}
@ -77,19 +86,55 @@ static int EnumerateMemoryCards( McdList& dest, const wxArrayString& files )
return pushed;
}
// =====================================================================================================
// MemoryCardListPanel
// BaseMcdListPanel (implementations)
// =====================================================================================================
Panels::MemoryCardListPanel::MemoryCardListPanel( wxWindow* parent )
: BaseSelectorPanel( parent )
Panels::BaseMcdListPanel::BaseMcdListPanel( wxWindow* parent )
: _parent( parent )
{
m_FolderPicker = new DirPickerPanel( this, FolderId_MemoryCards,
//_("MemoryCard Search Path:"), // static box label
_("Select folder with PS2 MemoryCards") // dir picker popup label
);
m_listview = new MemoryCardListView(this);
m_listview = NULL;
m_btn_Refresh = new wxButton( this, wxID_ANY, _("Refresh list") );
Connect( m_btn_Refresh->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseMcdListPanel::OnRefresh) );
}
void Panels::BaseMcdListPanel::CreateLayout()
{
if( m_listview ) m_listview->SetMinSize( wxSize( m_idealWidth, 140 ) );
wxBoxSizer& s_buttons(*new wxBoxSizer( wxHORIZONTAL ));
s_leftside_buttons = new wxBoxSizer( wxHORIZONTAL );
s_rightside_buttons = new wxBoxSizer( wxHORIZONTAL );
s_buttons += s_leftside_buttons | pxAlignLeft;
s_buttons += pxStretchSpacer();
s_buttons += s_rightside_buttons | pxAlignRight;
if( m_FolderPicker ) *this += m_FolderPicker | pxExpand;
if( m_listview ) *this += m_listview | pxExpand;
*this += s_buttons | pxExpand;
*s_leftside_buttons += m_btn_Refresh;
}
// =====================================================================================================
// MemoryCardListPanel_Advanced (implementations)
// =====================================================================================================
Panels::MemoryCardListPanel_Advanced::MemoryCardListPanel_Advanced( wxWindow* parent )
: _parent( parent )
{
m_FolderPicker = new DirPickerPanel( this, FolderId_MemoryCards,
//_("MemoryCard Search Path:"), // static box label
_("Select folder with PS2 MemoryCards") // dir picker popup label
);
m_listview = new MemoryCardListView_Advanced(this);
wxButton* button_Create = new wxButton(this, wxID_ANY, _("Create new card..."));
@ -97,35 +142,22 @@ Panels::MemoryCardListPanel::MemoryCardListPanel( wxWindow* parent )
// Sizer / Layout Section
// ------------------------------------
wxBoxSizer& s_buttons (*new wxBoxSizer( wxHORIZONTAL ));
wxBoxSizer& s_leftside (*new wxBoxSizer( wxHORIZONTAL ));
wxBoxSizer& s_rightside (*new wxBoxSizer( wxHORIZONTAL ));
CreateLayout();
*s_leftside_buttons += button_Create | StdSpace();
s_leftside += button_Create | StdSpace();
s_buttons += s_leftside | pxAlignLeft;
s_buttons += pxStretchSpacer();
s_buttons += s_rightside | pxAlignRight;
*this += m_FolderPicker | pxExpand;
*this += m_listview | pxExpand;
*this += s_buttons | pxExpand;
m_listview->SetMinSize( wxSize( m_idealWidth, 120 ) );
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel::OnListDrag));
Connect( button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel::OnCreateNewCard));
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel_Advanced::OnListDrag));
Connect( button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Advanced::OnCreateNewCard));
}
void Panels::MemoryCardListPanel::Apply()
void Panels::MemoryCardListPanel_Advanced::Apply()
{
}
void Panels::MemoryCardListPanel::AppStatusEvent_OnSettingsApplied()
void Panels::MemoryCardListPanel_Advanced::AppStatusEvent_OnSettingsApplied()
{
}
bool Panels::MemoryCardListPanel::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
bool Panels::MemoryCardListPanel_Advanced::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
{
if( filenames.GetCount() == 1 && wxFileName(filenames[0]).IsDir() )
{
@ -135,7 +167,7 @@ bool Panels::MemoryCardListPanel::OnDropFiles(wxCoord x, wxCoord y, const wxArra
return false;
}
bool Panels::MemoryCardListPanel::ValidateEnumerationStatus()
bool Panels::MemoryCardListPanel_Advanced::ValidateEnumerationStatus()
{
bool validated = true;
@ -159,7 +191,7 @@ bool Panels::MemoryCardListPanel::ValidateEnumerationStatus()
return validated;
}
void Panels::MemoryCardListPanel::DoRefresh()
void Panels::MemoryCardListPanel_Advanced::DoRefresh()
{
if( !m_KnownCards ) return;
@ -188,12 +220,12 @@ void Panels::MemoryCardListPanel::DoRefresh()
//m_listview->SetCardCount( m_KnownCards->size() );
}
void Panels::MemoryCardListPanel::OnCreateNewCard(wxCommandEvent& evt)
void Panels::MemoryCardListPanel_Advanced::OnCreateNewCard(wxCommandEvent& evt)
{
}
void Panels::MemoryCardListPanel::OnListDrag(wxListEvent& evt)
void Panels::MemoryCardListPanel_Advanced::OnListDrag(wxListEvent& evt)
{
wxFileDataObject my_data;
my_data.AddFile( (*m_KnownCards)[m_listview->GetItemData(m_listview->GetFirstSelected())].Filename.GetFullPath() );
@ -203,19 +235,218 @@ void Panels::MemoryCardListPanel::OnListDrag(wxListEvent& evt)
wxDragResult result = dragSource.DoDragDrop();
}
int Panels::MemoryCardListPanel::GetLength() const
int Panels::MemoryCardListPanel_Advanced::GetLength() const
{
return m_KnownCards ? m_KnownCards->size() : 0;
}
const McdListItem& Panels::MemoryCardListPanel::Get( int idx ) const
const McdListItem& Panels::MemoryCardListPanel_Advanced::GetCard( int idx ) const
{
pxAssume(!!m_KnownCards);
return (*m_KnownCards)[idx];
}
McdListItem& Panels::MemoryCardListPanel::Get( int idx )
McdListItem& Panels::MemoryCardListPanel_Advanced::GetCard( int idx )
{
pxAssume(!!m_KnownCards);
return (*m_KnownCards)[idx];
}
uint Panels::MemoryCardListPanel_Advanced::GetPort( int idx ) const
{
pxAssume(!!m_KnownCards);
return (*m_KnownCards)[idx].Port;
}
uint Panels::MemoryCardListPanel_Advanced::GetSlot( int idx ) const
{
pxAssume(!!m_KnownCards);
return (*m_KnownCards)[idx].Slot;
}
// =====================================================================================================
// MemoryCardListPanel_Simple (implementations)
// =====================================================================================================
Panels::MemoryCardListPanel_Simple::MemoryCardListPanel_Simple( wxWindow* parent )
: _parent( parent )
{
m_MultitapEnabled[0] = false;
m_MultitapEnabled[1] = false;
m_listview = new MemoryCardListView_Simple(this);
m_button_Create = new wxButton(this, wxID_ANY, _("Create"));
m_button_Mount = new wxButton(this, wxID_ANY, _("Mount"));
// ------------------------------------
// Sizer / Layout Section
// ------------------------------------
CreateLayout();
*s_leftside_buttons += m_button_Create;
*s_leftside_buttons += 2;
*s_leftside_buttons += m_button_Mount;
//*s_leftside_buttons += 2;
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListPanel_Simple::OnListDrag));
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged));
Connect( m_listview->GetId(), wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(MemoryCardListPanel_Simple::OnListSelectionChanged));
Connect( m_button_Mount->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnMountCard));
Connect( m_button_Create->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MemoryCardListPanel_Simple::OnCreateCard));
}
void Panels::MemoryCardListPanel_Simple::UpdateUI()
{
if( !m_listview ) return;
int sel = m_listview->GetFirstSelected();
/*if( !pxAssertDev( m_listview->GetItemData(sel), "Selected memorycard item data is NULL!" ) )
{
m_button_Create->Disable();
m_button_Mount->Disable();
return;
}*/
//const McdListItem& item( *(McdListItem*)m_listview->GetItemData(sel) );
const McdListItem& item( m_Cards[GetPort(sel)][GetSlot(sel)] );
m_button_Create->SetLabel( item.IsPresent ? _("Delete") : _("Create") );
pxSetToolTip( m_button_Create,
item.IsPresent
? _("Deletes the existing MemoryCard from disk (all contents are lost)." )
: _("Creates a new MemoryCard in the empty slot." )
);
m_button_Mount->Enable( item.IsPresent );
m_button_Mount->SetLabel( item.IsEnabled ? _("Disable") : _("Enable") );
pxSetToolTip( m_button_Mount,
item.IsEnabled
? _("Disables the selected MemoryCard, so that it will not be seen by games or BIOS.")
: _("Mounts the selected MemoryCard, so that games can see it again.")
);
}
void Panels::MemoryCardListPanel_Simple::Apply()
{
}
void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied()
{
}
bool Panels::MemoryCardListPanel_Simple::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
{
if( filenames.GetCount() == 1 && wxFileName(filenames[0]).IsDir() )
{
m_FolderPicker->SetPath( filenames[0] );
return true;
}
return false;
}
static wxString GetAutoMcdName(uint port, uint slot)
{
if( slot > 0 )
return wxsFormat( L"mcd-port%u-slot%02u.ps2", port+1, slot+1 );
else
return wxsFormat( L"Mcd%03u.ps2", port+1 );
}
bool Panels::MemoryCardListPanel_Simple::ValidateEnumerationStatus()
{
if( m_listview ) m_listview->SetInterface( NULL );
return false;
}
void Panels::MemoryCardListPanel_Simple::DoRefresh()
{
for( uint port=0; port<2; ++port )
{
for( uint slot=0; slot<4; ++slot )
{
wxFileName fullpath( m_FolderPicker->GetPath() + GetAutoMcdName(port,slot) );
EnumerateMemoryCard( m_Cards[port][slot], fullpath );
if( (slot > 0) && !m_MultitapEnabled[port] )
m_Cards[port][slot].IsEnabled = false;
}
}
if( m_listview ) m_listview->SetInterface( this );
}
void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
{
}
void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt)
{
}
void Panels::MemoryCardListPanel_Simple::OnListDrag(wxListEvent& evt)
{
wxFileDataObject my_data;
/*my_data.AddFile( (*m_KnownCards)[m_listview->GetItemData(m_listview->GetFirstSelected())].Filename.GetFullPath() );
wxDropSource dragSource( m_listview );
dragSource.SetData( my_data );
wxDragResult result = dragSource.DoDragDrop();*/
}
void Panels::MemoryCardListPanel_Simple::OnListSelectionChanged(wxListEvent& evt)
{
UpdateUI();
}
// Interface Implementation for IMcdList
int Panels::MemoryCardListPanel_Simple::GetLength() const
{
uint baselen = 2;
if( m_MultitapEnabled[0] ) baselen += 3;
if( m_MultitapEnabled[1] ) baselen += 3;
return baselen;
}
const McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx ) const
{
return m_Cards[GetPort(idx)][GetSlot(idx)];
}
McdListItem& Panels::MemoryCardListPanel_Simple::GetCard( int idx )
{
return m_Cards[GetPort(idx)][GetSlot(idx)];
}
uint Panels::MemoryCardListPanel_Simple::GetPort( int idx ) const
{
if( !m_MultitapEnabled[0] && !m_MultitapEnabled[1] )
{
pxAssume( idx < 2 );
return idx;
}
if( !m_MultitapEnabled[0] )
return (idx==0) ? 0 : 1;
else
return idx / 4;
}
uint Panels::MemoryCardListPanel_Simple::GetSlot( int idx ) const
{
if( !m_MultitapEnabled[0] && !m_MultitapEnabled[1] )
{
pxAssume( idx < 2 );
return 0;
}
if( !m_MultitapEnabled[0] )
return (idx==0) ? 0 : (idx-1);
else
return idx & 3;
}

View File

@ -0,0 +1,119 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 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 "ConfigurationPanels.h"
#include "MemoryCardPanels.h"
#include "Dialogs/ConfigurationDialog.h"
using namespace pxSizerFlags;
using namespace Panels;
enum McdColumnType_Simple
{
McdColS_PortSlot, // port and slot of the card
McdColS_Status, // either Enabled/Disabled, or Missing (no card).
McdColS_Size,
McdColS_Formatted,
McdColS_DateModified,
McdColS_DateCreated,
McdColS_Count
};
void MemoryCardListView_Simple::CreateColumns()
{
struct ColumnInfo
{
wxString name;
wxListColumnFormat align;
};
const ColumnInfo columns[] =
{
{ _("Slot"), wxLIST_FORMAT_LEFT },
{ _("Status"), wxLIST_FORMAT_CENTER },
{ _("Size"), wxLIST_FORMAT_LEFT },
{ _("Formatted"), wxLIST_FORMAT_CENTER },
{ _("Modified"), wxLIST_FORMAT_LEFT },
{ _("Created On"), wxLIST_FORMAT_LEFT },
};
for( int i=0; i<McdColS_Count; ++i )
InsertColumn( i, columns[i].name, columns[i].align, -1 );
}
MemoryCardListView_Simple::MemoryCardListView_Simple( wxWindow* parent )
: _parent( parent )
{
CreateColumns();
Connect( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListView_Advanced::OnListDrag));
}
void MemoryCardListView_Simple::SetCardCount( int length )
{
if( !m_CardProvider ) length = 0;
SetItemCount( length );
Refresh();
}
void MemoryCardListView_Simple::OnListDrag(wxListEvent& evt)
{
evt.Skip();
}
// return the text for the given column of the given item
wxString MemoryCardListView_Simple::OnGetItemText(long item, long column) const
{
if( !m_CardProvider ) return _parent::OnGetItemText(item, column);
const McdListItem& it( m_CardProvider->GetCard(item) );
switch( column )
{
case McdColS_PortSlot: return wxsFormat( L"%u/%u", m_CardProvider->GetPort(item)+1, m_CardProvider->GetSlot(item)+1);
case McdColS_Status: return it.IsPresent ? ( it.IsEnabled ? _("Enabled") : _("Disabled")) : _("Missing");
case McdColS_Size: return it.IsPresent ? wxsFormat( L"%u MB", it.SizeInMB ) : _("N/A");
case McdColS_Formatted: return it.IsFormatted ? _("Yes") : _("No");
case McdColS_DateModified: return it.DateModified.FormatDate();
case McdColS_DateCreated: return it.DateCreated.FormatDate();
//case McdCol_Path: return it.Filename.GetPath();
}
pxFail( "Unknown column index in MemoryCardListView_Advanced -- returning an empty string." );
return wxEmptyString;
}
// return the icon for the given item. In report view, OnGetItemImage will
// only be called for the first column. See OnGetItemColumnImage for
// details.
int MemoryCardListView_Simple::OnGetItemImage(long item) const
{
return _parent::OnGetItemImage( item );
}
// return the icon for the given item and column.
int MemoryCardListView_Simple::OnGetItemColumnImage(long item, long column) const
{
return _parent::OnGetItemColumnImage( item, column );
}
// return the attribute for the item (may return NULL if none)
wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const
{
wxListItemAttr* retval = _parent::OnGetItemAttr(item);
//const McdListItem& it( (*m_KnownCards)[item] );
return retval;
}

View File

@ -25,27 +25,43 @@
// --------------------------------------------------------------------------------------
struct McdListItem
{
uint SizeInMB; // size, in megabytes!
bool IsPresent;
bool IsEnabled;
bool IsFormatted;
uint SizeInMB; // size, in megabytes!
wxDateTime DateCreated;
wxDateTime DateModified;
wxFileName Filename; // full pathname
int Port;
int Slot;
wxFileName Filename; // full pathname (optional)
McdListItem()
{
Port = -1;
Slot = -1;
IsPresent = false;
IsEnabled = false;
}
// Compares two cards -- If this equality comparison is used on items where
// no filename is specified, then the check will include port and slot.
bool operator==( const McdListItem& right ) const
{
return
bool fileEqu;
if( Filename.GetFullName().IsEmpty() )
fileEqu = OpEqu(Port) && OpEqu(Slot);
else
fileEqu = OpEqu(Filename);
return fileEqu &&
OpEqu(IsPresent) && OpEqu(IsEnabled) &&
OpEqu(SizeInMB) && OpEqu(IsFormatted) &&
OpEqu(DateCreated) && OpEqu(DateModified) &&
OpEqu(Filename);
OpEqu(DateCreated) && OpEqu(DateModified);
}
bool operator!=( const McdListItem& right ) const
@ -56,36 +72,79 @@ struct McdListItem
typedef std::vector<McdListItem> McdList;
class IMemoryCardList
class IMcdList
{
public:
virtual int GetLength() const=0;
virtual const McdListItem& Get( int idx ) const=0;
virtual McdListItem& Get( int idx )=0;
virtual const McdListItem& GetCard( int idx ) const=0;
virtual McdListItem& GetCard( int idx )=0;
virtual uint GetPort( int idx ) const=0;
virtual uint GetSlot( int idx ) const=0;
};
// --------------------------------------------------------------------------------------
// MemoryCardListView
// --------------------------------------------------------------------------------------
class MemoryCardListView : public wxListView
class BaseMcdListView : public wxListView
{
typedef wxListView _parent;
protected:
IMemoryCardList* m_CardsList;
const IMcdList* m_CardProvider;
public:
virtual ~MemoryCardListView() throw() { }
MemoryCardListView( wxWindow* parent );
virtual ~BaseMcdListView() throw() { }
BaseMcdListView( wxWindow* parent )
: _parent( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_VIRTUAL )
{
m_CardProvider = NULL;
}
virtual void SetCardCount( int length )=0;
virtual void SetInterface( IMcdList* face )
{
m_CardProvider = face;
SetCardCount( m_CardProvider ? m_CardProvider->GetLength() : 0 );
}
};
// --------------------------------------------------------------------------------------
// MemoryCardListView_Simple
// --------------------------------------------------------------------------------------
class MemoryCardListView_Simple : public BaseMcdListView
{
typedef BaseMcdListView _parent;
public:
virtual ~MemoryCardListView_Simple() throw() { }
MemoryCardListView_Simple( wxWindow* parent );
virtual void OnListDrag(wxListEvent& evt);
virtual void CreateColumns();
void CreateColumns();
virtual void SetCardCount( int length );
protected:
// Overrides for wxLC_VIRTUAL
virtual wxString OnGetItemText(long item, long column) const;
virtual int OnGetItemImage(long item) const;
virtual int OnGetItemColumnImage(long item, long column) const;
virtual wxListItemAttr *OnGetItemAttr(long item) const;
};
// --------------------------------------------------------------------------------------
// MemoryCardListView_Advanced
// --------------------------------------------------------------------------------------
class MemoryCardListView_Advanced : public BaseMcdListView
{
typedef BaseMcdListView _parent;
public:
virtual ~MemoryCardListView_Advanced() throw() { }
MemoryCardListView_Advanced( wxWindow* parent );
virtual void OnListDrag(wxListEvent& evt);
void CreateColumns();
virtual void SetCardCount( int length );
virtual void SetInterface( IMemoryCardList* face )
{
m_CardsList = face;
SetCardCount( m_CardsList ? m_CardsList->GetLength() : 0 );
}
protected:
// Overrides for wxLC_VIRTUAL
@ -98,29 +157,102 @@ protected:
namespace Panels
{
// --------------------------------------------------------------------------------------
// MemoryCardListPanel
// BaseMcdListPanel
// --------------------------------------------------------------------------------------
class MemoryCardListPanel
class BaseMcdListPanel
: public BaseSelectorPanel
, public wxFileDropTarget
, public IMemoryCardList
{
typedef BaseSelectorPanel _parent;
protected:
DirPickerPanel* m_FolderPicker;
MemoryCardListView* m_listview;
BaseMcdListView* m_listview;
wxButton* m_btn_Refresh;
wxBoxSizer* s_leftside_buttons;
wxBoxSizer* s_rightside_buttons;
public:
virtual ~BaseMcdListPanel() throw() {}
BaseMcdListPanel( wxWindow* parent );
void CreateLayout();
};
// --------------------------------------------------------------------------------------
// MemoryCardListPanel_Simple
// --------------------------------------------------------------------------------------
class MemoryCardListPanel_Simple
: public BaseMcdListPanel
, public IMcdList
{
typedef BaseMcdListPanel _parent;
protected:
McdListItem m_Cards[2][4];
// Doubles as Create and Delete buttons
wxButton* m_button_Create;
// Doubles as Mount and Unmount buttons
wxButton* m_button_Mount;
bool m_MultitapEnabled[2];
public:
virtual ~MemoryCardListPanel_Simple() throw() {}
MemoryCardListPanel_Simple( wxWindow* parent );
void UpdateUI();
// Interface Implementation for IMcdList
virtual int GetLength() const;
virtual const McdListItem& GetCard( int idx ) const;
virtual McdListItem& GetCard( int idx );
virtual uint GetPort( int idx ) const;
virtual uint GetSlot( int idx ) const;
protected:
void OnCreateCard(wxCommandEvent& evt);
void OnMountCard(wxCommandEvent& evt);
virtual void OnListDrag(wxListEvent& evt);
virtual void OnListSelectionChanged(wxListEvent& evt);
virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames);
virtual void Apply();
virtual void AppStatusEvent_OnSettingsApplied();
virtual void DoRefresh();
virtual bool ValidateEnumerationStatus();
};
// --------------------------------------------------------------------------------------
// MemoryCardListPanel_Advanced
// --------------------------------------------------------------------------------------
class MemoryCardListPanel_Advanced
: public BaseMcdListPanel
, public IMcdList
{
typedef BaseMcdListPanel _parent;
protected:
ScopedPtr<McdList> m_KnownCards;
public:
virtual ~MemoryCardListPanel() throw() {}
MemoryCardListPanel( wxWindow* parent );
virtual ~MemoryCardListPanel_Advanced() throw() {}
MemoryCardListPanel_Advanced( wxWindow* parent );
// Interface Implementation for IMemoryCardList
// Interface Implementation for IMcdList
virtual int GetLength() const;
virtual const McdListItem& Get( int idx ) const;
virtual McdListItem& Get( int idx );
virtual const McdListItem& GetCard( int idx ) const;
virtual McdListItem& GetCard( int idx );
virtual uint GetPort( int idx ) const;
virtual uint GetSlot( int idx ) const;
protected:
virtual void OnCreateNewCard(wxCommandEvent& evt);
void OnCreateNewCard(wxCommandEvent& evt);
virtual void OnListDrag(wxListEvent& evt);
virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames);
@ -139,12 +271,15 @@ namespace Panels
uint m_port;
uint m_slot;
wxFileName m_filename;
wxString m_DisplayName;
wxString m_ErrorMessage;
ScopedPtr<McdListItem> m_cardInfo;
public:
virtual ~MemoryCardInfoPanel() throw() {}
MemoryCardInfoPanel( wxWindow* parent, uint port, uint slot );
void Apply();
void Eject();
protected:
void AppStatusEvent_OnSettingsApplied();
@ -211,3 +346,6 @@ namespace Panels
};
};
extern bool EnumerateMemoryCard( McdListItem& dest, const wxFileName& filename );
//extern bool EnumerateMemoryCard( SimpleMcdItem& dest, const wxFileName& filename );

View File

@ -27,7 +27,7 @@ using namespace pxSizerFlags;
using namespace Panels;
enum McdColumnType
enum McdColumnType_Advanced
{
McdCol_Filename,
McdCol_Mounted,
@ -35,11 +35,10 @@ enum McdColumnType
McdCol_Formatted,
McdCol_DateModified,
McdCol_DateCreated,
//McdCol_Path,
McdCol_Count
};
void MemoryCardListView::CreateColumns()
void MemoryCardListView_Advanced::CreateColumns()
{
struct ColumnInfo
{
@ -62,33 +61,31 @@ void MemoryCardListView::CreateColumns()
InsertColumn( i, columns[i].name, columns[i].align, -1 );
}
void MemoryCardListView::SetCardCount( int length )
void MemoryCardListView_Advanced::SetCardCount( int length )
{
if( !m_CardsList ) length = 0;
if( !m_CardProvider ) length = 0;
SetItemCount( length );
Refresh();
}
MemoryCardListView::MemoryCardListView( wxWindow* parent )
: wxListView( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_VIRTUAL )
MemoryCardListView_Advanced::MemoryCardListView_Advanced( wxWindow* parent )
: _parent( parent )
{
m_CardsList = NULL;
CreateColumns();
Connect( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListView::OnListDrag));
Connect( wxEVT_COMMAND_LIST_BEGIN_DRAG, wxListEventHandler(MemoryCardListView_Advanced::OnListDrag));
}
void MemoryCardListView::OnListDrag(wxListEvent& evt)
void MemoryCardListView_Advanced::OnListDrag(wxListEvent& evt)
{
evt.Skip();
}
// return the text for the given column of the given item
wxString MemoryCardListView::OnGetItemText(long item, long column) const
wxString MemoryCardListView_Advanced::OnGetItemText(long item, long column) const
{
if( !m_CardsList ) return _parent::OnGetItemText(item, column);
if( !m_CardProvider ) return _parent::OnGetItemText(item, column);
const McdListItem& it( m_CardsList->Get(item) );
const McdListItem& it( m_CardProvider->GetCard(item) );
switch( column )
{
@ -106,26 +103,26 @@ wxString MemoryCardListView::OnGetItemText(long item, long column) const
//case McdCol_Path: return it.Filename.GetPath();
}
pxFail( "Unknown column index in MemoryCardListView -- returning an empty string." );
pxFail( "Unknown column index in MemoryCardListView_Advanced -- returning an empty string." );
return wxEmptyString;
}
// return the icon for the given item. In report view, OnGetItemImage will
// only be called for the first column. See OnGetItemColumnImage for
// details.
int MemoryCardListView::OnGetItemImage(long item) const
int MemoryCardListView_Advanced::OnGetItemImage(long item) const
{
return _parent::OnGetItemImage( item );
}
// return the icon for the given item and column.
int MemoryCardListView::OnGetItemColumnImage(long item, long column) const
int MemoryCardListView_Advanced::OnGetItemColumnImage(long item, long column) const
{
return _parent::OnGetItemColumnImage( item, column );
}
// return the attribute for the item (may return NULL if none)
wxListItemAttr* MemoryCardListView::OnGetItemAttr(long item) const
wxListItemAttr* MemoryCardListView_Advanced::OnGetItemAttr(long item) const
{
wxListItemAttr* retval = _parent::OnGetItemAttr(item);
//const McdListItem& it( (*m_KnownCards)[item] );
@ -145,57 +142,129 @@ MemoryCardInfoPanel::MemoryCardInfoPanel( wxWindow* parent, uint port, uint slot
SetMinSize( wxSize(128, 48) );
Connect( wxEVT_PAINT, wxPaintEventHandler(MemoryCardInfoPanel::paintEvent) );
// [TODO] Add Unmount button.
}
static void DrawTextCentered( wxDC& dc, const wxString msg )
{
int tWidth, tHeight;
dc.GetTextExtent( msg, &tWidth, &tHeight );
dc.DrawText( msg, (dc.GetSize().GetWidth() - tWidth) / 2, 0 );
}
void MemoryCardInfoPanel::paintEvent(wxPaintEvent & evt)
{
// Collect Info and Format Strings
wxPaintDC dc( this );
pxWindowTextWriter writer( dc );
wxString fname( m_filename.GetFullPath() );
if( fname.IsEmpty() ) fname = _("No Card (empty)");
writer.Bold();
// Create DC and plot some text (and images!)
wxPaintDC dc( this );
wxFont normal( dc.GetFont() );
wxFont bold( normal );
normal.SetWeight( wxNORMAL );
bold.SetWeight( wxBOLD );
dc.SetFont( bold );
DrawTextCentered( dc, fname );
writer.WriteLn( m_DisplayName );
//dc.DrawCircle( dc.GetSize().GetWidth()/2, 24, dc.GetSize().GetWidth()/4 );
if( !m_ErrorMessage.IsEmpty() )
{
writer.WriteLn();
writer.WriteLn( m_ErrorMessage );
}
else if( m_cardInfo )
{
writer.Normal();
writer.WriteLn( wxsFormat( L"%d MB (%s)",
m_cardInfo->SizeInMB,
m_cardInfo->IsFormatted ? _("Formatted") : _("Unformatted") )
);
}
}
void MemoryCardInfoPanel::Eject()
{
m_cardInfo = NULL;
Refresh();
}
void MemoryCardInfoPanel::Apply()
{
if( m_filename.IsDir() )
{
throw Exception::CannotApplySettings( this,
wxLt("Cannot use or create memorycard: the filename is an existing directory."),
true
);
}
if( m_cardInfo && m_cardInfo->Filename.GetFullName().IsEmpty() ) m_cardInfo = NULL;
if( m_filename.FileExists() )
if( m_cardInfo )
{
// TODO : Prompt user to create non-existing files. For now we just creat them implicitly.
}
wxFileName absfile( Path::Combine( g_Conf->Folders.MemoryCards, m_cardInfo->Filename ) );
g_Conf->Mcd[m_port][m_slot].Filename = m_filename;
// The following checks should be theoretically unreachable, unless the user's
// filesystem is changed form under our nose. A little validation goes a
// long way. :p
if( absfile.IsDir() )
{
Eject();
throw Exception::CannotApplySettings( this,
// Diagnostic
wxsFormat( L"Memorycard in Port %u, Slot %u conflicts with an existing directory.", m_port, m_slot ),
// Translated
wxsFormat(
_("Cannot use or create the memorycard in Port %u, Slot %u: the filename conflicts with an existing directory."),
m_port, m_slot
)
);
}
if( !absfile.FileExists() )
{
Eject();
throw Exception::CannotApplySettings( this,
// Diagnostic
wxsFormat( L"Memorycard in Port %u, Slot %u is no longer valid.", m_port, m_slot ),
// Translated
wxsFormat(
_("The configured memorycard in Port %u, Slot %u no longer exists. Please create a new memory card, or leave the slot unmounted."),
m_port, m_slot
)
);
}
g_Conf->Mcd[m_port][m_slot].Filename = m_cardInfo->Filename;
g_Conf->Mcd[m_port][m_slot].Enabled = true;
}
else
{
// Card is either disabled or in an error state.
g_Conf->Mcd[m_port][m_slot].Enabled = false;
g_Conf->Mcd[m_port][m_slot].Filename.Clear();
}
}
void MemoryCardInfoPanel::AppStatusEvent_OnSettingsApplied()
{
m_filename = g_Conf->Mcd[m_port][m_slot].Filename;
m_cardInfo = NULL;
// Collect Info and Format Strings
wxString fname( g_Conf->Mcd[m_port][m_slot].Filename.GetFullPath() );
if( fname.IsEmpty() )
{
m_DisplayName = _("No Card (empty)");
m_cardInfo = NULL;
}
else
{
wxFileName absfile( Path::Combine( g_Conf->Folders.MemoryCards, fname ) );
wxFileName relfile( fname );
if( !m_cardInfo )
{
m_cardInfo = new McdListItem();
if( !EnumerateMemoryCard( *m_cardInfo, absfile.GetFullPath() ) )
{
m_ErrorMessage = _("Read Error: Card is truncated or corrupted.");
}
}
absfile.Normalize();
relfile.Normalize();
m_DisplayName = ( absfile == relfile ) ? relfile.GetFullName() : relfile.GetFullPath();
}
Refresh();
}
@ -206,8 +275,7 @@ void MemoryCardInfoPanel::AppStatusEvent_OnSettingsApplied()
Panels::MemoryCardsPanel::MemoryCardsPanel( wxWindow* parent )
: BaseApplicableConfigPanel( parent )
{
m_panel_AllKnownCards = new MemoryCardListPanel( this );
m_panel_AllKnownCards = new MemoryCardListPanel_Advanced( this );
for( uint port=0; port<2; ++port )
{
@ -251,4 +319,3 @@ void Panels::MemoryCardsPanel::AppStatusEvent_OnSettingsApplied()
//m_panel_cardinfo[port][slot]->Enable( emuconf.MultitapEnabled(port) );
}
}

View File

@ -70,7 +70,7 @@ void pxLogTextCtrl::OnResize( wxSizeEvent& evt )
// Windows has retarded console window update patterns. This helps smarten them up.
int ctrly = GetSize().y;
int fonty;
GetTextExtent( L"blaH yeah", NULL, &fonty );
GetTextExtent( L"blH yh", NULL, &fonty );
m_win32_LinesPerPage = (ctrly / fonty) + 1;
m_win32_LinesPerScroll = m_win32_LinesPerPage * 0.40;
#endif

View File

@ -2665,6 +2665,10 @@
RelativePath="..\..\gui\Panels\MemoryCardListPanel.cpp"
>
</File>
<File
RelativePath="..\..\gui\Panels\MemoryCardListView.cpp"
>
</File>
<File
RelativePath="..\..\gui\Panels\MemoryCardPanels.h"
>