diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 8731a8441..57e21d285 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -893,6 +893,9 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, wxTheApp->Bind(EVT_AUDIOIO_CAPTURE, &AdornedRulerPanel::OnRecordStartStop, this); + + // Delay until after CommandManager has been populated: + this->CallAfter( &AdornedRulerPanel::UpdatePrefs ); } AdornedRulerPanel::~AdornedRulerPanel() @@ -1797,8 +1800,11 @@ void AdornedRulerPanel::OnAutoScroll(wxCommandEvent&) gPrefs->Write(wxT("/GUI/AutoScroll"), false); else gPrefs->Write(wxT("/GUI/AutoScroll"), true); - mProject->UpdatePrefs(); + gPrefs->Flush(); + + wxTheApp->AddPendingEvent(wxCommandEvent{ + EVT_PREFS_UPDATE, ViewInfo::UpdateScrollPrefsID() }); } diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index 7d2f95c35..572a47f18 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -13,6 +13,7 @@ #include "CellularPanel.h" #include "widgets/Ruler.h" // member variable +#include "Prefs.h" class ViewInfo; class AudacityProject; @@ -20,7 +21,9 @@ class SnapManager; class TrackList; // This is an Audacity Specific ruler panel. -class AUDACITY_DLL_API AdornedRulerPanel final : public CellularPanel +class AUDACITY_DLL_API AdornedRulerPanel final +: public CellularPanel +, private PrefsListener { public: AdornedRulerPanel(AudacityProject *project, @@ -53,7 +56,7 @@ public: void InvalidateRuler(); - void UpdatePrefs(); + void UpdatePrefs() override; void ReCreateButtons(); void RegenerateTooltips(); diff --git a/src/Menus.cpp b/src/Menus.cpp index fdcaf0768..4076cc717 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -51,14 +51,6 @@ #include -PrefsListener::~PrefsListener() -{ -} - -void PrefsListener::UpdatePrefs() -{ -} - MenuManager &GetMenuManager(AudacityProject &project) { return *project.mMenuManager; } @@ -70,6 +62,11 @@ MenuCreator::~MenuCreator() { } +MenuManager::MenuManager() +{ + UpdatePrefs(); +} + void MenuManager::UpdatePrefs() { bool bSelectAllIfNone; @@ -388,6 +385,7 @@ CommandFlag MenuManager::GetFocusedFrame(AudacityProject &project) return AlwaysEnabledFlag; } + CommandFlag MenuManager::GetUpdateFlags (AudacityProject &project, bool checkActive) { diff --git a/src/Menus.h b/src/Menus.h index 2edcb03f4..1d39a250c 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -13,6 +13,7 @@ #include "audacity/Types.h" #include // member variable +#include "Prefs.h" class wxArrayString; class AudacityProject; @@ -32,13 +33,6 @@ enum EffectType : int; typedef wxString PluginID; typedef wxArrayString PluginIDs; -class PrefsListener -{ -public: - virtual ~PrefsListener(); - virtual void UpdatePrefs(); // default is no-op -}; - class MenuCreator { public: @@ -56,9 +50,11 @@ public: PluginID mLastEffect{}; }; -class MenuManager : public MenuCreator +class MenuManager final : public MenuCreator, private PrefsListener { public: + MenuManager(); + static void ModifyUndoMenuItems(AudacityProject &project); static void ModifyToolbarMenus(AudacityProject &project); // Calls ModifyToolbarMenus() on all projects @@ -72,7 +68,7 @@ public: // inactive project as it is needlessly expensive. CommandFlag GetUpdateFlags( AudacityProject &project, bool checkActive = false); - void UpdatePrefs(); + void UpdatePrefs() override; // Command Handling bool ReportIfActionNotAllowed( diff --git a/src/MixerBoard.cpp b/src/MixerBoard.cpp index d4b9beb4e..e16b0382b 100644 --- a/src/MixerBoard.cpp +++ b/src/MixerBoard.cpp @@ -356,8 +356,6 @@ void MixerTrackCluster::UpdatePrefs() { this->SetBackgroundColour( theTheme.Colour( clrMedium ) ); mStaticText_TrackName->SetForegroundColour(theTheme.Colour(clrTrackPanelText)); - if (mMeter) - mMeter->UpdatePrefs(); // in case meter range has changed HandleResize(); // in case prefs "/GUI/Solo" changed } #endif diff --git a/src/MixerBoard.h b/src/MixerBoard.h index 3f10396b3..570dd5d62 100644 --- a/src/MixerBoard.h +++ b/src/MixerBoard.h @@ -20,6 +20,8 @@ #include "widgets/ASlider.h" // to inherit #include "commands/CommandManagerWindowClasses.h" +#include "Prefs.h" + class wxArrayString; class wxBitmapButton; class wxImage; @@ -188,7 +190,7 @@ public: class MixerBoardFrame; class TrackList; -class MixerBoard final : public wxWindow +class MixerBoard final : public wxWindow, private PrefsListener { friend class MixerBoardFrame; @@ -198,7 +200,7 @@ public: const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize); - void UpdatePrefs(); + void UpdatePrefs() override; // Add clusters for any tracks we're not yet showing. // Update pointers for tracks we're aleady showing. diff --git a/src/Prefs.cpp b/src/Prefs.cpp index 97268379a..3da5c2d27 100755 --- a/src/Prefs.cpp +++ b/src/Prefs.cpp @@ -69,6 +69,33 @@ std::unique_ptr ugPrefs {}; AudacityPrefs *gPrefs = NULL; int gMenusDirty = 0; +wxDEFINE_EVENT(EVT_PREFS_UPDATE, wxCommandEvent); + +PrefsListener::PrefsListener() +{ + wxTheApp->Bind(EVT_PREFS_UPDATE, &PrefsListener::OnEvent, this); +} + +PrefsListener::~PrefsListener() +{ + // Explicit unbinding is needed because this is not a wxEvtHandler + wxTheApp->Unbind(EVT_PREFS_UPDATE, &PrefsListener::OnEvent, this); +} + +void PrefsListener::UpdateSelectedPrefs( int ) +{ +} + +void PrefsListener::OnEvent( wxCommandEvent &evt ) +{ + evt.Skip(); + auto id = evt.GetId(); + if (id <= 0) + UpdatePrefs(); + else + UpdateSelectedPrefs( id ); +} + #if 0 // Copy one entry from one wxConfig object to another static void CopyEntry(wxString path, wxConfigBase *src, wxConfigBase *dst, wxString entry) diff --git a/src/Prefs.h b/src/Prefs.h index 7afa5ef27..0f1d40160 100644 --- a/src/Prefs.h +++ b/src/Prefs.h @@ -34,6 +34,7 @@ #include "../include/audacity/ComponentInterface.h" #include // to inherit wxFileConfig +#include // to declare custom event types void InitPreferences(); void FinishPreferences(); @@ -159,4 +160,29 @@ private: const wxString mOldKey; }; +// An event emitted by the application when the Preference dialog commits +// changes +wxDECLARE_EVENT(EVT_PREFS_UPDATE, wxCommandEvent); + +// Invoke UpdatePrefs() when Preference dialog commits changes. +class PrefsListener +{ +public: + PrefsListener(); + virtual ~PrefsListener(); + + // Called when all preferences should be updated. + virtual void UpdatePrefs() = 0; + +protected: + // Called when only selected preferences are to be updated. + // id is some value generated by wxNewId() that identifies the portion + // of preferences. + // Default function does nothing. + virtual void UpdateSelectedPrefs( int id ); + +private: + void OnEvent(wxCommandEvent&); +}; + #endif diff --git a/src/Project.cpp b/src/Project.cpp index 8c56a7a2a..280eeb0a2 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -1497,7 +1497,6 @@ void AudacityProject::UpdatePrefsVariables() { gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &mShowId3Dialog, true); gPrefs->Read(wxT("/AudioFiles/NormalizeOnLoad"),&mNormalizeOnLoad, false); - gPrefs->Read(wxT("/GUI/AutoScroll"), &mViewInfo.bUpdateTrackIndicator, true); gPrefs->Read(wxT("/GUI/EmptyCanBeDirty"), &mEmptyCanBeDirty, true ); gPrefs->Read(wxT("/GUI/ShowSplashScreen"), &mShowSplashScreen, true); gPrefs->Read(wxT("/GUI/Solo"), &mSoloPref, wxT("Simple")); @@ -1531,20 +1530,6 @@ void AudacityProject::UpdatePrefs() UpdatePrefsVariables(); SetProjectTitle(); - - { - ObjectFactorySetLocker locker; - for( const auto &pObject : mAttachedObjects ) - pObject->UpdatePrefs(); - } - - GetMenuManager(*this).UpdatePrefs(); - - mTrackPanel->UpdatePrefs(); - mToolManager->UpdatePrefs(); - mRuler->UpdatePrefs(); - if (mMixerBoard) - mMixerBoard->UpdatePrefs(); } void AudacityProject::RedrawProject(const bool bForceWaveTracks /*= false*/) @@ -3633,8 +3618,6 @@ bool AudacityProject::HandleXMLTag(const wxChar *tag, const wxChar **attrs) NumericConverter::LookupFormat( NumericConverter::BANDWIDTH, value ) ); } // while - mViewInfo.UpdatePrefs(); - if (longVpos != 0) { // PRL: It seems this must happen after SetSnapTo mViewInfo.vpos = longVpos; @@ -5530,10 +5513,8 @@ LyricsWindow* AudacityProject::GetLyricsWindow(bool create) MixerBoardFrame* AudacityProject::GetMixerBoardFrame(bool create) { - if (create && !mMixerBoardFrame) { + if (create && !mMixerBoardFrame) mMixerBoardFrame = safenew MixerBoardFrame{ this }; - mMixerBoard = mMixerBoardFrame->mMixerBoard; - } return mMixerBoardFrame; } diff --git a/src/Project.h b/src/Project.h index 143860b04..eac8cd477 100644 --- a/src/Project.h +++ b/src/Project.h @@ -23,6 +23,7 @@ #include "Experimental.h" #include "Track.h" +#include "Prefs.h" #include "SelectionState.h" #include "ViewInfo.h" #include "commands/CommandManagerWindowClasses.h" @@ -171,14 +172,13 @@ class WaveTrack; class MenuManager; -class PrefsListener; - class AUDACITY_DLL_API AudacityProject final : public wxFrame, public TrackPanelListener, public SelectionBarListener, public SpectralSelectionBarListener, public XMLTagHandler, - public AudioIOListener + public AudioIOListener, + private PrefsListener { public: AudacityProject(wxWindow * parent, wxWindowID id, @@ -188,7 +188,7 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame, // Next available ID for sub-windows int NextWindowID(); - using AttachedObject = PrefsListener; + using AttachedObject = wxObject; using AttachedObjectFactory = std::function< std::unique_ptr() >; @@ -391,7 +391,7 @@ public: int GetProjectNumber(){ return mProjectNo;}; static int CountUnnamed(); static void RefreshAllTitles(bool bShowProjectNumbers ); - void UpdatePrefs(); + void UpdatePrefs() override; void UpdatePrefsVariables(); void RedrawProject(const bool bForceWaveTracks = false); void RefreshCursor(); @@ -627,7 +627,6 @@ private: HistoryWindow *mHistoryWindow{}; LyricsWindow* mLyricsWindow{}; MixerBoardFrame* mMixerBoardFrame{}; - MixerBoard* mMixerBoard{}; Destroy_ptr mFreqWindow; Destroy_ptr mContrastDialog; diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index dc83a769b..057d0d849 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -77,6 +77,7 @@ audio tracks. #include "LabelTrack.h" #include "TimeTrack.h" #include "Prefs.h" +#include "prefs/GUIPrefs.h" #include "prefs/GUISettings.h" #include "prefs/SpectrogramSettings.h" #include "prefs/TracksPrefs.h" @@ -142,7 +143,6 @@ TrackArtist::TrackArtist( TrackPanel *parent_ ) mdBrange = ENV_DB_RANGE; mShowClipping = false; mSampleDisplay = 1;// Stem plots by default. - UpdatePrefs(); SetColours(0); vruler = std::make_unique(); @@ -3267,15 +3267,22 @@ void TrackArt::DrawTimeTrack(TrackPanelDrawingContext &context, track->GetDisplayLog(), dbRange, lower, upper, false ); } +void TrackArtist::UpdateSelectedPrefs( int id ) +{ + if( id == ShowClippingPrefsID()) + mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping); +} + void TrackArtist::UpdatePrefs() { mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange); - mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping); mSampleDisplay = TracksPrefs::SampleViewChoice(); mbShowTrackNameInTrack = gPrefs->ReadBool(wxT("/GUI/ShowTrackNameInWaveform"), false); + UpdateSelectedPrefs( ShowClippingPrefsID() ); + SetColours(0); } diff --git a/src/TrackArtist.h b/src/TrackArtist.h index 4cb5e3ef2..dd28f67c7 100644 --- a/src/TrackArtist.h +++ b/src/TrackArtist.h @@ -25,6 +25,7 @@ #include // member variable #include // member variables #include "audacity/Types.h" +#include "Prefs.h" class wxRect; @@ -157,7 +158,7 @@ namespace TrackArt { const wxRect & rect, int x0, int y0, int cy, bool top); } -class AUDACITY_DLL_API TrackArtist { +class AUDACITY_DLL_API TrackArtist final : private PrefsListener { public: TrackArtist( TrackPanel *parent_ ); @@ -174,7 +175,8 @@ public: void SetColours(int iColorIndex); - void UpdatePrefs(); + void UpdatePrefs() override; + void UpdateSelectedPrefs( int id ) override; void UpdateVRuler(const Track *t, const wxRect & rect); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index da1190be3..220c6fa39 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -273,6 +273,8 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id, wxTheApp->Bind(EVT_AUDIOIO_PLAYBACK, &TrackPanel::OnPlayback, this); + + UpdatePrefs(); } @@ -319,16 +321,8 @@ wxString TrackPanel::gSoloPref; void TrackPanel::UpdatePrefs() { - gPrefs->Read(wxT("/GUI/AutoScroll"), &mViewInfo->bUpdateTrackIndicator, - true); gPrefs->Read(wxT("/GUI/Solo"), &gSoloPref, wxT("Simple")); - mViewInfo->UpdatePrefs(); - - if (mTrackArtist) { - mTrackArtist->UpdatePrefs(); - } - // All vertical rulers must be recalculated since the minimum and maximum // frequences may have been changed. UpdateVRulers(); diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 64f798cdb..4aad1cc11 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -20,6 +20,7 @@ #include // to inherit #include "HitTestResult.h" +#include "Prefs.h" #include "SelectedRegion.h" @@ -210,6 +211,8 @@ namespace TrackInfo wxWindow *pParent); #endif + // Non-member, namespace function relying on TrackPanel to invoke it + // when it handles preference update events void UpdatePrefs( wxWindow *pParent ); }; @@ -251,6 +254,7 @@ enum : int { class AUDACITY_DLL_API TrackPanel final : public CellularPanel , public NonKeystrokeInterceptingWindow + , private PrefsListener { public: TrackPanel(wxWindow * parent, @@ -264,7 +268,7 @@ class AUDACITY_DLL_API TrackPanel final virtual ~ TrackPanel(); - void UpdatePrefs(); + void UpdatePrefs() override; void ApplyUpdatedTheme(); void OnPaint(wxPaintEvent & event); diff --git a/src/ViewInfo.cpp b/src/ViewInfo.cpp index 2af0132e2..51aca87c5 100644 --- a/src/ViewInfo.cpp +++ b/src/ViewInfo.cpp @@ -146,6 +146,14 @@ ViewInfo::ViewInfo(double start, double screenDuration, double pixelsPerSecond) UpdatePrefs(); } +void ViewInfo::UpdateSelectedPrefs( int id ) +{ + if (id == UpdateScrollPrefsID()) + gPrefs->Read(wxT("/GUI/AutoScroll"), &bUpdateTrackIndicator, + true); + ZoomInfo::UpdateSelectedPrefs( id ); +} + void ViewInfo::UpdatePrefs() { ZoomInfo::UpdatePrefs(); @@ -155,6 +163,8 @@ void ViewInfo::UpdatePrefs() #endif gPrefs->Read(wxT("/GUI/AdjustSelectionEdges"), &bAdjustSelectionEdges, true); + + UpdateSelectedPrefs( UpdateScrollPrefsID() ); } void ViewInfo::SetBeforeScreenWidth(wxInt64 beforeWidth, wxInt64 screenWidth, double lowerBoundTime) @@ -206,3 +216,9 @@ void ViewInfo::OnTimer(wxCommandEvent &event) // Propagate the message to other listeners bound to this this->ProcessEvent( event ); } + +int ViewInfo::UpdateScrollPrefsID() +{ + static int value = wxNewId(); + return value; +} diff --git a/src/ViewInfo.h b/src/ViewInfo.h index 0143cddca..1b208aa52 100644 --- a/src/ViewInfo.h +++ b/src/ViewInfo.h @@ -15,6 +15,7 @@ #include // inherit wxEvtHandler #include "SelectedRegion.h" #include "MemoryX.h" +#include "Prefs.h" class Track; @@ -31,6 +32,7 @@ class Track; class AUDACITY_DLL_API ZoomInfo /* not final */ // Note that ViewInfo inherits from ZoomInfo but there are no virtual functions. // That's okay if we pass always by reference and never copy, suffering "slicing." +: protected PrefsListener { public: ZoomInfo(double start, double pixelsPerSecond); @@ -40,7 +42,7 @@ public: ZoomInfo(const ZoomInfo&) PROHIBITED; ZoomInfo& operator= (const ZoomInfo&) PROHIBITED; - void UpdatePrefs(); + void UpdatePrefs() override; int vpos; // vertical scroll pos @@ -146,7 +148,9 @@ class AUDACITY_DLL_API ViewInfo final public: ViewInfo(double start, double screenDuration, double pixelsPerSecond); - void UpdatePrefs(); + static int UpdateScrollPrefsID(); + void UpdatePrefs() override; + void UpdateSelectedPrefs( int id ) override; double GetBeforeScreenWidth() const { diff --git a/src/menus/ViewMenus.cpp b/src/menus/ViewMenus.cpp index 7545e63a0..f3eb8521d 100644 --- a/src/menus/ViewMenus.cpp +++ b/src/menus/ViewMenus.cpp @@ -10,6 +10,7 @@ #include "../TrackPanel.h" #include "../commands/CommandContext.h" #include "../commands/CommandManager.h" +#include "../prefs/GUIPrefs.h" #include "../prefs/TracksPrefs.h" #ifdef EXPERIMENTAL_EFFECTS_RACK @@ -367,7 +368,10 @@ void OnShowClipping(const CommandContext &context) gPrefs->Write(wxT("/GUI/ShowClipping"), checked); gPrefs->Flush(); commandManager->Check(wxT("ShowClipping"), checked); - trackPanel->UpdatePrefs(); + + wxTheApp->AddPendingEvent(wxCommandEvent{ + EVT_PREFS_UPDATE, ShowClippingPrefsID() }); + trackPanel->Refresh(false); } diff --git a/src/prefs/GUIPrefs.cpp b/src/prefs/GUIPrefs.cpp index 78bdd3436..b329a6fc8 100644 --- a/src/prefs/GUIPrefs.cpp +++ b/src/prefs/GUIPrefs.cpp @@ -269,6 +269,10 @@ bool GUIPrefs::Commit() gPrefs->Flush(); } + // Reads preference /GUI/Theme + theTheme.LoadPreferredTheme(); + ThemePrefs::ApplyUpdatedImages(); + return true; } @@ -366,6 +370,12 @@ wxString GUIPrefs::GetLang() return {}; } +int ShowClippingPrefsID() +{ + static int value = wxNewId(); + return value; +} + PrefsPanel::Factory GUIPrefsFactory = [](wxWindow *parent, wxWindowID winid) { diff --git a/src/prefs/GUIPrefs.h b/src/prefs/GUIPrefs.h index d6f913cb4..c97f25ada 100644 --- a/src/prefs/GUIPrefs.h +++ b/src/prefs/GUIPrefs.h @@ -67,4 +67,7 @@ class GUIPrefs final : public PrefsPanel /// A PrefsPanel::Factory that creates one GUIPrefs panel. extern PrefsPanel::Factory GUIPrefsFactory; + +int ShowClippingPrefsID(); + #endif diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index cb62197c4..4538fd5f9 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -68,7 +68,6 @@ #include "MidiIOPrefs.h" #endif -#include "../Theme.h" #include "../widgets/HelpSystem.h" #if wxUSE_ACCESSIBILITY @@ -813,10 +812,6 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) } gPrefs->Flush(); - // Reads preference /GUI/Theme - theTheme.LoadPreferredTheme(); - ThemePrefs::ApplyUpdatedImages(); - SavePreferredPage(); #if USE_PORTMIXER @@ -844,12 +839,14 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event)) } #endif + // PRL: Is the following concern still valid, now that prefs update is + // handled instead by delayed event processing? + // LL: wxMac can't handle recreating the menus when this dialog is still active, // so AudacityProject::UpdatePrefs() or any of the routines it calls must // not cause MenuCreator::RebuildMenuBar() to be executed. - for (size_t i = 0; i < gAudacityProjects.size(); i++) { - gAudacityProjects[i]->UpdatePrefs(); - } + + wxTheApp->AddPendingEvent(wxCommandEvent{ EVT_PREFS_UPDATE }); WaveformSettings::defaults().LoadPrefs(); SpectrogramSettings::defaults().LoadPrefs(); diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index affa80811..c65239d29 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -127,6 +127,7 @@ ControlToolBar::~ControlToolBar() void ControlToolBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); } // This is a convenience function that allows for button creation in diff --git a/src/toolbars/DeviceToolBar.cpp b/src/toolbars/DeviceToolBar.cpp index 4eaada867..1a41352b9 100644 --- a/src/toolbars/DeviceToolBar.cpp +++ b/src/toolbars/DeviceToolBar.cpp @@ -64,6 +64,12 @@ BEGIN_EVENT_TABLE(DeviceToolBar, ToolBar) EVT_COMMAND(wxID_ANY, EVT_CAPTURE_KEY, DeviceToolBar::OnCaptureKey) END_EVENT_TABLE() +static int DeviceToolbarPrefsID() +{ + static int value = wxNewId(); + return value; +} + //Standard contructor DeviceToolBar::DeviceToolBar() : ToolBar(DeviceBarID, _("Device"), wxT("Device"), true) @@ -313,6 +319,13 @@ void DeviceToolBar::UpdatePrefs() Refresh(); } +void DeviceToolBar::UpdateSelectedPrefs( int id ) +{ + if (id == DeviceToolbarPrefsID()) + UpdatePrefs(); + ToolBar::UpdateSelectedPrefs( id ); +} + void DeviceToolBar::EnableDisableButtons() { @@ -773,10 +786,8 @@ void DeviceToolBar::OnChoice(wxCommandEvent &event) gAudioIO->HandleDeviceChange(); } - // Update all projects' DeviceToolBar. - for (size_t i = 0; i < gAudacityProjects.size(); i++) { - gAudacityProjects[i]->GetDeviceToolBar()->UpdatePrefs(); - } + wxTheApp->AddPendingEvent(wxCommandEvent{ + EVT_PREFS_UPDATE, DeviceToolbarPrefsID() }); } void DeviceToolBar::ShowInputDialog() diff --git a/src/toolbars/DeviceToolBar.h b/src/toolbars/DeviceToolBar.h index 5c996a014..66b7f670b 100644 --- a/src/toolbars/DeviceToolBar.h +++ b/src/toolbars/DeviceToolBar.h @@ -29,6 +29,7 @@ class DeviceToolBar final : public ToolBar { void Create(wxWindow * parent) override; void UpdatePrefs() override; + void UpdateSelectedPrefs( int ) override; void DeinitChildren(); void Populate() override; diff --git a/src/toolbars/EditToolBar.cpp b/src/toolbars/EditToolBar.cpp index d167e7d75..206622d2c 100644 --- a/src/toolbars/EditToolBar.cpp +++ b/src/toolbars/EditToolBar.cpp @@ -89,6 +89,7 @@ EditToolBar::~EditToolBar() void EditToolBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); } void EditToolBar::AddSeparator() diff --git a/src/toolbars/MeterToolBar.cpp b/src/toolbars/MeterToolBar.cpp index b8c67c3cb..a1e656462 100644 --- a/src/toolbars/MeterToolBar.cpp +++ b/src/toolbars/MeterToolBar.cpp @@ -78,6 +78,8 @@ void MeterToolBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); + // Simulate a size event to set initial meter placement/size wxSizeEvent dummy; OnSize(dummy); @@ -156,18 +158,6 @@ void MeterToolBar::Populate() void MeterToolBar::UpdatePrefs() { - if( mPlayMeter ) - { - mPlayMeter->UpdatePrefs(); - mPlayMeter->Refresh(); - } - - if( mRecordMeter ) - { - mRecordMeter->UpdatePrefs(); - mRecordMeter->Refresh(); - } - RegenerateTooltips(); // Set label to pull in language change @@ -175,8 +165,6 @@ void MeterToolBar::UpdatePrefs() // Give base class a chance ToolBar::UpdatePrefs(); - - } void MeterToolBar::RegenerateTooltips() diff --git a/src/toolbars/MixerToolBar.cpp b/src/toolbars/MixerToolBar.cpp index 96d15ec90..48837f670 100644 --- a/src/toolbars/MixerToolBar.cpp +++ b/src/toolbars/MixerToolBar.cpp @@ -67,6 +67,7 @@ MixerToolBar::~MixerToolBar() void MixerToolBar::Create(wxWindow *parent) { ToolBar::Create(parent); + UpdatePrefs(); } void MixerToolBar::Populate() diff --git a/src/toolbars/ScrubbingToolBar.cpp b/src/toolbars/ScrubbingToolBar.cpp index a00a63591..f0e36d88f 100644 --- a/src/toolbars/ScrubbingToolBar.cpp +++ b/src/toolbars/ScrubbingToolBar.cpp @@ -68,6 +68,7 @@ ScrubbingToolBar::~ScrubbingToolBar() void ScrubbingToolBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); } /// This is a convenience function that allows for button creation in diff --git a/src/toolbars/SelectionBar.cpp b/src/toolbars/SelectionBar.cpp index 90a5b6888..2e694620b 100644 --- a/src/toolbars/SelectionBar.cpp +++ b/src/toolbars/SelectionBar.cpp @@ -132,6 +132,7 @@ SelectionBar::~SelectionBar() void SelectionBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); } @@ -504,7 +505,8 @@ void SelectionBar::OnUpdate(wxCommandEvent &evt) // Save format name before recreating the controls so they resize properly { auto format = mStartTime->GetBuiltinName(index); - mListener->AS_SetSelectionFormat(format); + if (mListener) + mListener->AS_SetSelectionFormat(format); } RegenerateTooltips(); diff --git a/src/toolbars/SpectralSelectionBar.cpp b/src/toolbars/SpectralSelectionBar.cpp index 7059c6a4a..1201b178c 100644 --- a/src/toolbars/SpectralSelectionBar.cpp +++ b/src/toolbars/SpectralSelectionBar.cpp @@ -107,6 +107,7 @@ SpectralSelectionBar::~SpectralSelectionBar() void SpectralSelectionBar::Create(wxWindow * parent) { ToolBar::Create(parent); + UpdatePrefs(); mHeight = wxWindowBase::GetSizer()->GetSize().GetHeight(); } @@ -370,12 +371,14 @@ void SpectralSelectionBar::OnUpdate(wxCommandEvent &evt) if (type == EVT_FREQUENCYTEXTCTRL_UPDATED) { NumericTextCtrl *frequencyCtrl = (mbCenterAndWidth ? mCenterCtrl : mLowCtrl); auto frequencyFormatName = frequencyCtrl->GetBuiltinName(index); - mListener->SSBL_SetFrequencySelectionFormatName(frequencyFormatName); + if (mListener) + mListener->SSBL_SetFrequencySelectionFormatName(frequencyFormatName); } else if (mbCenterAndWidth && type == EVT_BANDWIDTHTEXTCTRL_UPDATED) { auto bandwidthFormatName = mWidthCtrl->GetBuiltinName(index); - mListener->SSBL_SetBandwidthSelectionFormatName(bandwidthFormatName); + if (mListener) + mListener->SSBL_SetBandwidthSelectionFormatName(bandwidthFormatName); } // ToolBar::ReCreateButtons() will get rid of our sizers and controls diff --git a/src/toolbars/ToolBar.h b/src/toolbars/ToolBar.h index f8b7999e5..beb6f2ae9 100644 --- a/src/toolbars/ToolBar.h +++ b/src/toolbars/ToolBar.h @@ -18,6 +18,7 @@ #include #include +#include "../Prefs.h" #include "../Theme.h" #include "../widgets/wxPanelWrapper.h" // to inherit @@ -84,7 +85,9 @@ enum // How may pixels padding each side of a floating toolbar enum { ToolBarFloatMargin = 1 }; -class ToolBar /* not final */ : public wxPanelWrapper +class ToolBar /* not final */ +: public wxPanelWrapper +, protected PrefsListener { public: @@ -101,7 +104,7 @@ class ToolBar /* not final */ : public wxPanelWrapper virtual void Create(wxWindow *parent); virtual void EnableDisableButtons() = 0; virtual void ReCreateButtons(); - virtual void UpdatePrefs(); + void UpdatePrefs() override; virtual void RegenerateTooltips() = 0; int GetType(); diff --git a/src/toolbars/ToolManager.cpp b/src/toolbars/ToolManager.cpp index a51137642..ba086ccaf 100644 --- a/src/toolbars/ToolManager.cpp +++ b/src/toolbars/ToolManager.cpp @@ -1091,21 +1091,6 @@ void ToolManager::LayoutToolBars() mBotDock->LayoutToolBars(); } -// -// Tell the toolbars that preferences have been updated -// -void ToolManager::UpdatePrefs() -{ - for( int ndx = 0; ndx < ToolBarCount; ndx++ ) - { - ToolBar *bar = mBars[ ndx ].get(); - if( bar ) - { - bar->UpdatePrefs(); - } - } -} - // // Handle toolbar dragging // diff --git a/src/toolbars/ToolManager.h b/src/toolbars/ToolManager.h index 84d70a52a..58bbfc0dd 100644 --- a/src/toolbars/ToolManager.h +++ b/src/toolbars/ToolManager.h @@ -48,7 +48,6 @@ class ToolManager final : public wxEvtHandler, public wxEventFilter ~ToolManager(); void LayoutToolBars(); - void UpdatePrefs(); bool IsDocked( int type ); diff --git a/src/toolbars/ToolsToolBar.cpp b/src/toolbars/ToolsToolBar.cpp index 0d53a5824..aaf27326c 100644 --- a/src/toolbars/ToolsToolBar.cpp +++ b/src/toolbars/ToolsToolBar.cpp @@ -258,3 +258,9 @@ void ToolsToolBar::OnTool(wxCommandEvent & evt) IsDown(multiTool)); gPrefs->Flush(); } + +void ToolsToolBar::Create(wxWindow * parent) +{ + ToolBar::Create(parent); + UpdatePrefs(); +} diff --git a/src/toolbars/ToolsToolBar.h b/src/toolbars/ToolsToolBar.h index a881d0d45..c6a91dac2 100644 --- a/src/toolbars/ToolsToolBar.h +++ b/src/toolbars/ToolsToolBar.h @@ -68,6 +68,7 @@ class ToolsToolBar final : public ToolBar { private: + void Create(wxWindow * parent) override; void RegenerateTooltips() override; wxImage *MakeToolImage(wxImage *tool, wxImage *mask, int style); static AButton *MakeTool( diff --git a/src/toolbars/TranscriptionToolBar.h b/src/toolbars/TranscriptionToolBar.h index 0ccb97acd..b9f093b6c 100644 --- a/src/toolbars/TranscriptionToolBar.h +++ b/src/toolbars/TranscriptionToolBar.h @@ -98,7 +98,6 @@ class TranscriptionToolBar final : public ToolBar { //void Populate() override; //void Repaint(wxDC * WXUNUSED(dc)) override {} //void EnableDisableButtons() override; - //void UpdatePrefs() override; //void OnFocus(wxFocusEvent &event); //void OnCaptureKey(wxCommandEvent &event); diff --git a/src/widgets/Meter.cpp b/src/widgets/Meter.cpp index eaff53515..9e89d9dee 100644 --- a/src/widgets/Meter.cpp +++ b/src/widgets/Meter.cpp @@ -253,9 +253,6 @@ bool MeterUpdateQueue::Get(MeterUpdateMsg &msg) // How many pixels between items? const static int gap = 2; -// Event used to notify all meters of preference changes -wxDEFINE_EVENT(EVT_METER_PREFERENCES_CHANGED, wxCommandEvent); - const static wxChar *PrefStyles[] = { wxT("AutomaticStereo"), @@ -348,11 +345,6 @@ MeterPanel::MeterPanel(AudacityProject *project, mPeakPeakPen = wxPen(theTheme.Colour( clrMeterPeak), 1, wxPENSTYLE_SOLID); mDisabledPen = wxPen(theTheme.Colour( clrMeterDisabledPen), 1, wxPENSTYLE_SOLID); - // Register for our preference update event - wxTheApp->Bind(EVT_METER_PREFERENCES_CHANGED, - &MeterPanel::OnMeterPrefsUpdated, - this); - if (mIsInput) { wxTheApp->Bind(EVT_AUDIOIO_MONITOR, &MeterPanel::OnAudioIOStatus, @@ -457,6 +449,20 @@ void MeterPanel::UpdatePrefs() Reset(mRate, false); mLayoutValid = false; + + Refresh(false); +} + +static int MeterPrefsID() +{ + static int value = wxNewId(); + return value; +} + +void MeterPanel::UpdateSelectedPrefs(int id) +{ + if (id == MeterPrefsID()) + UpdatePrefs(); } void MeterPanel::OnErase(wxEraseEvent & WXUNUSED(event)) @@ -1964,15 +1970,6 @@ void MeterPanel::OnMonitor(wxCommandEvent & WXUNUSED(event)) StartMonitoring(); } -void MeterPanel::OnMeterPrefsUpdated(wxCommandEvent & evt) -{ - evt.Skip(); - - UpdatePrefs(); - - Refresh(false); -} - void MeterPanel::OnPreferences(wxCommandEvent & WXUNUSED(event)) { wxTextCtrl *rate; @@ -2099,9 +2096,8 @@ void MeterPanel::OnPreferences(wxCommandEvent & WXUNUSED(event)) // Currently, there are 2 playback meters and 2 record meters and any number of // mixerboard meters, so we have to send out an preferences updated message to // ensure they all update themselves. - wxCommandEvent e(EVT_METER_PREFERENCES_CHANGED); - e.SetEventObject(this); - GetParent()->GetEventHandler()->ProcessEvent(e); + wxTheApp->AddPendingEvent(wxCommandEvent{ + EVT_PREFS_UPDATE, MeterPrefsID() }); } } diff --git a/src/widgets/Meter.h b/src/widgets/Meter.h index 8a2b8d5e9..f28bcc2d1 100644 --- a/src/widgets/Meter.h +++ b/src/widgets/Meter.h @@ -22,14 +22,11 @@ #include // member variable #include "../SampleFormat.h" +#include "../Prefs.h" #include "Ruler.h" // member variable class AudacityProject; -// Event used to notify all meters of preference changes -wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, - EVT_METER_PREFERENCES_CHANGED, wxCommandEvent); - // Increase this when we add support for multichannel meters // (most of the code is already there) const int kMaxMeterBars = 2; @@ -94,7 +91,7 @@ class MeterAx; \brief MeterPanel is a panel that paints the meter used for monitoring or playback. ************************************************************************/ -class MeterPanel final : public wxPanelWrapper +class MeterPanel final : public wxPanelWrapper, private PrefsListener { DECLARE_DYNAMIC_CLASS(MeterPanel) @@ -124,7 +121,6 @@ class MeterPanel final : public wxPanelWrapper void SetFocusFromKbd() override; - void UpdatePrefs(); void Clear(); Style GetStyle() const { return mStyle; } @@ -192,6 +188,9 @@ class MeterPanel final : public wxPanelWrapper int GetDBRange() const { return mDB ? mDBRange : -1; } private: + void UpdatePrefs() override; + void UpdateSelectedPrefs( int ) override; + static bool s_AcceptsFocus; struct Resetter { void operator () (bool *p) const { if(p) *p = false; } }; using TempAllowFocus = std::unique_ptr; @@ -232,7 +231,6 @@ class MeterPanel final : public wxPanelWrapper void ShowMenu(const wxPoint & pos); void OnMonitor(wxCommandEvent &evt); void OnPreferences(wxCommandEvent &evt); - void OnMeterPrefsUpdated(wxCommandEvent &evt); wxString Key(const wxString & key) const;