Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
SelectHandle Class Reference

#include <SelectHandle.h>

Inheritance diagram for SelectHandle:
[legend]
Collaboration diagram for SelectHandle:
[legend]

Classes

class  TimerHandler
 

Public Member Functions

 SelectHandle (const std::shared_ptr< ChannelView > &pChannelView, bool useSnap, const TrackList &trackList, const TrackPanelMouseState &st, const ViewInfo &viewInfo)
 
SelectHandleoperator= (const SelectHandle &)=default
 
virtual ~SelectHandle ()
 
std::shared_ptr< const ChannelFindChannel () const override
 
bool IsDragging () const override
 
void SetUseSnap (bool use, AudacityProject *pProject)
 
void Enter (bool forward, AudacityProject *pProject) override
 
bool HasSnap () const
 
bool HasEscape (AudacityProject *pProject) const override
 
bool Escape (AudacityProject *pProject) override
 
Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject) override
 
Result Drag (const TrackPanelMouseEvent &event, AudacityProject *pProject) override
 
HitTestPreview Preview (const TrackPanelMouseState &state, AudacityProject *pProject) override
 
Result Release (const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
 
Result Cancel (AudacityProject *) override
 
- Public Member Functions inherited from UIHandle
virtual ~UIHandle ()=0
 
virtual void Enter (bool forward, AudacityProject *pProject)
 
virtual bool HasRotation () const
 
virtual bool Rotate (bool forward)
 
virtual bool HasEscape (AudacityProject *pProject) const
 
virtual bool Escape (AudacityProject *pProject)
 
virtual bool HandlesRightClick ()
 Whether the handle has any special right-button handling. More...
 
virtual Result Click (const TrackPanelMouseEvent &event, AudacityProject *pProject)=0
 
virtual Result Drag (const TrackPanelMouseEvent &event, AudacityProject *pProject)=0
 
virtual HitTestPreview Preview (const TrackPanelMouseState &state, AudacityProject *pProject)=0
 
virtual Result Release (const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent)=0
 
virtual Result Cancel (AudacityProject *pProject)=0
 
virtual bool StopsOnKeystroke ()
 
virtual void OnProjectChange (AudacityProject *pProject)
 
virtual std::shared_ptr< const ChannelFindChannel () const =0
 
virtual bool IsDragging () const
 
Result GetChangeHighlight () const
 
void SetChangeHighlight (Result val)
 
- Public Member Functions inherited from TrackPanelDrawable
virtual ~TrackPanelDrawable ()=0
 
virtual void Draw (TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass)
 
virtual wxRect DrawingArea (TrackPanelDrawingContext &context, const wxRect &rect, const wxRect &panelRect, unsigned iPass)
 

Static Public Member Functions

static UIHandlePtr HitTest (std::weak_ptr< SelectHandle > &holder, const TrackPanelMouseState &state, const AudacityProject *pProject, const std::shared_ptr< ChannelView > &pChannelView)
 
static UIHandle::Result NeedChangeHighlight (const SelectHandle &oldState, const SelectHandle &newState)
 
static void SnapCenterOnce (SpectrumAnalyst &analyst, ViewInfo &viewInfo, const WaveTrack *pTrack, bool up)
 
- Static Public Member Functions inherited from UIHandle
static UIHandle::Result NeedChangeHighlight (const UIHandle &, const UIHandle &)
 
- Static Public Member Functions inherited from TrackPanelDrawable
static wxRect MaximizeWidth (const wxRect &rect, const wxRect &panelRect)
 
static wxRect MaximizeHeight (const wxRect &rect, const wxRect &panelRect)
 

Private Types

enum  eFreqSelMode {
  FREQ_SEL_INVALID , FREQ_SEL_SNAPPING_CENTER , FREQ_SEL_PINNED_CENTER , FREQ_SEL_DRAG_CENTER ,
  FREQ_SEL_FREE , FREQ_SEL_TOP_FREE , FREQ_SEL_BOTTOM_FREE
}
 

Private Member Functions

 SelectHandle (const SelectHandle &)
 
std::weak_ptr< TrackFindTrack ()
 
void Connect (AudacityProject *pProject)
 
void StartSelection (AudacityProject *pProject)
 Reset our selection markers. More...
 
void AdjustSelection (AudacityProject *pProject, ViewInfo &viewInfo, int mouseXCoordinate, int trackLeftEdge, Track *pTrack)
 Extend or contract the existing selection. More...
 
void AssignSelection (ViewInfo &viewInfo, double selend, Track *pTrack)
 
void StartFreqSelection (ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, ChannelView *pChannelView)
 
void AdjustFreqSelection (const WaveTrack *wt, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight)
 
void HandleCenterFrequencyClick (const ViewInfo &viewInfo, bool shiftDown, const WaveTrack *pTrack, double value)
 
void MoveSnappingFreqSelection (AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, ChannelView *pChannelView)
 
void Draw (TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
 
wxRect DrawingArea (TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
 

Static Private Member Functions

static void StartSnappingFreqSelection (SpectrumAnalyst &analyst, const ViewInfo &viewInfo, const WaveTrack *pTrack)
 

Private Attributes

std::weak_ptr< ChannelViewmpView
 
wxRect mRect {}
 
SelectedRegion mInitialSelection {}
 
std::shared_ptr< SnapManagermSnapManager
 
SnapResults mSnapStart
 
SnapResults mSnapEnd
 
bool mUseSnap { true }
 
bool mSelStartValid {}
 
double mSelStart { 0.0 }
 
int mSelectionBoundary { 0 }
 
enum SelectHandle::eFreqSelMode FREQ_SEL_INVALID
 
std::weak_ptr< const WaveTrackmFreqSelTrack
 
double mFreqSelPin { -1.0 }
 
std::shared_ptr< SpectrumAnalystmFrequencySnapper
 
int mMostRecentX { -1 }
 
int mMostRecentY { -1 }
 
bool mAutoScrolling {}
 
std::shared_ptr< SelectionStateChangermSelectionStateChanger
 
friend TimerHandler
 
std::shared_ptr< TimerHandlermTimerHandler
 

Additional Inherited Members

- Public Types inherited from UIHandle
using Result = unsigned
 
using Cell = TrackPanelCell
 
- Protected Attributes inherited from UIHandle
Result mChangeHighlight { 0 }
 

Detailed Description

Definition at line 30 of file SelectHandle.h.

Member Enumeration Documentation

◆ eFreqSelMode

Enumerator
FREQ_SEL_INVALID 
FREQ_SEL_SNAPPING_CENTER 
FREQ_SEL_PINNED_CENTER 
FREQ_SEL_DRAG_CENTER 
FREQ_SEL_FREE 
FREQ_SEL_TOP_FREE 
FREQ_SEL_BOTTOM_FREE 

Definition at line 146 of file SelectHandle.h.

146 {
148
152
156 } mFreqSelMode{ FREQ_SEL_INVALID };
enum SelectHandle::eFreqSelMode FREQ_SEL_INVALID
@ FREQ_SEL_SNAPPING_CENTER
Definition: SelectHandle.h:149
@ FREQ_SEL_PINNED_CENTER
Definition: SelectHandle.h:150

Constructor & Destructor Documentation

◆ SelectHandle() [1/2]

SelectHandle::SelectHandle ( const SelectHandle )
private

◆ SelectHandle() [2/2]

SelectHandle::SelectHandle ( const std::shared_ptr< ChannelView > &  pChannelView,
bool  useSnap,
const TrackList trackList,
const TrackPanelMouseState st,
const ViewInfo viewInfo 
)

Definition at line 432 of file SelectHandle.cpp.

436 : mpView{ pChannelView }
437 // Selection dragging can snap to play region boundaries
438 , mSnapManager{ std::make_shared<SnapManager>(
439 *trackList.GetOwner(), trackList, viewInfo, SnapPointArray{
440 SnapPoint{ viewInfo.playRegion.GetLastActiveStart() },
441 SnapPoint{ viewInfo.playRegion.GetLastActiveEnd() },
442 } ) }
443{
444 const wxMouseState &state = st.state;
445 mRect = st.rect;
446
447 auto time = std::max(0.0, viewInfo.PositionToTime(state.m_x, mRect.x));
448 auto pTrack = pChannelView->FindTrack();
449 mSnapStart = mSnapManager->Snap(pTrack.get(), time, false);
452 else
453 mSnapStart.outCoord = -1;
454
455 mUseSnap = useSnap;
456}
std::vector< SnapPoint > SnapPointArray
Definition: Snap.h:43
SnapResults mSnapStart
Definition: SelectHandle.h:138
std::weak_ptr< ChannelView > mpView
Definition: SelectHandle.h:133
std::shared_ptr< SnapManager > mSnapManager
Definition: SelectHandle.h:137
Definition: Snap.h:31
AudacityProject * GetOwner()
Definition: Track.h:1014
double PositionToTime(int64 position, int64 origin=0, bool ignoreFisheye=false) const
Definition: ZoomInfo.cpp:34
wxInt64 outCoord
Definition: Snap.h:48
bool snappedPoint
Definition: Snap.h:49

References mRect, mSnapManager, mSnapStart, mUseSnap, SnapResults::outCoord, ZoomInfo::PositionToTime(), TrackPanelMouseState::rect, SnapResults::snappedPoint, and TrackPanelMouseState::state.

Here is the call graph for this function:

◆ ~SelectHandle()

SelectHandle::~SelectHandle ( )
virtual

Definition at line 458 of file SelectHandle.cpp.

459{
460}

Member Function Documentation

◆ AdjustFreqSelection()

void SelectHandle::AdjustFreqSelection ( const WaveTrack wt,
ViewInfo viewInfo,
int  mouseYCoordinate,
int  trackTopEdge,
int  trackHeight 
)
private

Definition at line 1255 of file SelectHandle.cpp.

1259{
1260 if (mFreqSelMode == FREQ_SEL_INVALID ||
1261 mFreqSelMode == FREQ_SEL_SNAPPING_CENTER)
1262 return;
1263
1264 // Extension happens only when dragging in the same track in which we
1265 // started, and that is of a spectrogram display type.
1266
1267 const double rate = wt->GetRate();
1268 const double frequency =
1269 PositionToFrequency(wt, true, mouseYCoordinate,
1270 trackTopEdge, trackHeight);
1271
1272 // Dragging center?
1273 if (mFreqSelMode == FREQ_SEL_DRAG_CENTER) {
1274 if (frequency == rate || frequency < 1.0)
1275 // snapped to top or bottom
1279 else {
1280 // mFreqSelPin holds the ratio of top to center
1281 const double maxRatio = findMaxRatio(frequency, rate);
1282 const double ratio = std::min(maxRatio, mFreqSelPin);
1284 frequency / ratio, frequency * ratio);
1285 }
1286 }
1287 else if (mFreqSelMode == FREQ_SEL_PINNED_CENTER) {
1288 if (mFreqSelPin >= 0) {
1289 // Change both upper and lower edges leaving centre where it is.
1290 if (frequency == rate || frequency < 1.0)
1291 // snapped to top or bottom
1295 else {
1296 // Given center and mouse position, find ratio of the larger to the
1297 // smaller, limit that to the frequency scale bounds, and adjust
1298 // top and bottom accordingly.
1299 const double maxRatio = findMaxRatio(mFreqSelPin, rate);
1300 double ratio = frequency / mFreqSelPin;
1301 if (ratio < 1.0)
1302 ratio = 1.0 / ratio;
1303 ratio = std::min(maxRatio, ratio);
1305 mFreqSelPin / ratio, mFreqSelPin * ratio);
1306 }
1307 }
1308 }
1309 else {
1310 // Dragging of upper or lower.
1311 const bool bottomDefined =
1312 !(mFreqSelMode == FREQ_SEL_TOP_FREE && mFreqSelPin < 0);
1313 const bool topDefined =
1314 !(mFreqSelMode == FREQ_SEL_BOTTOM_FREE && mFreqSelPin < 0);
1315 if (!bottomDefined || (topDefined && mFreqSelPin < frequency)) {
1316 // Adjust top
1317 if (frequency == rate)
1318 // snapped high; upper frequency is undefined
1320 else
1321 viewInfo.selectedRegion.setF1(std::max(1.0, frequency));
1322
1324 }
1325 else {
1326 // Adjust bottom
1327 if (frequency < 1.0)
1328 // snapped low; lower frequency is undefined
1330 else
1331 viewInfo.selectedRegion.setF0(std::min(rate / 2.0, frequency));
1332
1334 }
1335 }
1336}
int min(int a, int b)
bool setF0(double f, bool maySwap=true)
Definition: ViewInfo.cpp:115
bool setFrequencies(double f0, double f1)
Definition: ViewInfo.cpp:105
bool setF1(double f, bool maySwap=true)
Definition: ViewInfo.cpp:125
double mFreqSelPin
Definition: SelectHandle.h:164
static const int UndefinedFrequency
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:215
double GetRate() const override
Definition: WaveTrack.cpp:1085
double findMaxRatio(double center, double rate)
double PositionToFrequency(const WaveTrack *wt, bool maySnap, wxInt64 mouseYCoordinate, wxInt64 trackTopEdge, int trackHeight)

References anonymous_namespace{SelectHandle.cpp}::findMaxRatio(), FREQ_SEL_BOTTOM_FREE, FREQ_SEL_DRAG_CENTER, FREQ_SEL_INVALID, FREQ_SEL_PINNED_CENTER, FREQ_SEL_SNAPPING_CENTER, FREQ_SEL_TOP_FREE, WaveTrack::GetRate(), mFreqSelPin, min(), anonymous_namespace{SelectHandle.cpp}::PositionToFrequency(), ViewInfo::selectedRegion, NotifyingSelectedRegion::setF0(), NotifyingSelectedRegion::setF1(), NotifyingSelectedRegion::setFrequencies(), and SelectedRegion::UndefinedFrequency.

Referenced by Click(), and Drag().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AdjustSelection()

void SelectHandle::AdjustSelection ( AudacityProject pProject,
ViewInfo viewInfo,
int  mouseXCoordinate,
int  trackLeftEdge,
Track pTrack 
)
private

Extend or contract the existing selection.

Definition at line 1177 of file SelectHandle.cpp.

1181{
1182 if (!mSelStartValid)
1183 // Must be dragging frequency bounds only.
1184 return;
1185
1186 double selend =
1187 std::max(0.0, viewInfo.PositionToTime(mouseXCoordinate, trackLeftEdge));
1188 double origSelend = selend;
1189
1190 auto pTrack = Track::SharedPointer( track );
1191 if (!pTrack)
1192 pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
1193
1194 if (pTrack && mSnapManager.get()) {
1195 bool rightEdge = (selend > mSelStart);
1196 mSnapEnd = mSnapManager->Snap(pTrack.get(), selend, rightEdge);
1197 if (mSnapEnd.Snapped()) {
1198 if (mUseSnap)
1199 selend = mSnapEnd.outTime;
1201 mSnapEnd.outCoord += trackLeftEdge;
1202 }
1204 mSnapEnd.outCoord = -1;
1205
1206 // Check if selection endpoints are too close together to snap (unless
1207 // using snap-to-time -- then we always accept the snap results)
1208 if (mSnapStart.outCoord >= 0 &&
1209 mSnapEnd.outCoord >= 0 &&
1210 std::abs(mSnapStart.outCoord - mSnapEnd.outCoord) < 3) {
1212 selend = origSelend;
1213 mSnapEnd.outCoord = -1;
1214 }
1215 }
1216 AssignSelection(viewInfo, selend, pTrack.get());
1217}
SnapResults mSnapEnd
Definition: SelectHandle.h:138
std::weak_ptr< Track > FindTrack()
void AssignSelection(ViewInfo &viewInfo, double selend, Track *pTrack)
bool mSelStartValid
Definition: SelectHandle.h:141
double mSelStart
Definition: SelectHandle.h:142
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:160
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1228
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
bool snappedTime
Definition: Snap.h:50
double outTime
Definition: Snap.h:47
bool Snapped() const
Definition: Snap.h:52

References AssignSelection(), FindTrack(), TrackList::Get(), TrackList::Lock(), mSelStart, mSelStartValid, mSnapEnd, mSnapManager, mSnapStart, mUseSnap, SnapResults::outCoord, SnapResults::outTime, ZoomInfo::PositionToTime(), Track::SharedPointer(), SnapResults::Snapped(), SnapResults::snappedPoint, and SnapResults::snappedTime.

Referenced by Click(), and Drag().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AssignSelection()

void SelectHandle::AssignSelection ( ViewInfo viewInfo,
double  selend,
Track pTrack 
)
private

Definition at line 1219 of file SelectHandle.cpp.

1221{
1222 double sel0, sel1;
1223 if (mSelStart < selend) {
1224 sel0 = mSelStart;
1225 sel1 = selend;
1226 }
1227 else {
1228 sel1 = mSelStart;
1229 sel0 = selend;
1230 }
1231
1232 viewInfo.selectedRegion.setTimes(sel0, sel1);
1233}
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51

References mSelStart, ViewInfo::selectedRegion, and NotifyingSelectedRegion::setTimes().

Referenced by AdjustSelection(), and SetUseSnap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Cancel()

UIHandle::Result SelectHandle::Cancel ( AudacityProject pProject)
overridevirtual

Implements UIHandle.

Definition at line 1022 of file SelectHandle.cpp.

1023{
1024 mSelectionStateChanger.reset();
1026
1028}
std::shared_ptr< SelectionStateChanger > mSelectionStateChanger
Definition: SelectHandle.h:171
SelectedRegion mInitialSelection
Definition: SelectHandle.h:135
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235

References ViewInfo::Get(), mInitialSelection, mSelectionStateChanger, RefreshCode::RefreshAll, and ViewInfo::selectedRegion.

Here is the call graph for this function:

◆ Click()

UIHandle::Result SelectHandle::Click ( const TrackPanelMouseEvent event,
AudacityProject pProject 
)
overridevirtual

This method gets called when we're handling selection and the mouse was just clicked.

Implements UIHandle.

Definition at line 531 of file SelectHandle.cpp.

533{
536
537 using namespace RefreshCode;
538
539 const auto pView = mpView.lock();
540 if ( !pView )
541 return Cancelled;
542
543 wxMouseEvent &event = evt.event;
544 auto &trackList = TrackList::Get(*pProject);
545 const auto sTrack = trackList.Lock(FindTrack());
546 const auto pTrack = sTrack.get();
547 const auto pLeader = *trackList.Find(pTrack);
548 auto &trackPanel = TrackPanel::Get(*pProject);
549 auto &viewInfo = ViewInfo::Get(*pProject);
550
551 mMostRecentX = event.m_x;
552 mMostRecentY = event.m_y;
553
554 bool selectChange = (
555 event.LeftDown() &&
556 event.ControlDown() &&
557 pTrack->TypeSwitch<bool>( [&](LabelTrack &){
558 // We should reach this, only in default of other hits on glyphs or
559 // text boxes.
560 bool bShift = event.ShiftDown();
561 bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive();
563 *pProject, *pTrack, bShift, true, !unsafe);
564 return true;
565 } )
566 );
567 if ( selectChange )
568 // Do not start a drag
569 return RefreshAll | Cancelled;
570
571 auto &selectionState = SelectionState::Get( *pProject );
572 if (event.LeftDClick() && !event.ShiftDown()) {
573 // Deselect all other tracks and select this one.
574 selectionState.SelectNone(trackList);
575
576 if (pLeader)
577 selectionState.SelectTrack(*pLeader, true, true);
578
579 // Default behavior: select whole track
581 viewInfo, *pLeader, SyncLockState::Get(*pProject).IsSyncLocked());
582
583 // Special case: if we're over a clip in a WaveTrack,
584 // select just that clip
585 pTrack->TypeSwitch( [&] ( WaveTrack &wt ) {
586 auto time = viewInfo.PositionToTime(event.m_x, mRect.x);
587 WaveClip *const selectedClip = wt.GetClipAtTime(time);
588 if (selectedClip) {
589 viewInfo.selectedRegion.setTimes(
590 selectedClip->GetPlayStartTime(), selectedClip->GetPlayEndTime());
591 }
592 } );
593
594 ProjectHistory::Get( *pProject ).ModifyState(false);
595
596 // Do not start a drag
597 return RefreshAll | Cancelled;
598 }
599 else if (!event.LeftDown())
600 return Cancelled;
601
602 mInitialSelection = viewInfo.selectedRegion;
603
605 std::make_shared<SelectionStateChanger>(selectionState, trackList);
606
608
609 bool bShiftDown = event.ShiftDown();
610 bool bCtrlDown = event.ControlDown();
611
613 auto xx = viewInfo.TimeToPosition(mSelStart, mRect.x);
614
615 // I. Shift-click adjusts an existing selection
616 if (bShiftDown || bCtrlDown) {
617 if (bShiftDown)
618 selectionState.ChangeSelectionOnShiftClick(trackList, *pTrack);
619 if( bCtrlDown ){
620 //Commented out bIsSelected toggles, as in Track Control Panel.
621 //bool bIsSelected = pTrack->GetSelected();
622 //Actual bIsSelected will always add.
623 bool bIsSelected = false;
624 // Don't toggle away the last selected track.
625 if (!bIsSelected || trackPanel.GetSelectedTrackCount() > 1)
626 if (pLeader)
627 selectionState.SelectTrack(*pLeader, !bIsSelected, true);
628 }
629
630 double value;
631 // Shift-click, choose closest boundary
632 SelectionBoundary boundary =
633 ChooseBoundary(viewInfo, xx, event.m_y,
634 pView.get(), mRect, false, false, &value);
635 mSelectionBoundary = boundary;
636 switch (boundary) {
637 case SBLeft:
638 case SBRight:
639 {
640#ifdef EXPERIMENTAL_SPECTRAL_EDITING
641 // If drag starts, change time selection only
642 // (also exit frequency snapping)
643 mFreqSelMode = FREQ_SEL_INVALID;
644#endif
645 mSelStartValid = true;
646 mSelStart = value;
648 AdjustSelection(pProject, viewInfo, event.m_x, mRect.x, pTrack);
649 break;
650 }
651#ifdef EXPERIMENTAL_SPECTRAL_EDITING
652 case SBBottom:
653 case SBTop:
654 {
655 mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
656 mFreqSelPin = value;
657 mFreqSelMode =
658 (boundary == SBBottom)
660
661 // Drag frequency only, not time:
662 mSelStartValid = false;
664 static_cast<WaveTrack*>(pTrack),
665 viewInfo, event.m_y, mRect.y, mRect.height);
666 break;
667 }
668 case SBCenter:
669 {
670 const auto wt = static_cast<const WaveTrack*>(pTrack);
671 HandleCenterFrequencyClick(viewInfo, true, wt, value);
672 break;
673 }
674#endif
675 default:
676 wxASSERT(false);
677 };
678
679 // For persistence of the selection change:
680 ProjectHistory::Get( *pProject ).ModifyState(false);
681
682 // Get timer events so we can auto-scroll
683 Connect(pProject);
684
685 // Full refresh since the label area may need to indicate
686 // newly selected tracks.
687 return RefreshAll;
688 }
689
690 // II. Unmodified click starts a NEW selection
691
692 //Make sure you are within the selected track
693 bool startNewSelection = true;
694 if (pTrack && pTrack->GetSelected()) {
695 // Adjusting selection edges can be turned off in the
696 // preferences now
697 if (viewInfo.bAdjustSelectionEdges) {
698#ifdef EXPERIMENTAL_SPECTRAL_EDITING
699 if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
700 isSpectralSelectionView(pView.get())) {
701 // This code is no longer reachable, but it had a place in the
702 // spectral selection prototype. It used to be that you could be
703 // in a center-frequency-snapping mode that was not a mouse drag
704 // but responded to mouse movements. Click exited that and dragged
705 // width instead. PRL.
706
707 // Ignore whether we are inside the time selection.
708 // Exit center-snapping, start dragging the width.
709 mFreqSelMode = FREQ_SEL_PINNED_CENTER;
710 mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
711 mFreqSelPin = viewInfo.selectedRegion.fc();
712 // Do not adjust time boundaries
713 mSelStartValid = false;
715 static_cast<WaveTrack*>(pTrack),
716 viewInfo, event.m_y, mRect.y, mRect.height);
717 // For persistence of the selection change:
718 ProjectHistory::Get( *pProject ).ModifyState(false);
719 mSelectionBoundary = SBWidth;
720 return RefreshNone;
721 }
722 else
723#endif
724 {
725 // Not shift-down, choose boundary only within snapping
726 double value;
727 SelectionBoundary boundary =
728 ChooseBoundary(viewInfo, xx, event.m_y,
729 pView.get(), mRect, true, true, &value);
730 mSelectionBoundary = boundary;
731 switch (boundary) {
732 case SBNone:
733 // startNewSelection remains true
734 break;
735 case SBLeft:
736 case SBRight:
737 startNewSelection = false;
738#ifdef EXPERIMENTAL_SPECTRAL_EDITING
739 // Disable frequency selection
740 mFreqSelMode = FREQ_SEL_INVALID;
741#endif
742 mSelStartValid = true;
743 mSelStart = value;
745 break;
746#ifdef EXPERIMENTAL_SPECTRAL_EDITING
747 case SBBottom:
748 case SBTop:
749 case SBWidth:
750 startNewSelection = false;
751 // Disable time selection
752 mSelStartValid = false;
753 mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
754 mFreqSelPin = value;
755 mFreqSelMode =
756 (boundary == SBWidth) ? FREQ_SEL_PINNED_CENTER :
757 (boundary == SBBottom) ? FREQ_SEL_BOTTOM_FREE :
759 break;
760 case SBCenter:
761 {
762 const auto wt = static_cast<const WaveTrack*>(pTrack);
763 HandleCenterFrequencyClick(viewInfo, false, wt, value);
764 startNewSelection = false;
765 break;
766 }
767#endif
768 default:
769 wxASSERT(false);
770 }
771 }
772 } // bAdjustSelectionEdges
773 }
774
775 // III. Common case for starting a NEW selection
776
777 if (startNewSelection) {
778 // If we didn't move a selection boundary, start a NEW selection
779 selectionState.SelectNone(trackList);
780#ifdef EXPERIMENTAL_SPECTRAL_EDITING
781 StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height,
782 pView.get());
783#endif
784 StartSelection(pProject);
785 if (pLeader)
786 selectionState.SelectTrack(*pLeader, true, true);
787 TrackFocus::Get(*pProject).Set(pTrack);
788
789 Connect(pProject);
790 return RefreshAll;
791 }
792 else {
793 Connect(pProject);
794 return RefreshAll;
795 }
796}
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
void HandleCenterFrequencyClick(const ViewInfo &viewInfo, bool shiftDown, const WaveTrack *pTrack, double value)
std::weak_ptr< const WaveTrack > mFreqSelTrack
Definition: SelectHandle.h:157
void StartFreqSelection(ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, ChannelView *pChannelView)
void AdjustSelection(AudacityProject *pProject, ViewInfo &viewInfo, int mouseXCoordinate, int trackLeftEdge, Track *pTrack)
Extend or contract the existing selection.
int mSelectionBoundary
Definition: SelectHandle.h:144
void AdjustFreqSelection(const WaveTrack *wt, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight)
void Connect(AudacityProject *pProject)
void StartSelection(AudacityProject *pProject)
Reset our selection markers.
static void SelectTrackLength(ViewInfo &viewInfo, Track &track, bool syncLocked)
static SelectionState & Get(AudacityProject &project)
bool IsSyncLocked() const
Definition: SyncLock.cpp:43
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:26
Track * Get()
Definition: TrackFocus.cpp:156
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:233
This allows multiple clips to be a part of one WaveTrack.
Definition: WaveClip.h:103
A Track that contains audio waveform data.
Definition: WaveTrack.h:222
const WaveClip * GetClipAtTime(double time) const
Definition: WaveTrack.cpp:3718
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
void DoListSelection(AudacityProject &project, Track &t, bool shift, bool ctrl, bool modifyState)
bool isSpectralSelectionView(const ChannelView *pChannelView)
SelectionBoundary ChooseBoundary(const ViewInfo &viewInfo, wxCoord xx, wxCoord yy, const ChannelView *pChannelView, const wxRect &rect, bool mayDragWidth, bool onlyWithinSnapDistance, double *pPinValue=NULL)
double timeSnappedTime
Definition: Snap.h:46

References AdjustFreqSelection(), AdjustSelection(), Cancelled, anonymous_namespace{SelectHandle.cpp}::ChooseBoundary(), Connect(), SelectUtilities::DoListSelection(), TrackPanelMouseEvent::event, FindTrack(), FREQ_SEL_BOTTOM_FREE, FREQ_SEL_INVALID, FREQ_SEL_PINNED_CENTER, FREQ_SEL_SNAPPING_CENTER, FREQ_SEL_TOP_FREE, TrackFocus::Get(), ProjectAudioIO::Get(), ProjectHistory::Get(), ViewInfo::Get(), SelectionState::Get(), SyncLockState::Get(), TrackList::Get(), TrackPanel::Get(), WaveTrack::GetClipAtTime(), HandleCenterFrequencyClick(), ProjectAudioIO::IsAudioActive(), anonymous_namespace{SelectHandle.cpp}::isSpectralSelectionView(), SyncLockState::IsSyncLocked(), mFreqSelPin, mFreqSelTrack, mInitialSelection, mMostRecentX, mMostRecentY, ProjectHistory::ModifyState(), mpView, mRect, mSelectionBoundary, mSelectionStateChanger, mSelStart, mSelStartValid, mSnapStart, mUseSnap, SnapResults::outTime, RefreshCode::RefreshAll, RefreshCode::RefreshNone, anonymous_namespace{SelectHandle.cpp}::SBLeft, anonymous_namespace{SelectHandle.cpp}::SBNone, anonymous_namespace{SelectHandle.cpp}::SBRight, SelectionState::SelectTrackLength(), StartFreqSelection(), StartSelection(), and SnapResults::timeSnappedTime.

Here is the call graph for this function:

◆ Connect()

void SelectHandle::Connect ( AudacityProject pProject)
private

Definition at line 1064 of file SelectHandle.cpp.

1065{
1066 mTimerHandler = std::make_shared<TimerHandler>( this, pProject );
1067}
std::shared_ptr< TimerHandler > mTimerHandler
Definition: SelectHandle.h:175

References mTimerHandler.

Referenced by Click().

Here is the caller graph for this function:

◆ Drag()

UIHandle::Result SelectHandle::Drag ( const TrackPanelMouseEvent event,
AudacityProject pProject 
)
overridevirtual

AS: If we're dragging to adjust a selection (or actually, if the screen is scrolling while you're selecting), we handle it here.

Implements UIHandle.

Definition at line 798 of file SelectHandle.cpp.

800{
801 using namespace RefreshCode;
802
803 const auto pView = mpView.lock();
804 if ( !pView )
805 return Cancelled;
806
807 auto &viewInfo = ViewInfo::Get( *pProject );
808 const wxMouseEvent &event = evt.event;
809
810 int x = mAutoScrolling ? mMostRecentX : event.m_x;
811 int y = mAutoScrolling ? mMostRecentY : event.m_y;
812 mMostRecentX = x;
813 mMostRecentY = y;
814
818
819 // Fuhggeddaboudit if we're not dragging and not autoscrolling.
820 if (!event.Dragging() && !mAutoScrolling)
821 return RefreshNone;
822
823 if (event.CmdDown()) {
824 // Ctrl-drag has no meaning, fuhggeddaboudit
825 // JKC YES it has meaning.
826 //return RefreshNone;
827 }
828
829 // Also fuhggeddaboudit if not in a track.
830 auto pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
831 if (!pTrack)
832 return RefreshNone;
833
834 // JKC: Logic to prevent a selection smaller than 5 pixels to
835 // prevent accidental dragging when selecting.
836 // (if user really wants a tiny selection, they should zoom in).
837 // Can someone make this value of '5' configurable in
838 // preferences?
839 enum { minimumSizedSelection = 5 }; //measured in pixels
840
841 // Might be dragging frequency bounds only, test
842 if (mSelStartValid) {
843 wxInt64 SelStart = viewInfo.TimeToPosition(mSelStart, mRect.x); //cvt time to pixels.
844 // Abandon this drag if selecting < 5 pixels.
845 if (wxLongLong(SelStart - x).Abs() < minimumSizedSelection)
846 return RefreshNone;
847 }
848
849 if (evt.pCell) {
850 if ( auto clickedTrack =
851 static_cast<CommonTrackPanelCell*>(evt.pCell.get())->FindTrack() ) {
852 // Handle which tracks are selected
853 Track *sTrack = pTrack.get();
854 Track *eTrack = clickedTrack.get();
855 auto &trackList = TrackList::Get( *pProject );
856 if ( sTrack && eTrack && !event.ControlDown() ) {
857 auto &selectionState = SelectionState::Get( *pProject );
858 selectionState.SelectRangeOfTracks( trackList, *sTrack, *eTrack );
859 }
860
861 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
862 #ifndef SPECTRAL_EDITING_ESC_KEY
863 if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
864 !viewInfo.selectedRegion.isPoint())
866 (pProject, viewInfo, y, mRect.y, mRect.height, pView.get());
867 else
868 #endif
869 if ( TrackList::Get( *pProject ).Lock(mFreqSelTrack) == pTrack )
871 static_cast<WaveTrack*>(pTrack.get()),
872 viewInfo, y, mRect.y, mRect.height);
873 #endif
874
875 AdjustSelection(pProject, viewInfo, x, mRect.x, clickedTrack.get());
876 }
877 }
878
879 return RefreshNone
880
881 // If scrubbing does not use the helper poller thread, then
882 // don't refresh at every mouse event, because it slows down seek-scrub.
883 // Instead, let OnTimer do it, which is often enough.
884 // And even if scrubbing does use the thread, then skipping refresh does not
885 // bring that advantage, but it is probably still a good idea anyway.
886
887 // | UpdateSelection
888
889 ;
890}
std::shared_ptr< Track > FindTrack()
bool mAutoScrolling
Definition: SelectHandle.h:169
void MoveSnappingFreqSelection(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge, int trackHeight, ChannelView *pChannelView)
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122

References AdjustFreqSelection(), AdjustSelection(), Cancelled, TrackPanelMouseEvent::event, CommonTrackPanelCell::FindTrack(), FindTrack(), FREQ_SEL_SNAPPING_CENTER, ViewInfo::Get(), SelectionState::Get(), TrackList::Get(), TrackList::Lock(), mAutoScrolling, mFreqSelTrack, mMostRecentX, mMostRecentY, MoveSnappingFreqSelection(), mpView, mRect, mSelStart, mSelStartValid, TrackPanelMouseEvent::pCell, and RefreshCode::RefreshNone.

Referenced by SelectHandle::TimerHandler::OnTimer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Draw()

void SelectHandle::Draw ( TrackPanelDrawingContext context,
const wxRect &  rect,
unsigned  iPass 
)
overrideprivatevirtual

Reimplemented from TrackPanelDrawable.

Definition at line 1030 of file SelectHandle.cpp.

1033{
1034 if ( iPass == TrackArtist::PassSnapping ) {
1035 auto &dc = context.dc;
1036 // Draw snap guidelines if we have any
1037 if ( mSnapManager ) {
1038 auto coord1 = (mUseSnap || IsDragging()) ? mSnapStart.outCoord : -1;
1039 auto coord2 = (!mUseSnap || !IsDragging()) ? -1 : mSnapEnd.outCoord;
1040 TrackArt::DrawSnapLines(&dc, coord1, coord2);
1041 }
1042 }
1043}
bool IsDragging() const override
AUDACITY_DLL_API void DrawSnapLines(wxDC *dc, wxInt64 snap0, wxInt64 snap1)
Definition: TrackArt.cpp:821

References TrackPanelDrawingContext::dc, TrackArt::DrawSnapLines(), IsDragging(), mSnapEnd, mSnapManager, mSnapStart, mUseSnap, SnapResults::outCoord, and TrackArtist::PassSnapping.

Here is the call graph for this function:

◆ DrawingArea()

wxRect SelectHandle::DrawingArea ( TrackPanelDrawingContext ,
const wxRect &  rect,
const wxRect &  panelRect,
unsigned  iPass 
)
overrideprivatevirtual

Reimplemented from TrackPanelDrawable.

Definition at line 1045 of file SelectHandle.cpp.

1048{
1049 if ( iPass == TrackArtist::PassSnapping )
1050 return MaximizeHeight( rect, panelRect );
1051 else
1052 return rect;
1053}
static wxRect MaximizeHeight(const wxRect &rect, const wxRect &panelRect)

References TrackPanelDrawable::MaximizeHeight(), and TrackArtist::PassSnapping.

Here is the call graph for this function:

◆ Enter()

void SelectHandle::Enter ( bool  forward,
AudacityProject pProject 
)
overridevirtual

Reimplemented from UIHandle.

Definition at line 488 of file SelectHandle.cpp.

489{
490 SetUseSnap(true, project);
491}
const auto project
void SetUseSnap(bool use, AudacityProject *pProject)

References project, and SetUseSnap().

Here is the call graph for this function:

◆ Escape()

bool SelectHandle::Escape ( AudacityProject pProject)
overridevirtual

Reimplemented from UIHandle.

Definition at line 522 of file SelectHandle.cpp.

523{
525 SetUseSnap(false, project);
526 return true;
527 }
528 return false;
529}
bool HasEscape(AudacityProject *pProject) const override

References HasEscape(), project, and SetUseSnap().

Here is the call graph for this function:

◆ FindChannel()

std::shared_ptr< const Channel > SelectHandle::FindChannel ( ) const
overridevirtual
Returns
pointer to associated channel, if any

Implements UIHandle.

Definition at line 462 of file SelectHandle.cpp.

463{
464 if (auto pView = mpView.lock())
465 return pView->FindChannel();
466 return nullptr;
467}

References mpView.

◆ FindTrack()

std::weak_ptr< Track > SelectHandle::FindTrack ( )
private

Definition at line 1055 of file SelectHandle.cpp.

1056{
1057 auto pView = mpView.lock();
1058 if (!pView)
1059 return {};
1060 else
1061 return pView->FindTrack();
1062}

References mpView.

Referenced by AdjustSelection(), Click(), Drag(), SelectHandle::TimerHandler::OnTimer(), and Preview().

Here is the caller graph for this function:

◆ HandleCenterFrequencyClick()

void SelectHandle::HandleCenterFrequencyClick ( const ViewInfo viewInfo,
bool  shiftDown,
const WaveTrack pTrack,
double  value 
)
private

Definition at line 1338 of file SelectHandle.cpp.

1340{
1341 if (shiftDown) {
1342 // Disable time selection
1343 mSelStartValid = false;
1344 mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
1345 mFreqSelPin = value;
1346 mFreqSelMode = FREQ_SEL_DRAG_CENTER;
1347 }
1348 else {
1349#ifndef SPECTRAL_EDITING_ESC_KEY
1350 // Start center snapping
1351 // Turn center snapping on (the only way to do this)
1352 mFreqSelMode = FREQ_SEL_SNAPPING_CENTER;
1353 // Disable time selection
1354 mSelStartValid = false;
1355 mFrequencySnapper = std::make_shared<SpectrumAnalyst>();
1357#endif
1358 }
1359}
std::shared_ptr< SpectrumAnalyst > mFrequencySnapper
Definition: SelectHandle.h:165
static void StartSnappingFreqSelection(SpectrumAnalyst &analyst, const ViewInfo &viewInfo, const WaveTrack *pTrack)

References FREQ_SEL_DRAG_CENTER, FREQ_SEL_SNAPPING_CENTER, mFreqSelPin, mFreqSelTrack, mFrequencySnapper, mSelStartValid, Track::SharedPointer(), and StartSnappingFreqSelection().

Referenced by Click().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HasEscape()

bool SelectHandle::HasEscape ( AudacityProject pProject) const
overridevirtual

Reimplemented from UIHandle.

Definition at line 517 of file SelectHandle.cpp.

518{
519 return HasSnap() && mUseSnap;
520}
bool HasSnap() const

References HasSnap(), and mUseSnap.

Referenced by Escape(), and Preview().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HasSnap()

bool SelectHandle::HasSnap ( ) const

Definition at line 511 of file SelectHandle.cpp.

512{
513 return
514 (IsDragging() ? mSnapEnd : mSnapStart).snappedPoint;
515}

References IsDragging(), mSnapEnd, and mSnapStart.

Referenced by HasEscape(), Preview(), and SetUseSnap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HitTest()

UIHandlePtr SelectHandle::HitTest ( std::weak_ptr< SelectHandle > &  holder,
const TrackPanelMouseState state,
const AudacityProject pProject,
const std::shared_ptr< ChannelView > &  pChannelView 
)
static

Definition at line 365 of file SelectHandle.cpp.

369{
370 // This handle is a little special because there may be some state to
371 // preserve during movement before the click.
372 auto old = holder.lock();
373 bool oldUseSnap = true;
374 if (old) {
375 // It should not have started listening to timer events
376 if( old->mTimerHandler ) {
377 wxASSERT(false);
378 // Handle this eventuality anyway, don't leave a dangling back-pointer
379 // in the attached event handler.
380 old->mTimerHandler.reset();
381 }
382 oldUseSnap = old->mUseSnap;
383 }
384
385 const auto &viewInfo = ViewInfo::Get( *pProject );
386 auto result = std::make_shared<SelectHandle>(
387 pChannelView, oldUseSnap, TrackList::Get(*pProject), st, viewInfo);
388
389 result = AssignUIHandlePtr(holder, result);
390
391 //Make sure we are within the selected track
392 // Adjusting the selection edges can be turned off in
393 // the preferences...
394 auto pTrack = pChannelView->FindTrack();
395 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
396 {
397 return result;
398 }
399
400 {
401 const wxRect &rect = st.rect;
402 wxInt64 leftSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t0(), rect.x);
403 wxInt64 rightSel = viewInfo.TimeToPosition(viewInfo.selectedRegion.t1(), rect.x);
404 // Something is wrong if right edge comes before left edge
405 wxASSERT(!(rightSel < leftSel));
406 static_cast<void>(leftSel); // Suppress unused variable warnings if not in debug-mode
407 static_cast<void>(rightSel);
408 }
409
410 return result;
411}
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:159

References AssignUIHandlePtr(), ViewInfo::Get(), TrackList::Get(), and TrackPanelMouseState::rect.

Referenced by CommonChannelView::HitTest(), NoteTrackAffordanceControls::HitTest(), and WaveTrackAffordanceControls::HitTest().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsDragging()

bool SelectHandle::IsDragging ( ) const
overridevirtual

Whether the handle is dragging, affecting other panel painting; default returns false

Reimplemented from UIHandle.

Definition at line 59 of file SelectHandle.cpp.

60{
61 return mSelectionStateChanger.get() != NULL;
62}

References mSelectionStateChanger.

Referenced by Draw(), HasSnap(), Preview(), and SetUseSnap().

Here is the caller graph for this function:

◆ MoveSnappingFreqSelection()

void SelectHandle::MoveSnappingFreqSelection ( AudacityProject pProject,
ViewInfo viewInfo,
int  mouseYCoordinate,
int  trackTopEdge,
int  trackHeight,
ChannelView pChannelView 
)
private

Definition at line 1404 of file SelectHandle.cpp.

1408{
1409 auto pTrack = pChannelView->FindTrack().get();
1410 if (pTrack &&
1411 pTrack->GetSelected() &&
1412 isSpectralSelectionView(pChannelView)) {
1413 // Spectral selection track is always wave
1414 WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
1415 // PRL:
1416 // What would happen if center snapping selection began in one spectrogram track,
1417 // then continues inside another? We do not then recalculate
1418 // the spectrum (as was done in StartSnappingFreqSelection)
1419 // but snap according to the peaks in the old track.
1420
1421 // But if we always supply the original clicked track here that doesn't matter.
1422 const double rate = wt->GetRate();
1423 const double frequency =
1424 PositionToFrequency(wt, false, mouseYCoordinate,
1425 trackTopEdge, trackHeight);
1426 const double snappedFrequency =
1427 mFrequencySnapper->FindPeak(frequency, NULL);
1428 const double maxRatio = findMaxRatio(snappedFrequency, rate);
1429 double ratio = 2.0; // An arbitrary octave on each side, at most
1430 {
1431 const double f0 = viewInfo.selectedRegion.f0();
1432 const double f1 = viewInfo.selectedRegion.f1();
1433 if (f1 >= f0 && f0 >= 0)
1434 // Preserve already chosen ratio instead
1435 ratio = sqrt(f1 / f0);
1436 }
1437 ratio = std::min(ratio, maxRatio);
1438
1439 mFreqSelPin = snappedFrequency;
1441 snappedFrequency / ratio, snappedFrequency * ratio);
1442
1443 // A change here would affect what AdjustFreqSelection() does
1444 // in the prototype version where you switch from moving center to
1445 // dragging width with a click. No effect now.
1446 mFreqSelTrack = wt->SharedPointer<const WaveTrack>();
1447
1448 // SelectNone();
1449 // SelectTrack(pTrack, true);
1450 TrackFocus::Get( *pProject ).Set(pTrack);
1451 }
1452}
double f1() const
Definition: ViewInfo.h:38
double f0() const
Definition: ViewInfo.h:37
__finl float_x4 __vecc sqrt(const float_x4 &a)

References NotifyingSelectedRegion::f0(), NotifyingSelectedRegion::f1(), anonymous_namespace{SelectHandle.cpp}::findMaxRatio(), CommonTrackPanelCell::FindTrack(), TrackFocus::Get(), WaveTrack::GetRate(), anonymous_namespace{SelectHandle.cpp}::isSpectralSelectionView(), mFreqSelPin, mFreqSelTrack, mFrequencySnapper, min(), anonymous_namespace{SelectHandle.cpp}::PositionToFrequency(), ViewInfo::selectedRegion, NotifyingSelectedRegion::setFrequencies(), Track::SharedPointer(), and staffpad::audio::simd::sqrt().

Referenced by Drag().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ NeedChangeHighlight()

UIHandle::Result SelectHandle::NeedChangeHighlight ( const SelectHandle oldState,
const SelectHandle newState 
)
static

Definition at line 413 of file SelectHandle.cpp.

415{
416 auto useSnap = oldState.mUseSnap;
417 // This is guaranteed when constructing the NEW handle:
418 wxASSERT( useSnap == newState.mUseSnap );
419 if (!useSnap)
420 return 0;
421
422 auto &oldSnapState = oldState.mSnapStart;
423 auto &newSnapState = newState.mSnapStart;
424 if ( oldSnapState.Snapped() == newSnapState.Snapped() &&
425 (!oldSnapState.Snapped() ||
426 oldSnapState.outCoord == newSnapState.outCoord) )
427 return 0;
428
430}

References mSnapStart, mUseSnap, and RefreshCode::RefreshAll.

◆ operator=()

SelectHandle & SelectHandle::operator= ( const SelectHandle )
default

◆ Preview()

HitTestPreview SelectHandle::Preview ( const TrackPanelMouseState state,
AudacityProject pProject 
)
overridevirtual

Implements UIHandle.

Definition at line 892 of file SelectHandle.cpp.

894{
895 if (!HasSnap() && !mUseSnap)
896 // Moved out of snapping; revert to un-escaped state
897 mUseSnap = true;
898
899 const auto pView = mpView.lock();
900 if ( !pView )
901 return {};
902
903 auto pTrack = FindTrack().lock();
904 if (!pTrack)
905 return {};
906
908 wxCursor *pCursor = SelectCursor();
909 if (IsDragging())
910 // Use same cursor as at the click
913 (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER),
914 tip, pCursor);
915 else {
916 // Choose one of many cursors for mouse-over
917
918 auto &viewInfo = ViewInfo::Get( *pProject );
919
920 auto &state = st.state;
922 auto xx = viewInfo.TimeToPosition(time, mRect.x);
923
924 const bool bMultiToolMode =
926
927 //In Multi-tool mode, give multitool prompt if no-special-hit.
928 if (bMultiToolMode) {
929 // Look up the current key binding for Preferences.
930 // (Don't assume it's the default!)
931 auto keyStr =
932 CommandManager::Get( *pProject ).GetKeyFromName(wxT("Preferences"))
933 .Display( true );
934 if (keyStr.empty())
935 // No keyboard preference defined for opening Preferences dialog
936 /* i18n-hint: These are the names of a menu and a command in that menu */
937 keyStr = _("Edit, Preferences...");
938
939 /* i18n-hint: %s is usually replaced by "Ctrl+P" for Windows/Linux, "Command+," for Mac */
940 tip = XO("Multi-Tool Mode: %s for Mouse and Keyboard Preferences.")
941 .Format( keyStr );
942 // Later in this function we may point to some other string instead.
943 if (!pTrack->GetSelected() ||
944 !viewInfo.bAdjustSelectionEdges)
945 ;
946 else {
947 const wxRect &rect = st.rect;
948 const bool bShiftDown = state.ShiftDown();
949 const bool bCtrlDown = state.ControlDown();
950 const bool bModifierDown = bShiftDown || bCtrlDown;
951
952 // If not shift-down and not snapping center, then
953 // choose boundaries only in snapping tolerance,
954 // and may choose center.
955 SelectionBoundary boundary =
956 ChooseBoundary(viewInfo, xx, state.m_y,
957 pView.get(), rect, !bModifierDown, !bModifierDown);
958
959 SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
960 }
961 }
962
963#if 0
964 // This is a vestige of an idea in the prototype version.
965 // Center would snap without mouse button down, click would pin the center
966 // and drag width.
967#ifdef EXPERIMENTAL_SPECTRAL_EDITING
968 if ((mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) &&
970 // Not shift-down, but center frequency snapping toggle is on
971 tip = XO("Click and drag to set frequency bandwidth.");
972 pCursor = &*envelopeCursor;
973 return {};
974 }
975#endif
976#endif
977
978 if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
979 ;
980 else {
981 const wxRect &rect = st.rect;
982 const bool bShiftDown = state.ShiftDown();
983 const bool bCtrlDown = state.ControlDown();
984 const bool bModifierDown = bShiftDown || bCtrlDown;
986 viewInfo, xx, state.m_y,
987 pView.get(), rect, !bModifierDown, !bModifierDown);
988 SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
989 }
990 }
991 if (tip.empty()) {
992 tip = XO("Click and drag to select audio");
993 }
994 if (HasEscape(pProject) && mUseSnap) {
995 tip.Join(
996/* i18n-hint: "Snapping" means automatic alignment of selection edges to any nearby label or clip boundaries */
997 XO("(snapping)"), wxT(" ")
998 );
999 }
1000 return { tip, pCursor };
1001}
wxT("CloseDown"))
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
static CommandManager & Get(AudacityProject &project)
NormalizedKeyString GetKeyFromName(const CommandID &name) const
static ProjectSettings & Get(AudacityProject &project)
int GetTool() const
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
void SetTipAndCursorForBoundary(SelectionBoundary boundary, bool frequencySnapping, TranslatableString &tip, wxCursor *&pCursor)
wxString Display(bool usesSpecialChars=false) const
Definition: Keyboard.cpp:56

References _, anonymous_namespace{SelectHandle.cpp}::ChooseBoundary(), NormalizedKeyString::Display(), TranslatableString::empty(), FindTrack(), FREQ_SEL_SNAPPING_CENTER, CommandManager::Get(), ViewInfo::Get(), ProjectSettings::Get(), CommandManager::GetKeyFromName(), ProjectSettings::GetTool(), HasEscape(), HasSnap(), IsDragging(), anonymous_namespace{SelectHandle.cpp}::isSpectralSelectionView(), TranslatableString::Join(), mpView, mRect, mSelectionBoundary, mSnapStart, ToolCodes::multiTool, mUseSnap, SnapResults::outTime, TrackPanelMouseState::rect, anonymous_namespace{SelectHandle.cpp}::SelectCursor(), anonymous_namespace{SelectHandle.cpp}::SetTipAndCursorForBoundary(), TrackPanelMouseState::state, SnapResults::timeSnappedTime, wxT(), and XO().

Here is the call graph for this function:

◆ Release()

UIHandle::Result SelectHandle::Release ( const TrackPanelMouseEvent event,
AudacityProject pProject,
wxWindow *  pParent 
)
overridevirtual

Implements UIHandle.

Definition at line 1003 of file SelectHandle.cpp.

1006{
1007 using namespace RefreshCode;
1008 ProjectHistory::Get( *pProject ).ModifyState(false);
1009 mFrequencySnapper.reset();
1010 mSnapManager.reset();
1012 mSelectionStateChanger->Commit();
1013 mSelectionStateChanger.reset();
1014 }
1015
1016 if (mUseSnap && (mSnapStart.outCoord != -1 || mSnapEnd.outCoord != -1))
1017 return RefreshAll;
1018 else
1019 return RefreshNone;
1020}

References ProjectHistory::Get(), mFrequencySnapper, ProjectHistory::ModifyState(), mSelectionStateChanger, mSnapEnd, mSnapManager, mSnapStart, mUseSnap, SnapResults::outCoord, RefreshCode::RefreshAll, and RefreshCode::RefreshNone.

Here is the call graph for this function:

◆ SetUseSnap()

void SelectHandle::SetUseSnap ( bool  use,
AudacityProject pProject 
)

Definition at line 493 of file SelectHandle.cpp.

494{
495 mUseSnap = use;
496
497 bool hasSnap = HasSnap();
498 if (hasSnap)
499 // Repaint to turn the snap lines on or off
501
502 if (IsDragging()) {
503 // Readjust the moving selection end
507 nullptr);
508 }
509}
Result mChangeHighlight
Definition: UIHandle.h:147

References AssignSelection(), ViewInfo::Get(), HasSnap(), IsDragging(), UIHandle::mChangeHighlight, mSnapEnd, mUseSnap, SnapResults::outTime, project, RefreshCode::RefreshAll, and SnapResults::timeSnappedTime.

Referenced by Enter(), and Escape().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SnapCenterOnce()

void SelectHandle::SnapCenterOnce ( SpectrumAnalyst analyst,
ViewInfo viewInfo,
const WaveTrack pTrack,
bool  up 
)
static

Definition at line 1454 of file SelectHandle.cpp.

1457{
1458 const auto &settings = SpectrogramSettings::Get(*pTrack);
1459 const auto windowSize = settings.GetFFTLength();
1460 const double rate = pTrack->GetRate();
1461 const double nyq = rate / 2.0;
1462 const double binFrequency = rate / windowSize;
1463
1464 double f1 = viewInfo.selectedRegion.f1();
1465 double centerFrequency = viewInfo.selectedRegion.fc();
1466 if (centerFrequency <= 0) {
1467 centerFrequency = up ? binFrequency : nyq;
1468 f1 = centerFrequency * sqrt(2.0);
1469 }
1470
1471 double ratio = f1 / centerFrequency;
1472 const int originalBin = floor(0.5 + centerFrequency / binFrequency);
1473 const int limitingBin = up ? floor(0.5 + nyq / binFrequency) : 1;
1474
1475 // This is crude and wasteful, doing the FFT each time the command is called.
1476 // It would be better to cache the data, but then invalidation of the cache would
1477 // need doing in all places that change the time selection.
1478 StartSnappingFreqSelection(analyst, viewInfo, pTrack);
1479 double snappedFrequency = centerFrequency;
1480 int bin = originalBin;
1481 if (up) {
1482 while (snappedFrequency <= centerFrequency &&
1483 bin < limitingBin)
1484 snappedFrequency = analyst.FindPeak(++bin * binFrequency, NULL);
1485 }
1486 else {
1487 while (snappedFrequency >= centerFrequency &&
1488 bin > limitingBin)
1489 snappedFrequency = analyst.FindPeak(--bin * binFrequency, NULL);
1490 }
1491
1492 // PRL: added these two lines with the big TrackPanel refactor
1493 const double maxRatio = findMaxRatio(snappedFrequency, rate);
1494 ratio = std::min(ratio, maxRatio);
1495
1497 (snappedFrequency / ratio, snappedFrequency * ratio);
1498}
static Settings & settings()
Definition: TrackInfo.cpp:69
double fc() const
Definition: ViewInfo.h:39
static SpectrogramSettings & Get(const WaveTrack &track)
Mutative access to attachment even if the track argument is const.
float FindPeak(float xPos, float *pY) const

References NotifyingSelectedRegion::f1(), NotifyingSelectedRegion::fc(), anonymous_namespace{SelectHandle.cpp}::findMaxRatio(), SpectrumAnalyst::FindPeak(), SpectrogramSettings::Get(), WaveTrack::GetRate(), min(), ViewInfo::selectedRegion, NotifyingSelectedRegion::setFrequencies(), settings(), staffpad::audio::simd::sqrt(), and StartSnappingFreqSelection().

Here is the call graph for this function:

◆ StartFreqSelection()

void SelectHandle::StartFreqSelection ( ViewInfo viewInfo,
int  mouseYCoordinate,
int  trackTopEdge,
int  trackHeight,
ChannelView pChannelView 
)
private

Definition at line 1235 of file SelectHandle.cpp.

1238{
1239 mFreqSelTrack.reset();
1240 mFreqSelMode = FREQ_SEL_INVALID;
1242
1243 if (isSpectralSelectionView(pChannelView)) {
1244 // Spectral selection track is always wave
1245 auto shTrack = pChannelView->FindTrack()->SharedPointer<const WaveTrack>();
1246 mFreqSelTrack = shTrack;
1247 mFreqSelMode = FREQ_SEL_FREE;
1248 mFreqSelPin =
1249 PositionToFrequency(shTrack.get(), false, mouseYCoordinate,
1250 trackTopEdge, trackHeight);
1252 }
1253}

References CommonTrackPanelCell::FindTrack(), FREQ_SEL_FREE, FREQ_SEL_INVALID, anonymous_namespace{SelectHandle.cpp}::isSpectralSelectionView(), mFreqSelPin, mFreqSelTrack, anonymous_namespace{SelectHandle.cpp}::PositionToFrequency(), ViewInfo::selectedRegion, NotifyingSelectedRegion::setFrequencies(), and SelectedRegion::UndefinedFrequency.

Referenced by Click().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartSelection()

void SelectHandle::StartSelection ( AudacityProject pProject)
private

Reset our selection markers.

Definition at line 1162 of file SelectHandle.cpp.

1163{
1164 auto &viewInfo = ViewInfo::Get( *pProject );
1165 mSelStartValid = true;
1166
1167 viewInfo.selectedRegion.setTimes(mSelStart, mSelStart);
1168
1169 // PRL: commented out the Sonify stuff with the TrackPanel refactor.
1170 // It was no-op anyway.
1171 //SonifyBeginModifyState();
1172 ProjectHistory::Get( *pProject ).ModifyState(false);
1173 //SonifyEndModifyState();
1174}

References ProjectHistory::Get(), ViewInfo::Get(), ProjectHistory::ModifyState(), mSelStart, and mSelStartValid.

Referenced by Click().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ StartSnappingFreqSelection()

void SelectHandle::StartSnappingFreqSelection ( SpectrumAnalyst analyst,
const ViewInfo viewInfo,
const WaveTrack pTrack 
)
staticprivate

Definition at line 1361 of file SelectHandle.cpp.

1364{
1365 static const size_t minLength = 8;
1366
1367 const double rate = pTrack->GetRate();
1368
1369 // Grab samples, just for this track, at these times
1370 std::vector<float> frequencySnappingData;
1371 const auto start =
1372 pTrack->TimeToLongSamples(viewInfo.selectedRegion.t0());
1373 const auto end =
1374 pTrack->TimeToLongSamples(viewInfo.selectedRegion.t1());
1375 const auto length =
1376 std::min(frequencySnappingData.max_size(),
1377 limitSampleBufferSize(10485760, // as in FreqWindow.cpp
1378 end - start));
1379 const auto effectiveLength = std::max(minLength, length);
1380 frequencySnappingData.resize(effectiveLength, 0.0f);
1381 pTrack->GetFloats(
1382 &frequencySnappingData[0],
1383 start, length, FillFormat::fillZero,
1384 // Don't try to cope with exceptions, just read zeroes instead.
1385 false);
1386
1387 // Use same settings as are now used for spectrogram display,
1388 // except, shrink the window as needed so we get some answers
1389
1390 const auto &settings = SpectrogramSettings::Get(*pTrack);
1391 auto windowSize = settings.GetFFTLength();
1392
1393 while(windowSize > effectiveLength)
1394 windowSize >>= 1;
1395 const int windowType = settings.windowType;
1396
1397 analyst.Calculate(
1398 SpectrumAnalyst::Spectrum, windowType, windowSize, rate,
1399 &frequencySnappingData[0], length);
1400
1401 // We can now throw away the sample data but we keep the spectrum.
1402}
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
Definition: SampleCount.cpp:22
double t1() const
Definition: ViewInfo.h:36
double t0() const
Definition: ViewInfo.h:35
bool Calculate(Algorithm alg, int windowFunc, size_t windowSize, double rate, const float *data, size_t dataLen, float *pYMin=NULL, float *pYMax=NULL, FreqGauge *progress=NULL)
bool GetFloats(float *buffer, sampleCount start, size_t len, fillFormat fill=FillFormat::fillZero, bool mayThrow=true, sampleCount *pNumWithinClips=nullptr) const
"narrow" overload fetches first channel only
Definition: SampleTrack.h:46
sampleCount TimeToLongSamples(double t0) const
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159

References SpectrumAnalyst::Calculate(), PackedArray::end(), fillZero, SpectrogramSettings::Get(), WaveTrack::GetFloats(), WaveTrack::GetRate(), limitSampleBufferSize(), min(), ViewInfo::selectedRegion, settings(), SpectrumAnalyst::Spectrum, NotifyingSelectedRegion::t0(), NotifyingSelectedRegion::t1(), and WideSampleSequence::TimeToLongSamples().

Referenced by HandleCenterFrequencyClick(), and SnapCenterOnce().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ FREQ_SEL_INVALID

enum SelectHandle::eFreqSelMode SelectHandle::FREQ_SEL_INVALID
private

◆ mAutoScrolling

bool SelectHandle::mAutoScrolling {}
private

Definition at line 169 of file SelectHandle.h.

Referenced by Drag(), and SelectHandle::TimerHandler::OnTimer().

◆ mFreqSelPin

double SelectHandle::mFreqSelPin { -1.0 }
private

◆ mFreqSelTrack

std::weak_ptr<const WaveTrack> SelectHandle::mFreqSelTrack
private

◆ mFrequencySnapper

std::shared_ptr<SpectrumAnalyst> SelectHandle::mFrequencySnapper
private

Definition at line 165 of file SelectHandle.h.

Referenced by HandleCenterFrequencyClick(), MoveSnappingFreqSelection(), and Release().

◆ mInitialSelection

SelectedRegion SelectHandle::mInitialSelection {}
private

Definition at line 135 of file SelectHandle.h.

Referenced by Cancel(), and Click().

◆ mMostRecentX

int SelectHandle::mMostRecentX { -1 }
private

Definition at line 167 of file SelectHandle.h.

Referenced by Click(), Drag(), and SelectHandle::TimerHandler::OnTimer().

◆ mMostRecentY

int SelectHandle::mMostRecentY { -1 }
private

Definition at line 167 of file SelectHandle.h.

Referenced by Click(), and Drag().

◆ mpView

std::weak_ptr<ChannelView> SelectHandle::mpView
private

Definition at line 133 of file SelectHandle.h.

Referenced by Click(), Drag(), FindChannel(), FindTrack(), and Preview().

◆ mRect

wxRect SelectHandle::mRect {}
private

◆ mSelectionBoundary

int SelectHandle::mSelectionBoundary { 0 }
private

Definition at line 144 of file SelectHandle.h.

Referenced by Click(), and Preview().

◆ mSelectionStateChanger

std::shared_ptr<SelectionStateChanger> SelectHandle::mSelectionStateChanger
private

Definition at line 171 of file SelectHandle.h.

Referenced by Cancel(), Click(), IsDragging(), and Release().

◆ mSelStart

double SelectHandle::mSelStart { 0.0 }
private

Definition at line 142 of file SelectHandle.h.

Referenced by AdjustSelection(), AssignSelection(), Click(), Drag(), and StartSelection().

◆ mSelStartValid

bool SelectHandle::mSelStartValid {}
private

◆ mSnapEnd

SnapResults SelectHandle::mSnapEnd
private

Definition at line 138 of file SelectHandle.h.

Referenced by AdjustSelection(), Draw(), HasSnap(), Release(), and SetUseSnap().

◆ mSnapManager

std::shared_ptr<SnapManager> SelectHandle::mSnapManager
private

Definition at line 137 of file SelectHandle.h.

Referenced by AdjustSelection(), Draw(), Release(), and SelectHandle().

◆ mSnapStart

SnapResults SelectHandle::mSnapStart
private

◆ mTimerHandler

std::shared_ptr<TimerHandler> SelectHandle::mTimerHandler
private

Definition at line 175 of file SelectHandle.h.

Referenced by Connect().

◆ mUseSnap

bool SelectHandle::mUseSnap { true }
private

◆ TimerHandler

Definition at line 174 of file SelectHandle.h.


The documentation for this class was generated from the following files: