[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.
This commit is contained in:
Fabrice de Gans 2024-04-08 16:58:04 -07:00 committed by Rafael Kitover
parent 41952d0625
commit 32627f6b85
27 changed files with 352 additions and 303 deletions

View File

@ -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

View File

@ -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();

View File

@ -5,12 +5,10 @@
#include <wx/listbox.h>
#include <wx/menu.h>
#include <wx/msgdlg.h>
#include <wx/xrc/xmlres.h>
#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<wxTreeCtrl>(this, "Commands");
current_keys_ = GetValidatedChild<wxListBox>(this, "Current");
assign_button_ = GetValidatedChild(this, "Assign");
remove_button_ = GetValidatedChild(this, "Remove");
key_input_ = GetValidatedChild<widgets::UserInputCtrl>(this, "Shortcut");
currently_assigned_label_ = GetValidatedChild<wxControl>(this, "AlreadyThere");
tree_ = GetValidatedChild<wxTreeCtrl>("Commands");
current_keys_ = GetValidatedChild<wxListBox>("Current");
assign_button_ = GetValidatedChild("Assign");
remove_button_ = GetValidatedChild("Remove");
key_input_ = GetValidatedChild<widgets::UserInputCtrl>("Shortcut");
currently_assigned_label_ = GetValidatedChild<wxControl>("AlreadyThere");
// Configure the key input.
key_input_->MoveBeforeInTabOrder(assign_button_);

View File

@ -3,11 +3,10 @@
#include <unordered_map>
#include <wx/dialog.h>
#include <wx/treectrl.h>
#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

View File

@ -0,0 +1,137 @@
#include "wx/dialogs/base-dialog.h"
#include <cassert>
#include <wx/persist.h>
#include <wx/persist/toplevel.h>
#include <wx/xrc/xmlres.h>
#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<BaseDialog> {
public:
PersistentBaseDialog(BaseDialog* window) : wxPersistentWindow<BaseDialog>(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

View File

@ -0,0 +1,42 @@
#ifndef VBAM_WX_DIALOGS_BASE_DIALOG_H_
#define VBAM_WX_DIALOGS_BASE_DIALOG_H_
#include <wx/dialog.h>
#include <wx/event.h>
#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 <class T>
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_

View File

@ -2,9 +2,7 @@
#include <wx/filepicker.h>
#include <wx/xrc/xmlres.h>
#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<wxDirPickerCtrl>(this, "GBARoms"),
DirectoriesConfig::DirectoriesConfig(wxWindow* parent) : BaseDialog(parent, "DirectoriesConfig") {
// clang-format off
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("GBARoms"),
config::OptionID::kGBAROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "GBRoms"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("GBRoms"),
config::OptionID::kGBROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "GBCRoms"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("GBCRoms"),
config::OptionID::kGBGBCROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "BatSaves"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("BatSaves"),
config::OptionID::kGenBatteryDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "StateSaves"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("StateSaves"),
config::OptionID::kGenStateDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "Screenshots"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("Screenshots"),
config::OptionID::kGenScreenshotDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "Recordings"),
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>("Recordings"),
config::OptionID::kGenRecordingDir);
// clang-format on
this->Fit();
}

View File

@ -1,14 +1,12 @@
#ifndef VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_
#define VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_
#include <wx/dialog.h>
#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

View File

@ -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<wxChoice>(this, "Filter");
filter_selector_ = GetValidatedChild<wxChoice>("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<wxControl>(this, "PluginLab");
plugin_selector_ = GetValidatedChild<wxChoice>(this, "Plugin");
plugin_label_ = GetValidatedChild<wxControl>("PluginLab");
plugin_selector_ = GetValidatedChild<wxChoice>("Plugin");
interframe_selector_ = GetValidatedChild<wxChoice>(this, "IFB");
interframe_selector_ = GetValidatedChild<wxChoice>("IFB");
interframe_selector_->SetValidator(InterframeValidator());
Bind(wxEVT_SHOW, &DisplayConfig::OnDialogShowEvent, this, GetId());

View File

@ -1,11 +1,8 @@
#ifndef VBAM_WX_DIALOGS_DISPLAY_CONFIG_H_
#define VBAM_WX_DIALOGS_DISPLAY_CONFIG_H_
#include <wx/dialog.h>
#include <wx/event.h>
#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

View File

@ -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<wxChoice>(panel, "DefaultPalette")),
option_id_(static_cast<config::OptionID>(
static_cast<size_t>(config::OptionID::kGBPalette0) + palette_id)) {
default_selector_(widgets::GetValidatedChild<wxChoice>(panel, "DefaultPalette")),
option_id_(static_cast<config::OptionID>(static_cast<size_t>(config::OptionID::kGBPalette0) +
palette_id)) {
assert(panel);
assert(palette_id < kNbPalettes);
default_selector_->Bind(
wxEVT_CHOICE, &GBPalettePanelData::OnDefaultPaletteSelected, this);
GetValidatedChild<wxCheckBox>(panel, "UsePalette")
->SetValidator(widgets::OptionSelectedValidator(
config::OptionID::kPrefGBPaletteOption, palette_id));
widgets::GetValidatedChild<wxCheckBox>(panel, "UsePalette")
->SetValidator(
widgets::OptionSelectedValidator(config::OptionID::kPrefGBPaletteOption, palette_id));
for (size_t i = 0; i < colour_pickers_.size(); i++) {
wxColourPickerCtrl* colour_picker =
GetValidatedChild<wxColourPickerCtrl>(
panel, wxString::Format("Color%zu", i));
widgets::GetValidatedChild<wxColourPickerCtrl>(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<wxStaticText>(this, "GBBiosLabel")));
GetValidatedChild("GBBiosPicker")
->SetValidator(BIOSPickerValidator(config::OptionID::kGBBiosFile,
GetValidatedChild<wxStaticText>("GBBiosLabel")));
// GBC BIOS ROM
GetValidatedChild(this, "GBCBiosPicker")
->SetValidator(BIOSPickerValidator(
config::OptionID::kGBGBCBiosFile,
GetValidatedChild<wxStaticText>(this, "GBCBiosLabel")));
GetValidatedChild("GBCBiosPicker")
->SetValidator(BIOSPickerValidator(config::OptionID::kGBGBCBiosFile,
GetValidatedChild<wxStaticText>("GBCBiosLabel")));
for (size_t i = 0; i < kNbPalettes; i++) {
// All of the wxPanel logic is handled in its client object.
wxPanel* panel =
GetValidatedChild<wxPanel>(this, wxString::Format("cp%zu", i));
wxPanel* panel = GetValidatedChild<wxPanel>(wxString::Format("cp%zu", i));
GBPalettePanelData* palette_data = new GBPalettePanelData(panel, i);
// `panel` takes ownership of `palette_data` here.

View File

@ -2,14 +2,13 @@
#define VBAM_WX_DIALOGS_GAME_BOY_CONFIG_H_
#include <wx/clrpicker.h>
#include <wx/dialog.h>
#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

View File

@ -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()));

View File

@ -1,13 +1,11 @@
#ifndef VBAM_WX_DIALOGS_GB_ROM_INFO_H_
#define VBAM_WX_DIALOGS_GB_ROM_INFO_H_
#include <wx/dialog.h>
#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

View File

@ -2,11 +2,11 @@
#include <wx/xrc/xmlres.h>
#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<wxCheckBox>(this, "SDLGameControllerMode")->SetValue(OPTION(kSDLGameControllerMode));
GetValidatedChild<wxCheckBox>("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<widgets::UserInputCtrl>(panel, game_key_name);
widgets::GetValidatedChild<widgets::UserInputCtrl>(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<widgets::UserInputCtrl>(panel, config::GameKeyToString(game_key))
widgets::GetValidatedChild<widgets::UserInputCtrl>(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<widgets::UserInputCtrl>(panel, config::GameKeyToString(game_key))
widgets::GetValidatedChild<widgets::UserInputCtrl>(panel, config::GameKeyToString(game_key))
->Clear();
}
}
void JoypadConfig::ToggleSDLGameControllerMode() {
OPTION(kSDLGameControllerMode) = GetValidatedChild<wxCheckBox>(this, "SDLGameControllerMode")
->IsChecked();
OPTION(kSDLGameControllerMode) =
GetValidatedChild<wxCheckBox>("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);
}

View File

@ -1,14 +1,11 @@
#ifndef VBAM_WX_DIALOGS_JOYPAD_CONFIG_H_
#define VBAM_WX_DIALOGS_JOYPAD_CONFIG_H_
#include <wx/dialog.h>
#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

View File

@ -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<wxSlider>(this, "Volume");
wxSlider* volume_slider = GetValidatedChild<wxSlider>("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<wxCheckBox>(this, "Upmix");
upmix_checkbox_ = GetValidatedChild<wxCheckBox>("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<wxCheckBox>(this, "HWAccel");
hw_accel_checkbox_ = GetValidatedChild<wxCheckBox>("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<wxControl>(this, "BuffersInfo");
buffers_slider_ = GetValidatedChild<wxSlider>(this, "Buffers");
buffers_info_label_ = GetValidatedChild<wxControl>("BuffersInfo");
buffers_slider_ = GetValidatedChild<wxSlider>("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<wxChoice>(this, "Device");
audio_device_selector_ = GetValidatedChild<wxChoice>("Device");
audio_device_selector_->SetValidator(AudioDeviceValidator());
this->Bind(wxEVT_SHOW, &SoundConfig::OnShow, this);

View File

@ -1,11 +1,8 @@
#ifndef VBAM_WX_DIALOGS_SOUND_CONFIG_H_
#define VBAM_WX_DIALOGS_SOUND_CONFIG_H_
#include <wx/dialog.h>
#include <wx/event.h>
#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

View File

@ -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<wxDialog*>(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<wxChoice, wxGenericValidator>(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<LogDialog>();
// activate OnDropFile event handler
#if !defined(__WXGTK__) || wxCHECK_VERSION(2, 8, 10)
// may not actually do anything, but verfied to work w/ Linux/Nautilus

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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 <wx/event.h>
@ -55,4 +55,4 @@ private:
} // namespace widgets
#endif // VBAM_WX_DIALOGS_BASE_DIALOG_H_
#endif // VBAM_WX_WIDGETS_KEEP_ON_TOP_STYLER_H_

16
src/wx/widgets/utils.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "wx/widgets/utils.h"
#include <wx/display.h>
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

View File

@ -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 <cassert>
#include <wx/string.h>
#include <wx/window.h>
#include <wx/gdicmn.h>
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_

View File

@ -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 <gdk/gdk.h>
@ -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();

View File

@ -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<LogDialog> 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);