From 0c4418af2246992b6021f0af23e4f48363f8bd6c Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 21 Jun 2015 10:41:28 -0400 Subject: [PATCH 1/4] Boilerplate for empty waveform preferences, analogous to Spectra --- src/Makefile.am | 4 + src/TrackPanel.cpp | 6 + src/WaveTrack.cpp | 38 ++++ src/WaveTrack.h | 7 + src/prefs/PrefsDialog.cpp | 3 + src/prefs/WaveformPrefs.cpp | 209 ++++++++++++++++++ src/prefs/WaveformPrefs.h | 58 +++++ src/prefs/WaveformSettings.cpp | 86 +++++++ src/prefs/WaveformSettings.h | 46 ++++ win/Projects/Audacity/Audacity.vcxproj | 4 + .../Audacity/Audacity.vcxproj.filters | 12 + 11 files changed, 473 insertions(+) create mode 100644 src/prefs/WaveformPrefs.cpp create mode 100644 src/prefs/WaveformPrefs.h create mode 100644 src/prefs/WaveformSettings.cpp create mode 100644 src/prefs/WaveformSettings.h diff --git a/src/Makefile.am b/src/Makefile.am index 023f1ec44..f002e7977 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -488,6 +488,10 @@ audacity_SOURCES = \ prefs/TracksPrefs.h \ prefs/WarningsPrefs.cpp \ prefs/WarningsPrefs.h \ + prefs/WaveformPrefs.cpp \ + prefs/WaveformPrefs.h \ + prefs/WaveformSettings.cpp \ + prefs/WaveformSettings.h \ toolbars/ControlToolBar.cpp \ toolbars/ControlToolBar.h \ toolbars/DeviceToolBar.cpp \ diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 6e1dd1bcc..2cb031d05 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -220,6 +220,7 @@ is time to refresh some aspect of the screen. #include "prefs/PrefsDialog.h" #include "prefs/SpectrumPrefs.h" +#include "prefs/WaveformPrefs.h" #include "toolbars/ControlToolBar.h" #include "toolbars/ToolManager.h" @@ -8939,11 +8940,16 @@ public: void TrackPanel::OnViewSettings(wxCommandEvent &) { WaveTrack *const wt = static_cast(mPopupMenuTarget); + WaveformPrefsFactory waveformFactory(wt); SpectrumPrefsFactory spectrumFactory(wt); + PrefsDialog::Factories factories; + factories.push_back(&waveformFactory); factories.push_back(&spectrumFactory); + wxString title(wt->GetName() + wxT(": ")); ViewSettingsDialog dialog(this, title, factories); + if (0 != dialog.ShowModal()) // Redraw Refresh(false); diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index fa8f064e6..d3a7fa7f6 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -55,6 +55,7 @@ Track classes. #include "effects/TimeWarper.h" #include "prefs/SpectrumPrefs.h" +#include "prefs/WaveformPrefs.h" using std::max; @@ -76,6 +77,7 @@ WaveTrack *TrackFactory::NewWaveTrack(sampleFormat format, double rate) WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate): Track(projDirManager) , mpSpectrumSettings(0) + , mpWaveformSettings(0) { if (format == (sampleFormat)0) { @@ -110,6 +112,8 @@ WaveTrack::WaveTrack(WaveTrack &orig): , mpSpectrumSettings(orig.mpSpectrumSettings ? new SpectrogramSettings(*orig.mpSpectrumSettings) : 0 ) + , mpWaveformSettings(orig.mpWaveformSettings + ? new WaveformSettings(*orig.mpWaveformSettings) : 0) { mDisplay = FindDefaultViewMode(); mLastDisplay = -1; @@ -150,6 +154,8 @@ void WaveTrack::Merge(const Track &orig) mPan = wt.mPan; SetSpectrogramSettings(wt.mpSpectrumSettings ? new SpectrogramSettings(*wt.mpSpectrumSettings) : 0); + SetWaveformSettings + (wt.mpWaveformSettings ? new WaveformSettings(*wt.mpWaveformSettings) : 0); } Track::Merge(orig); } @@ -168,6 +174,7 @@ WaveTrack::~WaveTrack() delete [] mDisplayLocations; delete mpSpectrumSettings; + delete mpWaveformSettings; } double WaveTrack::GetOffset() const @@ -682,6 +689,37 @@ void WaveTrack::SetSpectrogramSettings(SpectrogramSettings *pSettings) } } +const WaveformSettings &WaveTrack::GetWaveformSettings() const +{ + if (mpWaveformSettings) + return *mpWaveformSettings; + else + return WaveformSettings::defaults(); +} + +WaveformSettings &WaveTrack::GetWaveformSettings() +{ + if (mpWaveformSettings) + return *mpWaveformSettings; + else + return WaveformSettings::defaults(); +} + +WaveformSettings &WaveTrack::GetIndependentWaveformSettings() +{ + if (!mpWaveformSettings) + mpWaveformSettings = new WaveformSettings(WaveformSettings::defaults()); + return *mpWaveformSettings; +} + +void WaveTrack::SetWaveformSettings(WaveformSettings *pSettings) +{ + if (mpWaveformSettings != pSettings) { + delete mpWaveformSettings; + mpWaveformSettings = pSettings; + } +} + // // ClearAndPaste() is a specialized version of HandleClear() // followed by Paste() and is used mostly by effects that diff --git a/src/WaveTrack.h b/src/WaveTrack.h index 7994b2a3e..6a327bb20 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -23,6 +23,7 @@ #include class SpectrogramSettings; +class WaveformSettings; class TimeWarper; // @@ -151,6 +152,11 @@ class AUDACITY_DLL_API WaveTrack: public Track { SpectrogramSettings &GetIndependentSpectrogramSettings(); void SetSpectrogramSettings(SpectrogramSettings *pSettings); + const WaveformSettings &GetWaveformSettings() const; + WaveformSettings &GetWaveformSettings(); + WaveformSettings &GetIndependentWaveformSettings(); + void SetWaveformSettings(WaveformSettings *pSettings); + // // High-level editing // @@ -495,6 +501,7 @@ class AUDACITY_DLL_API WaveTrack: public Track { int mAutoSaveIdent; SpectrogramSettings *mpSpectrumSettings; + WaveformSettings *mpWaveformSettings; }; // This is meant to be a short-lived object, during whose lifetime, diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 71a63fe5b..39cc0a56c 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -64,6 +64,7 @@ #include "ThemePrefs.h" #include "TracksPrefs.h" #include "WarningsPrefs.h" +#include "WaveformPrefs.h" #include "ExtImportPrefs.h" #ifdef EXPERIMENTAL_MIDI_OUT @@ -131,6 +132,7 @@ PrefsDialog::Factories #if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) static LibraryPrefsFactory libraryPrefsFactory; #endif + static WaveformPrefsFactory waveformPrefsFactory; static SpectrumPrefsFactory spectrumPrefsFactory; static DirectoriesPrefsFactory directoriesPrefsFactory; static WarningsPrefsFactory warningsPrefsFactory; @@ -161,6 +163,7 @@ PrefsDialog::Factories #if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || !defined(DISABLE_DYNAMIC_LOADING_LAME) &libraryPrefsFactory, #endif + &waveformPrefsFactory, &spectrumPrefsFactory, &directoriesPrefsFactory, &warningsPrefsFactory, diff --git a/src/prefs/WaveformPrefs.cpp b/src/prefs/WaveformPrefs.cpp new file mode 100644 index 000000000..733f62f0f --- /dev/null +++ b/src/prefs/WaveformPrefs.cpp @@ -0,0 +1,209 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformPrefs.cpp + +Paul Licameli + +*******************************************************************//** + +\class WaveformPrefs +\brief A PrefsPanel for spectrum settings. + +*//*******************************************************************/ + +#include "../Audacity.h" +#include "WaveformPrefs.h" + +#include + +#include "../Project.h" +#include "../TrackPanel.h" +#include "../ShuttleGUI.h" + +WaveformPrefs::WaveformPrefs(wxWindow * parent, WaveTrack *wt) +: PrefsPanel(parent, _("Waveforms")) +, mWt(wt) +, mPopulating(false) +{ + if (mWt) { + WaveformSettings &settings = wt->GetWaveformSettings(); + mDefaulted = (&WaveformSettings::defaults() == &settings); + mTempSettings = settings; + } + else { + mTempSettings = WaveformSettings::defaults(); + mDefaulted = false; + } + + Populate(); +} + +WaveformPrefs::~WaveformPrefs() +{ +} + +enum { + ID_DEFAULTS = 10001, + ID_APPLY, +}; + +void WaveformPrefs::Populate() +{ + // Create control objects + + //------------------------- Main section -------------------- + // Now construct the GUI itself. + ShuttleGui S(this, eIsCreating); + PopulateOrExchange(S); + // ----------------------- End of main section -------------- +} + +void WaveformPrefs::PopulateOrExchange(ShuttleGui & S) +{ + mPopulating = true; + + S.SetBorder(2); + + // S.StartStatic(_("Track Settings")); + { + mDefaultsCheckbox = 0; + if (mWt) { + mDefaultsCheckbox = S.Id(ID_DEFAULTS).TieCheckBox(_("Defaults"), mDefaulted); + } + + S.StartStatic(_("Display")); + { + S.StartTwoColumn(); + { + } + S.EndTwoColumn(); + } + S.EndStatic(); + } + // S.EndStatic(); + + /* + S.StartStatic(_("Global settings")); + { + } + S.EndStatic(); + */ + + S.StartMultiColumn(2, wxALIGN_RIGHT); + { + S.Id(ID_APPLY).AddButton(_("Appl&y")); + } + S.EndMultiColumn(); + + mPopulating = false; +} + +bool WaveformPrefs::Validate() +{ + // Do checking for whole numbers + + // ToDo: use wxIntegerValidator when available + + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + // Delegate range checking to WaveformSettings class + const bool result = mTempSettings.Validate(false); + return result; +} + +bool WaveformPrefs::Apply() +{ + const bool isOpenPage = this->IsShown(); + + WaveTrack *const partner = + mWt ? static_cast(mWt->GetLink()) : 0; + + ShuttleGui S(this, eIsGettingFromDialog); + PopulateOrExchange(S); + + WaveformSettings::Globals::Get().SavePrefs(); + + if (mWt) { + if (mDefaulted) { + mWt->SetWaveformSettings(NULL); + if (partner) + partner->SetWaveformSettings(NULL); + } + else { + WaveformSettings *pSettings = + &mWt->GetIndependentWaveformSettings(); + *pSettings = mTempSettings; + if (partner) { + pSettings = &partner->GetIndependentWaveformSettings(); + *pSettings = mTempSettings; + } + } + } + + if (!mWt || mDefaulted) { + WaveformSettings *const pSettings = + &WaveformSettings::defaults(); + *pSettings = mTempSettings; + pSettings->SavePrefs(); + } + + if (mWt && isOpenPage) { + // Future: open page will determine view type + /* + mWt->SetDisplay(WaveTrack::Waveform); + if (partner) + partner->SetDisplay(WaveTrack::Waveform); + */ + } + + return true; +} + +void WaveformPrefs::OnControl(wxCommandEvent&) +{ + // Common routine for most controls + // If any per-track setting is changed, break the association with defaults + // Skip this, and View Settings... will be able to change defaults instead + // when the checkbox is on, as in the original design. + + if (mDefaultsCheckbox && !mPopulating) { + mDefaulted = false; + mDefaultsCheckbox->SetValue(false); + } +} + +void WaveformPrefs::OnDefaults(wxCommandEvent &) +{ + if (mDefaultsCheckbox->IsChecked()) { + mTempSettings = WaveformSettings::defaults(); + mDefaulted = true; + ShuttleGui S(this, eIsSettingToDialog); + PopulateOrExchange(S); + } +} + +void WaveformPrefs::OnApply(wxCommandEvent &) +{ + if (Validate()) { + Apply(); + ::GetActiveProject()->GetTrackPanel()->Refresh(false); + } +} + +BEGIN_EVENT_TABLE(WaveformPrefs, PrefsPanel) +EVT_CHECKBOX(ID_DEFAULTS, WaveformPrefs::OnDefaults) +EVT_BUTTON(ID_APPLY, WaveformPrefs::OnApply) +END_EVENT_TABLE() + +WaveformPrefsFactory::WaveformPrefsFactory(WaveTrack *wt) +: mWt(wt) +{ +} + +PrefsPanel *WaveformPrefsFactory::Create(wxWindow *parent) +{ + return new WaveformPrefs(parent, mWt); +} diff --git a/src/prefs/WaveformPrefs.h b/src/prefs/WaveformPrefs.h new file mode 100644 index 000000000..b25042333 --- /dev/null +++ b/src/prefs/WaveformPrefs.h @@ -0,0 +1,58 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformPrefs.h + +Paul Licameli + +**********************************************************************/ + + +#ifndef __AUDACITY_WAVEFORM_PREFS__ +#define __AUDACITY_WAVEFORM_PREFS__ + +#include "PrefsPanel.h" +#include "WaveformSettings.h" + +class ShuttleGui; +class WaveTrack; +class wxCheckBox; + +class WaveformPrefs :public PrefsPanel +{ +public: + WaveformPrefs(wxWindow * parent, WaveTrack *wt); + virtual ~WaveformPrefs(); + virtual bool Apply(); + virtual bool Validate(); + +private: + void Populate(); + void PopulateOrExchange(ShuttleGui & S); + + void OnControl(wxCommandEvent&); + void OnDefaults(wxCommandEvent&); + void OnApply(wxCommandEvent &); + DECLARE_EVENT_TABLE() + + WaveTrack *const mWt; + bool mDefaulted; + + wxCheckBox *mDefaultsCheckbox; + + WaveformSettings mTempSettings; + + bool mPopulating; +}; + +class WaveformPrefsFactory : public PrefsPanelFactory +{ +public: + explicit WaveformPrefsFactory(WaveTrack *wt = 0); + virtual PrefsPanel *Create(wxWindow *parent); + +private: + WaveTrack *const mWt; +}; +#endif diff --git a/src/prefs/WaveformSettings.cpp b/src/prefs/WaveformSettings.cpp new file mode 100644 index 000000000..7a6324284 --- /dev/null +++ b/src/prefs/WaveformSettings.cpp @@ -0,0 +1,86 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformSettings.cpp + +Paul Licameli + +*******************************************************************//** + +\class WaveformSettings +\brief Waveform settings, either for one track or as defaults. + +*//*******************************************************************/ + +#include "../Audacity.h" +#include "WaveformSettings.h" + +WaveformSettings::Globals::Globals() +{ + LoadPrefs(); +} + +void WaveformSettings::Globals::SavePrefs() +{ +} + +void WaveformSettings::Globals::LoadPrefs() +{ +} + +WaveformSettings::Globals +&WaveformSettings::Globals::Get() +{ + static Globals instance; + return instance; +} + +WaveformSettings::WaveformSettings() +{ + LoadPrefs(); +} + +WaveformSettings::WaveformSettings(const WaveformSettings &other) +{ +} + +WaveformSettings &WaveformSettings::operator= (const WaveformSettings &other) +{ + if (this != &other) { + } + return *this; +} + +WaveformSettings& WaveformSettings::defaults() +{ + static WaveformSettings instance; + return instance; +} + +bool WaveformSettings::Validate(bool quiet) +{ + quiet; + + return true; +} + +void WaveformSettings::LoadPrefs() +{ + // Enforce legal values + Validate(true); + + Update(); +} + +void WaveformSettings::SavePrefs() +{ +} + +void WaveformSettings::Update() +{ +} + +WaveformSettings::~WaveformSettings() +{ +} diff --git a/src/prefs/WaveformSettings.h b/src/prefs/WaveformSettings.h new file mode 100644 index 000000000..672daf825 --- /dev/null +++ b/src/prefs/WaveformSettings.h @@ -0,0 +1,46 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +WaveformSettings.h + +Paul Licameli + +**********************************************************************/ + +#ifndef __AUDACITY_WAVEFORM_SETTINGS__ +#define __AUDACITY_WAVEFORM_SETTINGS__ + +class WaveformSettings +{ +public: + + // Singleton for settings that are not per-track + class Globals + { + public: + static Globals &Get(); + void SavePrefs(); + + private: + Globals(); + void LoadPrefs(); + }; + + static WaveformSettings &defaults(); + WaveformSettings(); + WaveformSettings(const WaveformSettings &other); + WaveformSettings& operator= (const WaveformSettings &other); + ~WaveformSettings(); + + bool IsDefault() const + { + return this == &defaults(); + } + + bool Validate(bool quiet); + void LoadPrefs(); + void SavePrefs(); + void Update(); +}; +#endif diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 30aeb05e2..5c18d208c 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -287,6 +287,8 @@ + + @@ -535,6 +537,8 @@ + + diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index e767fbf09..ada5c9291 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -843,6 +843,12 @@ src/prefs + + src/prefs + + + src/prefs + @@ -1688,6 +1694,12 @@ src + + src/prefs + + + src/prefs + From 5b72b1f23b6019d6e3706e2ca175094bd54abc98 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 21 Jun 2015 11:54:49 -0400 Subject: [PATCH 2/4] Open the appropriate initial page in View Settings dialog --- src/TrackPanel.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 2cb031d05..74e01a382 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -8921,20 +8921,24 @@ class ViewSettingsDialog : public PrefsDialog { public: ViewSettingsDialog - (wxWindow *parent, const wxString &title, PrefsDialog::Factories &factories) + (wxWindow *parent, const wxString &title, PrefsDialog::Factories &factories, + int page) : PrefsDialog(parent, title, factories) + , mPage(page) { } virtual long GetPreferredPage() { - // Future: choose Spectrum or Waveform page - return 0; + return mPage; } virtual void SavePreferredPage() { } + +private: + const int mPage; }; void TrackPanel::OnViewSettings(wxCommandEvent &) @@ -8943,12 +8947,15 @@ void TrackPanel::OnViewSettings(wxCommandEvent &) WaveformPrefsFactory waveformFactory(wt); SpectrumPrefsFactory spectrumFactory(wt); + // Put Waveform page first PrefsDialog::Factories factories; factories.push_back(&waveformFactory); factories.push_back(&spectrumFactory); + const int page = (wt->GetDisplay() == WaveTrack::Spectrum) + ? 1 : 0; wxString title(wt->GetName() + wxT(": ")); - ViewSettingsDialog dialog(this, title, factories); + ViewSettingsDialog dialog(this, title, factories, page); if (0 != dialog.ShowModal()) // Redraw From 5abbd463b26076fd0a6184794663cffd0c7f270c Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 21 Jun 2015 20:03:15 -0400 Subject: [PATCH 3/4] Waveform dB is not a track type. Logarithmic is a Wavetrack scale type... ... Also removed one line from the track control drop-down, and changed accelerators to more mnemonic choices. Also the open page of View Settings... determines track view type after OK --- src/AudacityApp.cpp | 2 + src/TrackArtist.cpp | 204 ++++++++++++++++---------------- src/TrackArtist.h | 2 +- src/TrackPanel.cpp | 50 +++----- src/WaveTrack.cpp | 19 +-- src/WaveTrack.h | 22 ++-- src/effects/nyquist/Nyquist.cpp | 3 +- src/prefs/TracksPrefs.cpp | 5 +- src/prefs/WaveformPrefs.cpp | 13 +- src/prefs/WaveformPrefs.h | 2 + src/prefs/WaveformSettings.cpp | 43 +++++++ src/prefs/WaveformSettings.h | 17 +++ 12 files changed, 221 insertions(+), 161 deletions(-) diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 68deb14f5..b2bdb7cfc 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -94,6 +94,7 @@ It handles initialization and termination by subclassing wxApp. #include "widgets/ErrorDialog.h" #include "prefs/DirectoriesPrefs.h" #include "prefs/SpectrogramSettings.h" +#include "prefs/WaveformSettings.h" //temporarilly commented out till it is added to all projects //#include "Profiler.h" @@ -1017,6 +1018,7 @@ void AudacityApp::InitLang( const wxString & lang ) // Some static arrays unconnected with any project want to be informed of language changes. SpectrogramSettings::InvalidateNames(); + WaveformSettings::InvalidateNames(); } void AudacityApp::OnFatalException() diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index 2d6d07296..bf76082a0 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -175,6 +175,7 @@ audio tracks. #include "TimeTrack.h" #include "Prefs.h" #include "prefs/SpectrogramSettings.h" +#include "prefs/WaveformSettings.h" #include "Sequence.h" #include "Spectrum.h" #include "ViewInfo.h" @@ -457,13 +458,9 @@ void TrackArtist::DrawTrack(const Track * t, bool muted = (hasSolo || t->GetMute()) && !t->GetSolo(); switch (wt->GetDisplay()) { - case WaveTrack::WaveformDisplay: + case WaveTrack::Waveform: DrawWaveform(wt, dc, rect, selectedRegion, zoomInfo, - drawEnvelope, bigPoints, drawSliders, false, muted); - break; - case WaveTrack::WaveformDBDisplay: - DrawWaveform(wt, dc, rect, selectedRegion, zoomInfo, - drawEnvelope, bigPoints, drawSliders, true, muted); + drawEnvelope, bigPoints, drawSliders, muted); break; case WaveTrack::Spectrum: DrawSpectrum(wt, dc, rect, selectedRegion, zoomInfo); @@ -685,107 +682,115 @@ void TrackArtist::UpdateVRuler(Track *t, wxRect & rect) // The ruler needs a bevelled surround. if (t->GetKind() == Track::Wave) { WaveTrack *wt = static_cast(t); - int display = wt->GetDisplay(); - if (display == WaveTrack::WaveformDisplay) { - // Waveform + const int display = wt->GetDisplay(); - float min, max; - wt->GetDisplayBounds(&min, &max); - if(wt->GetLastDisplay()==WaveTrack::WaveformDBDisplay) - { - // do a translation into the WaveTrack::WaveformDisplay space - wt->SetDisplay(WaveTrack::WaveformDisplay); // this makes the last display not WaveformDBDisplay - float sign = (min >= 0 ? 1 : -1); - if (min != 0.) { - min = DB_TO_LINEAR(fabs(min)*mdBrange - mdBrange); - if (min < 0.0) - min = 0.0; - min *= sign; - } - sign = (max >= 0 ? 1 : -1); + if (display == WaveTrack::Waveform) { + WaveformSettings::ScaleType scaleType = + wt->GetWaveformSettings().scaleType; - if (max != 0.) { - max = DB_TO_LINEAR(fabs(max)*mdBrange - mdBrange); - if (max < 0.0) - max = 0.0; - max *= sign; - } - wt->SetDisplayBounds(min, max); - } + if (scaleType == WaveformSettings::stLinear) { + // Waveform - vruler->SetBounds(rect.x, rect.y+1, rect.x + rect.width, rect.y + rect.height-1); - vruler->SetOrientation(wxVERTICAL); - vruler->SetRange(max, min); - vruler->SetFormat(Ruler::RealFormat); - vruler->SetUnits(wxT("")); - vruler->SetLabelEdges(false); - vruler->SetLog(false); - } - else if (display == WaveTrack::WaveformDBDisplay) { - // Waveform (db) + float min, max; + wt->GetDisplayBounds(&min, &max); + if (wt->GetLastScaleType() != scaleType) + { + // do a translation into the linear space + wt->SetLastScaleType(scaleType); + float sign = (min >= 0 ? 1 : -1); + if (min != 0.) { + min = DB_TO_LINEAR(fabs(min)*mdBrange - mdBrange); + if (min < 0.0) + min = 0.0; + min *= sign; + } + sign = (max >= 0 ? 1 : -1); - vruler->SetUnits(wxT("")); - - float min, max; - wt->GetDisplayBounds(&min, &max); - - if(wt->GetLastDisplay()==WaveTrack::WaveformDisplay) - { - // do a translation into the WaveTrack::WaveformDBDisplay space - wt->SetDisplay(WaveTrack::WaveformDBDisplay); // this makes the last display not WaveformDisplay - float sign = (min >= 0 ? 1 : -1); - if (min != 0.) { - min = (LINEAR_TO_DB(fabs(min)) + mdBrange) / mdBrange; - if (min < 0.0) - min = 0.0; - min *= sign; - } - sign = (max >= 0 ? 1 : -1); - - if (max != 0.) { - max = (LINEAR_TO_DB(fabs(max)) + mdBrange) / mdBrange; - if (max < 0.0) - max = 0.0; - max *= sign; - } - wt->SetDisplayBounds(min, max); - } - - if (max > 0) { - int top = 0; - float topval = 0; - int bot = rect.height; - float botval = -mdBrange; - - if (min < 0) { - bot = top + (int)((max / (max-min))*(bot-top)); - min = 0; + if (max != 0.) { + max = DB_TO_LINEAR(fabs(max)*mdBrange - mdBrange); + if (max < 0.0) + max = 0.0; + max *= sign; + } + wt->SetDisplayBounds(min, max); } - if (max > 1) { - top += (int)((max-1)/(max-min) * (bot-top)); - max = 1; - } - - if (max < 1 && max > 0) - topval = -((1-max)*mdBrange); - - if (min > 0) { - botval = -((1-min)*mdBrange); - } - - vruler->SetBounds(rect.x, rect.y+top+1, rect.x + rect.width, rect.y + bot-1); + vruler->SetBounds(rect.x, rect.y + 1, rect.x + rect.width, rect.y + rect.height - 1); vruler->SetOrientation(wxVERTICAL); - vruler->SetRange(topval, botval); - } - else - vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it? - vruler->SetFormat(Ruler::RealLogFormat); - vruler->SetLabelEdges(true); - vruler->SetLog(false); + vruler->SetRange(max, min); + vruler->SetFormat(Ruler::RealFormat); + vruler->SetUnits(wxT("")); + vruler->SetLabelEdges(false); + vruler->SetLog(false); + } + else { + wxASSERT(scaleType == WaveformSettings::stLogarithmic); + scaleType = WaveformSettings::stLogarithmic; + + vruler->SetUnits(wxT("")); + + float min, max; + wt->GetDisplayBounds(&min, &max); + + if (wt->GetLastScaleType() != scaleType) + { + // do a translation into the dB space + wt->SetLastScaleType(scaleType); + float sign = (min >= 0 ? 1 : -1); + if (min != 0.) { + min = (LINEAR_TO_DB(fabs(min)) + mdBrange) / mdBrange; + if (min < 0.0) + min = 0.0; + min *= sign; + } + sign = (max >= 0 ? 1 : -1); + + if (max != 0.) { + max = (LINEAR_TO_DB(fabs(max)) + mdBrange) / mdBrange; + if (max < 0.0) + max = 0.0; + max *= sign; + } + wt->SetDisplayBounds(min, max); + } + + if (max > 0) { + int top = 0; + float topval = 0; + int bot = rect.height; + float botval = -mdBrange; + + if (min < 0) { + bot = top + (int)((max / (max - min))*(bot - top)); + min = 0; + } + + if (max > 1) { + top += (int)((max - 1) / (max - min) * (bot - top)); + max = 1; + } + + if (max < 1 && max > 0) + topval = -((1 - max)*mdBrange); + + if (min > 0) { + botval = -((1 - min)*mdBrange); + } + + vruler->SetBounds(rect.x, rect.y + top + 1, rect.x + rect.width, rect.y + bot - 1); + vruler->SetOrientation(wxVERTICAL); + vruler->SetRange(topval, botval); + } + else + vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it? + vruler->SetFormat(Ruler::RealLogFormat); + vruler->SetLabelEdges(true); + vruler->SetLog(false); + } } - else if (display == WaveTrack::Spectrum) { + else { + wxASSERT(display == WaveTrack::Spectrum); switch (wt->GetSpectrogramSettings().scaleType) { default: wxASSERT(false); @@ -1416,9 +1421,10 @@ void TrackArtist::DrawWaveform(WaveTrack *track, bool drawEnvelope, bool bigPoints, bool drawSliders, - bool dB, bool muted) { + const bool dB = !track->GetWaveformSettings().isLinear(); + DrawBackgroundWithSelection(&dc, rect, track, blankSelectedBrush, blankBrush, selectedRegion, zoomInfo); diff --git a/src/TrackArtist.h b/src/TrackArtist.h index ebb280e3d..b6876d9f6 100644 --- a/src/TrackArtist.h +++ b/src/TrackArtist.h @@ -97,7 +97,7 @@ class AUDACITY_DLL_API TrackArtist { wxDC & dc, const wxRect & rect, const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo, bool drawEnvelope, bool bigPoints, bool drawSliders, - bool dB, bool muted); + bool muted); void DrawSpectrum(WaveTrack *track, wxDC & dc, const wxRect & rect, diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 74e01a382..41a12f4d6 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -327,7 +327,6 @@ enum { OnFloatID, // <--- OnWaveformID, - OnWaveformDBID, OnSpectrumID, OnViewSettingsID, @@ -723,10 +722,9 @@ void TrackPanel::BuildMenus(void) /* build the pop-down menu used on wave (sampled audio) tracks */ mWaveTrackMenu = new wxMenu(); BuildCommonDropMenuItems(mWaveTrackMenu); // does name, up/down etc - mWaveTrackMenu->Append(OnWaveformID, _("Wa&veform")); - mWaveTrackMenu->Append(OnWaveformDBID, _("&Waveform (dB)")); + mWaveTrackMenu->Append(OnWaveformID, _("&Waveform")); mWaveTrackMenu->Append(OnSpectrumID, _("&Spectrum")); - mWaveTrackMenu->Append(OnViewSettingsID, _("View& Settings...")); // PRL: all the other letters already taken for accelerators! + mWaveTrackMenu->Append(OnViewSettingsID, _("&View Settings...")); mWaveTrackMenu->AppendSeparator(); mWaveTrackMenu->AppendRadioItem(OnChannelMonoID, _("&Mono")); @@ -3776,10 +3774,8 @@ void TrackPanel::ForwardEventToWaveTrackEnvelope(wxMouseEvent & event) // This asks which one is in use. (ie, Wave, Spectrum, etc) int display = pwavetrack->GetDisplay(); - // AS: If we're using the right type of display for envelope operations - // ie one of the Wave displays - const bool dB = (display == WaveTrack::WaveformDBDisplay); - if (dB || (display == WaveTrack::WaveformDisplay)) { + if (display == WaveTrack::Waveform) { + const bool dB = !pwavetrack->GetWaveformSettings().isLinear(); bool needUpdate; // AS: Then forward our mouse event to the envelope. @@ -4850,20 +4846,12 @@ bool TrackPanel::IsSampleEditingPossible( wxMouseEvent &event, Track * t ) //If we aren't displaying the waveform, Display a message dialog WaveTrack *const wt = static_cast(t); const int display = wt->GetDisplay(); -#if 1 - if (!(WaveTrack::WaveformDisplay == display || - WaveTrack::WaveformDBDisplay == display)) - { - wxMessageBox(_("To use Draw, choose 'Waveform' or 'Waveform dB' in the Track Drop-down Menu."), wxT("Draw Tool")); - return false; - } -#else - if(WaveTrack::WaveformDisplay != display) + + if (WaveTrack::Waveform != display) { wxMessageBox(_("To use Draw, choose 'Waveform' in the Track Drop-down Menu."), wxT("Draw Tool")); return false; } -#endif bool showPoints; { @@ -4901,7 +4889,7 @@ float TrackPanel::FindSampleEditingLevel(wxMouseEvent &event, double t0) const int y = event.m_y - mDrawingTrackTop; const int height = mDrawingTrack->GetHeight(); - const bool dB = (WaveTrack::WaveformDBDisplay == mDrawingTrack->GetDisplay()); + const bool dB = !mDrawingTrack->GetWaveformSettings().isLinear(); float newLevel = ::ValueOfPixel(y, height, false, dB, mdBr, zoomMin, zoomMax); //Take the envelope into account @@ -6909,16 +6897,14 @@ bool TrackPanel::HitTestEnvelope(Track *track, wxRect &r, wxMouseEvent & event) if (!envelope) return false; - int displayType = wavetrack->GetDisplay(); + const int displayType = wavetrack->GetDisplay(); // Not an envelope hit, unless we're using a type of wavetrack display // suitable for envelopes operations, ie one of the Wave displays. - const bool dB = (displayType == WaveTrack::WaveformDBDisplay); - if (! - (dB || (displayType == WaveTrack::WaveformDisplay)) - ) + if ( displayType != WaveTrack::Waveform) return false; // No envelope, not a hit, so return. // Get envelope point, range 0.0 to 1.0 + const bool dB = !wavetrack->GetWaveformSettings().isLinear(); // Convert x to time. const double envValue = envelope->GetValue(mViewInfo->PositionToTime(event.m_x, r.x)); @@ -6976,10 +6962,10 @@ bool TrackPanel::HitTestSamples(Track *track, wxRect &r, wxMouseEvent & event) //Get rate in order to calculate the critical zoom threshold double rate = wavetrack->GetRate(); - int displayType = wavetrack->GetDisplay(); - bool dB = (WaveTrack::WaveformDBDisplay == displayType); - if (!(WaveTrack::WaveformDisplay == displayType || dB)) + const int displayType = wavetrack->GetDisplay(); + if (WaveTrack::Waveform != displayType) return false; // Not a wave, so return. + const bool dB = !wavetrack->GetWaveformSettings().isLinear(); const double tt = mViewInfo->PositionToTime(event.m_x, r.x); if (!SampleResolutionTest(*mViewInfo, wavetrack, tt, rate)) @@ -8449,11 +8435,9 @@ void TrackPanel::OnTrackMenu(Track *t) theMenu->Enable(OnChannelLeftID, !t->GetLinked()); theMenu->Enable(OnChannelRightID, !t->GetLinked()); - int display = ((WaveTrack *) t)->GetDisplay(); + const int display = static_cast(t)->GetDisplay(); - theMenu->Enable(OnWaveformID, display != WaveTrack::WaveformDisplay); - theMenu->Enable(OnWaveformDBID, - display != WaveTrack::WaveformDBDisplay); + theMenu->Enable(OnWaveformID, display != WaveTrack::Waveform); theMenu->Enable(OnSpectrumID, display != WaveTrack::Spectrum); theMenu->Enable(OnViewSettingsID, true); @@ -8977,9 +8961,7 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) switch (idInt) { default: case OnWaveformID: - id = WaveTrack::WaveformDisplay; break; - case OnWaveformDBID: - id = WaveTrack::WaveformDBDisplay; break; + id = WaveTrack::Waveform; break; case OnSpectrumID: id = WaveTrack::Spectrum; break; } diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index d3a7fa7f6..ba6ac693c 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -74,7 +74,7 @@ WaveTrack *TrackFactory::NewWaveTrack(sampleFormat format, double rate) return new WaveTrack(mDirManager, format, rate); } -WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate): +WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rate) : Track(projDirManager) , mpSpectrumSettings(0) , mpWaveformSettings(0) @@ -103,7 +103,7 @@ WaveTrack::WaveTrack(DirManager *projDirManager, sampleFormat format, double rat mDisplayNumLocations = 0; mDisplayLocations = NULL; mDisplayNumLocationsAllocated = 0; - mLastDisplay = -1; + mLastScaleType = -1; mAutoSaveIdent = 0; } @@ -116,7 +116,7 @@ WaveTrack::WaveTrack(WaveTrack &orig): ? new WaveformSettings(*orig.mpWaveformSettings) : 0) { mDisplay = FindDefaultViewMode(); - mLastDisplay = -1; + mLastScaleType = -1; mLegacyProjectFileOffset = 0; @@ -211,7 +211,7 @@ WaveTrack::WaveTrackDisplay WaveTrack::FindDefaultViewMode() if (viewMode < 0) { int oldMode; gPrefs->Read(wxT("/GUI/DefaultViewMode"), &oldMode, - int(WaveTrack::WaveformDisplay)); + int(WaveTrack::Waveform)); viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode); } @@ -238,9 +238,12 @@ WaveTrack::ConvertLegacyDisplayValue(int oldValue) switch (oldValue) { default: case Waveform: - newValue = WaveTrack::WaveformDisplay; break; + case WaveformDB: + newValue = WaveTrack::Waveform; break; + /* case WaveformDB: newValue = WaveTrack::WaveformDBDisplay; break; + */ case Spectrogram: case SpectrogramLogF: case Pitch: @@ -261,8 +264,7 @@ WaveTrack::ValidateWaveTrackDisplay(WaveTrackDisplay display) { switch (display) { // non-obsolete codes - case WaveformDisplay: - case WaveformDBDisplay: + case Waveform: case Spectrum: return display; @@ -273,6 +275,9 @@ WaveTrack::ValidateWaveTrackDisplay(WaveTrackDisplay display) case obsolete4: // was PitchDisplay return Spectrum; + case obsolete5: // was WaveformDBDisplay + return Waveform; + // codes out of bounds (from future prefs files?) default: return MinDisplay; diff --git a/src/WaveTrack.h b/src/WaveTrack.h index 6a327bb20..13483cd37 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -420,10 +420,11 @@ class AUDACITY_DLL_API WaveTrack: public Track { // DO NOT REORDER OLD VALUES! Replace obsoletes with placeholders. - WaveformDisplay = 0, - MinDisplay = WaveformDisplay, + Waveform = 0, + MinDisplay = Waveform, + + obsolete5, // was WaveformDBDisplay - WaveformDBDisplay, Spectrum, obsolete1, // was SpectrumLogDisplay @@ -447,14 +448,15 @@ class AUDACITY_DLL_API WaveTrack: public Track { // Handle restriction of range of values of the enum from future versions static WaveTrackDisplay ValidateWaveTrackDisplay(WaveTrackDisplay display); - void SetDisplay(WaveTrackDisplay display) { - if (mDisplay < Spectrum) - // remember last display mode for wave and wavedb so they can remap the vertical ruler - mLastDisplay = mDisplay; - mDisplay = display; + int GetLastScaleType() { return mLastScaleType; } + void SetLastScaleType(int scaleType) + { + // remember last display mode for wave and wavedb so vertical ruler can remap + mLastScaleType = scaleType; } + WaveTrackDisplay GetDisplay() const { return mDisplay; } - int GetLastDisplay() {return mLastDisplay;} + void SetDisplay(WaveTrackDisplay display) { mDisplay = display; } void GetDisplayBounds(float *min, float *max); void SetDisplayBounds(float min, float max); @@ -480,7 +482,7 @@ class AUDACITY_DLL_API WaveTrack: public Track { float mDisplayMin; float mDisplayMax; WaveTrackDisplay mDisplay; - int mLastDisplay; // last display mode + int mLastScaleType; // last scale type choice int mDisplayNumLocations; int mDisplayNumLocationsAllocated; Location* mDisplayLocations; diff --git a/src/effects/nyquist/Nyquist.cpp b/src/effects/nyquist/Nyquist.cpp index 336d16a29..580d0d178 100644 --- a/src/effects/nyquist/Nyquist.cpp +++ b/src/effects/nyquist/Nyquist.cpp @@ -789,8 +789,7 @@ bool NyquistEffect::ProcessOne() type = wxT("wave"); switch (((WaveTrack *) mCurTrack[0])->GetDisplay()) { - case WaveTrack::WaveformDisplay: view = wxT("\"Waveform\""); break; - case WaveTrack::WaveformDBDisplay: view = wxT("\"Waveform (dB)\""); break; + case WaveTrack::Waveform: view = wxT("\"Waveform\""); break; case WaveTrack::Spectrum: view = wxT("\"Spectrum\""); break; default: view = wxT("NIL"); break; } diff --git a/src/prefs/TracksPrefs.cpp b/src/prefs/TracksPrefs.cpp index 1bbccf5d2..1af1c7e4a 100644 --- a/src/prefs/TracksPrefs.cpp +++ b/src/prefs/TracksPrefs.cpp @@ -60,10 +60,7 @@ void TracksPrefs::Populate() // we don't display them by increasing integer values. mViewChoices.Add(_("Waveform")); - mViewCodes.Add(int(WaveTrack::WaveformDisplay)); - - mViewChoices.Add(_("Waveform (dB)")); - mViewCodes.Add(int(WaveTrack::WaveformDBDisplay)); + mViewCodes.Add(int(WaveTrack::Waveform)); mViewChoices.Add(_("Spectrum")); mViewCodes.Add(WaveTrack::Spectrum); diff --git a/src/prefs/WaveformPrefs.cpp b/src/prefs/WaveformPrefs.cpp index 733f62f0f..41fc6f385 100644 --- a/src/prefs/WaveformPrefs.cpp +++ b/src/prefs/WaveformPrefs.cpp @@ -47,11 +47,13 @@ WaveformPrefs::~WaveformPrefs() enum { ID_DEFAULTS = 10001, ID_APPLY, + + ID_SCALE, }; void WaveformPrefs::Populate() { - // Create control objects + mScaleChoices = WaveformSettings::GetScaleNames(); //------------------------- Main section -------------------- // Now construct the GUI itself. @@ -77,6 +79,9 @@ void WaveformPrefs::PopulateOrExchange(ShuttleGui & S) { S.StartTwoColumn(); { + S.Id(ID_SCALE).TieChoice(_("S&cale") + wxString(wxT(":")), + *(int*)&mTempSettings.scaleType, + &mScaleChoices); } S.EndTwoColumn(); } @@ -151,12 +156,9 @@ bool WaveformPrefs::Apply() } if (mWt && isOpenPage) { - // Future: open page will determine view type - /* mWt->SetDisplay(WaveTrack::Waveform); if (partner) partner->SetDisplay(WaveTrack::Waveform); - */ } return true; @@ -194,6 +196,9 @@ void WaveformPrefs::OnApply(wxCommandEvent &) } BEGIN_EVENT_TABLE(WaveformPrefs, PrefsPanel) + +EVT_CHOICE(ID_SCALE, WaveformPrefs::OnControl) + EVT_CHECKBOX(ID_DEFAULTS, WaveformPrefs::OnDefaults) EVT_BUTTON(ID_APPLY, WaveformPrefs::OnApply) END_EVENT_TABLE() diff --git a/src/prefs/WaveformPrefs.h b/src/prefs/WaveformPrefs.h index b25042333..9d119c1c6 100644 --- a/src/prefs/WaveformPrefs.h +++ b/src/prefs/WaveformPrefs.h @@ -41,6 +41,8 @@ private: wxCheckBox *mDefaultsCheckbox; + wxArrayString mScaleChoices; + WaveformSettings mTempSettings; bool mPopulating; diff --git a/src/prefs/WaveformSettings.cpp b/src/prefs/WaveformSettings.cpp index 7a6324284..3aa15f4bf 100644 --- a/src/prefs/WaveformSettings.cpp +++ b/src/prefs/WaveformSettings.cpp @@ -16,6 +16,11 @@ Paul Licameli #include "../Audacity.h" #include "WaveformSettings.h" +#include +#include + +#include "../Prefs.h" + WaveformSettings::Globals::Globals() { LoadPrefs(); @@ -42,12 +47,14 @@ WaveformSettings::WaveformSettings() } WaveformSettings::WaveformSettings(const WaveformSettings &other) + : scaleType(other.scaleType) { } WaveformSettings &WaveformSettings::operator= (const WaveformSettings &other) { if (this != &other) { + scaleType = other.scaleType; } return *this; } @@ -62,11 +69,17 @@ bool WaveformSettings::Validate(bool quiet) { quiet; + scaleType = ScaleType( + std::max(0, std::min(int(stNumScaleTypes) - 1, int(scaleType))) + ); + return true; } void WaveformSettings::LoadPrefs() { + scaleType = ScaleType(gPrefs->Read(wxT("/Waveform/ScaleType"), 0L)); + // Enforce legal values Validate(true); @@ -75,12 +88,42 @@ void WaveformSettings::LoadPrefs() void WaveformSettings::SavePrefs() { + gPrefs->Write(wxT("/Waveform/ScaleType"), long(scaleType)); } void WaveformSettings::Update() { } +namespace +{ + wxArrayString &scaleNamesArray() + { + static wxArrayString theArray; + return theArray; + } +} + +//static +void WaveformSettings::InvalidateNames() +{ + scaleNamesArray().Clear(); +} + +//static +const wxArrayString &WaveformSettings::GetScaleNames() +{ + wxArrayString &theArray = scaleNamesArray(); + + if (theArray.IsEmpty()) { + // Keep in correspondence with enum WaveTrack::WaveTrackDisplay: + theArray.Add(_("Linear")); + theArray.Add(_("Logarithmic")); + } + + return theArray; +} + WaveformSettings::~WaveformSettings() { } diff --git a/src/prefs/WaveformSettings.h b/src/prefs/WaveformSettings.h index 672daf825..a62243aa3 100644 --- a/src/prefs/WaveformSettings.h +++ b/src/prefs/WaveformSettings.h @@ -11,6 +11,8 @@ Paul Licameli #ifndef __AUDACITY_WAVEFORM_SETTINGS__ #define __AUDACITY_WAVEFORM_SETTINGS__ +class wxArrayString; + class WaveformSettings { public: @@ -42,5 +44,20 @@ public: void LoadPrefs(); void SavePrefs(); void Update(); + + enum ScaleType { + stLinear, + stLogarithmic, + + stNumScaleTypes, + }; + + static void InvalidateNames(); // in case of language change + static const wxArrayString &GetScaleNames(); + + ScaleType scaleType; + + // Convenience + bool isLinear() const { return stLinear == scaleType; } }; #endif From 1fda7eb5c3650a45079e7d571d2b1103a10595a2 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 21 Jun 2015 21:41:49 -0400 Subject: [PATCH 4/4] Waveform and Spectrum menu items are a radio group, neither ever disabled. --- src/TrackPanel.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 41a12f4d6..d9cb8d247 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -722,8 +722,8 @@ void TrackPanel::BuildMenus(void) /* build the pop-down menu used on wave (sampled audio) tracks */ mWaveTrackMenu = new wxMenu(); BuildCommonDropMenuItems(mWaveTrackMenu); // does name, up/down etc - mWaveTrackMenu->Append(OnWaveformID, _("&Waveform")); - mWaveTrackMenu->Append(OnSpectrumID, _("&Spectrum")); + mWaveTrackMenu->AppendRadioItem(OnWaveformID, _("&Waveform")); + mWaveTrackMenu->AppendRadioItem(OnSpectrumID, _("&Spectrum")); mWaveTrackMenu->Append(OnViewSettingsID, _("&View Settings...")); mWaveTrackMenu->AppendSeparator(); @@ -8436,10 +8436,10 @@ void TrackPanel::OnTrackMenu(Track *t) theMenu->Enable(OnChannelRightID, !t->GetLinked()); const int display = static_cast(t)->GetDisplay(); - - theMenu->Enable(OnWaveformID, display != WaveTrack::Waveform); - theMenu->Enable(OnSpectrumID, display != WaveTrack::Spectrum); - theMenu->Enable(OnViewSettingsID, true); + theMenu->Check( + (display == WaveTrack::Waveform) ? OnWaveformID : OnSpectrumID, + true + ); WaveTrack * track = (WaveTrack *)t; SetMenuCheck(*mRateMenu, IdOfRate((int) track->GetRate())); @@ -8980,9 +8980,10 @@ void TrackPanel::OnSetDisplay(wxCommandEvent & event) } #endif UpdateVRuler(wt); + + MakeParentModifyState(true); + Refresh(false); } - MakeParentModifyState(true); - Refresh(false); } /// Sets the sample rate for a track, and if it is linked to