Files
archived-pcsx2/pcsx2/gui/Dialogs/BaseConfigurationDialog.cpp
Gregory Hainaut 2ff43f2ed8 core: remove throw specifier on destructor
It is the 'default' on C++11
2017-05-13 10:38:35 +02:00

305 lines
9.5 KiB
C++

/* 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 "System.h"
#include "App.h"
#include "MSWstuff.h"
#include "ConfigurationDialog.h"
#include "ModalPopups.h"
#include "Panels/ConfigurationPanels.h"
#include <wx/artprov.h>
#include <wx/filepicker.h>
#include <wx/listbook.h>
#include <wx/spinctrl.h>
wxDEFINE_EVENT(pxEvt_ApplySettings, wxCommandEvent);
wxDEFINE_EVENT(pxEvt_SetSettingsPage, wxCommandEvent);
wxDEFINE_EVENT(pxEvt_SomethingChanged, wxCommandEvent);
using namespace Panels;
// configure the orientation of the listbox based on the platform
// For now, they're all on the left.
static const int s_orient = wxLB_LEFT;
class ScopedOkButtonDisabler
{
protected:
Dialogs::BaseConfigurationDialog* m_parent;
wxWindow* m_apply;
wxWindow* m_ok;
wxWindow* m_cancel;
public:
ScopedOkButtonDisabler( Dialogs::BaseConfigurationDialog* parent )
{
m_parent = parent;
m_parent->AllowApplyActivation( false );
m_apply = m_parent->FindWindow( wxID_APPLY );
m_ok = m_parent->FindWindow( wxID_OK );
m_cancel = m_parent->FindWindow( wxID_CANCEL );
if (m_apply) m_apply ->Disable();
if (m_ok) m_ok ->Disable();
if (m_cancel) m_cancel->Disable();
}
// Use this to prevent the Apply button from being re-enabled.
void DetachApply()
{
m_apply = NULL;
}
void DetachAll()
{
m_apply = m_ok = m_cancel = NULL;
}
virtual ~ScopedOkButtonDisabler()
{
if (m_apply) m_apply ->Enable();
if (m_ok) m_ok ->Enable();
if (m_cancel) m_cancel->Enable();
m_parent->AllowApplyActivation( true );
}
};
// --------------------------------------------------------------------------------------
// BaseApplicableDialog (implementations)
// --------------------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(BaseApplicableDialog, wxDialogWithHelpers)
BaseApplicableDialog::BaseApplicableDialog( wxWindow* parent, const wxString& title, const pxDialogCreationFlags& cflags )
: wxDialogWithHelpers( parent, title, cflags.MinWidth(425).Minimize() )
{
Init();
}
BaseApplicableDialog::~BaseApplicableDialog()
{
m_ApplyState.DoCleanup();
}
wxString BaseApplicableDialog::GetDialogName() const
{
pxFailDev( "This class must implement GetDialogName!" );
return L"Unnamed";
}
void BaseApplicableDialog::Init()
{
Bind(pxEvt_ApplySettings, &BaseApplicableDialog::OnSettingsApplied, this);
wxCommandEvent applyEvent( pxEvt_ApplySettings );
applyEvent.SetId( GetId() );
AddPendingEvent( applyEvent );
}
void BaseApplicableDialog::OnSettingsApplied( wxCommandEvent& evt )
{
evt.Skip();
if( evt.GetId() == GetId() )
AppStatusEvent_OnSettingsApplied();
}
// --------------------------------------------------------------------------------------
// BaseConfigurationDialog Implementations
// --------------------------------------------------------------------------------------
Dialogs::BaseConfigurationDialog::BaseConfigurationDialog( wxWindow* parent, const wxString& title, int idealWidth )
: _parent( parent, title )
{
float scale = MSW_GetDPIScale();
SetMinWidth( scale * idealWidth );
m_listbook = NULL;
m_allowApplyActivation = true;
Bind(wxEVT_BUTTON, &BaseConfigurationDialog::OnOk_Click, this, wxID_OK);
Bind(wxEVT_BUTTON, &BaseConfigurationDialog::OnCancel_Click, this, wxID_CANCEL);
Bind(wxEVT_BUTTON, &BaseConfigurationDialog::OnApply_Click, this, wxID_APPLY);
Bind(wxEVT_BUTTON, &BaseConfigurationDialog::OnScreenshot_Click, this, wxID_SAVE);
Bind(pxEvt_SetSettingsPage, &BaseConfigurationDialog::OnSetSettingsPage, this);
// ----------------------------------------------------------------------------
// Bind a variety of standard "something probably changed" events. If the user invokes
// any of these, we'll automatically de-gray the Apply button for this dialog box. :)
Bind(wxEVT_TEXT, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_TEXT_ENTER, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_RADIOBUTTON, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_COMBOBOX, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_CHECKBOX, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_BUTTON, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_CHOICE, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_LISTBOX, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_SPINCTRL, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_SLIDER, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(wxEVT_DIRPICKER_CHANGED, &BaseConfigurationDialog::OnSomethingChanged, this);
Bind(pxEvt_SomethingChanged, &BaseConfigurationDialog::OnSomethingChanged, this);
}
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 );
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Disable();
SomethingChanged_StateModified_IsChanged();
wxBitmapButton& screenshotButton(*new wxBitmapButton(this, wxID_SAVE, wxGetApp().GetScreenshotBitmap()));
screenshotButton.SetToolTip( _("Saves a snapshot of this settings panel to a PNG file.") );
*m_extraButtonSizer += screenshotButton|pxMiddle;
}
void Dialogs::BaseConfigurationDialog::OnSetSettingsPage( wxCommandEvent& evt )
{
if( !m_listbook ) return;
size_t pages = m_labels.GetCount();
for( size_t i=0; i<pages; ++i )
{
if( evt.GetString() == m_labels[i] )
{
m_listbook->SetSelection( i );
break;
}
}
}
void Dialogs::BaseConfigurationDialog::SomethingChanged()
{
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Enable();
SomethingChanged_StateModified_IsChanged();
}
void Dialogs::BaseConfigurationDialog::OnSomethingChanged( wxCommandEvent& evt )
{
evt.Skip();
if (!m_allowApplyActivation) return;
if ((evt.GetId() != wxID_OK) && (evt.GetId() != wxID_CANCEL) && (evt.GetId() != wxID_APPLY))
SomethingChanged();
}
void Dialogs::BaseConfigurationDialog::AllowApplyActivation( bool allow )
{
m_allowApplyActivation = allow;
}
void Dialogs::BaseConfigurationDialog::OnOk_Click( wxCommandEvent& evt )
{
ScopedOkButtonDisabler disabler(this);
//same as for OnApply_Click
Apply();
if( m_ApplyState.ApplyAll() )
{
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Disable();
SomethingChanged_StateModified_IsChanged();
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
AppSaveSettings();
disabler.DetachAll();
evt.Skip();
}
}
void Dialogs::BaseConfigurationDialog::OnApply_Click( wxCommandEvent& evt )
{
ScopedOkButtonDisabler disabler(this);
//if current instance also holds settings that need to be applied, apply them.
//Currently only used by SysConfigDialog, which applies the preset and derivatives (menu system).
//Needs to come before actual panels Apply since they enable/disable themselves upon Preset state,
// so the preset needs to be applied first.
Apply();
if( m_ApplyState.ApplyAll() )
disabler.DetachApply();
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
AppSaveSettings();
SomethingChanged_StateModified_IsChanged();
}
void Dialogs::BaseConfigurationDialog::OnCancel_Click( wxCommandEvent& evt )
{
//same as for Ok/Apply: let SysConfigDialog clean-up the presets and derivatives (menu system) if needed.
Cancel();
evt.Skip();
if( m_listbook ) GetConfSettingsTabName() = m_labels[m_listbook->GetSelection()];
}
void Dialogs::BaseConfigurationDialog::OnScreenshot_Click( wxCommandEvent& evt )
{
wxBitmap memBmp;
{
wxWindowDC dc( this );
wxSize dcsize( dc.GetSize() );
wxMemoryDC memDC( memBmp = wxBitmap( dcsize.x, dcsize.y ) );
memDC.Blit( wxPoint(), dcsize, &dc, wxPoint() );
}
wxString pagename( m_listbook ? (L"_" + m_listbook->GetPageText( m_listbook->GetSelection() )) : wxString() );
wxString filenameDefault;
filenameDefault.Printf( L"%s_%s%s.png", pxGetAppName().Lower().c_str(), GetDialogName().c_str(), pagename.c_str() );
filenameDefault.Replace( L"/", L"-" );
wxString filename( wxFileSelector( _("Save dialog screenshots to..."), g_Conf->Folders.Snapshots.ToString(),
filenameDefault, L"png", wxEmptyString, wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this ) );
if( !filename.IsEmpty() )
{
ScopedBusyCursor busy( Cursor_ReallyBusy );
#ifdef __WXMSW__
// HACK: This works around an actual wx3.0 bug at the cost of icon
// quality. See http://trac.wxwidgets.org/ticket/14403 .
wxImage image = memBmp.ConvertToImage();
if (image.HasAlpha())
image.ClearAlpha();
image.SaveFile( filename, wxBITMAP_TYPE_PNG );
#else
memBmp.SaveFile( filename, wxBITMAP_TYPE_PNG );
#endif
}
}