diff --git a/src/prefs/SpectrumPrefs.cpp b/src/prefs/SpectrumPrefs.cpp index 65f272cdf..51dae7154 100644 --- a/src/prefs/SpectrumPrefs.cpp +++ b/src/prefs/SpectrumPrefs.cpp @@ -49,7 +49,7 @@ SpectrumPrefs::SpectrumPrefs(wxWindow * parent, wxWindowID winid, WaveTrack *wt) wt->GetSpectrumBounds(&mOrigMin, &mOrigMax); mTempSettings.maxFreq = mOrigMax; mTempSettings.minFreq = mOrigMin; - mOrigDisplay = WaveTrackView::Get( *mWt ).GetDisplay(); + mOrigPlacements = WaveTrackView::Get( *mWt ).SavePlacements(); } else { mTempSettings = mOrigSettings = SpectrogramSettings::defaults(); @@ -424,7 +424,7 @@ void SpectrumPrefs::Rollback() if (mWt && isOpenPage) { auto channels = TrackList::Channels(mWt); for (auto channel : channels) - WaveTrackView::Get( *channel ).SetDisplay( mOrigDisplay ); + WaveTrackView::Get( *channel ).RestorePlacements( mOrigPlacements ); } if (isOpenPage) { diff --git a/src/prefs/SpectrumPrefs.h b/src/prefs/SpectrumPrefs.h index 4158e0f42..f22e1e7e1 100644 --- a/src/prefs/SpectrumPrefs.h +++ b/src/prefs/SpectrumPrefs.h @@ -23,6 +23,7 @@ #include "../Experimental.h" +#include #include #include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h" @@ -38,6 +39,7 @@ struct FFTParam; class ShuttleGui; class SpectrogramSettings; class WaveTrack; +struct WaveTrackSubViewPlacement; #define SPECTRUM_PREFS_PLUGIN_SYMBOL ComponentInterfaceSymbol{ XO("Spectrum") } @@ -98,7 +100,7 @@ class SpectrumPrefs final : public PrefsPanel SpectrogramSettings mTempSettings, mOrigSettings; - WaveTrackViewConstants::Display mOrigDisplay; + std::vector mOrigPlacements; float mOrigMin, mOrigMax; bool mPopulating; diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp index 9ec4a0ecc..77ae52c87 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp @@ -889,7 +889,7 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &) view.SetMinimized(bBothMinimizedp); partnerView.SetMinimized(bBothMinimizedp); - partnerView.SetDisplay( view.GetDisplay() ); + partnerView.RestorePlacements( view.SavePlacements() ); //On Demand - join the queues together. if (ODManager::IsInstanceCreated()) diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp index c88296345..efab68bc1 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp @@ -42,16 +42,20 @@ WaveTrackView::WaveTrackView( const std::shared_ptr &pTrack ) { WaveTrackSubViews::BuildAll(); - mDisplay = TracksPrefs::ViewModeChoice(); + auto display = TracksPrefs::ViewModeChoice(); // Force creation always: WaveformSettings &settings = static_cast< WaveTrack* >( pTrack.get() ) ->GetIndependentWaveformSettings(); - if (mDisplay == WaveTrackViewConstants::obsoleteWaveformDBDisplay) { - mDisplay = WaveTrackViewConstants::Waveform; + if (display == WaveTrackViewConstants::obsoleteWaveformDBDisplay) { + display = WaveTrackViewConstants::Waveform; settings.scaleType = WaveformSettings::stLogarithmic; } + + mPlacements.resize( WaveTrackSubViews::size() ); + + SetDisplay( display ); } WaveTrackView::~WaveTrackView() @@ -65,7 +69,7 @@ void WaveTrackView::CopyTo( Track &track ) const if ( const auto pOther = dynamic_cast< WaveTrackView* >( &other ) ) { // only one field is important to preserve in undo/redo history - pOther->mDisplay = mDisplay; + pOther->RestorePlacements( SavePlacements() ); } } @@ -109,22 +113,67 @@ WaveTrackView::DoDetailedHitTest return { false, results }; } -auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement +auto WaveTrackView::GetDisplay() const -> WaveTrackDisplay { - auto display = mDisplay; - std::shared_ptr pSubView; + // To do: make the return a vector of values. For now, just report the + // last sub-view that is visible. + WaveTrackDisplay display{ WaveTrackViewConstants::NoDisplay }; + size_t ii = 0; + WaveTrackSubViews::ForEach( [&]( const WaveTrackSubView &subView ){ + if ( mPlacements[ii].fraction > 0 ) + display = subView.SubViewType(); + ++ii; + } ); + return display; +} + +void WaveTrackView::SetDisplay(WaveTrackDisplay display) +{ + size_t ii = 0; WaveTrackSubViews::ForEach( [&,display]( WaveTrackSubView &subView ){ if ( subView.SubViewType() == display ) - pSubView = subView.shared_from_this(); + mPlacements[ii] = { 0, 1.0 }; + else + mPlacements[ii] = { -1, 0.0 }; + ++ii; } ); - if ( !pSubView ) - return {}; - return { - { - rect.GetTop(), - pSubView - } - }; +} + +auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement +{ + // Collect the visible views + using Pair = std::pair< float, std::shared_ptr< TrackView > >; + std::vector< Pair > pairs( mPlacements.size() ); + size_t ii = 0; + float total = 0; + WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){ + const auto &placement = mPlacements[ii]; + auto index = placement.index; + auto fraction = placement.fraction; + if ( index >= 0 && fraction > 0.0 ) + total += fraction, + pairs[ index ] = { fraction, subView.shared_from_this() }; + ++ii; + } ); + + // Remove views we don't need + auto begin = pairs.begin(), end = pairs.end(), + newEnd = std::remove_if( begin, end, + []( const Pair &item ){ return !item.second; } ); + pairs.erase( newEnd, end ); + + // Assign coordinates + Refinement results; + results.reserve( pairs.size() ); + float partial = 0; + const auto top = rect.GetTop(); + const auto height = rect.GetHeight(); + for ( const auto &pair : pairs ) { + results.emplace_back( top + (partial / total) * height, pair.second ); + partial += pair.first; + } + + return results; } void WaveTrackView::DoSetMinimized( bool minimized ) diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h index b78dbccee..92ec347b2 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h @@ -24,6 +24,12 @@ public: virtual WaveTrackViewConstants::Display SubViewType() const = 0; }; +struct WaveTrackSubViewPlacement { + int index; + float fraction; +}; +using WaveTrackSubViewPlacements = std::vector< WaveTrackSubViewPlacement >; + class WaveTrackView; using WaveTrackSubViews = ClientData::Site< WaveTrackView, WaveTrackSubView, ClientData::SkipCopying, std::shared_ptr @@ -63,8 +69,13 @@ public: using WaveTrackDisplay = WaveTrackViewConstants::Display; - WaveTrackDisplay GetDisplay() const { return mDisplay; } - void SetDisplay(WaveTrackDisplay display) { mDisplay = display; } + WaveTrackDisplay GetDisplay() const; + void SetDisplay(WaveTrackDisplay display); + + const WaveTrackSubViewPlacements &SavePlacements() const + { return mPlacements; } + void RestorePlacements( const WaveTrackSubViewPlacements &placements ) + { mPlacements = placements; } private: // TrackPanelDrawable implementation @@ -83,7 +94,7 @@ private: protected: void DoSetMinimized( bool minimized ) override; - WaveTrackDisplay mDisplay; + WaveTrackSubViewPlacements mPlacements; }; // Helper for drawing routines