From 32627f6b85e64fd9aeaecdc45a2584c1ca359cea Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Mon, 8 Apr 2024 16:58:04 -0700 Subject: [PATCH] [Dialogs] Save and restore dialog positions This changes most dialogs in the wx frontend to use a common base abstraction, `dialogs::BaseDialog`. This base class sets up common style options for every dialog and automatically saves and restores the dialog position. In addition, this moves the first time show position of the dialog to be slightly to the bottom and right of the main window, even if the main window is on a screen other than the main screen. --- src/wx/CMakeLists.txt | 5 +- src/wx/cmdevents.cpp | 2 +- src/wx/dialogs/accel-config.cpp | 23 +-- src/wx/dialogs/accel-config.h | 7 +- src/wx/dialogs/base-dialog.cpp | 137 ++++++++++++++++++ src/wx/dialogs/base-dialog.h | 42 ++++++ src/wx/dialogs/directories-config.cpp | 30 ++-- src/wx/dialogs/directories-config.h | 8 +- src/wx/dialogs/display-config.cpp | 48 +++--- src/wx/dialogs/display-config.h | 8 +- src/wx/dialogs/game-boy-config.cpp | 54 +++---- src/wx/dialogs/game-boy-config.h | 7 +- src/wx/dialogs/gb-rom-info.cpp | 37 ++--- src/wx/dialogs/gb-rom-info.h | 8 +- src/wx/dialogs/joypad-config.cpp | 32 ++-- src/wx/dialogs/joypad-config.h | 9 +- src/wx/dialogs/sound-config.cpp | 43 +++--- src/wx/dialogs/sound-config.h | 8 +- src/wx/guiinit.cpp | 70 +-------- src/wx/opts.cpp | 6 +- src/wx/sys.cpp | 2 +- src/wx/viewers.cpp | 6 +- src/wx/widgets/keep-on-top-styler.h | 6 +- src/wx/widgets/utils.cpp | 16 ++ .../validated-child.h => widgets/utils.h} | 19 ++- src/wx/wxvbam.cpp | 14 +- src/wx/wxvbam.h | 8 +- 27 files changed, 352 insertions(+), 303 deletions(-) create mode 100644 src/wx/dialogs/base-dialog.cpp create mode 100644 src/wx/dialogs/base-dialog.h create mode 100644 src/wx/widgets/utils.cpp rename src/wx/{dialogs/validated-child.h => widgets/utils.h} (56%) diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index 6cf1b787..765e7cbe 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -31,6 +31,8 @@ set(VBAM_WX_COMMON config/user-input.h dialogs/accel-config.cpp dialogs/accel-config.h + dialogs/base-dialog.cpp + dialogs/base-dialog.h dialogs/directories-config.cpp dialogs/directories-config.h dialogs/display-config.cpp @@ -45,7 +47,6 @@ set(VBAM_WX_COMMON dialogs/joypad-config.h dialogs/sound-config.cpp dialogs/sound-config.h - dialogs/validated-child.h drawing.h extra-translations.cpp gfxviewers.cpp @@ -79,6 +80,8 @@ set(VBAM_WX_COMMON widgets/user-input-ctrl.h widgets/sdljoy.cpp widgets/sdljoy.h + widgets/utils.cpp + widgets/utils.h widgets/webupdatedef.h widgets/wxmisc.h widgets/wxmisc.cpp diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 0fd99727..62471ca8 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -1714,7 +1714,7 @@ EVT_HANDLER_MASK(Disassemble, "Disassemble...", CMDEN_GB | CMDEN_GBA) EVT_HANDLER(Logging, "Logging...") { - wxDialog* dlg = wxGetApp().frame->logdlg; + wxDialog* dlg = wxGetApp().frame->logdlg.get(); dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER); dlg->Show(); dlg->Raise(); diff --git a/src/wx/dialogs/accel-config.cpp b/src/wx/dialogs/accel-config.cpp index 4ec92180..104501cf 100644 --- a/src/wx/dialogs/accel-config.cpp +++ b/src/wx/dialogs/accel-config.cpp @@ -5,12 +5,10 @@ #include #include #include -#include #include "wx/config/shortcuts.h" #include "wx/config/user-input.h" -#include "wx/dialogs/validated-child.h" -#include "wx/opts.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/user-input-ctrl.h" #include "wx/wxvbam.h" @@ -132,21 +130,16 @@ AccelConfig* AccelConfig::NewInstance(wxWindow* parent, wxMenuBar* menu, wxMenu* } AccelConfig::AccelConfig(wxWindow* parent, wxMenuBar* menu, wxMenu* recents) - : wxDialog(), keep_on_top_styler_(this) { - assert(parent); + : BaseDialog(parent, "AccelConfig") { assert(menu); - // Load the dialog XML. - const bool success = wxXmlResource::Get()->LoadDialog(this, parent, "AccelConfig"); - assert(success); - // Loads the various dialog elements. - tree_ = GetValidatedChild(this, "Commands"); - current_keys_ = GetValidatedChild(this, "Current"); - assign_button_ = GetValidatedChild(this, "Assign"); - remove_button_ = GetValidatedChild(this, "Remove"); - key_input_ = GetValidatedChild(this, "Shortcut"); - currently_assigned_label_ = GetValidatedChild(this, "AlreadyThere"); + tree_ = GetValidatedChild("Commands"); + current_keys_ = GetValidatedChild("Current"); + assign_button_ = GetValidatedChild("Assign"); + remove_button_ = GetValidatedChild("Remove"); + key_input_ = GetValidatedChild("Shortcut"); + currently_assigned_label_ = GetValidatedChild("AlreadyThere"); // Configure the key input. key_input_->MoveBeforeInTabOrder(assign_button_); diff --git a/src/wx/dialogs/accel-config.h b/src/wx/dialogs/accel-config.h index b999d34c..11c9ce42 100644 --- a/src/wx/dialogs/accel-config.h +++ b/src/wx/dialogs/accel-config.h @@ -3,11 +3,10 @@ #include -#include #include #include "wx/config/shortcuts.h" -#include "wx/widgets/keep-on-top-styler.h" +#include "wx/dialogs/base-dialog.h" // Forward declarations. class wxControl; @@ -23,7 +22,7 @@ class UserInputCtrl; namespace dialogs { // Manages the shortcuts editor dialog. -class AccelConfig : public wxDialog { +class AccelConfig : public BaseDialog { public: static AccelConfig* NewInstance(wxWindow* parent, wxMenuBar* menu_bar, wxMenu* recents); @@ -74,8 +73,6 @@ private: config::Shortcuts config_shortcuts_; int selected_command_ = 0; - - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/base-dialog.cpp b/src/wx/dialogs/base-dialog.cpp new file mode 100644 index 00000000..0817782b --- /dev/null +++ b/src/wx/dialogs/base-dialog.cpp @@ -0,0 +1,137 @@ +#include "wx/dialogs/base-dialog.h" + +#include + +#include +#include +#include + +#include "wx/config/option-proxy.h" +#include "wx/widgets/utils.h" + +namespace dialogs { + +namespace { + +// Due to the way wxWidgets handles initialization, we need to use a custom +// persistent object to save and restore the dialog's position. In particular, +// when the dialog is constructed, the the main window is not (yet) in its final +// position. This means we need to differentiate between 2 states here: +// 1. The dialog was registered for the first time and never shown. +// We don't want to save the position in this case. +// 2. The dialog was registered and shown at least once. +// We want to save the position in this case. However, on restore, we need +// to check we are not drawing out of bounds. +// +// We can't use the built-in wxPersistenceManager for this, as it doesn't allow +// us to differentiate between these 2 states. +class PersistentBaseDialog : public wxPersistentWindow { +public: + PersistentBaseDialog(BaseDialog* window) : wxPersistentWindow(window) {} + +private: + // wxPersistentObject implementation. + wxString GetKind() const override { return "Dialog"; } + + void Save() const override { + if (!dialog_shown_) { + // Do not update the position if the dialog was not shown. + return; + } + + const wxRect dialog_rect = this->Get()->GetRect(); + this->SaveValue("x", dialog_rect.x); + this->SaveValue("y", dialog_rect.y); + this->SaveValue("width", dialog_rect.width); + this->SaveValue("height", dialog_rect.height); + } + + bool Restore() override { + dialog_shown_ = true; + wxRect dialog_rect(0, 0, 0, 0); + if (!this->RestoreValue("x", &dialog_rect.x)) { + return false; + }; + if (!this->RestoreValue("y", &dialog_rect.y)) { + return false; + }; + if (!this->RestoreValue("width", &dialog_rect.width)) { + return false; + }; + if (!this->RestoreValue("height", &dialog_rect.height)) { + return false; + }; + + this->Get()->SetSize(dialog_rect); + return true; + } + + bool dialog_shown_ = false; +}; + +} // namespace + +// static +wxDialog* BaseDialog::LoadDialog(wxWindow* parent, const wxString& xrc_file) { + assert(parent); + return new BaseDialog(parent, xrc_file); +} + +BaseDialog::BaseDialog(wxWindow* parent, const wxString& xrc_file) + : wxDialog(), keep_on_top_styler_(this) { +#if !wxCHECK_VERSION(3, 1, 0) + // This needs to be set before loading any element on the window. This also + // has no effect since wx 3.1.0, where it became the default. + this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); +#endif + + [[maybe_unused]] const bool success = wxXmlResource::Get()->LoadDialog(this, parent, xrc_file); + assert(success); + + // Bind the event handler. + this->Bind(wxEVT_SHOW, &BaseDialog::OnBaseDialogShow, this); + + wxPersistenceManager::Get().Register(this, new PersistentBaseDialog(this)); +} + +wxWindow* BaseDialog::GetValidatedChild(const wxString& name) const { + wxWindow* window = this->FindWindow(name); + assert(window); + return window; +} + +void BaseDialog::OnBaseDialogShow(wxShowEvent& event) { + if (event.IsShown()) { + // Restore the dialog saved position. + if (wxPersistenceManager::Get().Restore(this)) { + // Ensure we are not restoring the dialog out of bounds. + if (!widgets::GetDisplayRect().Intersects(this->GetRect())) { + this->RepositionDialog(); + } + } else { + // First-time use. + this->RepositionDialog(); + } + + // Do not run this again. + this->Unbind(wxEVT_SHOW, &BaseDialog::OnBaseDialogShow, this); + } + + // Let the event propagate. + event.Skip(); +} + +void BaseDialog::RepositionDialog() { + // Re-position the dialog slightly to the bottom-right of the parent. + const wxWindow* parent = this->GetParent(); + wxPoint parent_pos; + if (parent) { + parent_pos = parent->GetPosition(); + } else { + parent_pos = wxPoint(OPTION(kGeomWindowX), OPTION(kGeomWindowY)); + } + const wxPoint dialog_pos = parent_pos + wxPoint(40, 40); + this->SetPosition(dialog_pos); +} + +} // namespace dialogs diff --git a/src/wx/dialogs/base-dialog.h b/src/wx/dialogs/base-dialog.h new file mode 100644 index 00000000..7ac7451d --- /dev/null +++ b/src/wx/dialogs/base-dialog.h @@ -0,0 +1,42 @@ +#ifndef VBAM_WX_DIALOGS_BASE_DIALOG_H_ +#define VBAM_WX_DIALOGS_BASE_DIALOG_H_ + +#include +#include + +#include "wx/widgets/keep-on-top-styler.h" + +namespace dialogs { + +class BaseDialog : public wxDialog { +public: + static wxDialog* LoadDialog(wxWindow* parent, const wxString& xrc_file); + + ~BaseDialog() override = default; + +protected: + BaseDialog(wxWindow* parent, const wxString& xrc_file); + + // Helper function to assert on the returned value. + wxWindow* GetValidatedChild(const wxString& name) const; + + template + T* GetValidatedChild(const wxString& name) const { + T* child = wxDynamicCast(this->GetValidatedChild(name), T); + assert(child); + return child; + } + +private: + // Handler for the wxEVT_SHOW event. + void OnBaseDialogShow(wxShowEvent& event); + + // Repositions the dialog to the bottom-right of the parent. + void RepositionDialog(); + + const widgets::KeepOnTopStyler keep_on_top_styler_; +}; + +} // namespace dialogs + +#endif // VBAM_WX_DIALOGS_BASE_DIALOG_H_ \ No newline at end of file diff --git a/src/wx/dialogs/directories-config.cpp b/src/wx/dialogs/directories-config.cpp index ff38a0b7..5e58a322 100644 --- a/src/wx/dialogs/directories-config.cpp +++ b/src/wx/dialogs/directories-config.cpp @@ -2,9 +2,7 @@ #include -#include - -#include "wx/dialogs/validated-child.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/option-validator.h" namespace dialogs { @@ -58,29 +56,23 @@ DirectoriesConfig* DirectoriesConfig::NewInstance(wxWindow* parent) { return new DirectoriesConfig(parent); } -DirectoriesConfig::DirectoriesConfig(wxWindow* parent) - : wxDialog(), keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "DirectoriesConfig"); - - SetUpDirPicker(GetValidatedChild(this, "GBARoms"), +DirectoriesConfig::DirectoriesConfig(wxWindow* parent) : BaseDialog(parent, "DirectoriesConfig") { + // clang-format off + SetUpDirPicker(GetValidatedChild("GBARoms"), config::OptionID::kGBAROMDir); - SetUpDirPicker(GetValidatedChild(this, "GBRoms"), + SetUpDirPicker(GetValidatedChild("GBRoms"), config::OptionID::kGBROMDir); - SetUpDirPicker(GetValidatedChild(this, "GBCRoms"), + SetUpDirPicker(GetValidatedChild("GBCRoms"), config::OptionID::kGBGBCROMDir); - SetUpDirPicker(GetValidatedChild(this, "BatSaves"), + SetUpDirPicker(GetValidatedChild("BatSaves"), config::OptionID::kGenBatteryDir); - SetUpDirPicker(GetValidatedChild(this, "StateSaves"), + SetUpDirPicker(GetValidatedChild("StateSaves"), config::OptionID::kGenStateDir); - SetUpDirPicker(GetValidatedChild(this, "Screenshots"), + SetUpDirPicker(GetValidatedChild("Screenshots"), config::OptionID::kGenScreenshotDir); - SetUpDirPicker(GetValidatedChild(this, "Recordings"), + SetUpDirPicker(GetValidatedChild("Recordings"), config::OptionID::kGenRecordingDir); + // clang-format on this->Fit(); } diff --git a/src/wx/dialogs/directories-config.h b/src/wx/dialogs/directories-config.h index 8ead7bf0..0b42b468 100644 --- a/src/wx/dialogs/directories-config.h +++ b/src/wx/dialogs/directories-config.h @@ -1,14 +1,12 @@ #ifndef VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_ #define VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_ -#include - -#include "wx/widgets/keep-on-top-styler.h" +#include "wx/dialogs/base-dialog.h" namespace dialogs { // Manages the directories configuration dialog. -class DirectoriesConfig : public wxDialog { +class DirectoriesConfig : public BaseDialog { public: static DirectoriesConfig* NewInstance(wxWindow* parent); ~DirectoriesConfig() override = default; @@ -18,8 +16,6 @@ private: // static method. This is because this class is destroyed when its // owner, `parent` is destroyed. This prevents accidental deletion. DirectoriesConfig(wxWindow* parent); - - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/display-config.cpp b/src/wx/dialogs/display-config.cpp index de656df0..797b5fde 100644 --- a/src/wx/dialogs/display-config.cpp +++ b/src/wx/dialogs/display-config.cpp @@ -16,7 +16,7 @@ #include "wx/config/option-id.h" #include "wx/config/option-proxy.h" #include "wx/config/option.h" -#include "wx/dialogs/validated-child.h" +#include "wx/dialogs/base-dialog.h" #include "wx/rpi.h" #include "wx/widgets/option-validator.h" #include "wx/widgets/render-plugin.h" @@ -225,7 +225,7 @@ DisplayConfig* DisplayConfig::NewInstance(wxWindow* parent) { } DisplayConfig::DisplayConfig(wxWindow* parent) - : wxDialog(), + : BaseDialog(parent, "DisplayConfig"), filter_observer_(config::OptionID::kDispFilter, std::bind(&DisplayConfig::OnFilterChanged, this, @@ -233,77 +233,69 @@ DisplayConfig::DisplayConfig(wxWindow* parent) interframe_observer_(config::OptionID::kDispIFB, std::bind(&DisplayConfig::OnInterframeChanged, this, - std::placeholders::_1)), - keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "DisplayConfig"); - + std::placeholders::_1)) { // Speed - GetValidatedChild(this, "FrameSkip") + GetValidatedChild("FrameSkip") ->SetValidator( widgets::OptionIntValidator(config::OptionID::kPrefFrameSkip)); // On-Screen Display - GetValidatedChild(this, "SpeedIndicator") + GetValidatedChild("SpeedIndicator") ->SetValidator( widgets::OptionChoiceValidator(config::OptionID::kPrefShowSpeed)); // Zoom - GetValidatedChild(this, "DefaultScale")->SetValidator(ScaleValidator()); + GetValidatedChild("DefaultScale")->SetValidator(ScaleValidator()); // this was a choice, but I'd rather not have to make an off-by-one // validator just for this, and spinctrl is good enough. - GetValidatedChild(this, "MaxScale") + GetValidatedChild("MaxScale") ->SetValidator(wxGenericValidator(&gopts.max_scale)); // Basic - GetValidatedChild(this, "OutputSimple") + GetValidatedChild("OutputSimple") ->SetValidator(RenderValidator(config::RenderMethod::kSimple)); #if defined(__WXMAC__) - GetValidatedChild(this, "OutputQuartz2D") + GetValidatedChild("OutputQuartz2D") ->SetValidator(RenderValidator(config::RenderMethod::kQuartz2d)); #else - GetValidatedChild(this, "OutputQuartz2D")->Hide(); + GetValidatedChild("OutputQuartz2D")->Hide(); #endif #ifdef NO_OGL - GetValidatedChild(this, "OutputOpenGL")->Hide(); + GetValidatedChild("OutputOpenGL")->Hide(); #elif defined(HAVE_WAYLAND_SUPPORT) && !defined(HAVE_WAYLAND_EGL) // wxGLCanvas segfaults on Wayland before wx 3.2. if (IsWayland()) { - GetValidatedChild(this, "OutputOpenGL")->Hide(); + GetValidatedChild("OutputOpenGL")->Hide(); } else { - GetValidatedChild(this, "OutputOpenGL") + GetValidatedChild("OutputOpenGL") ->SetValidator(RenderValidator(config::RenderMethod::kOpenGL)); } #else - GetValidatedChild(this, "OutputOpenGL") + GetValidatedChild("OutputOpenGL") ->SetValidator(RenderValidator(config::RenderMethod::kOpenGL)); #endif // NO_OGL #if defined(__WXMSW__) && !defined(NO_D3D) // Enable the Direct3D option on Windows. - GetValidatedChild(this, "OutputDirect3D") + GetValidatedChild("OutputDirect3D") ->SetValidator(RenderValidator(config::RenderMethod::kDirect3d)); #else - GetValidatedChild(this, "OutputDirect3D")->Hide(); + GetValidatedChild("OutputDirect3D")->Hide(); #endif - filter_selector_ = GetValidatedChild(this, "Filter"); + filter_selector_ = GetValidatedChild("Filter"); filter_selector_->SetValidator(FilterValidator()); filter_selector_->Bind(wxEVT_CHOICE, &DisplayConfig::UpdatePlugin, this, GetId()); // These are filled and/or hidden at dialog load time. - plugin_label_ = GetValidatedChild(this, "PluginLab"); - plugin_selector_ = GetValidatedChild(this, "Plugin"); + plugin_label_ = GetValidatedChild("PluginLab"); + plugin_selector_ = GetValidatedChild("Plugin"); - interframe_selector_ = GetValidatedChild(this, "IFB"); + interframe_selector_ = GetValidatedChild("IFB"); interframe_selector_->SetValidator(InterframeValidator()); Bind(wxEVT_SHOW, &DisplayConfig::OnDialogShowEvent, this, GetId()); diff --git a/src/wx/dialogs/display-config.h b/src/wx/dialogs/display-config.h index ec99b2a3..82bbfee1 100644 --- a/src/wx/dialogs/display-config.h +++ b/src/wx/dialogs/display-config.h @@ -1,11 +1,8 @@ #ifndef VBAM_WX_DIALOGS_DISPLAY_CONFIG_H_ #define VBAM_WX_DIALOGS_DISPLAY_CONFIG_H_ -#include -#include - +#include "wx/dialogs/base-dialog.h" #include "wx/config/option-observer.h" -#include "wx/widgets/keep-on-top-styler.h" // Forward declarations. class wxChoice; @@ -19,7 +16,7 @@ class Option; namespace dialogs { // Manages the display configuration dialog. -class DisplayConfig : public wxDialog { +class DisplayConfig : public BaseDialog { public: static DisplayConfig* NewInstance(wxWindow* parent); ~DisplayConfig() override = default; @@ -58,7 +55,6 @@ private: wxChoice* interframe_selector_; const config::OptionsObserver filter_observer_; const config::OptionsObserver interframe_observer_; - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/game-boy-config.cpp b/src/wx/dialogs/game-boy-config.cpp index ec7f53a2..757fb694 100644 --- a/src/wx/dialogs/game-boy-config.cpp +++ b/src/wx/dialogs/game-boy-config.cpp @@ -15,8 +15,9 @@ #include "wx/config/option-observer.h" #include "wx/config/option-proxy.h" -#include "wx/dialogs/validated-child.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/option-validator.h" +#include "wx/widgets/utils.h" namespace dialogs { @@ -221,23 +222,22 @@ private: GBPalettePanelData::GBPalettePanelData(wxPanel* panel, size_t palette_id) : wxClientData(), - default_selector_(GetValidatedChild(panel, "DefaultPalette")), - option_id_(static_cast( - static_cast(config::OptionID::kGBPalette0) + palette_id)) { + default_selector_(widgets::GetValidatedChild(panel, "DefaultPalette")), + option_id_(static_cast(static_cast(config::OptionID::kGBPalette0) + + palette_id)) { assert(panel); assert(palette_id < kNbPalettes); default_selector_->Bind( wxEVT_CHOICE, &GBPalettePanelData::OnDefaultPaletteSelected, this); - GetValidatedChild(panel, "UsePalette") - ->SetValidator(widgets::OptionSelectedValidator( - config::OptionID::kPrefGBPaletteOption, palette_id)); + widgets::GetValidatedChild(panel, "UsePalette") + ->SetValidator( + widgets::OptionSelectedValidator(config::OptionID::kPrefGBPaletteOption, palette_id)); for (size_t i = 0; i < colour_pickers_.size(); i++) { wxColourPickerCtrl* colour_picker = - GetValidatedChild( - panel, wxString::Format("Color%zu", i)); + widgets::GetValidatedChild(panel, wxString::Format("Color%zu", i)); colour_pickers_[i] = colour_picker; // Update the internal palette reference on colour change. @@ -247,7 +247,7 @@ GBPalettePanelData::GBPalettePanelData(wxPanel* panel, size_t palette_id) colour_picker->GetId()); } - GetValidatedChild(panel, "Reset") + widgets::GetValidatedChild(panel, "Reset") ->Bind(wxEVT_BUTTON, &GBPalettePanelData::OnPaletteReset, this); } @@ -317,39 +317,27 @@ GameBoyConfig* GameBoyConfig::NewInstance(wxWindow* parent) { return new GameBoyConfig(parent); } -GameBoyConfig::GameBoyConfig(wxWindow* parent) - : wxDialog(), keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "GameBoyConfig"); - +GameBoyConfig::GameBoyConfig(wxWindow* parent) : BaseDialog(parent, "GameBoyConfig") { // System and Peripherals. - GetValidatedChild(this, "System") - ->SetValidator(widgets::OptionChoiceValidator( - config::OptionID::kPrefEmulatorType)); + GetValidatedChild("System")->SetValidator( + widgets::OptionChoiceValidator(config::OptionID::kPrefEmulatorType)); // "Display borders" corresponds to 2 variables. - GetValidatedChild(this, "Borders")->SetValidator(BorderSelectorValidator()); + GetValidatedChild("Borders")->SetValidator(BorderSelectorValidator()); // GB BIOS ROM - GetValidatedChild(this, "GBBiosPicker") - ->SetValidator(BIOSPickerValidator( - config::OptionID::kGBBiosFile, - GetValidatedChild(this, "GBBiosLabel"))); + GetValidatedChild("GBBiosPicker") + ->SetValidator(BIOSPickerValidator(config::OptionID::kGBBiosFile, + GetValidatedChild("GBBiosLabel"))); // GBC BIOS ROM - GetValidatedChild(this, "GBCBiosPicker") - ->SetValidator(BIOSPickerValidator( - config::OptionID::kGBGBCBiosFile, - GetValidatedChild(this, "GBCBiosLabel"))); + GetValidatedChild("GBCBiosPicker") + ->SetValidator(BIOSPickerValidator(config::OptionID::kGBGBCBiosFile, + GetValidatedChild("GBCBiosLabel"))); for (size_t i = 0; i < kNbPalettes; i++) { // All of the wxPanel logic is handled in its client object. - wxPanel* panel = - GetValidatedChild(this, wxString::Format("cp%zu", i)); + wxPanel* panel = GetValidatedChild(wxString::Format("cp%zu", i)); GBPalettePanelData* palette_data = new GBPalettePanelData(panel, i); // `panel` takes ownership of `palette_data` here. diff --git a/src/wx/dialogs/game-boy-config.h b/src/wx/dialogs/game-boy-config.h index 520473fd..ff765ad4 100644 --- a/src/wx/dialogs/game-boy-config.h +++ b/src/wx/dialogs/game-boy-config.h @@ -2,14 +2,13 @@ #define VBAM_WX_DIALOGS_GAME_BOY_CONFIG_H_ #include -#include -#include "wx/widgets/keep-on-top-styler.h" +#include "wx/dialogs/base-dialog.h" namespace dialogs { // Manages the Game Boy configuration dialog. -class GameBoyConfig : public wxDialog { +class GameBoyConfig : public BaseDialog { public: static GameBoyConfig* NewInstance(wxWindow* parent); ~GameBoyConfig() override = default; @@ -19,8 +18,6 @@ private: // static method. This is because this class is destroyed when its // owner, `parent` is destroyed. This prevents accidental deletion. GameBoyConfig(wxWindow* parent); - - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/gb-rom-info.cpp b/src/wx/dialogs/gb-rom-info.cpp index e5dfef09..cc1dd450 100644 --- a/src/wx/dialogs/gb-rom-info.cpp +++ b/src/wx/dialogs/gb-rom-info.cpp @@ -5,8 +5,8 @@ #include "core/base/sizes.h" #include "core/gb/gb.h" +#include "wx/dialogs/base-dialog.h" #include "wx/dialogs/game-maker.h" -#include "wx/dialogs/validated-child.h" namespace dialogs { @@ -171,14 +171,7 @@ GbRomInfo* GbRomInfo::NewInstance(wxWindow* parent) { return new GbRomInfo(parent); } -GbRomInfo::GbRomInfo(wxWindow* parent) : wxDialog(), keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "GBROMInfo"); - +GbRomInfo::GbRomInfo(wxWindow* parent) : BaseDialog(parent, "GBROMInfo") { Bind(wxEVT_SHOW, &GbRomInfo::OnDialogShowEvent, this); } @@ -191,23 +184,23 @@ void GbRomInfo::OnDialogShowEvent(wxShowEvent& event) { } // Populate the dialog. - GetValidatedChild(this, "Title")->SetLabel(g_gbCartData.title()); - GetValidatedChild(this, "MakerCode")->SetLabel(g_gbCartData.maker_code()); - GetValidatedChild(this, "MakerName")->SetLabel(GetGameMakerName(g_gbCartData.maker_code())); - GetValidatedChild(this, "CartridgeType")->SetLabel(GetCartType()); - GetValidatedChild(this, "SGBCode")->SetLabel(GetCartSGBFlag()); - GetValidatedChild(this, "CGBCode")->SetLabel(GetCartCGBFlag()); - GetValidatedChild(this, "ROMSize")->SetLabel(GetCartRomSize()); - GetValidatedChild(this, "RAMSize")->SetLabel(GetCartRamSize()); - GetValidatedChild(this, "DestCode")->SetLabel(GetCartDestinationCode()); - GetValidatedChild(this, "LicCode") + GetValidatedChild("Title")->SetLabel(g_gbCartData.title()); + GetValidatedChild("MakerCode")->SetLabel(g_gbCartData.maker_code()); + GetValidatedChild("MakerName")->SetLabel(GetGameMakerName(g_gbCartData.maker_code())); + GetValidatedChild("CartridgeType")->SetLabel(GetCartType()); + GetValidatedChild("SGBCode")->SetLabel(GetCartSGBFlag()); + GetValidatedChild("CGBCode")->SetLabel(GetCartCGBFlag()); + GetValidatedChild("ROMSize")->SetLabel(GetCartRomSize()); + GetValidatedChild("RAMSize")->SetLabel(GetCartRamSize()); + GetValidatedChild("DestCode")->SetLabel(GetCartDestinationCode()); + GetValidatedChild("LicCode") ->SetLabel(wxString::Format("%02X", g_gbCartData.old_licensee_code())); - GetValidatedChild(this, "Version") + GetValidatedChild("Version") ->SetLabel(wxString::Format("%02X", g_gbCartData.version_flag())); - GetValidatedChild(this, "HeaderChecksum") + GetValidatedChild("HeaderChecksum") ->SetLabel(wxString::Format(_("%02X (Actual: %02X)"), g_gbCartData.header_checksum(), g_gbCartData.actual_header_checksum())); - GetValidatedChild(this, "CartridgeChecksum") + GetValidatedChild("CartridgeChecksum") ->SetLabel(wxString::Format(_("%04X (Actual: %04X)"), g_gbCartData.global_checksum(), g_gbCartData.actual_global_checksum())); diff --git a/src/wx/dialogs/gb-rom-info.h b/src/wx/dialogs/gb-rom-info.h index 1e5b51ec..ed25a221 100644 --- a/src/wx/dialogs/gb-rom-info.h +++ b/src/wx/dialogs/gb-rom-info.h @@ -1,13 +1,11 @@ #ifndef VBAM_WX_DIALOGS_GB_ROM_INFO_H_ #define VBAM_WX_DIALOGS_GB_ROM_INFO_H_ -#include - -#include "wx/widgets/keep-on-top-styler.h" +#include "wx/dialogs/base-dialog.h" namespace dialogs { -class GbRomInfo : public wxDialog { +class GbRomInfo : public BaseDialog { public: static GbRomInfo* NewInstance(wxWindow* parent); ~GbRomInfo() override = default; @@ -20,8 +18,6 @@ private: // Handler for the wxEVT_SHOW event. void OnDialogShowEvent(wxShowEvent& event); - - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/joypad-config.cpp b/src/wx/dialogs/joypad-config.cpp index 9729fe41..43c61311 100644 --- a/src/wx/dialogs/joypad-config.cpp +++ b/src/wx/dialogs/joypad-config.cpp @@ -2,11 +2,11 @@ #include -#include "wx/dialogs/validated-child.h" #include "wx/config/option-proxy.h" -#include "wx/config/option.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/option-validator.h" #include "wx/widgets/user-input-ctrl.h" +#include "wx/widgets/utils.h" #include "wx/wxvbam.h" namespace dialogs { @@ -17,23 +17,17 @@ JoypadConfig* JoypadConfig::NewInstance(wxWindow* parent) { return new JoypadConfig(parent); } -JoypadConfig::JoypadConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "JoypadConfig"); - +JoypadConfig::JoypadConfig(wxWindow* parent) : BaseDialog(parent, "JoypadConfig") { this->Bind(wxEVT_CHECKBOX, std::bind(&JoypadConfig::ToggleSDLGameControllerMode, this), XRCID("SDLGameControllerMode")); - GetValidatedChild(this, "SDLGameControllerMode")->SetValue(OPTION(kSDLGameControllerMode)); + GetValidatedChild("SDLGameControllerMode") + ->SetValue(OPTION(kSDLGameControllerMode)); for (int joypad = 0; joypad < 4; joypad++) { - wxWindow* panel = GetValidatedChild(this, wxString::Format("joy%d", joypad + 1)); + wxWindow* panel = GetValidatedChild(wxString::Format("joy%d", joypad + 1)); - GetValidatedChild(panel, "DefaultConfig") + widgets::GetValidatedChild(panel, "DefaultConfig") ->SetValidator( widgets::OptionSelectedValidator(config::OptionID::kJoyDefault, joypad + 1)); @@ -45,7 +39,7 @@ JoypadConfig::JoypadConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(t for (const config::GameKey& game_key : config::kAllGameKeys) { const wxString game_key_name = config::GameKeyToString(game_key); widgets::UserInputCtrl* game_key_control = - GetValidatedChild(panel, game_key_name); + widgets::GetValidatedChild(panel, game_key_name); wxWindow* current_parent = game_key_control->GetParent(); game_key_control->SetValidator( @@ -77,28 +71,28 @@ JoypadConfig::JoypadConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(t void JoypadConfig::ResetToDefaults(wxWindow* panel) { for (const config::GameKey& game_key : config::kAllGameKeys) { - GetValidatedChild(panel, config::GameKeyToString(game_key)) + widgets::GetValidatedChild(panel, config::GameKeyToString(game_key)) ->SetInputs(kDefaultBindings.find(config::GameControl(0, game_key))->second); } } void JoypadConfig::ClearJoypad(wxWindow* panel) { for (const config::GameKey& game_key : config::kAllGameKeys) { - GetValidatedChild(panel, config::GameKeyToString(game_key)) + widgets::GetValidatedChild(panel, config::GameKeyToString(game_key)) ->Clear(); } } void JoypadConfig::ToggleSDLGameControllerMode() { - OPTION(kSDLGameControllerMode) = GetValidatedChild(this, "SDLGameControllerMode") - ->IsChecked(); + OPTION(kSDLGameControllerMode) = + GetValidatedChild("SDLGameControllerMode")->IsChecked(); ClearAllJoypads(); wxGetApp().frame->PollAllJoysticks(); } void JoypadConfig::ClearAllJoypads() { for (unsigned joypad = 0; joypad < 4; joypad++) { - wxWindow* panel = GetValidatedChild(this, wxString::Format("joy%d", joypad + 1)); + wxWindow* panel = GetValidatedChild(wxString::Format("joy%d", joypad + 1)); ClearJoypad(panel); } diff --git a/src/wx/dialogs/joypad-config.h b/src/wx/dialogs/joypad-config.h index 0ba191d3..92af73f6 100644 --- a/src/wx/dialogs/joypad-config.h +++ b/src/wx/dialogs/joypad-config.h @@ -1,14 +1,11 @@ #ifndef VBAM_WX_DIALOGS_JOYPAD_CONFIG_H_ #define VBAM_WX_DIALOGS_JOYPAD_CONFIG_H_ -#include - -#include "wx/widgets/keep-on-top-styler.h" - +#include "wx/dialogs/base-dialog.h" namespace dialogs { // Manages the Joypad configuration dialog. -class JoypadConfig : public wxDialog { +class JoypadConfig : public BaseDialog { public: static JoypadConfig* NewInstance(wxWindow* parent); ~JoypadConfig() override = default; @@ -30,8 +27,6 @@ private: // Toggle SDL GameController mode for all joysticks. void ToggleSDLGameControllerMode(); - - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/dialogs/sound-config.cpp b/src/wx/dialogs/sound-config.cpp index 64c07d54..181ec0b7 100644 --- a/src/wx/dialogs/sound-config.cpp +++ b/src/wx/dialogs/sound-config.cpp @@ -16,7 +16,7 @@ #include "wx/config/option-id.h" #include "wx/config/option-proxy.h" #include "wx/config/option.h" -#include "wx/dialogs/validated-child.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/option-validator.h" namespace dialogs { @@ -140,31 +140,24 @@ SoundConfig* SoundConfig::NewInstance(wxWindow* parent) { return new SoundConfig(parent); } -SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(this) { -#if !wxCHECK_VERSION(3, 1, 0) - // This needs to be set before loading any element on the window. This also - // has no effect since wx 3.1.0, where it became the default. - this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); -#endif - wxXmlResource::Get()->LoadDialog(this, parent, "SoundConfig"); - +SoundConfig::SoundConfig(wxWindow* parent) : BaseDialog(parent, "SoundConfig") { // Volume slider configuration. - wxSlider* volume_slider = GetValidatedChild(this, "Volume"); + wxSlider* volume_slider = GetValidatedChild("Volume"); volume_slider->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundVolume)); - GetValidatedChild(this, "Volume100") + GetValidatedChild("Volume100") ->Bind(wxEVT_BUTTON, std::bind(&wxSlider::SetValue, volume_slider, 100)); // Sound quality. - GetValidatedChild(this, "Rate")->SetValidator(SoundRateValidator()); + GetValidatedChild("Rate")->SetValidator(SoundRateValidator()); // Audio API selection. - wxWindow* audio_api_button = GetValidatedChild(this, "OpenAL"); + wxWindow* audio_api_button = GetValidatedChild("OpenAL"); audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kOpenAL)); audio_api_button->Bind(wxEVT_RADIOBUTTON, std::bind(&SoundConfig::OnAudioApiChanged, this, std::placeholders::_1, config::AudioApi::kOpenAL)); - audio_api_button = GetValidatedChild(this, "DirectSound"); + audio_api_button = GetValidatedChild("DirectSound"); #if defined(__WXMSW__) audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kDirectSound)); audio_api_button->Bind(wxEVT_RADIOBUTTON, @@ -174,7 +167,7 @@ SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(thi audio_api_button->Hide(); #endif - audio_api_button = GetValidatedChild(this, "XAudio2"); + audio_api_button = GetValidatedChild("XAudio2"); #if defined(VBAM_ENABLE_XAUDIO2) audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kXAudio2)); audio_api_button->Bind(wxEVT_RADIOBUTTON, @@ -184,7 +177,7 @@ SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(thi audio_api_button->Hide(); #endif - audio_api_button = GetValidatedChild(this, "FAudio"); + audio_api_button = GetValidatedChild("FAudio"); #if defined(VBAM_ENABLE_FAUDIO) audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kFAudio)); audio_api_button->Bind(wxEVT_RADIOBUTTON, @@ -195,7 +188,7 @@ SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(thi #endif // Upmix configuration. - upmix_checkbox_ = GetValidatedChild(this, "Upmix"); + upmix_checkbox_ = GetValidatedChild("Upmix"); #if defined(VBAM_ENABLE_XAUDIO2) || defined(VBAM_ENABLE_FAUDIO) upmix_checkbox_->SetValidator(widgets::OptionBoolValidator(config::OptionID::kSoundUpmix)); #else @@ -203,7 +196,7 @@ SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(thi #endif // DSound HW acceleration. - hw_accel_checkbox_ = GetValidatedChild(this, "HWAccel"); + hw_accel_checkbox_ = GetValidatedChild("HWAccel"); #if defined(__WXMSW__) hw_accel_checkbox_->SetValidator( widgets::OptionBoolValidator(config::OptionID::kSoundDSoundHWAccel)); @@ -212,23 +205,23 @@ SoundConfig::SoundConfig(wxWindow* parent) : wxDialog(), keep_on_top_styler_(thi #endif // Buffers configuration. - buffers_info_label_ = GetValidatedChild(this, "BuffersInfo"); - buffers_slider_ = GetValidatedChild(this, "Buffers"); + buffers_info_label_ = GetValidatedChild("BuffersInfo"); + buffers_slider_ = GetValidatedChild("Buffers"); buffers_slider_->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundBuffers)); buffers_slider_->Bind(wxEVT_SLIDER, &SoundConfig::OnBuffersChanged, this); // Game Boy configuration. - GetValidatedChild(this, "GBEcho") - ->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBEcho)); - GetValidatedChild(this, "GBStereo") + GetValidatedChild("GBEcho")->SetValidator( + widgets::OptionIntValidator(config::OptionID::kSoundGBEcho)); + GetValidatedChild("GBStereo") ->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBStereo)); // Game Boy Advance configuration. - GetValidatedChild(this, "GBASoundFiltering") + GetValidatedChild("GBASoundFiltering") ->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBAFiltering)); // Audio Device configuration. - audio_device_selector_ = GetValidatedChild(this, "Device"); + audio_device_selector_ = GetValidatedChild("Device"); audio_device_selector_->SetValidator(AudioDeviceValidator()); this->Bind(wxEVT_SHOW, &SoundConfig::OnShow, this); diff --git a/src/wx/dialogs/sound-config.h b/src/wx/dialogs/sound-config.h index a9f39f28..a5abe57f 100644 --- a/src/wx/dialogs/sound-config.h +++ b/src/wx/dialogs/sound-config.h @@ -1,11 +1,8 @@ #ifndef VBAM_WX_DIALOGS_SOUND_CONFIG_H_ #define VBAM_WX_DIALOGS_SOUND_CONFIG_H_ -#include -#include - #include "wx/config/option.h" -#include "wx/widgets/keep-on-top-styler.h" +#include "wx/dialogs/base-dialog.h" // Forward declarations. class wxChoice; @@ -17,7 +14,7 @@ class wxWindow; namespace dialogs { // Manages the sound configuration dialog. -class SoundConfig : public wxDialog { +class SoundConfig : public BaseDialog { public: static SoundConfig* NewInstance(wxWindow* parent); ~SoundConfig() override = default; @@ -42,7 +39,6 @@ private: wxCheckBox* upmix_checkbox_; wxCheckBox* hw_accel_checkbox_; config::AudioApi current_audio_api_; - const widgets::KeepOnTopStyler keep_on_top_styler_; }; } // namespace dialogs diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index e5688393..6e506c48 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -40,6 +40,7 @@ #include "core/gba/gbaGlobals.h" #include "wx/config/option-proxy.h" #include "wx/dialogs/accel-config.h" +#include "wx/dialogs/base-dialog.h" #include "wx/dialogs/directories-config.h" #include "wx/dialogs/display-config.h" #include "wx/dialogs/game-boy-config.h" @@ -64,26 +65,8 @@ const #undef wxvbam #endif - // this is supposed to happen automatically if a parent is marked recursive - // but some dialogs don't do it (propertydialog?) - // so go ahead and mark all dialogs for fully recursive validation - static void - mark_recursive(wxWindowBase* w) -{ - w->SetExtraStyle(w->GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY); - wxWindowList l = w->GetChildren(); - - for (wxWindowList::iterator ch = l.begin(); ch != l.end(); ++ch) - mark_recursive(*ch); -} - -#if (wxMAJOR_VERSION < 3) -#define GetXRCDialog(n) \ - wxStaticCast(wxGetApp().frame->FindWindow(XRCID(n)), wxDialog) -#else #define GetXRCDialog(n) \ wxStaticCast(wxGetApp().frame->FindWindowByName(n), wxDialog) -#endif // Event handlers must be methods of wxEvtHandler-derived objects @@ -343,11 +326,6 @@ public: wxDialog* subdlg = GetXRCDialog("CheatEdit"); dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER); - if (OPTION(kDispKeepOnTop)) - subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP); - else - subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP); - subdlg->ShowModal(); AddCheat(); Reload(ncheats); @@ -566,11 +544,6 @@ public: wxDialog* subdlg = GetXRCDialog("CheatEdit"); dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER); - if (OPTION(kDispKeepOnTop)) - subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP); - else - subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP); - if (subdlg->ShowModal() != wxID_OK) return; @@ -1098,11 +1071,6 @@ public: wxDialog* subdlg = GetXRCDialog("CheatAdd"); dlg->SetWindowStyle(wxCAPTION | wxRESIZE_BORDER); - if (OPTION(kDispKeepOnTop)) - subdlg->SetWindowStyle(subdlg->GetWindowStyle() | wxSTAY_ON_TOP); - else - subdlg->SetWindowStyle(subdlg->GetWindowStyle() & ~wxSTAY_ON_TOP); - if (subdlg->ShowModal() != wxID_OK) return; @@ -1629,38 +1597,8 @@ void CheckThrowXRCError(T pointer, const char* name) wxDialog* MainFrame::LoadXRCDialog(const char* name) { wxString dname = wxString::FromUTF8(name); - wxDialog* dialog = wxXmlResource::Get()->LoadDialog(this, dname); + wxDialog* dialog = dialogs::BaseDialog::LoadDialog(this, dname); CheckThrowXRCError(dialog, name); -/* wx-2.9.1 doesn't set parent for propertysheetdialogs for some reason */ -/* this will generate a gtk warning but it is necessary for later */ -/* retrieval using FindWindow() */ -#if (wxMAJOR_VERSION < 3) - - if (!dialog->GetParent()) - dialog->Reparent(this); - -#endif - mark_recursive(dialog); - return dialog; -} - -wxDialog* MainFrame::LoadXRCropertySheetDialog(const char* name) -{ - wxString dname = wxString::FromUTF8(name); - //Seems like the only way to do this - wxObject* anObject = wxXmlResource::Get()->LoadObject(this, dname, wxEmptyString); - wxDialog* dialog = dynamic_cast(anObject); - CheckThrowXRCError(dialog, name); -/* wx-2.9.1 doesn't set parent for propertysheetdialogs for some reason */ -/* this will generate a gtk warning but it is necessary for later */ -/* retrieval using FindWindow() */ -#if (wxMAJOR_VERSION < 3) - - if (!dialog->GetParent()) - dialog->Reparent(this); - -#endif - mark_recursive(dialog); return dialog; } @@ -2488,7 +2426,7 @@ bool MainFrame::BindControls() fp->SetValidator(wxFileDirPickerValidator(&o, l)); \ } while (0) dialogs::GameBoyConfig::NewInstance(this); - d = LoadXRCropertySheetDialog("GameBoyAdvanceConfig"); + d = LoadXRCDialog("GameBoyAdvanceConfig"); { /// System and peripherals ch = GetValidatedChild(d, "SaveType", wxGenericValidator(&coreOptions.cpuSaveType)); @@ -2554,7 +2492,7 @@ bool MainFrame::BindControls() // at popup time. // The only one that can only be popped up once is logging, so allocate // and check it already. - logdlg = new LogDialog; + logdlg = std::make_unique(); // activate OnDropFile event handler #if !defined(__WXGTK__) || wxCHECK_VERSION(2, 8, 10) // may not actually do anything, but verfied to work w/ Linux/Nautilus diff --git a/src/wx/opts.cpp b/src/wx/opts.cpp index c6483998..cdc4d411 100644 --- a/src/wx/opts.cpp +++ b/src/wx/opts.cpp @@ -295,12 +295,14 @@ void load_opts(bool first_time_launch) { for (cont = cfg->GetFirstGroup(s, grp_idx); cont; cont = cfg->GetNextGroup(s, grp_idx)) { // ignore wxWidgets-managed global library settings - if (s == wxT("wxWindows")) + if (s == "Persistent_Options") { continue; + } // ignore file history - if (s == wxT("Recent")) + if (s == "Recent") { continue; + } cfg->SetPath(s); int poff = s.size(); diff --git a/src/wx/sys.cpp b/src/wx/sys.cpp index 590d181f..95ceccc4 100644 --- a/src/wx/sys.cpp +++ b/src/wx/sys.cpp @@ -1428,7 +1428,7 @@ void log(const char* defaultMsg, ...) wxGetApp().log.append(msg); if (wxGetApp().IsMainLoopRunning()) { - LogDialog* d = wxGetApp().frame->logdlg; + LogDialog* d = wxGetApp().frame->logdlg.get(); if (d && d->IsShown()) { d->Update(); diff --git a/src/wx/viewers.cpp b/src/wx/viewers.cpp index 0f892689..e1365694 100644 --- a/src/wx/viewers.cpp +++ b/src/wx/viewers.cpp @@ -544,12 +544,10 @@ void MainFrame::IOViewer() baddialog(); \ cb->SetValidator(wxBoolIntValidator(&systemVerbose, val, val)); \ } while (0) -LogDialog::LogDialog() : keep_on_top_styler_(this) { +LogDialog::LogDialog() : +dialogs::BaseDialog(nullptr, "Logging") { const wxString dname = wxT("Logging"); - if (!wxXmlResource::Get()->LoadDialog(this, wxGetApp().frame, dname)) - baddialog(); - SetEscapeId(wxID_OK); getlogf("SWI", VERBOSE_SWI); getlogf("UnalignedMemory", VERBOSE_UNALIGNED_MEMORY); diff --git a/src/wx/widgets/keep-on-top-styler.h b/src/wx/widgets/keep-on-top-styler.h index 7cb00682..e8ca62cc 100644 --- a/src/wx/widgets/keep-on-top-styler.h +++ b/src/wx/widgets/keep-on-top-styler.h @@ -1,5 +1,5 @@ -#ifndef VBAM_WX_DIALOGS_BASE_DIALOG_H_ -#define VBAM_WX_DIALOGS_BASE_DIALOG_H_ +#ifndef VBAM_WX_WIDGETS_KEEP_ON_TOP_STYLER_H_ +#define VBAM_WX_WIDGETS_KEEP_ON_TOP_STYLER_H_ #include @@ -55,4 +55,4 @@ private: } // namespace widgets -#endif // VBAM_WX_DIALOGS_BASE_DIALOG_H_ +#endif // VBAM_WX_WIDGETS_KEEP_ON_TOP_STYLER_H_ diff --git a/src/wx/widgets/utils.cpp b/src/wx/widgets/utils.cpp new file mode 100644 index 00000000..443f0aa4 --- /dev/null +++ b/src/wx/widgets/utils.cpp @@ -0,0 +1,16 @@ +#include "wx/widgets/utils.h" + +#include + +namespace widgets { + +wxRect GetDisplayRect() { + wxRect display_rect; + for (unsigned int i = 0; i < wxDisplay::GetCount(); i++) { + display_rect.Union(wxDisplay(i).GetClientArea()); + } + + return display_rect; +} + +} // namespace widgets diff --git a/src/wx/dialogs/validated-child.h b/src/wx/widgets/utils.h similarity index 56% rename from src/wx/dialogs/validated-child.h rename to src/wx/widgets/utils.h index e3051e82..a9285e69 100644 --- a/src/wx/dialogs/validated-child.h +++ b/src/wx/widgets/utils.h @@ -1,12 +1,18 @@ -#ifndef VBAM_WX_DIALOGS_VALIDATED_CHILD_H_ -#define VBAM_WX_DIALOGS_VALIDATED_CHILD_H_ +#ifndef VBAM_WX_WIDGETS_UTILS_H_ +#define VBAM_WX_WIDGETS_UTILS_H_ #include -#include #include +#include -namespace dialogs { +// This file contains a collection of various utility functions for wxWidgets. + +namespace widgets { + +// Helper function to get the display rectangle. Useful for avoiding drawing a +// dialog outside the screen. +wxRect GetDisplayRect(); // Helper functions to assert on the returned value. inline wxWindow* GetValidatedChild(const wxWindow* parent, @@ -23,6 +29,7 @@ T* GetValidatedChild(const wxWindow* parent, const wxString& name) { return child; } -} // namespace dialogs -#endif // VBAM_WX_DIALOGS_VALIDATED_CHILD_H_ +} // namespace widgets + +#endif // VBAM_WX_WIDGETS_UTILS_H_ diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index d0b933dd..a7b2c7b0 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -51,6 +51,7 @@ #include "wx/wayland.h" #include "wx/widgets/group-check-box.h" #include "wx/widgets/user-input-ctrl.h" +#include "wx/widgets/utils.h" #ifdef __WXGTK__ #include @@ -567,14 +568,8 @@ bool wxvbamApp::OnInit() { return false; } - // Measure the full display area. - wxRect display_rect; - for (unsigned int i = 0; i < wxDisplay::GetCount(); i++) { - display_rect.Union(wxDisplay(i).GetClientArea()); - } - // Ensure we are not drawing out of bounds. - if (display_rect.Intersects(client_rect)) { + if (widgets::GetDisplayRect().Intersects(client_rect)) { frame->SetSize(client_rect); } @@ -1258,11 +1253,6 @@ int MainFrame::ShowModal(wxDialog* dlg) { dlg->SetWindowStyle(dlg->GetWindowStyle() | wxCAPTION | wxRESIZE_BORDER); - if (OPTION(kDispKeepOnTop)) - dlg->SetWindowStyle(dlg->GetWindowStyle() | wxSTAY_ON_TOP); - else - dlg->SetWindowStyle(dlg->GetWindowStyle() & ~wxSTAY_ON_TOP); - CheckPointer(dlg); StartModal(); int ret = dlg->ShowModal(); diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 2752a3e8..217bd877 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -14,6 +14,7 @@ #include "core/base/system.h" #include "wx/config/option-observer.h" #include "wx/config/option.h" +#include "wx/dialogs/base-dialog.h" #include "wx/widgets/dpi-support.h" #include "wx/widgets/keep-on-top-styler.h" #include "wx/widgets/sdljoy.h" @@ -292,7 +293,7 @@ public: // this won't actually be destroyed, but it needs to be tracked so only // one is ever up and it needs to be pinged when new messages arrive - LogDialog* logdlg; + std::unique_ptr logdlg; // the cheat search dialog isn't destroyed or tracked, but it needs // to be cleared between games @@ -385,8 +386,6 @@ private: void OnSize(wxSizeEvent& event); // Load a named wxDialog from the XRC file wxDialog* LoadXRCDialog(const char* name); - // Load a named wxDialog from the XRC file - wxDialog* LoadXRCropertySheetDialog(const char* name); #include "wx/cmdhandlers.h" }; @@ -695,14 +694,13 @@ public: DrawingPanel(wxWindow* parent, int _width, int _height); }; -class LogDialog : public wxDialog { +class LogDialog : public dialogs::BaseDialog { public: LogDialog(); void Update(); private: wxTextCtrl* log; - widgets::KeepOnTopStyler keep_on_top_styler_; void Save(wxCommandEvent& ev); void Clear(wxCommandEvent& ev);