Simplify platform differences handling in the preferences sample

Use an alternative and arguably simpler (at least with real-life
applications, where settings are somewhat more complex) way of handling
the differences between platforms in the preferences sample: instead of
executing completely different code under different platforms, always
update the local copy of the settings immediately and just propagate, or
not, it to the application-level settings depending on the current
platform.

This costs an extra copy of the settings object on each change, but this
shouldn't be a problem in practice, and OTOH results in using mostly the
same code under all platforms, reducing the probability of
platform-specific bugs and avoiding any code duplication between the
event handlers and TransferDataFromWindow().
This commit is contained in:
Vadim Zeitlin
2017-07-11 23:34:37 +02:00
parent 552c942a76
commit 101509eb4b

View File

@@ -54,15 +54,14 @@ public:
void ShowPreferencesEditor(wxWindow* parent); void ShowPreferencesEditor(wxWindow* parent);
void DismissPreferencesEditor(); void DismissPreferencesEditor();
void UpdateSettings();
// Make them public for simplicity, we could also provide accessors, of const MySettings& GetSettings() const { return m_settings; }
// course. void UpdateSettings(const MySettings& settings);
MySettings m_settings;
private: private:
class MyFrame* m_frame; class MyFrame* m_frame;
wxScopedPtr<wxPreferencesEditor> m_prefEditor; wxScopedPtr<wxPreferencesEditor> m_prefEditor;
MySettings m_settings;
}; };
wxIMPLEMENT_APP(MyApp); wxIMPLEMENT_APP(MyApp);
@@ -108,7 +107,7 @@ public:
{ {
// Here we should update the settings we use. As we don't actually do // Here we should update the settings we use. As we don't actually do
// anything in this sample, just update their values shown on screen. // anything in this sample, just update their values shown on screen.
const MySettings& settings = wxGetApp().m_settings; const MySettings& settings = wxGetApp().GetSettings();
m_textMarkdownSyntax->SetLabel(settings.m_useMarkdown ? "yes" : "no"); m_textMarkdownSyntax->SetLabel(settings.m_useMarkdown ? "yes" : "no");
m_textSpellcheck->SetLabel(settings.m_spellcheck ? "on" : "off"); m_textSpellcheck->SetLabel(settings.m_spellcheck ? "on" : "off");
} }
@@ -149,24 +148,19 @@ public:
SetSizerAndFit(sizer); SetSizerAndFit(sizer);
// On some platforms (OS X, GNOME), changes to preferences are applied m_useMarkdown->Bind(wxEVT_CHECKBOX,
// immediately rather than after the OK or Apply button is pressed. &PrefsPageGeneralPanel::ChangedUseMarkdown,
if ( wxPreferencesEditor::ShouldApplyChangesImmediately() ) this);
{ m_spellcheck->Bind(wxEVT_CHECKBOX,
m_useMarkdown->Bind(wxEVT_CHECKBOX, &PrefsPageGeneralPanel::ChangedSpellcheck,
&PrefsPageGeneralPanel::ChangedUseMarkdown, this);
this);
m_spellcheck->Bind(wxEVT_CHECKBOX,
&PrefsPageGeneralPanel::ChangedSpellcheck,
this);
}
} }
virtual bool TransferDataToWindow() virtual bool TransferDataToWindow()
{ {
const MySettings& settings = wxGetApp().m_settings; m_settingsCurrent = wxGetApp().GetSettings();
m_useMarkdown->SetValue(settings.m_useMarkdown); m_useMarkdown->SetValue(m_settingsCurrent.m_useMarkdown);
m_spellcheck->SetValue(settings.m_spellcheck); m_spellcheck->SetValue(m_settingsCurrent.m_spellcheck);
return true; return true;
} }
@@ -174,28 +168,43 @@ public:
{ {
// Called on platforms with modal preferences dialog to save and apply // Called on platforms with modal preferences dialog to save and apply
// the changes. // the changes.
MySettings& settings = wxGetApp().m_settings; wxGetApp().UpdateSettings(m_settingsCurrent);
settings.m_useMarkdown = m_useMarkdown->GetValue();
settings.m_spellcheck = m_spellcheck->GetValue();
wxGetApp().UpdateSettings();
return true; return true;
} }
private: private:
void UpdateSettingsIfNecessary()
{
// On some platforms (OS X, GNOME), changes to preferences are applied
// immediately rather than after the OK or Apply button is pressed, so
// we need to take them into account as soon as they happen. On others
// (MSW), we need to wait until the changes are accepted by the user by
// pressing the "OK" button. To reuse the same code for both cases, we
// always update m_settingsCurrent object under all platforms, but only
// update the real application settings if necessary here.
if ( wxPreferencesEditor::ShouldApplyChangesImmediately() )
{
wxGetApp().UpdateSettings(m_settingsCurrent);
}
}
void ChangedUseMarkdown(wxCommandEvent& e) void ChangedUseMarkdown(wxCommandEvent& e)
{ {
wxGetApp().m_settings.m_useMarkdown = e.IsChecked(); m_settingsCurrent.m_useMarkdown = e.IsChecked();
wxGetApp().UpdateSettings(); UpdateSettingsIfNecessary();
} }
void ChangedSpellcheck(wxCommandEvent& e) void ChangedSpellcheck(wxCommandEvent& e)
{ {
wxGetApp().m_settings.m_spellcheck = e.IsChecked(); m_settingsCurrent.m_spellcheck = e.IsChecked();
wxGetApp().UpdateSettings(); UpdateSettingsIfNecessary();
} }
wxCheckBox *m_useMarkdown; wxCheckBox *m_useMarkdown;
wxCheckBox *m_spellcheck; wxCheckBox *m_spellcheck;
// Settings corresponding to the current values in this dialog.
MySettings m_settingsCurrent;
}; };
class PrefsPageGeneral : public wxStockPreferencesPage class PrefsPageGeneral : public wxStockPreferencesPage
@@ -304,7 +313,8 @@ void MyApp::DismissPreferencesEditor()
m_prefEditor->Dismiss(); m_prefEditor->Dismiss();
} }
void MyApp::UpdateSettings() void MyApp::UpdateSettings(const MySettings& settings)
{ {
m_settings = settings;
m_frame->UpdateSettings(); m_frame->UpdateSettings();
} }