Audacity 3.2.0
SelectionState.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 SelectionState.h
6
7 **********************************************************************/
8
9#include "SelectionState.h"
10
11#include "ViewInfo.h"
12#include "SyncLock.h"
13#include "Track.h"
14#include "Project.h"
15
16#include <cassert>
17
19 [](AudacityProject &){ return std::make_shared< SelectionState >(); }
20};
21
23{
24 return project.AttachedObjects::Get< SelectionState >( key );
25}
26
28{
29 return Get( const_cast< AudacityProject & >( project ) );
30}
31
33 ViewInfo &viewInfo, Track &track, bool syncLocked)
34{
35 assert(track.IsLeader());
36 auto trackRange = syncLocked
37 // If we have a sync-lock group and sync-lock linking is on,
38 // check the sync-lock group tracks.
39 ? SyncLock::Group(&track)
40
41 // Otherwise, check for one track
43
44 auto minOffset = trackRange.min(&Track::GetStartTime);
45 auto maxEnd = trackRange.max(&Track::GetEndTime);
46
47 // PRL: double click or click on track control.
48 // should this select all frequencies too? I think not.
49 viewInfo.selectedRegion.setTimes(minOffset, maxEnd);
50}
51
53 Track &track, bool selected, bool updateLastPicked)
54{
55 assert(track.IsLeader());
56 //bool wasCorrect = (selected == track.GetSelected());
57
58 track.SetSelected(selected);
59
60 if (updateLastPicked)
62
63//The older code below avoids an anchor on an unselected track.
64
65 /*
66 if (selected) {
67 // This handles the case of linked tracks, selecting all channels
68 mTracks->Select(pTrack, true);
69 if (updateLastPicked)
70 mLastPickedTrack = Track::Pointer( pTrack );
71 }
72 else {
73 mTracks->Select(pTrack, false);
74 if (updateLastPicked && pTrack == mLastPickedTrack.lock().get())
75 mLastPickedTrack.reset();
76 }
77*/
78}
79
81 TrackList &tracks, Track &rsTrack, Track &reTrack)
82{
83 Track *sTrack = &rsTrack, *eTrack = &reTrack;
84 // Swap the track pointers if needed
85 auto begin = tracks.begin(),
86 iterS = tracks.Find(sTrack),
87 iterE = tracks.Find(eTrack);
88 // Be sure to substitute the leaders for given tracks
89 sTrack = *iterS;
90 eTrack = *iterE;
91 auto indS = std::distance(begin, iterS),
92 indE = std::distance(begin, iterE);
93 if (indE < indS)
94 std::swap(sTrack, eTrack);
95
96 for (auto track :
97 tracks.Any().StartingWith(sTrack).EndingAfter(eTrack))
98 SelectTrack(*track, true, false);
99}
100
102{
103 for (auto t : tracks)
104 SelectTrack(*t, false, false);
105}
106
108 TrackList &tracks, Track &track)
109{
110 // We will either extend from the first or from the last.
111 auto pExtendFrom = tracks.Lock(mLastPickedTrack);
112
113 if (!pExtendFrom) {
114 auto trackRange = tracks.Selected();
115 auto pFirst = *trackRange.begin();
116
117 // If our track is at or after the first, extend from the first.
118 if (pFirst) {
119 auto begin = tracks.begin(),
120 iterT = tracks.Find(&track),
121 iterF = tracks.Find(pFirst);
122 auto indT = std::distance(begin, iterT),
123 indF = std::distance(begin, iterF);
124 if (indT >= indF)
125 pExtendFrom = pFirst->SharedPointer();
126 }
127
128 // Our track was earlier than the first. Extend from the last.
129 if (!pExtendFrom)
130 pExtendFrom = Track::SharedPointer(*trackRange.rbegin());
131 }
132 // Either it's null, or mLastPickedTrack, or the first or last of
133 // Selected()
134 assert(!pExtendFrom || pExtendFrom->IsLeader());
135
137 if (pExtendFrom)
138 SelectRangeOfTracks(tracks, track, *pExtendFrom);
139 else
140 SelectTrack(track, true, true);
141 mLastPickedTrack = pExtendFrom;
142}
143
145 Track &track, bool shift, bool ctrl, bool syncLocked)
146{
147 assert(track.IsLeader());
148 // AS: If the shift button is being held down, invert
149 // the selection on this track.
150 if (ctrl)
151 SelectTrack(track, !track.GetSelected(), true);
152 else {
153 if (shift && mLastPickedTrack.lock())
155 else {
157 SelectTrack(track, true, true);
158 SelectTrackLength(viewInfo, track, syncLocked);
159 }
160 }
161}
162
165 : mpState{ &state }
166 , mTracks{ tracks }
167 , mInitialLastPickedTrack{ state.mLastPickedTrack }
168{
169 // Save initial state of track selections
170 const auto range = tracks.Any();
172 mInitialTrackSelection.reserve(range.size());
173 for (const auto track : range) {
174 const bool isSelected = track->GetSelected();
175 mInitialTrackSelection.push_back(isSelected);
176 }
177}
178
180{
181 if ( mpState ) {
182 // roll back changes
184 std::vector<bool>::const_iterator
185 it = mInitialTrackSelection.begin(),
187
188 for (auto track : mTracks) {
189 if (it == end)
190 break;
191 track->SetSelected( *it++ );
192 }
193 }
194}
195
197{
198 mpState = nullptr;
199}
static const AudacityProject::AttachedObjects::RegisteredFactory key
const auto tracks
const auto project
declares abstract base class Track, TrackList, and iterators over TrackList
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:135
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Definition: Channel.cpp:124
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:274
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
SelectionState * mpState
SelectionStateChanger(SelectionState &state, TrackList &tracks)
std::vector< bool > mInitialTrackSelection
std::weak_ptr< Track > mInitialLastPickedTrack
std::weak_ptr< Track > mLastPickedTrack
void HandleListSelection(TrackList &tracks, ViewInfo &viewInfo, Track &track, bool shift, bool ctrl, bool syncLocked)
void ChangeSelectionOnShiftClick(TrackList &tracks, Track &track)
static void SelectTrackLength(ViewInfo &viewInfo, Track &track, bool syncLocked)
void SelectRangeOfTracks(TrackList &tracks, Track &sTrack, Track &eTrack)
void SelectNone(TrackList &tracks)
static SelectionState & Get(AudacityProject &project)
void SelectTrack(Track &track, bool selected, bool updateLastPicked)
static TrackIterRange< Track > Group(Track *pTrack)
Definition: SyncLock.cpp:161
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:70
virtual void SetSelected(bool s)
Definition: Track.cpp:75
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:160
bool IsLeader() const override
Definition: Track.cpp:291
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:975
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1110
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:215
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:645