1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-18 17:10:05 +02:00

Test view class, not track display type, for spectral selection

This commit is contained in:
Paul Licameli 2019-07-05 19:57:09 -04:00
parent 357b593c66
commit 3715c079b4
7 changed files with 89 additions and 38 deletions

View File

@ -31,6 +31,11 @@ Paul Licameli split from WaveTrackView.cpp
SpectrumView::~SpectrumView() = default; SpectrumView::~SpectrumView() = default;
bool SpectrumView::IsSpectral() const
{
return true;
}
std::vector<UIHandlePtr> SpectrumView::DetailedHitTest( std::vector<UIHandlePtr> SpectrumView::DetailedHitTest(
const TrackPanelMouseState &state, const TrackPanelMouseState &state,
const AudacityProject *pProject, int currentTool, bool bMultiTool ) const AudacityProject *pProject, int currentTool, bool bMultiTool )

View File

@ -28,6 +28,7 @@ public:
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override; std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
bool IsSpectral() const override;
private: private:
// TrackPanelDrawable implementation // TrackPanelDrawable implementation

View File

@ -73,7 +73,7 @@ std::vector<UIHandlePtr> CommonTrackView::HitTest
// Finally, default of all is adjustment of the selection box. // Finally, default of all is adjustment of the selection box.
if ( isMultiTool || currentTool == selectTool ) { if ( isMultiTool || currentTool == selectTool ) {
result = SelectHandle::HitTest( result = SelectHandle::HitTest(
mSelectHandle, st, pProject, FindTrack() ); mSelectHandle, st, pProject, shared_from_this() );
if (result) if (result)
results.push_back(result); results.push_back(result);
} }

View File

@ -128,13 +128,16 @@ namespace
} }
// This returns true if we're a spectral editing track. // This returns true if we're a spectral editing track.
inline bool isSpectralSelectionTrack(const Track *pTrack) { inline bool isSpectralSelectionView(const TrackView *pTrackView) {
return pTrack && pTrack->TypeSwitch< bool >( [&](const WaveTrack *wt) { return
const SpectrogramSettings &settings = wt->GetSpectrogramSettings(); pTrackView &&
const int display = wt->GetDisplay(); pTrackView->IsSpectral() &&
return (display == WaveTrackViewConstants::Spectrum) && pTrackView->FindTrack() &&
settings.SpectralSelectionEnabled(); pTrackView->FindTrack()->TypeSwitch< bool >(
}); [&](const WaveTrack *wt) {
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
return settings.SpectralSelectionEnabled();
});
} }
enum SelectionBoundary { enum SelectionBoundary {
@ -187,7 +190,7 @@ namespace
SelectionBoundary ChooseBoundary SelectionBoundary ChooseBoundary
(const ViewInfo &viewInfo, (const ViewInfo &viewInfo,
wxCoord xx, wxCoord yy, const Track *pTrack, const wxRect &rect, wxCoord xx, wxCoord yy, const TrackView *pTrackView, const wxRect &rect,
bool mayDragWidth, bool onlyWithinSnapDistance, bool mayDragWidth, bool onlyWithinSnapDistance,
double *pPinValue = NULL) double *pPinValue = NULL)
{ {
@ -220,9 +223,11 @@ namespace
// within the time boundaries // within the time boundaries
if (!viewInfo.selectedRegion.isPoint() && if (!viewInfo.selectedRegion.isPoint() &&
t0 <= selend && selend < t1 && t0 <= selend && selend < t1 &&
isSpectralSelectionTrack(pTrack)) { isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave // Spectral selection track is always wave
const WaveTrack *const wt = static_cast<const WaveTrack*>(pTrack); auto pTrack = pTrackView->FindTrack();
const WaveTrack *const wt =
static_cast<const WaveTrack*>(pTrack.get());
const wxInt64 bottomSel = (f0 >= 0) const wxInt64 bottomSel = (f0 >= 0)
? FrequencyToPosition(wt, f0, rect.y, rect.height) ? FrequencyToPosition(wt, f0, rect.y, rect.height)
: rect.y + rect.height; : rect.y + rect.height;
@ -374,7 +379,7 @@ namespace
UIHandlePtr SelectHandle::HitTest UIHandlePtr SelectHandle::HitTest
(std::weak_ptr<SelectHandle> &holder, (std::weak_ptr<SelectHandle> &holder,
const TrackPanelMouseState &st, const AudacityProject *pProject, const TrackPanelMouseState &st, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack) const std::shared_ptr<TrackView> &pTrackView)
{ {
// This handle is a little special because there may be some state to // This handle is a little special because there may be some state to
// preserve during movement before the click. // preserve during movement before the click.
@ -393,13 +398,14 @@ UIHandlePtr SelectHandle::HitTest
const auto &viewInfo = ViewInfo::Get( *pProject ); const auto &viewInfo = ViewInfo::Get( *pProject );
auto result = std::make_shared<SelectHandle>( auto result = std::make_shared<SelectHandle>(
pTrack, oldUseSnap, TrackList::Get( *pProject ), st, viewInfo ); pTrackView, oldUseSnap, TrackList::Get( *pProject ), st, viewInfo );
result = AssignUIHandlePtr(holder, result); result = AssignUIHandlePtr(holder, result);
//Make sure we are within the selected track //Make sure we are within the selected track
// Adjusting the selection edges can be turned off in // Adjusting the selection edges can be turned off in
// the preferences... // the preferences...
auto pTrack = pTrackView->FindTrack();
if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges) if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
{ {
return result; return result;
@ -438,16 +444,17 @@ UIHandle::Result SelectHandle::NeedChangeHighlight
} }
SelectHandle::SelectHandle SelectHandle::SelectHandle
( const std::shared_ptr<Track> &pTrack, bool useSnap, ( const std::shared_ptr<TrackView> &pTrackView, bool useSnap,
const TrackList &trackList, const TrackList &trackList,
const TrackPanelMouseState &st, const ViewInfo &viewInfo ) const TrackPanelMouseState &st, const ViewInfo &viewInfo )
: mpTrack{ pTrack } : mpView{ pTrackView }
, mSnapManager{ std::make_shared<SnapManager>(&trackList, &viewInfo) } , mSnapManager{ std::make_shared<SnapManager>(&trackList, &viewInfo) }
{ {
const wxMouseState &state = st.state; const wxMouseState &state = st.state;
mRect = st.rect; mRect = st.rect;
auto time = std::max(0.0, viewInfo.PositionToTime(state.m_x, mRect.x)); auto time = std::max(0.0, viewInfo.PositionToTime(state.m_x, mRect.x));
auto pTrack = pTrackView->FindTrack();
mSnapStart = mSnapManager->Snap(pTrack.get(), time, false); mSnapStart = mSnapManager->Snap(pTrack.get(), time, false);
if (mSnapStart.snappedPoint) if (mSnapStart.snappedPoint)
mSnapStart.outCoord += mRect.x; mSnapStart.outCoord += mRect.x;
@ -531,8 +538,12 @@ UIHandle::Result SelectHandle::Click
using namespace RefreshCode; using namespace RefreshCode;
const auto pView = mpView.lock();
if ( !pView )
return Cancelled;
wxMouseEvent &event = evt.event; wxMouseEvent &event = evt.event;
const auto sTrack = TrackList::Get( *pProject ).Lock(mpTrack); const auto sTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
const auto pTrack = sTrack.get(); const auto pTrack = sTrack.get();
auto &trackPanel = TrackPanel::Get( *pProject ); auto &trackPanel = TrackPanel::Get( *pProject );
auto &viewInfo = ViewInfo::Get( *pProject ); auto &viewInfo = ViewInfo::Get( *pProject );
@ -620,7 +631,8 @@ UIHandle::Result SelectHandle::Click
double value; double value;
// Shift-click, choose closest boundary // Shift-click, choose closest boundary
SelectionBoundary boundary = SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, event.m_y, pTrack, mRect, false, false, &value); ChooseBoundary(viewInfo, xx, event.m_y,
pView.get(), mRect, false, false, &value);
mSelectionBoundary = boundary; mSelectionBoundary = boundary;
switch (boundary) { switch (boundary) {
case SBLeft: case SBLeft:
@ -686,7 +698,7 @@ UIHandle::Result SelectHandle::Click
if (viewInfo.bAdjustSelectionEdges) { if (viewInfo.bAdjustSelectionEdges) {
#ifdef EXPERIMENTAL_SPECTRAL_EDITING #ifdef EXPERIMENTAL_SPECTRAL_EDITING
if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER && if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
isSpectralSelectionTrack(pTrack)) { isSpectralSelectionView(pView.get())) {
// This code is no longer reachable, but it had a place in the // This code is no longer reachable, but it had a place in the
// spectral selection prototype. It used to be that you could be // spectral selection prototype. It used to be that you could be
// in a center-frequency-snapping mode that was not a mouse drag // in a center-frequency-snapping mode that was not a mouse drag
@ -714,7 +726,8 @@ UIHandle::Result SelectHandle::Click
// Not shift-down, choose boundary only within snapping // Not shift-down, choose boundary only within snapping
double value; double value;
SelectionBoundary boundary = SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, event.m_y, pTrack, mRect, true, true, &value); ChooseBoundary(viewInfo, xx, event.m_y,
pView.get(), mRect, true, true, &value);
mSelectionBoundary = boundary; mSelectionBoundary = boundary;
switch (boundary) { switch (boundary) {
case SBNone: case SBNone:
@ -766,7 +779,8 @@ UIHandle::Result SelectHandle::Click
// If we didn't move a selection boundary, start a NEW selection // If we didn't move a selection boundary, start a NEW selection
selectionState.SelectNone( trackList ); selectionState.SelectNone( trackList );
#ifdef EXPERIMENTAL_SPECTRAL_EDITING #ifdef EXPERIMENTAL_SPECTRAL_EDITING
StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height, pTrack); StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height,
pView.get());
#endif #endif
StartSelection(pProject); StartSelection(pProject);
selectionState.SelectTrack( *pTrack, true, true ); selectionState.SelectTrack( *pTrack, true, true );
@ -791,6 +805,10 @@ UIHandle::Result SelectHandle::Drag
{ {
using namespace RefreshCode; using namespace RefreshCode;
const auto pView = mpView.lock();
if ( !pView )
return Cancelled;
auto &viewInfo = ViewInfo::Get( *pProject ); auto &viewInfo = ViewInfo::Get( *pProject );
const wxMouseEvent &event = evt.event; const wxMouseEvent &event = evt.event;
@ -814,7 +832,7 @@ UIHandle::Result SelectHandle::Drag
} }
// Also fuhggeddaboudit if not in a track. // Also fuhggeddaboudit if not in a track.
auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack); auto pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
if (!pTrack) if (!pTrack)
return RefreshNone; return RefreshNone;
@ -850,7 +868,7 @@ UIHandle::Result SelectHandle::Drag
if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER && if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
!viewInfo.selectedRegion.isPoint()) !viewInfo.selectedRegion.isPoint())
MoveSnappingFreqSelection MoveSnappingFreqSelection
(pProject, viewInfo, y, mRect.y, mRect.height, pTrack.get()); (pProject, viewInfo, y, mRect.y, mRect.height, pView.get());
else else
#endif #endif
if ( TrackList::Get( *pProject ).Lock(mFreqSelTrack) == pTrack ) if ( TrackList::Get( *pProject ).Lock(mFreqSelTrack) == pTrack )
@ -883,7 +901,11 @@ HitTestPreview SelectHandle::Preview
// Moved out of snapping; revert to un-escaped state // Moved out of snapping; revert to un-escaped state
mUseSnap = true; mUseSnap = true;
auto pTrack = mpTrack.lock(); const auto pView = mpView.lock();
if ( !pView )
return {};
auto pTrack = FindTrack().lock();
if (!pTrack) if (!pTrack)
return {}; return {};
@ -937,7 +959,8 @@ HitTestPreview SelectHandle::Preview
// choose boundaries only in snapping tolerance, // choose boundaries only in snapping tolerance,
// and may choose center. // and may choose center.
SelectionBoundary boundary = SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, state.m_y, pTrack.get(), rect, !bModifierDown, !bModifierDown); ChooseBoundary(viewInfo, xx, state.m_y,
pView.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor); SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
} }
@ -949,7 +972,7 @@ HitTestPreview SelectHandle::Preview
// and drag width. // and drag width.
#ifdef EXPERIMENTAL_SPECTRAL_EDITING #ifdef EXPERIMENTAL_SPECTRAL_EDITING
if ((mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) && if ((mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) &&
isSpectralSelectionTrack(pTrack)) { isSpectralSelectionView(pView)) {
// Not shift-down, but center frequency snapping toggle is on // Not shift-down, but center frequency snapping toggle is on
tip = _("Click and drag to set frequency bandwidth."); tip = _("Click and drag to set frequency bandwidth.");
pCursor = &*envelopeCursor; pCursor = &*envelopeCursor;
@ -966,7 +989,8 @@ HitTestPreview SelectHandle::Preview
const bool bCtrlDown = state.ControlDown(); const bool bCtrlDown = state.ControlDown();
const bool bModifierDown = bShiftDown || bCtrlDown; const bool bModifierDown = bShiftDown || bCtrlDown;
SelectionBoundary boundary = ChooseBoundary( SelectionBoundary boundary = ChooseBoundary(
viewInfo, xx, state.m_y, pTrack.get(), rect, !bModifierDown, !bModifierDown); viewInfo, xx, state.m_y,
pView.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor); SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
} }
@ -1034,6 +1058,15 @@ wxRect SelectHandle::DrawingArea(
return rect; return rect;
} }
std::weak_ptr<Track> SelectHandle::FindTrack()
{
auto pView = mpView.lock();
if (!pView)
return {};
else
return pView->FindTrack();
}
void SelectHandle::Connect(AudacityProject *pProject) void SelectHandle::Connect(AudacityProject *pProject)
{ {
mTimerHandler = std::make_shared<TimerHandler>( this, pProject ); mTimerHandler = std::make_shared<TimerHandler>( this, pProject );
@ -1113,7 +1146,7 @@ void SelectHandle::TimerHandler::OnTimer(wxCommandEvent &event)
} }
} }
auto pTrack = mParent->mpTrack.lock(); // TrackList::Lock() ? auto pTrack = mParent->FindTrack().lock(); // TrackList::Lock() ?
if (mParent->mAutoScrolling && pTrack) { if (mParent->mAutoScrolling && pTrack) {
// AS: To keep the selection working properly as we scroll, // AS: To keep the selection working properly as we scroll,
// we fake a mouse event (remember, this method is called // we fake a mouse event (remember, this method is called
@ -1164,7 +1197,7 @@ void SelectHandle::AdjustSelection
auto pTrack = Track::SharedPointer( track ); auto pTrack = Track::SharedPointer( track );
if (!pTrack) if (!pTrack)
pTrack = TrackList::Get( *pProject ).Lock(mpTrack); pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
if (pTrack && mSnapManager.get()) { if (pTrack && mSnapManager.get()) {
bool rightEdge = (selend > mSelStart); bool rightEdge = (selend > mSelStart);
@ -1216,15 +1249,15 @@ void SelectHandle::AssignSelection
void SelectHandle::StartFreqSelection(ViewInfo &viewInfo, void SelectHandle::StartFreqSelection(ViewInfo &viewInfo,
int mouseYCoordinate, int trackTopEdge, int mouseYCoordinate, int trackTopEdge,
int trackHeight, Track *pTrack) int trackHeight, TrackView *pTrackView)
{ {
mFreqSelTrack.reset(); mFreqSelTrack.reset();
mFreqSelMode = FREQ_SEL_INVALID; mFreqSelMode = FREQ_SEL_INVALID;
mFreqSelPin = SelectedRegion::UndefinedFrequency; mFreqSelPin = SelectedRegion::UndefinedFrequency;
if (isSpectralSelectionTrack(pTrack)) { if (isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave // Spectral selection track is always wave
auto shTrack = pTrack->SharedPointer<const WaveTrack>(); auto shTrack = pTrackView->FindTrack()->SharedPointer<const WaveTrack>();
mFreqSelTrack = shTrack; mFreqSelTrack = shTrack;
mFreqSelMode = FREQ_SEL_FREE; mFreqSelMode = FREQ_SEL_FREE;
mFreqSelPin = mFreqSelPin =
@ -1386,11 +1419,12 @@ void SelectHandle::StartSnappingFreqSelection
void SelectHandle::MoveSnappingFreqSelection void SelectHandle::MoveSnappingFreqSelection
(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate, (AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate,
int trackTopEdge, int trackTopEdge,
int trackHeight, Track *pTrack) int trackHeight, TrackView *pTrackView)
{ {
auto pTrack = pTrackView->FindTrack().get();
if (pTrack && if (pTrack &&
pTrack->GetSelected() && pTrack->GetSelected() &&
isSpectralSelectionTrack(pTrack)) { isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave // Spectral selection track is always wave
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack); WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
// PRL: // PRL:

View File

@ -21,6 +21,7 @@ class SelectionStateChanger;
class SnapManager; class SnapManager;
class SpectrumAnalyst; class SpectrumAnalyst;
class Track; class Track;
class TrackView;
class TrackList; class TrackList;
class ViewInfo; class ViewInfo;
class WaveTrack; class WaveTrack;
@ -32,7 +33,7 @@ class SelectHandle : public UIHandle
public: public:
explicit SelectHandle explicit SelectHandle
(const std::shared_ptr<Track> &pTrack, bool useSnap, (const std::shared_ptr<TrackView> &pTrackView, bool useSnap,
const TrackList &trackList, const TrackList &trackList,
const TrackPanelMouseState &st, const ViewInfo &viewInfo); const TrackPanelMouseState &st, const ViewInfo &viewInfo);
@ -41,7 +42,7 @@ public:
static UIHandlePtr HitTest static UIHandlePtr HitTest
(std::weak_ptr<SelectHandle> &holder, (std::weak_ptr<SelectHandle> &holder,
const TrackPanelMouseState &state, const AudacityProject *pProject, const TrackPanelMouseState &state, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack); const std::shared_ptr<TrackView> &pTrackView);
SelectHandle &operator=(const SelectHandle&) = default; SelectHandle &operator=(const SelectHandle&) = default;
@ -78,6 +79,8 @@ public:
const SelectHandle &newState); const SelectHandle &newState);
private: private:
std::weak_ptr<Track> FindTrack();
void Connect(AudacityProject *pProject); void Connect(AudacityProject *pProject);
void StartSelection(AudacityProject *pProject); void StartSelection(AudacityProject *pProject);
@ -89,7 +92,7 @@ private:
void StartFreqSelection void StartFreqSelection
(ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, (ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge,
int trackHeight, Track *pTrack); int trackHeight, TrackView *pTrackView);
void AdjustFreqSelection void AdjustFreqSelection
(const WaveTrack *wt, (const WaveTrack *wt,
ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge,
@ -104,7 +107,7 @@ private:
void MoveSnappingFreqSelection void MoveSnappingFreqSelection
(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate, (AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate,
int trackTopEdge, int trackTopEdge,
int trackHeight, Track *pTrack); int trackHeight, TrackView *pTrackView);
public: public:
// This is needed to implement a command assignable to keystrokes // This is needed to implement a command assignable to keystrokes
static void SnapCenterOnce static void SnapCenterOnce
@ -124,7 +127,7 @@ private:
// (const ViewInfo &viewInfo, double hintFrequency, bool logF); // (const ViewInfo &viewInfo, double hintFrequency, bool logF);
std::weak_ptr<Track> mpTrack; std::weak_ptr<TrackView> mpView;
wxRect mRect{}; wxRect mRect{};
SelectedRegion mInitialSelection{}; SelectedRegion mInitialSelection{};

View File

@ -114,6 +114,11 @@ auto TrackView::GetSubViews( const wxRect &rect ) -> Refinement
return { { rect.GetTop(), shared_from_this() } }; return { { rect.GetTop(), shared_from_this() } };
} }
bool TrackView::IsSpectral() const
{
return false;
}
void TrackView::DoSetMinimized(bool isMinimized) void TrackView::DoSetMinimized(bool isMinimized)
{ {
mMinimized = isMinimized; mMinimized = isMinimized;

View File

@ -73,6 +73,9 @@ public:
> >; > >;
virtual Refinement GetSubViews( const wxRect &rect ); virtual Refinement GetSubViews( const wxRect &rect );
// default is false
virtual bool IsSpectral() const;
virtual void DoSetMinimized( bool isMinimized ); virtual void DoSetMinimized( bool isMinimized );
protected: protected: