From f7a30c32911536ec430cf9dc441482c8e2e18b73 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Thu, 20 May 2010 12:23:13 +0000 Subject: [PATCH] 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 --- common/build/Utilities/utilities.vcproj | 8 + common/include/Utilities/StringHelpers.h | 3 + common/include/Utilities/wxGuiTools.h | 75 +++++ common/src/Utilities/Console.cpp | 163 +--------- common/src/Utilities/FastFormatString.cpp | 163 ++++++++++ common/src/Utilities/pxWindowTextWriter.cpp | 136 ++++++++ pcsx2/gui/App.h | 2 +- pcsx2/gui/AppMain.cpp | 2 +- pcsx2/gui/ApplyState.h | 42 ++- pcsx2/gui/Dialogs/AboutBoxDialog.cpp | 2 - pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp | 77 ++++- pcsx2/gui/Dialogs/BaseConfigurationDialog.inl | 2 +- pcsx2/gui/Dialogs/BiosSelectorDialog.cpp | 2 - pcsx2/gui/Dialogs/ConfigurationDialog.h | 46 ++- pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp | 2 +- pcsx2/gui/Dialogs/LogOptionsDialog.cpp | 2 - pcsx2/gui/Dialogs/LogOptionsDialog.h | 3 +- pcsx2/gui/Dialogs/McdConfigDialog.cpp | 45 ++- pcsx2/gui/Dialogs/ModalPopups.h | 3 +- pcsx2/gui/Dialogs/SysConfigDialog.cpp | 12 +- pcsx2/gui/MSWstuff.cpp | 7 + pcsx2/gui/MSWstuff.h | 1 + .../gui/Panels/BaseApplicableConfigPanel.cpp | 7 - pcsx2/gui/Panels/ConfigurationPanels.h | 4 +- pcsx2/gui/Panels/MemoryCardListPanel.cpp | 301 ++++++++++++++++-- pcsx2/gui/Panels/MemoryCardListView.cpp | 119 +++++++ pcsx2/gui/Panels/MemoryCardPanels.h | 202 ++++++++++-- pcsx2/gui/Panels/MemoryCardsPanel.cpp | 169 +++++++--- pcsx2/gui/pxLogTextCtrl.cpp | 2 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 4 + 30 files changed, 1252 insertions(+), 354 deletions(-) create mode 100644 common/src/Utilities/FastFormatString.cpp create mode 100644 common/src/Utilities/pxWindowTextWriter.cpp create mode 100644 pcsx2/gui/Panels/MemoryCardListView.cpp diff --git a/common/build/Utilities/utilities.vcproj b/common/build/Utilities/utilities.vcproj index 0dc4a724d3..a6cfc2e79b 100644 --- a/common/build/Utilities/utilities.vcproj +++ b/common/build/Utilities/utilities.vcproj @@ -211,6 +211,10 @@ RelativePath="..\..\src\Utilities\Exceptions.cpp" > + + @@ -263,6 +267,10 @@ RelativePath="..\..\src\Utilities\pxStaticText.cpp" > + + diff --git a/common/include/Utilities/StringHelpers.h b/common/include/Utilities/StringHelpers.h index 18389111fa..7f259b1e18 100644 --- a/common/include/Utilities/StringHelpers.h +++ b/common/include/Utilities/StringHelpers.h @@ -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) diff --git a/common/include/Utilities/wxGuiTools.h b/common/include/Utilities/wxGuiTools.h index 63edc3de4e..fb37627eee 100644 --- a/common/include/Utilities/wxGuiTools.h +++ b/common/include/Utilities/wxGuiTools.h @@ -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 // -------------------------------------------------------------------------------------- diff --git a/common/src/Utilities/Console.cpp b/common/src/Utilities/Console.cpp index 368d2dfab8..0c520605b1 100644 --- a/common/src/Utilities/Console.cpp +++ b/common/src/Utilities/Console.cpp @@ -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 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 ascii_buffer( ascii_buffer_is_deleted ); -static FormatBuffer unicode_buffer( unicode_buffer_is_deleted ); - -static void format_that_ascii_mess( SafeArray& 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& 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 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 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; diff --git a/common/src/Utilities/FastFormatString.cpp b/common/src/Utilities/FastFormatString.cpp new file mode 100644 index 0000000000..d39229be11 --- /dev/null +++ b/common/src/Utilities/FastFormatString.cpp @@ -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 . + */ + +#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 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 ascii_buffer( ascii_buffer_is_deleted ); +static FormatBuffer unicode_buffer( unicode_buffer_is_deleted ); + +static void format_that_ascii_mess( SafeArray& 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& 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 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 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(); + } +} diff --git a/common/src/Utilities/pxWindowTextWriter.cpp b/common/src/Utilities/pxWindowTextWriter.cpp new file mode 100644 index 0000000000..d8cebfeede --- /dev/null +++ b/common/src/Utilities/pxWindowTextWriter.cpp @@ -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 . + */ + +#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 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(); diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 26845adcd2..33873bc51e 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -50,7 +50,7 @@ ConfigOverrides OverrideOptions; template 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 ) ) diff --git a/pcsx2/gui/ApplyState.h b/pcsx2/gui/ApplyState.h index c204042b95..457aa42d24 100644 --- a/pcsx2/gui/ApplyState.h +++ b/pcsx2/gui/ApplyState.h @@ -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; diff --git a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp index 91038df9a4..3209bf7ceb 100644 --- a/pcsx2/gui/Dialogs/AboutBoxDialog.cpp +++ b/pcsx2/gui/Dialogs/AboutBoxDialog.cpp @@ -53,8 +53,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent ) wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN ) { - SetName( GetNameStatic() ); - static const wxString LabelAuthors = fromUTF8( "Developers" "\n\n" diff --git a/pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp b/pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp index eafa3576de..fa4bac5f54 100644 --- a/pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp +++ b/pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp @@ -28,6 +28,9 @@ #include #include +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(), diff --git a/pcsx2/gui/Dialogs/BaseConfigurationDialog.inl b/pcsx2/gui/Dialogs/BaseConfigurationDialog.inl index 03a7bb0795..c17d06fb1e 100644 --- a/pcsx2/gui/Dialogs/BaseConfigurationDialog.inl +++ b/pcsx2/gui/Dialogs/BaseConfigurationDialog.inl @@ -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 ); } diff --git a/pcsx2/gui/Dialogs/BiosSelectorDialog.cpp b/pcsx2/gui/Dialogs/BiosSelectorDialog.cpp index 6ef113376c..9812404096 100644 --- a/pcsx2/gui/Dialogs/BiosSelectorDialog.cpp +++ b/pcsx2/gui/Dialogs/BiosSelectorDialog.cpp @@ -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 ); diff --git a/pcsx2/gui/Dialogs/ConfigurationDialog.h b/pcsx2/gui/Dialogs/ConfigurationDialog.h index 5485e7e5ab..cf4fb672f9 100644 --- a/pcsx2/gui/Dialogs/ConfigurationDialog.h +++ b/pcsx2/gui/Dialogs/ConfigurationDialog.h @@ -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 ); diff --git a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp index 9b9fa69110..b743a740ac 100644 --- a/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp +++ b/pcsx2/gui/Dialogs/CreateMemoryCardDialog.cpp @@ -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; diff --git a/pcsx2/gui/Dialogs/LogOptionsDialog.cpp b/pcsx2/gui/Dialogs/LogOptionsDialog.cpp index 10c05e2476..29c4693685 100644 --- a/pcsx2/gui/Dialogs/LogOptionsDialog.cpp +++ b/pcsx2/gui/Dialogs/LogOptionsDialog.cpp @@ -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 ); diff --git a/pcsx2/gui/Dialogs/LogOptionsDialog.h b/pcsx2/gui/Dialogs/LogOptionsDialog.h index 53cda64726..957c2c965a 100644 --- a/pcsx2/gui/Dialogs/LogOptionsDialog.h +++ b/pcsx2/gui/Dialogs/LogOptionsDialog.h @@ -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 ); diff --git a/pcsx2/gui/Dialogs/McdConfigDialog.cpp b/pcsx2/gui/Dialogs/McdConfigDialog.cpp index 1f0d02c051..5528e63b68 100644 --- a/pcsx2/gui/Dialogs/McdConfigDialog.cpp +++ b/pcsx2/gui/Dialogs/McdConfigDialog.cpp @@ -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 ( wxLt("Settings"), cfgid.MemoryCard ); - AddPage ( wxLt("Slots 1/2"), cfgid.MemoryCard ); - AddPage ( wxLt("Multitap 1"), cfgid.MemoryCard ); - AddPage ( wxLt("Multitap 2"), cfgid.MemoryCard ); + CreateListbook( wxGetApp().GetImgList_Config() ); + + const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config ); + AddPage ( wxLt("Settings"), cfgid.MemoryCard ); + AddPage ( wxLt("Slots 1/2"), cfgid.MemoryCard ); + AddPage ( wxLt("Multitap 1"), cfgid.MemoryCard ); + AddPage ( wxLt("Multitap 2"), cfgid.MemoryCard ); - MSW_ListView_SetIconSpacing( m_listbook, m_idealWidth ); + MSW_ListView_SetIconSpacing( m_listbook, m_idealWidth ); - m_panel_mcdlist = new MemoryCardListPanel( this ); + AddListbook(); - *this += StdPadding; - *this += new wxStaticLine( this ) | StdExpand(); - *this += StdPadding; - *this += m_panel_mcdlist | StdExpand(); + *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(); } diff --git a/pcsx2/gui/Dialogs/ModalPopups.h b/pcsx2/gui/Dialogs/ModalPopups.h index 02fadeeede..b5fca843d0 100644 --- a/pcsx2/gui/Dialogs/ModalPopups.h +++ b/pcsx2/gui/Dialogs/ModalPopups.h @@ -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(); } }; diff --git a/pcsx2/gui/Dialogs/SysConfigDialog.cpp b/pcsx2/gui/Dialogs/SysConfigDialog.cpp index a7837b750a..21235ff65b 100644 --- a/pcsx2/gui/Dialogs/SysConfigDialog.cpp +++ b/pcsx2/gui/Dialogs/SysConfigDialog.cpp @@ -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 ( 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 ( wxLt("GS Window"), cfgid.Paths ); @@ -58,5 +57,6 @@ Dialogs::AppConfigDialog::AppConfigDialog(wxWindow* parent) MSW_ListView_SetIconSpacing( m_listbook, GetClientSize().GetWidth() ); + AddListbook(); AddOkCancel(); } diff --git a/pcsx2/gui/MSWstuff.cpp b/pcsx2/gui/MSWstuff.cpp index ec1fe0c0c0..3f4437e1d0 100644 --- a/pcsx2/gui/MSWstuff.cpp +++ b/pcsx2/gui/MSWstuff.cpp @@ -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) { diff --git a/pcsx2/gui/MSWstuff.h b/pcsx2/gui/MSWstuff.h index b24035bb68..f28148b50b 100644 --- a/pcsx2/gui/MSWstuff.h +++ b/pcsx2/gui/MSWstuff.h @@ -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(); diff --git a/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp b/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp index 7cafa831bd..c8c1295991 100644 --- a/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp +++ b/pcsx2/gui/Panels/BaseApplicableConfigPanel.cpp @@ -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(); diff --git a/pcsx2/gui/Panels/ConfigurationPanels.h b/pcsx2/gui/Panels/ConfigurationPanels.h index a5406fa6f6..ab86ebfa54 100644 --- a/pcsx2/gui/Panels/ConfigurationPanels.h +++ b/pcsx2/gui/Panels/ConfigurationPanels.h @@ -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]; diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index 815fa5ff92..b35b1dc2ed 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -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; } +// ===================================================================================================== +// BaseMcdListPanel (implementations) +// ===================================================================================================== +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 = 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 +// MemoryCardListPanel_Advanced (implementations) // ===================================================================================================== -Panels::MemoryCardListPanel::MemoryCardListPanel( wxWindow* parent ) - : BaseSelectorPanel( parent ) +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(this); + 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 )); - - 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 ) ); + CreateLayout(); + *s_leftside_buttons += button_Create | StdSpace(); - 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; +} diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp new file mode 100644 index 0000000000..983f2e47a6 --- /dev/null +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -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 . + */ + +#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; iGetCard(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; +} diff --git a/pcsx2/gui/Panels/MemoryCardPanels.h b/pcsx2/gui/Panels/MemoryCardPanels.h index 40a5799028..c88f166689 100644 --- a/pcsx2/gui/Panels/MemoryCardPanels.h +++ b/pcsx2/gui/Panels/MemoryCardPanels.h @@ -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 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 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 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 ); diff --git a/pcsx2/gui/Panels/MemoryCardsPanel.cpp b/pcsx2/gui/Panels/MemoryCardsPanel.cpp index 7d090c78df..2d6943c95e 100644 --- a/pcsx2/gui/Panels/MemoryCardsPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardsPanel.cpp @@ -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 - - wxString fname( m_filename.GetFullPath() ); - if( fname.IsEmpty() ) fname = _("No Card (empty)"); + wxPaintDC dc( this ); + pxWindowTextWriter writer( dc ); + + 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() ) + if( m_cardInfo && m_cardInfo->Filename.GetFullName().IsEmpty() ) m_cardInfo = NULL; + + if( m_cardInfo ) { - throw Exception::CannotApplySettings( this, - wxLt("Cannot use or create memorycard: the filename is an existing directory."), - true - ); - } + wxFileName absfile( Path::Combine( g_Conf->Folders.MemoryCards, m_cardInfo->Filename ) ); - if( m_filename.FileExists() ) + // 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 { - // TODO : Prompt user to create non-existing files. For now we just creat them implicitly. - } + // Card is either disabled or in an error state. - g_Conf->Mcd[m_port][m_slot].Filename = m_filename; + 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) ); } } - diff --git a/pcsx2/gui/pxLogTextCtrl.cpp b/pcsx2/gui/pxLogTextCtrl.cpp index bfbdfe4ab6..9251c8baec 100644 --- a/pcsx2/gui/pxLogTextCtrl.cpp +++ b/pcsx2/gui/pxLogTextCtrl.cpp @@ -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 diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 01eda5e273..0c0a2eb70b 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2665,6 +2665,10 @@ RelativePath="..\..\gui\Panels\MemoryCardListPanel.cpp" > + +