1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-16 08:34:10 +02:00

Rollback preview in Spectrogram settings or preferences if cancelled

* commit '5b229847d5205597e2eaf447bf9bdaba03e5dde7':
  Do rollback of cancelled Preview for Spectrogram settings/prefs
  Change virtual function interface of PrefsPanel
  Rename Apply in spectrum settings & prefs dialogs, reposition it too
This commit is contained in:
Paul Licameli 2017-06-25 11:48:40 -04:00
commit 3f670118c7
48 changed files with 156 additions and 83 deletions

View File

@ -351,7 +351,10 @@ enum
enum
{
ePreviewID = wxID_LOWEST - 1,
// ePreviewID = wxID_LOWEST - 1,
// But there is a wxID_PREVIEW
ePreviewID = wxID_PREVIEW,
eDebugID = wxID_LOWEST - 2,
eSettingsID = wxID_LOWEST - 3,
ePreviewDryID = wxID_LOWEST - 4,

View File

@ -70,7 +70,7 @@ void BatchPrefs::PopulateOrExchange( ShuttleGui & S )
}
/// Send changed values back to Prefs, and update Audacity.
bool BatchPrefs::Apply()
bool BatchPrefs::Commit()
{
ShuttleGui S( this, eIsSavingToPrefs );
PopulateOrExchange( S );

View File

@ -25,7 +25,7 @@ class BatchPrefs final : public PrefsPanel
public:
BatchPrefs(wxWindow * parent);
~BatchPrefs();
bool Apply() override;
bool Commit() override;
private:
void Populate();

View File

@ -370,7 +370,7 @@ void DevicePrefs::OnDevice(wxCommandEvent & WXUNUSED(event))
Layout();
}
bool DevicePrefs::Apply()
bool DevicePrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -28,7 +28,7 @@ class DevicePrefs final : public PrefsPanel
public:
DevicePrefs(wxWindow * parent);
virtual ~DevicePrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -256,7 +256,7 @@ bool DirectoriesPrefs::Validate()
return true;
}
bool DirectoriesPrefs::Apply()
bool DirectoriesPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -23,7 +23,7 @@ class DirectoriesPrefs final : public PrefsPanel
public:
DirectoriesPrefs(wxWindow * parent);
~DirectoriesPrefs();
bool Apply() override;
bool Commit() override;
bool Validate() override;
wxString HelpPageName() override;

View File

@ -160,7 +160,7 @@ void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
#endif
}
bool EffectsPrefs::Apply()
bool EffectsPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -27,7 +27,7 @@ class EffectsPrefs final : public PrefsPanel
public:
EffectsPrefs(wxWindow * parent);
~EffectsPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -185,7 +185,7 @@ void ExtImportPrefs::PopulateOrExchange(ShuttleGui & S)
SetMinSize(GetSize());
}
bool ExtImportPrefs::Apply()
bool ExtImportPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -48,7 +48,7 @@ class ExtImportPrefs final : public PrefsPanel
public:
ExtImportPrefs(wxWindow * parent);
~ExtImportPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
void OnPluginKeyDown(wxListEvent& event);

View File

@ -207,7 +207,7 @@ void GUIPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool GUIPrefs::Apply()
bool GUIPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -27,7 +27,7 @@ class GUIPrefs final : public PrefsPanel
public:
GUIPrefs(wxWindow * parent);
~GUIPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
static void GetRangeChoices(wxArrayString *pChoices, wxArrayString *pCodes);

View File

@ -102,7 +102,7 @@ void ImportExportPrefs::PopulateOrExchange(ShuttleGui & S)
#endif
}
bool ImportExportPrefs::Apply()
bool ImportExportPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -26,7 +26,7 @@ class ImportExportPrefs final : public PrefsPanel
public:
ImportExportPrefs(wxWindow * parent);
~ImportExportPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -688,7 +688,7 @@ void KeyConfigPrefs::OnViewBy(wxCommandEvent & e)
mFilter->SetName(wxStripMenuCodes(mFilterLabel->GetLabel()));
}
bool KeyConfigPrefs::Apply()
bool KeyConfigPrefs::Commit()
{
// On the Mac, preferences may be changed without any active
// projects. This means that the CommandManager isn't availabe
@ -1233,7 +1233,7 @@ void KeyConfigPrefs::OnItemSelected(wxListEvent & e)
mKey->AppendText(item.GetText());
}
bool KeyConfigPrefs::Apply()
bool KeyConfigPrefs::Commit()
{
for (size_t i = 0; i < mNames.GetCount(); i++) {
// wxString dkey = KeyStringNormalize(mManager->GetDefaultKeyFromName(mNames[i]));

View File

@ -39,7 +39,7 @@ class KeyConfigPrefs final : public PrefsPanel
public:
KeyConfigPrefs(wxWindow * parent);
~KeyConfigPrefs();
bool Apply() override;
bool Commit() override;
void Cancel() override;
wxString HelpPageName() override;
@ -109,7 +109,7 @@ class KeyConfigPrefs final : public PrefsPanel
public:
KeyConfigPrefs(wxWindow * parent);
~KeyConfigPrefs();
bool Apply() override;
bool Commit() override;
void Cancel() override;
wxString HelpPageName() override;

View File

@ -231,7 +231,7 @@ void LibraryPrefs::OnFFmpegDownButton(wxCommandEvent & WXUNUSED(event))
HelpSystem::ShowHelpDialog(this, wxT("FAQ:Installation_and_Plug-Ins#ffdown"), true);
}
bool LibraryPrefs::Apply()
bool LibraryPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -27,7 +27,7 @@ class LibraryPrefs final : public PrefsPanel
public:
LibraryPrefs(wxWindow * parent);
~LibraryPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -250,7 +250,7 @@ void MidiIOPrefs::OnHost(wxCommandEvent & e)
// OnDevice(e);
}
bool MidiIOPrefs::Apply()
bool MidiIOPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -31,7 +31,7 @@ class MidiIOPrefs final : public PrefsPanel
public:
MidiIOPrefs(wxWindow * parent);
virtual ~MidiIOPrefs();
bool Apply() override;
bool Commit() override;
bool Validate() override;
wxString HelpPageName() override;

View File

@ -126,7 +126,7 @@ void ModulePrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool ModulePrefs::Apply()
bool ModulePrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -36,7 +36,7 @@ class ModulePrefs final : public PrefsPanel
public:
ModulePrefs(wxWindow * parent);
~ModulePrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
static int GetModuleStatus( const wxString &fname );

View File

@ -189,7 +189,7 @@ void MousePrefs::AddItem(wxString const & buttons, wxString const & tool,
/// Update the preferences stored on disk.
/// Currently does nothing as Mouse Preferences don't change.
bool MousePrefs::Apply()
bool MousePrefs::Commit()
{
// Not yet required...
// ShuttleGui S(this, eIsSavingToPrefs);

View File

@ -24,7 +24,7 @@ class MousePrefs final : public PrefsPanel
public:
MousePrefs(wxWindow * parent);
~MousePrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -115,7 +115,7 @@ void PlaybackPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool PlaybackPrefs::Apply()
bool PlaybackPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -25,7 +25,7 @@ class PlaybackPrefs final : public PrefsPanel
public:
PlaybackPrefs(wxWindow * parent);
virtual ~PlaybackPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -75,7 +75,7 @@
BEGIN_EVENT_TABLE(PrefsDialog, wxDialogWrapper)
EVT_BUTTON(wxID_OK, PrefsDialog::OnOK)
EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
EVT_BUTTON(wxID_APPLY, PrefsDialog::OnApply)
EVT_BUTTON(wxID_PREVIEW, PrefsDialog::OnPreview)
EVT_BUTTON(wxID_HELP, PrefsDialog::OnHelp)
EVT_TREE_KEY_DOWN(wxID_ANY, PrefsDialog::OnTreeKeyDown) // Handles key events when tree has focus
END_EVENT_TABLE()
@ -113,9 +113,9 @@ int wxTreebookExt::SetSelection(size_t n)
PrefsPanel *const panel = static_cast<PrefsPanel *>(GetPage(n));
const bool showHelp = (panel->HelpPageName() != wxEmptyString);
const bool showApply = panel->ShowsApplyButton();
const bool showPreview = panel->ShowsPreviewButton();
wxWindow *const helpButton = wxWindow::FindWindowById(wxID_HELP, GetParent());
wxWindow *const applyButton = wxWindow::FindWindowById(wxID_APPLY, GetParent());
wxWindow *const previewButton = wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
if (helpButton) {
if (showHelp) {
@ -137,8 +137,8 @@ int wxTreebookExt::SetSelection(size_t n)
GetParent()->Layout();
}
if (applyButton) { // might still be NULL during population
const bool changed = applyButton->Show(showApply);
if (previewButton) { // might still be NULL during population
const bool changed = previewButton->Show(showPreview);
if (changed)
GetParent()->Layout();
}
@ -305,13 +305,13 @@ PrefsDialog::PrefsDialog
}
S.EndVerticalLay();
S.AddStandardButtons(eOkButton | eCancelButton | eApplyButton | eHelpButton);
S.AddStandardButtons(eOkButton | eCancelButton | ePreviewButton | eHelpButton);
static_cast<wxButton*>(wxWindow::FindWindowById(wxID_OK, this))->SetDefault();
if (mUniquePage && !mUniquePage->ShowsApplyButton()) {
wxWindow *const applyButton =
wxWindow::FindWindowById(wxID_APPLY, GetParent());
applyButton->Show(false);
if (mUniquePage && !mUniquePage->ShowsPreviewButton()) {
wxWindow *const previewButton =
wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
previewButton->Show(false);
}
#if defined(__WXGTK__)
@ -413,9 +413,9 @@ PrefsPanel * PrefsDialog::GetCurrentPanel()
}
}
void PrefsDialog::OnApply(wxCommandEvent & WXUNUSED(event))
void PrefsDialog::OnPreview(wxCommandEvent & WXUNUSED(event))
{
GetCurrentPanel()->Apply();
GetCurrentPanel()->Preview();
}
void PrefsDialog::OnHelp(wxCommandEvent & WXUNUSED(event))
@ -467,11 +467,14 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event))
for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
panel->Apply();
panel->Preview();
panel->Commit();
}
}
else
mUniquePage->Apply();
else {
mUniquePage->Preview();
mUniquePage->Commit();
}
gPrefs->Flush();
@ -583,7 +586,7 @@ void PrefsPanel::Cancel()
{
}
bool PrefsPanel::ShowsApplyButton()
bool PrefsPanel::ShowsPreviewButton()
{
return false;
}

View File

@ -59,7 +59,7 @@ class PrefsDialog /* not final */ : public wxDialogWrapper
void OnCategoryChange(wxCommandEvent & e);
void OnOK(wxCommandEvent & e);
void OnCancel(wxCommandEvent & e);
void OnApply(wxCommandEvent & e);
void OnPreview(wxCommandEvent & e);
void OnHelp(wxCommandEvent & e);
void OnTreeKeyDown(wxTreeEvent & e); // Used to dismiss the dialog when enter is pressed with focus on tree

View File

@ -53,11 +53,12 @@ class PrefsPanel /* not final */ : public wxPanelWrapper
virtual ~PrefsPanel();
// NEW virtuals
virtual bool Apply() = 0;
virtual bool Preview() {} // Make tentative changes
virtual bool Commit() = 0; // used to be called "Apply"
// If it returns True, the Apply button is added below the panel
// If it returns True, the Preview button is added below the panel
// Default returns false
virtual bool ShowsApplyButton();
virtual bool ShowsPreviewButton();
// If not empty string, the Help button is added below the panel
// Default returns empty string.

View File

@ -72,7 +72,7 @@ void ProjectsPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool ProjectsPrefs::Apply()
bool ProjectsPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -26,7 +26,7 @@ class ProjectsPrefs final : public PrefsPanel
public:
ProjectsPrefs(wxWindow * parent);
~ProjectsPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -210,7 +210,7 @@ void QualityPrefs::OnSampleRateChoice(wxCommandEvent & WXUNUSED(e))
mOtherSampleRate->Enable(sel == (int)mSampleRates->GetCount() - 1);
}
bool QualityPrefs::Apply()
bool QualityPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -29,7 +29,7 @@ class QualityPrefs final : public PrefsPanel
QualityPrefs(wxWindow * parent);
virtual ~QualityPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -207,7 +207,7 @@ void RecordingPrefs::PopulateOrExchange(ShuttleGui & S)
#endif
}
bool RecordingPrefs::Apply()
bool RecordingPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -26,7 +26,7 @@ class RecordingPrefs final : public PrefsPanel
public:
RecordingPrefs(wxWindow * parent);
virtual ~RecordingPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -41,16 +41,16 @@ SpectrumPrefs::SpectrumPrefs(wxWindow * parent, WaveTrack *wt)
{
if (mWt) {
SpectrogramSettings &settings = wt->GetSpectrogramSettings();
mDefaulted = (&SpectrogramSettings::defaults() == &settings);
mTempSettings = settings;
float minFreq, maxFreq;
wt->GetSpectrumBounds(&minFreq, &maxFreq);
mTempSettings.maxFreq = maxFreq;
mTempSettings.minFreq = minFreq;
mOrigDefaulted = mDefaulted = (&SpectrogramSettings::defaults() == &settings);
mTempSettings = mOrigSettings = settings;
wt->GetSpectrumBounds(&mOrigMin, &mOrigMax);
mTempSettings.maxFreq = mOrigMax;
mTempSettings.minFreq = mOrigMin;
mOrigDisplay = mWt->GetDisplay();
}
else {
mTempSettings = SpectrogramSettings::defaults();
mDefaulted = false;
mTempSettings = mOrigSettings = SpectrogramSettings::defaults();
mOrigDefaulted = mDefaulted = false;
}
const auto windowSize = mTempSettings.WindowSize();
@ -60,6 +60,8 @@ SpectrumPrefs::SpectrumPrefs(wxWindow * parent, WaveTrack *wt)
SpectrumPrefs::~SpectrumPrefs()
{
if (!mCommitted)
Rollback();
}
enum {
@ -365,7 +367,56 @@ bool SpectrumPrefs::Validate()
return result;
}
bool SpectrumPrefs::Apply()
void SpectrumPrefs::Rollback()
{
const auto partner =
mWt ?
// Assume linked track is wave or null
static_cast<WaveTrack*>(mWt->GetLink())
: nullptr;
if (mWt) {
if (mOrigDefaulted) {
mWt->SetSpectrogramSettings({});
mWt->SetSpectrumBounds(-1, -1);
if (partner) {
partner->SetSpectrogramSettings({});
partner->SetSpectrumBounds(-1, -1);
}
}
else {
SpectrogramSettings *pSettings =
&mWt->GetIndependentSpectrogramSettings();
mWt->SetSpectrumBounds(mOrigMin, mOrigMax);
*pSettings = mOrigSettings;
if (partner) {
pSettings = &partner->GetIndependentSpectrogramSettings();
partner->SetSpectrumBounds(mOrigMin, mOrigMax);
*pSettings = mOrigSettings;
}
}
}
if (!mWt || mOrigDefaulted) {
SpectrogramSettings *const pSettings = &SpectrogramSettings::defaults();
*pSettings = mOrigSettings;
}
const bool isOpenPage = this->IsShown();
if (mWt && isOpenPage) {
mWt->SetDisplay(mOrigDisplay);
if (partner)
partner->SetDisplay(mOrigDisplay);
}
if (isOpenPage) {
TrackPanel *const tp = ::GetActiveProject()->GetTrackPanel();
tp->UpdateVRulers();
tp->Refresh(false);
}
}
bool SpectrumPrefs::Preview()
{
if (!Validate())
return false;
@ -383,7 +434,6 @@ bool SpectrumPrefs::Apply()
mTempSettings.ConvertToActualWindowSizes();
SpectrogramSettings::Globals::Get().SavePrefs(); // always
if (mWt) {
if (mDefaulted) {
@ -411,7 +461,6 @@ bool SpectrumPrefs::Apply()
if (!mWt || mDefaulted) {
SpectrogramSettings *const pSettings = &SpectrogramSettings::defaults();
*pSettings = mTempSettings;
pSettings->SavePrefs();
}
mTempSettings.ConvertToEnumeratedWindowSizes();
@ -430,7 +479,17 @@ bool SpectrumPrefs::Apply()
return true;
}
bool SpectrumPrefs::ShowsApplyButton()
bool SpectrumPrefs::Commit()
{
mCommitted = true;
SpectrogramSettings::Globals::Get().SavePrefs(); // always
if (!mWt || mDefaulted) {
SpectrogramSettings *const pSettings = &SpectrogramSettings::defaults();
pSettings->SavePrefs();
}
}
bool SpectrumPrefs::ShowsPreviewButton()
{
return true;
}

View File

@ -26,6 +26,7 @@
#include <wx/window.h>
#include "../Experimental.h"
#include "../WaveTrack.h"
#include "PrefsPanel.h"
#include "SpectrogramSettings.h"
@ -43,8 +44,10 @@ class SpectrumPrefs final : public PrefsPanel
public:
SpectrumPrefs(wxWindow * parent, WaveTrack *wt);
virtual ~SpectrumPrefs();
bool Apply() override;
bool ShowsApplyButton() override;
bool Preview() override;
bool Commit() override;
void Rollback();
bool ShowsPreviewButton() override;
bool Validate() override;
wxString HelpPageName() override;
@ -62,7 +65,7 @@ class SpectrumPrefs final : public PrefsPanel
void EnableDisableSTFTOnlyControls();
WaveTrack *const mWt;
bool mDefaulted;
bool mDefaulted, mOrigDefaulted;
wxTextCtrl *mMinFreq;
wxTextCtrl *mMaxFreq;
@ -92,9 +95,13 @@ class SpectrumPrefs final : public PrefsPanel
wxCheckBox *mDefaultsCheckbox;
SpectrogramSettings mTempSettings;
SpectrogramSettings mTempSettings, mOrigSettings;
WaveTrack::WaveTrackDisplay mOrigDisplay;
float mOrigMin, mOrigMax;
bool mPopulating;
bool mCommitted{};
};
class SpectrumPrefsFactory final : public PrefsPanelFactory

View File

@ -186,7 +186,7 @@ void ThemePrefs::OnSaveThemeAsCode(wxCommandEvent & WXUNUSED(event))
}
/// Update the preferences stored on disk.
bool ThemePrefs::Apply()
bool ThemePrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -26,7 +26,7 @@ class ThemePrefs final : public PrefsPanel
public:
ThemePrefs(wxWindow * parent);
~ThemePrefs(void);
bool Apply() override;
bool Commit() override;
private:
void Populate();

View File

@ -101,7 +101,7 @@ void TracksBehaviorsPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool TracksBehaviorsPrefs::Apply()
bool TracksBehaviorsPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -23,7 +23,7 @@ class TracksBehaviorsPrefs final : public PrefsPanel
public:
TracksBehaviorsPrefs(wxWindow * parent);
~TracksBehaviorsPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
static const wxChar *ScrollingPreferenceKey();

View File

@ -158,7 +158,7 @@ void TracksPrefs::SetPinnedHeadPreference(bool value, bool flush)
gPrefs->Flush();
}
bool TracksPrefs::Apply()
bool TracksPrefs::Commit()
{
// Bug 1583: Clear the caching of the preference pinned state.
iPreferencePinned = -1;

View File

@ -27,7 +27,7 @@ class TracksPrefs final : public PrefsPanel
public:
TracksPrefs(wxWindow * parent);
~TracksPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
static bool GetPinnedHeadPreference();

View File

@ -79,7 +79,7 @@ void WarningsPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndStatic();
}
bool WarningsPrefs::Apply()
bool WarningsPrefs::Commit()
{
ShuttleGui S(this, eIsSavingToPrefs);
PopulateOrExchange(S);

View File

@ -26,7 +26,7 @@ class WarningsPrefs final : public PrefsPanel
public:
WarningsPrefs(wxWindow * parent);
~WarningsPrefs();
bool Apply() override;
bool Commit() override;
wxString HelpPageName() override;
private:

View File

@ -134,7 +134,7 @@ bool WaveformPrefs::Validate()
return result;
}
bool WaveformPrefs::Apply()
bool WaveformPrefs::Commit()
{
const bool isOpenPage = this->IsShown();
@ -191,7 +191,7 @@ bool WaveformPrefs::Apply()
return true;
}
bool WaveformPrefs::ShowsApplyButton()
bool WaveformPrefs::ShowsPreviewButton()
{
return true;
}

View File

@ -25,8 +25,8 @@ class WaveformPrefs final : public PrefsPanel
public:
WaveformPrefs(wxWindow * parent, WaveTrack *wt);
virtual ~WaveformPrefs();
bool Apply() override;
bool ShowsApplyButton() override;
bool Commit() override;
bool ShowsPreviewButton() override;
bool Validate() override;
private: