diff --git a/src/tracks/playabletrack/wavetrack/ui/SpectrumView.h b/src/tracks/playabletrack/wavetrack/ui/SpectrumView.h index 98d833a27..bbf05696c 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SpectrumView.h +++ b/src/tracks/playabletrack/wavetrack/ui/SpectrumView.h @@ -13,6 +13,8 @@ Paul Licameli split from WaveTrackView.h #include "../../../ui/CommonTrackView.h" // to inherit +class WaveTrack; + class SpectrumView final : public CommonTrackView { SpectrumView( const SpectrumView& ) = delete; @@ -35,9 +37,16 @@ private: const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool ) override; + static std::vector DoDetailedHitTest( + const TrackPanelMouseState &state, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &wt, + CommonTrackView &view); protected: void DoSetMinimized( bool minimized ) override; + + friend class WaveTrackView; }; #endif diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp index 80b579470..f6149e6c6 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp @@ -19,6 +19,8 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../WaveTrack.h" #include "WaveTrackControls.h" +#include "SpectrumVRulerControls.h" +#include "WaveformVRulerControls.h" #include "WaveTrackVRulerControls.h" #include "SpectrumView.h" @@ -60,12 +62,42 @@ std::vector SpectrumView::DetailedHitTest( const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool ) { - return {}; + const auto wt = std::static_pointer_cast< WaveTrack >( FindTrack() ); + return DoDetailedHitTest( state, pProject, currentTool, bMultiTool, wt, + *this ); +} + +std::vector SpectrumView::DoDetailedHitTest( + const TrackPanelMouseState &state, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &wt, + CommonTrackView &view) +{ + return WaveTrackView::DoDetailedHitTest( + state, pProject, currentTool, bMultiTool,wt, view + ).second; } std::vector WaveTrackView::DetailedHitTest (const TrackPanelMouseState &st, const AudacityProject *pProject, int currentTool, bool bMultiTool) +{ + const auto pTrack = std::static_pointer_cast< WaveTrack >( FindTrack() ); + bool isWaveform = (pTrack->GetDisplay() == WaveTrackViewConstants::Waveform); + if ( isWaveform ) + return WaveformView::DoDetailedHitTest( + st, pProject, currentTool, bMultiTool, pTrack, *this); + else + return SpectrumView::DoDetailedHitTest( + st, pProject, currentTool, bMultiTool, pTrack, *this); +} + +std::pair< bool, std::vector > +WaveTrackView::DoDetailedHitTest +(const TrackPanelMouseState &st, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &pTrack, + CommonTrackView &view) { // This is the only override of Track::DetailedHitTest that still // depends on the state of the Tools toolbar. @@ -74,26 +106,46 @@ std::vector WaveTrackView::DetailedHitTest UIHandlePtr result; std::vector results; - const auto pTrack = std::static_pointer_cast< WaveTrack >( FindTrack() ); - bool isWaveform = (pTrack->GetDisplay() == WaveTrackViewConstants::Waveform); if (bMultiTool && st.state.CmdDown()) { // Ctrl modifier key in multi-tool overrides everything else // (But this does not do the time shift constrained to the vertical only, // which is what happens when you hold Ctrl in the Time Shift tool mode) result = TimeShiftHandle::HitAnywhere( - mTimeShiftHandle, pTrack, false); + view.mTimeShiftHandle, pTrack, false); if (result) results.push_back(result); - return results; + return { true, results }; } + return { false, results }; +} - // Some special targets are not drawn in spectrogram, - // so don't hit them in such views. - else if (isWaveform) { +std::vector WaveformView::DetailedHitTest( + const TrackPanelMouseState &state, + const AudacityProject *pProject, int currentTool, bool bMultiTool ) +{ + const auto wt = std::static_pointer_cast< WaveTrack >( FindTrack() ); + return DoDetailedHitTest( state, pProject, currentTool, bMultiTool, wt, + *this ); +} + +std::vector WaveformView::DoDetailedHitTest( + const TrackPanelMouseState &st, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &wt, + CommonTrackView &view ) +{ + auto pair = WaveTrackView::DoDetailedHitTest( + st, pProject, currentTool, bMultiTool, wt, view); + auto &results = pair.second; + + if (!pair.first) { + const auto pTrack = + std::static_pointer_cast< WaveTrack >( view.FindTrack() ); + UIHandlePtr result; if (NULL != (result = CutlineHandle::HitTest( - mCutlineHandle, st.state, st.rect, + view.mCutlineHandle, st.state, st.rect, pProject, pTrack ))) // This overriding test applies in all tools results.push_back(result); @@ -103,16 +155,16 @@ std::vector WaveTrackView::DetailedHitTest // The priority of these, in case more than one might apply at one // point, seems arbitrary if (NULL != (result = EnvelopeHandle::WaveTrackHitTest( - mEnvelopeHandle, st.state, st.rect, + view.mEnvelopeHandle, st.state, st.rect, pProject, pTrack ))) results.push_back(result); if (NULL != (result = TimeShiftHandle::HitTest( - mTimeShiftHandle, st.state, st.rect, pTrack ))) + view.mTimeShiftHandle, st.state, st.rect, pTrack ))) // This is the hit test on the "grips" drawn left and // right in Multi only results.push_back(result); if (NULL != (result = SampleHandle::HitTest( - mSampleHandle, st.state, st.rect, + view.mSampleHandle, st.state, st.rect, pProject, pTrack ))) results.push_back(result); } @@ -123,12 +175,12 @@ std::vector WaveTrackView::DetailedHitTest case ToolCodes::envelopeTool: { auto envelope = pTrack->GetEnvelopeAtX( st.state.m_x ); result = EnvelopeHandle::HitAnywhere( - mEnvelopeHandle, envelope, false); + view.mEnvelopeHandle, envelope, false); break; } case ToolCodes::drawTool: result = SampleHandle::HitAnywhere( - mSampleHandle, st.state, pTrack ); + view.mSampleHandle, st.state, pTrack ); break; default: result = {}; @@ -139,22 +191,53 @@ std::vector WaveTrackView::DetailedHitTest } } - return results; -} - -std::vector WaveformView::DetailedHitTest( - const TrackPanelMouseState &state, - const AudacityProject *pProject, int currentTool, bool bMultiTool ) -{ - return {}; + return std::move( results ); } void SpectrumView::DoSetMinimized( bool minimized ) { + auto wt = static_cast( FindTrack().get() ); + +#ifdef EXPERIMENTAL_HALF_WAVE + bool bHalfWave; + gPrefs->Read(wxT("/GUI/CollapseToHalfWave"), &bHalfWave, false); + if( bHalfWave ) + { + // It is all right to set the top of scale to a huge number, + // not knowing the track rate here -- because when retrieving the + // value, then we pass in a sample rate and clamp it above to the + // Nyquist frequency. + constexpr auto max = std::numeric_limits::max(); + const bool spectrumLinear = + (wt->GetSpectrogramSettings().scaleType == + SpectrogramSettings::stLinear); + // Zoom out full + wt->SetSpectrumBounds( spectrumLinear ? 0.0f : 1.0f, max ); + } +#endif + + TrackView::DoSetMinimized( minimized ); } void WaveformView::DoSetMinimized( bool minimized ) { + auto wt = static_cast( FindTrack().get() ); + +#ifdef EXPERIMENTAL_HALF_WAVE + bool bHalfWave; + gPrefs->Read(wxT("/GUI/CollapseToHalfWave"), &bHalfWave, false); + if( bHalfWave ) + { + if (minimized) + // Zoom to show fractionally more than the top half of the wave. + wt->SetDisplayBounds( -0.01f, 1.0f ); + else + // Zoom out full + wt->SetDisplayBounds( -1.0f, 1.0f ); + } +#endif + + TrackView::DoSetMinimized( minimized ); } void WaveTrackView::DoSetMinimized( bool minimized ) @@ -204,12 +287,12 @@ static DoGetWaveTrackView registerDoGetWaveTrackView; std::shared_ptr WaveformView::DoGetVRulerControls() { - return {}; + return std::make_shared( shared_from_this() ); } std::shared_ptr SpectrumView::DoGetVRulerControls() { - return {}; + return std::make_shared( shared_from_this() ); } std::shared_ptr WaveTrackView::DoGetVRulerControls() @@ -1892,11 +1975,60 @@ void WaveTrackView::Reparent( const std::shared_ptr &parent ) void WaveformView::Draw( TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass ) { + if ( iPass == TrackArtist::PassTracks ) { + auto &dc = context.dc; + const auto wt = std::static_pointer_cast( + FindTrack()->SubstitutePendingChangedTrack()); + + for (const auto &clip : wt->GetClips()) { + clip->ClearDisplayRect(); + } + + const auto artist = TrackArtist::Get( context ); + const auto hasSolo = artist->hasSolo; + bool muted = (hasSolo || wt->GetMute()) && + !wt->GetSolo(); + +#if defined(__WXMAC__) + wxAntialiasMode aamode = dc.GetGraphicsContext()->GetAntialiasMode(); + dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE); +#endif + + DrawWaveform(context, wt.get(), rect, muted); + +#if defined(__WXMAC__) + dc.GetGraphicsContext()->SetAntialiasMode(aamode); +#endif + } + CommonTrackView::Draw( context, rect, iPass ); } void SpectrumView::Draw( TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass ) { + if ( iPass == TrackArtist::PassTracks ) { + auto &dc = context.dc; + const auto wt = std::static_pointer_cast( + FindTrack()->SubstitutePendingChangedTrack()); + + for (const auto &clip : wt->GetClips()) { + clip->ClearDisplayRect(); + } + + const auto artist = TrackArtist::Get( context ); + +#if defined(__WXMAC__) + wxAntialiasMode aamode = dc.GetGraphicsContext()->GetAntialiasMode(); + dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE); +#endif + + DrawSpectrum( context, wt.get(), rect ); + +#if defined(__WXMAC__) + dc.GetGraphicsContext()->SetAntialiasMode(aamode); +#endif + } + CommonTrackView::Draw( context, rect, iPass ); } void WaveTrackView::Draw( diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h index 234ddb684..eafdd4121 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.h @@ -13,9 +13,7 @@ Paul Licameli split from class WaveTrack #include "../../../ui/CommonTrackView.h" -class CutlineHandle; -class SampleHandle; -class EnvelopeHandle; +class WaveTrack; class WaveTrackView final : public CommonTrackView { @@ -43,15 +41,22 @@ private: (const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool) override; - - std::weak_ptr mCutlineHandle; - std::weak_ptr mSampleHandle; - std::weak_ptr mEnvelopeHandle; + static std::pair< + bool, // if true, hit-testing is finished + std::vector + > DoDetailedHitTest( + const TrackPanelMouseState &state, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &wt, + CommonTrackView &view); protected: void DoSetMinimized( bool minimized ) override; std::shared_ptr< CommonTrackView > mWaveformView, mSpectrumView; + + friend class SpectrumView; + friend class WaveformView; }; #endif diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveformView.h b/src/tracks/playabletrack/wavetrack/ui/WaveformView.h index 7d99d082e..743c675ce 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveformView.h +++ b/src/tracks/playabletrack/wavetrack/ui/WaveformView.h @@ -13,6 +13,8 @@ Paul Licameli split from WaveTrackView.h #include "../../../ui/CommonTrackView.h" // to inherit +class WaveTrack; + class WaveformView final : public CommonTrackView { WaveformView( const WaveformView& ) = delete; @@ -35,9 +37,16 @@ private: const TrackPanelMouseState &state, const AudacityProject *pProject, int currentTool, bool bMultiTool ) override; + static std::vector DoDetailedHitTest( + const TrackPanelMouseState &state, + const AudacityProject *pProject, int currentTool, bool bMultiTool, + const std::shared_ptr &wt, + CommonTrackView &view); protected: void DoSetMinimized( bool minimized ) override; + + friend class WaveTrackView; }; #endif diff --git a/src/tracks/ui/CommonTrackView.h b/src/tracks/ui/CommonTrackView.h index 325a81a7b..1863c3999 100644 --- a/src/tracks/ui/CommonTrackView.h +++ b/src/tracks/ui/CommonTrackView.h @@ -16,6 +16,10 @@ Paul Licameli split from class TrackView class SelectHandle; class TimeShiftHandle; +class CutlineHandle; +class SampleHandle; +class EnvelopeHandle; + class CommonTrackView /* not final */ : public TrackView { public: @@ -49,6 +53,13 @@ protected: std::weak_ptr mSelectHandle; std::weak_ptr mTimeShiftHandle; + + // Temporarily demoting these fields here from WaveTrackView + std::weak_ptr mCutlineHandle; + std::weak_ptr mSampleHandle; + std::weak_ptr mEnvelopeHandle; + friend class WaveformView; + friend class WaveTrackView; }; #endif