From 18f39928012b4b1e6092fbd9ced5b107c027848c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Jul 2017 22:45:18 +0200 Subject: [PATCH 1/4] Just fix a typo in the preferences sample "Use" and not "User". --- samples/preferences/preferences.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/preferences/preferences.cpp b/samples/preferences/preferences.cpp index da1e3a1c0a..d1bf8f8022 100644 --- a/samples/preferences/preferences.cpp +++ b/samples/preferences/preferences.cpp @@ -90,7 +90,7 @@ class PrefsPageGeneralPanel : public wxPanel public: PrefsPageGeneralPanel(wxWindow *parent) : wxPanel(parent) { - m_useMarkdown = new wxCheckBox(this, wxID_ANY, "User Markdown syntax"); + m_useMarkdown = new wxCheckBox(this, wxID_ANY, "Use Markdown syntax"); m_spellcheck = new wxCheckBox(this, wxID_ANY, "Check spelling"); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); From 6de9a284a752c9264457a372d6e5d02cd79229a4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Jul 2017 22:47:32 +0200 Subject: [PATCH 2/4] Use Bind() instead of Connect() in preferences sample This makes the code shorter and more clear. --- samples/preferences/preferences.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/samples/preferences/preferences.cpp b/samples/preferences/preferences.cpp index d1bf8f8022..b485fbfdf0 100644 --- a/samples/preferences/preferences.cpp +++ b/samples/preferences/preferences.cpp @@ -56,14 +56,9 @@ public: menuBar->Append(fileMenu, "&File"); SetMenuBar(menuBar); - Connect(wxID_PREFERENCES, - wxEVT_MENU, - wxCommandEventHandler(MyFrame::OnPref), NULL, this); - Connect(wxID_EXIT, - wxEVT_MENU, - wxCommandEventHandler(MyFrame::OnExit), NULL, this); - Connect(wxEVT_CLOSE_WINDOW, - wxCloseEventHandler(MyFrame::OnClose), NULL, this); + Bind(wxEVT_MENU, &MyFrame::OnPref, this, wxID_PREFERENCES); + Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); + Bind(wxEVT_CLOSE_WINDOW, &MyFrame::OnClose, this); } private: @@ -103,12 +98,12 @@ public: // immediately rather than after the OK or Apply button is pressed. if ( wxPreferencesEditor::ShouldApplyChangesImmediately() ) { - m_useMarkdown->Connect(wxEVT_CHECKBOX, - wxCommandEventHandler(PrefsPageGeneralPanel::ChangedUseMarkdown), - NULL, this); - m_spellcheck->Connect(wxEVT_CHECKBOX, - wxCommandEventHandler(PrefsPageGeneralPanel::ChangedSpellcheck), - NULL, this); + m_useMarkdown->Bind(wxEVT_CHECKBOX, + &PrefsPageGeneralPanel::ChangedUseMarkdown, + this); + m_spellcheck->Bind(wxEVT_CHECKBOX, + &PrefsPageGeneralPanel::ChangedSpellcheck, + this); } } @@ -172,9 +167,9 @@ public: if ( wxPreferencesEditor::ShouldApplyChangesImmediately() ) { - m_fulltext->Connect(wxEVT_CHECKBOX, - wxCommandEventHandler(PrefsPageTopicsPanel::ChangedFulltext), - NULL, this); + m_fulltext->Bind(wxEVT_CHECKBOX, + &PrefsPageTopicsPanel::ChangedFulltext, + this); } } From 552c942a764c3504ac5fd803d54c57540a41987d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Jul 2017 23:05:28 +0200 Subject: [PATCH 3/4] Actually show settings changing in the preferences sample Make the sample slightly more realistic by adding a MySettings struct whose fields are updated the dialog and also make it more visual by showing the current values of (some) settings on the screen. --- samples/preferences/preferences.cpp | 88 ++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/samples/preferences/preferences.cpp b/samples/preferences/preferences.cpp index b485fbfdf0..8bf35191f4 100644 --- a/samples/preferences/preferences.cpp +++ b/samples/preferences/preferences.cpp @@ -28,6 +28,25 @@ #include "wx/artprov.h" #include "wx/frame.h" +// This struct combines the settings edited in the preferences dialog. +struct MySettings +{ + MySettings() + { + // Normally we would initialize values by loading them from some + // persistent storage, e.g. using wxConfig. + // For demonstration purposes, we just set hardcoded values here. + m_useMarkdown = true; + m_spellcheck = false; + } + + bool m_useMarkdown; + bool m_spellcheck; + + // We don't do the same thing for the second preferences page fields, but + // we would have included them in a real application. +}; + class MyApp : public wxApp { public: @@ -35,8 +54,14 @@ public: void ShowPreferencesEditor(wxWindow* parent); void DismissPreferencesEditor(); + void UpdateSettings(); + + // Make them public for simplicity, we could also provide accessors, of + // course. + MySettings m_settings; private: + class MyFrame* m_frame; wxScopedPtr m_prefEditor; }; @@ -59,6 +84,33 @@ public: Bind(wxEVT_MENU, &MyFrame::OnPref, this, wxID_PREFERENCES); Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT); Bind(wxEVT_CLOSE_WINDOW, &MyFrame::OnClose, this); + + wxPanel* const panel = new wxPanel(this); + m_textMarkdownSyntax = new wxStaticText(panel, wxID_ANY, ""); + m_textSpellcheck = new wxStaticText(panel, wxID_ANY, ""); + + wxSizer* const sizer = new wxFlexGridSizer(2, wxSize(5, 5)); + sizer->Add(new wxStaticText(panel, wxID_ANY, "Markdown syntax:"), + wxSizerFlags().Center().Right()); + sizer->Add(m_textMarkdownSyntax, + wxSizerFlags().Center()); + sizer->Add(new wxStaticText(panel, wxID_ANY, "Spell checking:"), + wxSizerFlags().Center().Right()); + sizer->Add(m_textSpellcheck, + wxSizerFlags().Center()); + panel->SetSizer(sizer); + + // Show the initial values. + UpdateSettings(); + } + + void UpdateSettings() + { + // 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. + const MySettings& settings = wxGetApp().m_settings; + m_textMarkdownSyntax->SetLabel(settings.m_useMarkdown ? "yes" : "no"); + m_textSpellcheck->SetLabel(settings.m_spellcheck ? "on" : "off"); } private: @@ -77,6 +129,9 @@ private: wxGetApp().DismissPreferencesEditor(); e.Skip(); } + + wxStaticText* m_textMarkdownSyntax; + wxStaticText* m_textSpellcheck; }; @@ -109,10 +164,9 @@ public: virtual bool TransferDataToWindow() { - // This is the place where you can initialize values, e.g. from wxConfig. - // For demonstration purposes, we just set hardcoded values. - m_useMarkdown->SetValue(true); - m_spellcheck->SetValue(false); + const MySettings& settings = wxGetApp().m_settings; + m_useMarkdown->SetValue(settings.m_useMarkdown); + m_spellcheck->SetValue(settings.m_spellcheck); return true; } @@ -120,21 +174,24 @@ public: { // Called on platforms with modal preferences dialog to save and apply // the changes. - wxCommandEvent dummy; - ChangedUseMarkdown(dummy); - ChangedSpellcheck(dummy); + MySettings& settings = wxGetApp().m_settings; + settings.m_useMarkdown = m_useMarkdown->GetValue(); + settings.m_spellcheck = m_spellcheck->GetValue(); + wxGetApp().UpdateSettings(); return true; } private: - void ChangedUseMarkdown(wxCommandEvent& WXUNUSED(e)) + void ChangedUseMarkdown(wxCommandEvent& e) { - // save new m_useMarkdown value and apply the change to the app + wxGetApp().m_settings.m_useMarkdown = e.IsChecked(); + wxGetApp().UpdateSettings(); } - void ChangedSpellcheck(wxCommandEvent& WXUNUSED(e)) + void ChangedSpellcheck(wxCommandEvent& e) { - // save new m_spellcheck value and apply the change to the app + wxGetApp().m_settings.m_spellcheck = e.IsChecked(); + wxGetApp().UpdateSettings(); } wxCheckBox *m_useMarkdown; @@ -223,8 +280,8 @@ bool MyApp::OnInit() // result in rather strange "Preferences Preferences" title. SetAppDisplayName("wxWidgets Sample"); - MyFrame *frame = new MyFrame(); - frame->Show(true); + m_frame = new MyFrame(); + m_frame->Show(true); return true; } @@ -246,3 +303,8 @@ void MyApp::DismissPreferencesEditor() if ( m_prefEditor ) m_prefEditor->Dismiss(); } + +void MyApp::UpdateSettings() +{ + m_frame->UpdateSettings(); +} From 101509eb4b62d4e62520d0ca13ac5cba25da7d27 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Jul 2017 23:34:37 +0200 Subject: [PATCH 4/4] 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(). --- samples/preferences/preferences.cpp | 66 +++++++++++++++++------------ 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/samples/preferences/preferences.cpp b/samples/preferences/preferences.cpp index 8bf35191f4..865aac5ecc 100644 --- a/samples/preferences/preferences.cpp +++ b/samples/preferences/preferences.cpp @@ -54,15 +54,14 @@ public: void ShowPreferencesEditor(wxWindow* parent); void DismissPreferencesEditor(); - void UpdateSettings(); - // Make them public for simplicity, we could also provide accessors, of - // course. - MySettings m_settings; + const MySettings& GetSettings() const { return m_settings; } + void UpdateSettings(const MySettings& settings); private: class MyFrame* m_frame; wxScopedPtr m_prefEditor; + MySettings m_settings; }; wxIMPLEMENT_APP(MyApp); @@ -108,7 +107,7 @@ public: { // 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. - const MySettings& settings = wxGetApp().m_settings; + const MySettings& settings = wxGetApp().GetSettings(); m_textMarkdownSyntax->SetLabel(settings.m_useMarkdown ? "yes" : "no"); m_textSpellcheck->SetLabel(settings.m_spellcheck ? "on" : "off"); } @@ -149,24 +148,19 @@ public: SetSizerAndFit(sizer); - // On some platforms (OS X, GNOME), changes to preferences are applied - // immediately rather than after the OK or Apply button is pressed. - if ( wxPreferencesEditor::ShouldApplyChangesImmediately() ) - { - m_useMarkdown->Bind(wxEVT_CHECKBOX, - &PrefsPageGeneralPanel::ChangedUseMarkdown, - this); - m_spellcheck->Bind(wxEVT_CHECKBOX, - &PrefsPageGeneralPanel::ChangedSpellcheck, - this); - } + m_useMarkdown->Bind(wxEVT_CHECKBOX, + &PrefsPageGeneralPanel::ChangedUseMarkdown, + this); + m_spellcheck->Bind(wxEVT_CHECKBOX, + &PrefsPageGeneralPanel::ChangedSpellcheck, + this); } virtual bool TransferDataToWindow() { - const MySettings& settings = wxGetApp().m_settings; - m_useMarkdown->SetValue(settings.m_useMarkdown); - m_spellcheck->SetValue(settings.m_spellcheck); + m_settingsCurrent = wxGetApp().GetSettings(); + m_useMarkdown->SetValue(m_settingsCurrent.m_useMarkdown); + m_spellcheck->SetValue(m_settingsCurrent.m_spellcheck); return true; } @@ -174,28 +168,43 @@ public: { // Called on platforms with modal preferences dialog to save and apply // the changes. - MySettings& settings = wxGetApp().m_settings; - settings.m_useMarkdown = m_useMarkdown->GetValue(); - settings.m_spellcheck = m_spellcheck->GetValue(); - wxGetApp().UpdateSettings(); + wxGetApp().UpdateSettings(m_settingsCurrent); return true; } 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) { - wxGetApp().m_settings.m_useMarkdown = e.IsChecked(); - wxGetApp().UpdateSettings(); + m_settingsCurrent.m_useMarkdown = e.IsChecked(); + UpdateSettingsIfNecessary(); } void ChangedSpellcheck(wxCommandEvent& e) { - wxGetApp().m_settings.m_spellcheck = e.IsChecked(); - wxGetApp().UpdateSettings(); + m_settingsCurrent.m_spellcheck = e.IsChecked(); + UpdateSettingsIfNecessary(); } wxCheckBox *m_useMarkdown; wxCheckBox *m_spellcheck; + + // Settings corresponding to the current values in this dialog. + MySettings m_settingsCurrent; }; class PrefsPageGeneral : public wxStockPreferencesPage @@ -304,7 +313,8 @@ void MyApp::DismissPreferencesEditor() m_prefEditor->Dismiss(); } -void MyApp::UpdateSettings() +void MyApp::UpdateSettings(const MySettings& settings) { + m_settings = settings; m_frame->UpdateSettings(); }