Audacity 3.2.0
WaveTrackAffordanceControls.cpp
Go to the documentation of this file.
1/*!********************************************************************
2*
3 Audacity: A Digital Audio Editor
4
5 WaveTrackAffordanceControls.cpp
6
7 Vitaly Sverchinsky
8
9 **********************************************************************/
10
12
13#include <wx/dc.h>
14#include <wx/frame.h>
15
16#include "AllThemeResources.h"
17#include "CommandContext.h"
18#include "CommandFlag.h"
19#include "CommandFunctors.h"
20#include "MenuRegistry.h"
21#include "../../../../TrackPanelMouseEvent.h"
22#include "../../../../TrackArt.h"
23#include "../../../../TrackArtist.h"
24#include "../../../../TrackPanelDrawingContext.h"
25#include "ViewInfo.h"
26#include "WaveTrack.h"
27#include "WaveClip.h"
28#include "WaveTrackUtilities.h"
29#include "UndoManager.h"
30#include "ShuttleGui.h"
31#include "../../../../ProjectWindows.h"
32#include "../../../../commands/AudacityCommand.h"
33
34#include "../../../ui/SelectHandle.h"
35#include "../../../ui/TextEditHelper.h"
36#include "ClipParameters.h"
37#include "WaveChannelView.h"
39
40#include "ProjectHistory.h"
41#include "../../../../ProjectSettings.h"
42#include "SelectionState.h"
43#include "../../../../RefreshCode.h"
44#include "Theme.h"
45#include "../../../../../images/Cursors.h"
46#include "../../../../HitTestResult.h"
47#include "../../../../TrackPanel.h"
48#include "TrackFocus.h"
49
50#include "../WaveTrackUtils.h"
51
54#include "LowlitClipButton.h"
55#include "PitchAndSpeedDialog.h"
57#include "WaveClipUtilities.h"
58
59#include "BasicUI.h"
60#include "UserException.h"
61
62
64{
65public:
67
69 {
70 return Symbol;
71 }
73 {
74 S.AddSpace(0, 5);
75
76 S.StartMultiColumn(2, wxALIGN_CENTER);
77 {
78 S.TieTextBox(XXO("Name:"), mName, 60);
79 }
80 S.EndMultiColumn();
81 }
82public:
83 wxString mName;
84};
85
87{ XO("Set Wave Clip Name") };
88
89//Handle which is used to send mouse events to TextEditHelper
91{
92 std::shared_ptr<TextEditHelper> mHelper;
93 std::shared_ptr<WaveTrack> mpTrack;
94public:
95
96 WaveClipTitleEditHandle(const std::shared_ptr<TextEditHelper>& helper,
97 const std::shared_ptr<WaveTrack> pTrack)
98 : mHelper(helper)
99 , mpTrack{ move(pTrack) }
100 { }
101
103 {
104 }
105
106 std::shared_ptr<const Channel> FindChannel() const override
107 {
108 return mpTrack;
109 }
110
112 {
113 if (mHelper->OnClick(event.event, project))
116 }
117
119 {
120 if (mHelper->OnDrag(event.event, project))
123 }
124
126 {
127 static auto ibeamCursor =
128 ::MakeCursor(wxCURSOR_IBEAM, IBeamCursorXpm, 17, 16);
129 return {
130 XO("Click and drag to select text"),
131 ibeamCursor.get()
132 };
133 }
134
135 Result Release(const TrackPanelMouseEvent& event, AudacityProject* project, wxWindow*) override
136 {
137 if (mHelper->OnRelease(event.event, project))
140 }
141
143 {
144 if (mHelper)
145 {
146 mHelper->Cancel(project);
147 mHelper.reset();
148 }
150 }
151};
152
154 : CommonTrackCell{ pTrack, 0 }
155 , mClipNameFont{ wxFontInfo{} }
156{
157 if (auto trackList = pTrack->GetOwner())
158 {
159 mTrackListEventSubscription = trackList->Subscribe(
161 if(auto project = trackList->GetOwner())
162 {
163 auto& viewInfo = ViewInfo::Get(*project);
165 viewInfo.selectedRegion.Subscribe(
166 *this,
168 }
169 }
170}
171
172std::vector<UIHandlePtr> WaveTrackAffordanceControls::HitTest(const TrackPanelMouseState& state, const AudacityProject* pProject)
173{
174 std::vector<UIHandlePtr> results;
175
176 const auto px = state.state.m_x;
177 const auto py = state.state.m_y;
178 const wxPoint mousePoint { px, py };
179
180 const auto rect = state.rect;
181
182 auto track = std::static_pointer_cast<WaveTrack>(FindTrack());
183 // Assume only leader channels have affordance areas
184 assert(track->IsLeader());
185
186 {
189 track,
190 pProject,
191 state);
192
193 if (handle)
194 results.push_back(handle);
195 }
196
197 if (mTextEditHelper && mTextEditHelper->GetBBox().Contains(px, py))
198 {
199 results.push_back(
202 std::make_shared<WaveClipTitleEditHandle>(
203 mTextEditHelper, track)
204 )
205 );
206 }
207
208 const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
209 auto& zoomInfo = ViewInfo::Get(*pProject);
210 const auto intervals = waveTrack->Intervals();
211 for(auto it = intervals.begin(); it != intervals.end(); ++it)
212 {
213 if (it == mEditedInterval)
214 continue;
215
216 const auto clip = (*it)->GetClip(0);
217 if (LowlitClipButton::HitTest<ClipButtonId::Overflow>(
218 { *clip, zoomInfo, rect }, mousePoint))
219 {
220 results.push_back(AssignUIHandlePtr(
221 mOverflowButtonHandle, std::make_shared<ClipOverflowButtonHandle>(
222 track, *it, weak_from_this())));
223 mFocusInterval = it;
224 break;
225 }
226 else if (LowlitClipButton::HitTest<ClipButtonId::Pitch>(
227 { *clip, zoomInfo, rect }, mousePoint))
228 {
229 results.push_back(AssignUIHandlePtr(
231 std::make_shared<ClipPitchAndSpeedButtonHandle>(
233 mFocusInterval = it;
234 break;
235 }
236 else if (LowlitClipButton::HitTest<ClipButtonId::Speed>(
237 { *clip, zoomInfo, rect }, mousePoint))
238 {
239 results.push_back(AssignUIHandlePtr(
241 std::make_shared<ClipPitchAndSpeedButtonHandle>(
243 mFocusInterval = it;
244 break;
245 }
247 *clip, zoomInfo, state.rect, mousePoint))
248 {
249 results.push_back(AssignUIHandlePtr(
251 std::make_shared<WaveTrackAffordanceHandle>(track, clip)));
252 mFocusInterval = it;
253 break;
254 }
255 }
256
257 const auto& settings = ProjectSettings::Get(*pProject);
258 const auto currentTool = settings.GetTool();
259 if (currentTool == ToolCodes::multiTool || currentTool == ToolCodes::selectTool)
260 {
261 results.push_back(
263 mSelectHandle, state, pProject,
264 ChannelView::Get(*track).shared_from_this()
265 )
266 );
267 }
268
269 return results;
270}
271
272void WaveTrackAffordanceControls::Draw(TrackPanelDrawingContext& context, const wxRect& rect, unsigned iPass)
273{
274 if (iPass == TrackArtist::PassBackground) {
275 auto track = FindTrack();
276 const auto artist = TrackArtist::Get(context);
277
278 TrackArt::DrawBackgroundWithSelection(context, rect, track.get(), artist->blankSelectedBrush, artist->blankBrush);
279
280 mVisibleIntervals.clear();
281
282 const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
283 const auto& zoomInfo = *artist->pZoomInfo;
284 {
285 wxDCClipper dcClipper(context.dc, rect);
286
287 context.dc.SetTextBackground(wxTransparentColor);
288 context.dc.SetTextForeground(theTheme.Colour(clrClipNameText));
289 context.dc.SetFont(mClipNameFont);
290
291 auto px = context.lastState.m_x;
292 auto py = context.lastState.m_y;
293
294 const auto overflowHandle = mOverflowButtonHandle.lock();
295 const auto intervals = waveTrack->Intervals();
296 for(auto it = intervals.begin(); it != intervals.end(); ++it)
297 {
298 auto interval = *it;
299 const auto& clip = *interval->GetClip(0);
300 const auto clipRect = ClipParameters::GetClipRect(
301 clip, zoomInfo, rect);
302
303 if(!WaveChannelView::ClipDetailsVisible(clip, zoomInfo, rect))
304 {
305 TrackArt::DrawClipFolded(context.dc, clipRect);
306 continue;
307 }
308
309 const auto selected = GetSelectedInterval() == it;
310 const auto highlightAffordance =
311 !overflowHandle && (selected || clipRect.Contains(px, py));
312 auto affordanceRect = TrackArt::DrawClipAffordance(
313 context.dc, clipRect, highlightAffordance, selected);
314
315 if (
316 const auto overflowButtonRect =
317 LowlitClipButton::DrawOnClip<ClipButtonId::Overflow>(
318 { clip, zoomInfo, rect }, context.dc))
319 affordanceRect.width -= overflowButtonRect->width;
320 if (
321 const auto speedButtonRect =
322 LowlitClipButton::DrawOnClip<ClipButtonId::Speed>(
323 { clip, zoomInfo, rect }, context.dc))
324 affordanceRect.width -= speedButtonRect->width;
325 if (
326 const auto pitchButtonRect =
327 LowlitClipButton::DrawOnClip<ClipButtonId::Pitch>(
328 { clip, zoomInfo, rect }, context.dc))
329 affordanceRect.width -= pitchButtonRect->width;
330
331 if (mTextEditHelper && mEditedInterval == it)
332 {
333 if (!mTextEditHelper->Draw(context.dc, affordanceRect))
334 {
335 mTextEditHelper->Cancel(nullptr);
337 context.dc, affordanceRect, interval->GetName());
338 }
339 }
341 context.dc, affordanceRect, interval->GetName()))
342 mVisibleIntervals.push_back(it);
343 }
344 }
345
346 }
347}
348
350{
351 return std::find(mVisibleIntervals.begin(),
352 mVisibleIntervals.end(),
353 it) != mVisibleIntervals.end();
354}
355
357{
358 bool useDialog{ false };
359 gPrefs->Read(wxT("/GUI/DialogForNameNewLabel"), &useDialog, false);
360
361 auto interval = *it;
362 if(!interval)
363 return false;
364
365 if (useDialog)
366 {
368 auto oldName = interval->GetName();
369 Command.mName = oldName;
370 auto result = Command.PromptUser(&GetProjectFrame(project));
371 if (result && Command.mName != oldName)
372 {
373 interval->SetName(Command.mName);
374 ProjectHistory::Get(project).PushState(XO("Modified Clip Name"),
375 XO("Clip Name Edit"));
376 }
377 }
378 else if(it != mEditedInterval)
379 {
380 if(!IsIntervalVisible(it))
381 return false;
382
383 if (mTextEditHelper)
384 mTextEditHelper->Finish(&project);
385
386 mEditedInterval = it;
387 mTextEditHelper = MakeTextEditHelper(interval->GetName());
388 }
389
390 return true;
391}
392
394{
395 if (auto handle = mAffordanceHandle.lock())
396 {
397 return handle->Clicked() ? mFocusInterval : IntervalIterator{};
398 }
399 return {};
400}
401
402namespace {
403
405{
406 auto &view = ChannelView::Get(track);
407 auto pAffordance = view.GetAffordanceControls();
408 return std::dynamic_pointer_cast<WaveTrackAffordanceControls>(
409 pAffordance );
410}
411
412std::pair<std::shared_ptr<WaveTrack>, ChannelGroup::IntervalIterator<WaveTrack::Interval>>
414{
415 // Note that TrackFocus may change its state as a side effect, defining
416 // a track focus if there was none
417 auto track = TrackFocus::Get(project).Get();
418 if (!track)
419 return {};
420 if (
421 auto pWaveTrack =
422 std::dynamic_pointer_cast<WaveTrack>(track->shared_from_this()))
423 {
424 if (FindAffordance(*pWaveTrack)) {
425 auto &viewInfo = ViewInfo::Get(project);
426 auto intervals = pWaveTrack->Intervals();
427
428 auto it = std::find_if(
429 intervals.begin(), intervals.end(), [&](const auto& interval) {
430 if (wholeInterval)
431 return interval->Start() == viewInfo.selectedRegion.t0() &&
432 interval->End() == viewInfo.selectedRegion.t1();
433 else
434 return interval->Start() <= viewInfo.selectedRegion.t0() &&
435 interval->End() > viewInfo.selectedRegion.t0();
436 });
437
438 if(it != intervals.end())
439 return { pWaveTrack, it };
440 }
441 }
442 return {};
443}
444
445// condition for enabling the command
447{
449 [](const AudacityProject &project){
450 // const_cast isn't pretty but not harmful in this case
451 return SelectedIntervalOfFocusedTrack(const_cast<AudacityProject&>(project)).first != nullptr;
452 }
453 };
454 return flag;
455}
456
458{
460 [](const AudacityProject &project){
461 // const_cast isn't pretty but not harmful in this case
462 auto result = SelectedIntervalOfFocusedTrack(
463 const_cast<AudacityProject&>(project));
464
465 auto interval = *result.second;
466 return interval != nullptr && interval->HasPitchOrSpeed();
467 }
468 };
469 return flag;
470}
471
472}
473
474unsigned WaveTrackAffordanceControls::CaptureKey(wxKeyEvent& event, ViewInfo& viewInfo, wxWindow* pParent, AudacityProject* project)
475{
476 if (!mTextEditHelper
477 || !mTextEditHelper->CaptureKey(event.GetKeyCode(), event.GetModifiers()))
478 // Handle the event if it can be processed by the text editor (if any)
479 event.Skip();
481}
482
483
484unsigned WaveTrackAffordanceControls::KeyDown(wxKeyEvent& event, ViewInfo& viewInfo, wxWindow*, AudacityProject* project)
485{
486 auto keyCode = event.GetKeyCode();
487
488 if (mTextEditHelper)
489 {
490 if (!mTextEditHelper->OnKeyDown(keyCode, event.GetModifiers(), project)
492 event.Skip();
493
495 }
497}
498
499unsigned WaveTrackAffordanceControls::Char(wxKeyEvent& event, ViewInfo& viewInfo, wxWindow* pParent, AudacityProject* project)
500{
501 if (mTextEditHelper && mTextEditHelper->OnChar(event.GetUnicodeKey(), project))
504}
505
507{
508 return ExitTextEditing();
509}
510
512{
513 if (auto interval = *mEditedInterval)
514 {
515 if (text != interval->GetName()) {
516 interval->SetName(text);
517
518 ProjectHistory::Get(*project).PushState(XO("Modified Clip Name"),
519 XO("Clip Name Edit"));
520 }
521 }
523}
524
526{
528}
529
531{
532 //Nothing to do
533}
534
536{
537}
538
540{
541 mTextEditHelper.reset();
542 mEditedInterval = {};
543}
544
546{
549}
550
552{
554}
555
557{
558 using namespace RefreshCode;
559 if (mTextEditHelper)
560 {
561 if (auto trackList = FindTrack()->GetOwner())
562 {
563 mTextEditHelper->Finish(trackList->GetOwner());
564 }
566 return RefreshCell;
567 }
568 return RefreshNone;
569}
570
572{
573 if (mTextEditHelper)
574 {
575 mTextEditHelper->CopySelectedText(project);
576 return true;
577 }
578 return false;
579}
580
582{
583 if (mTextEditHelper)
584 {
585 mTextEditHelper->CutSelectedText(project);
586 return true;
587 }
588 return false;
589}
590
592{
593 if (mTextEditHelper)
594 {
595 mTextEditHelper->PasteSelectedText(project);
596 return true;
597 }
598 return false;
599}
600
602{
603 if (mTextEditHelper)
604 {
605 mTextEditHelper->SelectAll();
606 return true;
607 }
608 return false;
609}
610
612{
613 auto& viewInfo = ViewInfo::Get(*project);
614 if (mTextEditHelper)
615 {
616 if (auto interval = *mEditedInterval)
617 {
618 auto affordanceRect = ClipParameters::GetClipRect(*interval->GetClip(0), viewInfo, event.rect);
619 if (!affordanceRect.Contains(event.event.GetPosition()))
620 return ExitTextEditing();
621 }
622 }
623 else if (auto interval = *mFocusInterval)
624 {
625 if (event.event.LeftDClick())
626 {
627 auto affordanceRect = ClipParameters::GetClipRect(*interval->GetClip(0), viewInfo, event.rect);
628 if (affordanceRect.Contains(event.event.GetPosition()) &&
630 {
631 event.event.Skip(false);
633 }
634 }
635 }
637}
638
640{
641 auto [track, it] = SelectedIntervalOfFocusedTrack(project);
642 if(track != FindTrack())
643 return;
645}
646
649{
650 constexpr auto wholeInterval = false;
651 auto [track, it] = SelectedIntervalOfFocusedTrack(project, wholeInterval);
652
653 if (track != FindTrack())
654 return;
655
656 auto interval = *it;
657
658 if (!interval)
659 return;
660
662}
663
666{
667 const auto [track, it] = SelectedIntervalOfFocusedTrack(project);
668
669 if (track != FindTrack())
670 return;
671
672 auto interval = *it;
673
674 if (!interval || !interval->HasPitchOrSpeed())
675 return;
676
678 [track = track, interval = interval](const ProgressReporter& progress) {
679 track->ApplyPitchAndSpeed(
680 { { interval->GetPlayStartTime(), interval->GetPlayEndTime() } },
681 progress);
682 },
683 XO("Applying..."));
684
686 XO("Rendered time-stretched audio"), XO("Render"));
687
689}
690
691std::shared_ptr<TextEditHelper> WaveTrackAffordanceControls::MakeTextEditHelper(const wxString& text)
692{
693 auto helper = std::make_shared<TextEditHelper>(shared_from_this(), text, mClipNameFont);
694 helper->SetTextColor(theTheme.Colour(clrClipNameText));
695 helper->SetTextSelectionColor(theTheme.Colour(clrClipNameTextSelection));
696 return helper;
697}
698
700 const wxRect &rect, const wxPoint *pPosition, AudacityProject *pProject)
701 -> std::vector<MenuItem>
702{
704}
705
706// Register a menu item
707
708namespace {
709
710// Menu handler functions
711
712void OnEditClipName(const CommandContext &context)
713{
714 auto &project = context.project;
715
716 if(auto pWaveTrack = dynamic_cast<WaveTrack *>(TrackFocus::Get(project).Get()))
717 {
718 if(auto pAffordance = FindAffordance(*pWaveTrack))
719 {
720 pAffordance->StartEditSelectedClipName(project);
721 // Refresh so the cursor appears
723 }
724 }
725}
726
728{
729 auto& project = context.project;
730
731 if (
732 auto pWaveTrack =
733 dynamic_cast<WaveTrack*>(TrackFocus::Get(project).Get()))
734 {
735 if (auto pAffordance = FindAffordance(*pWaveTrack))
736 pAffordance->StartEditSelectedClipSpeed(project);
737 }
738}
739
741{
742 auto& project = context.project;
743
744 if (
745 auto pWaveTrack =
746 dynamic_cast<WaveTrack*>(TrackFocus::Get(project).Get()))
747 {
748 if (auto pAffordance = FindAffordance(*pWaveTrack))
749 pAffordance->OnRenderClipStretching(project);
750 }
751}
752
754 const CommandContext& context, bool up)
755{
756 auto [track, it] = SelectedIntervalOfFocusedTrack(context.project);
757 if (!track)
758 return;
759 const auto interval = *it;
760 if (interval->SetCentShift(interval->GetCentShift() + (up ? 100 : -100)))
762 .PushState(
763 XO("Pitch Shift"), XO("Changed Pitch Shift"),
765}
766
767void OnPitchUp(const CommandContext& context)
768{
769 OnPitchShift(context, true);
770}
771
772void OnPitchDown(const CommandContext& context)
773{
774 OnPitchShift(context, false);
775}
776
777using namespace MenuRegistry;
778
779// Register menu items
780
782 Command( L"RenameClip", XXO("&Rename Clip..."),
784 wxT("Edit/Other/Clip")
785};
786
788 Command(
789 L"ChangePitchAndSpeed", XXO("&Pitch and Speed..."), OnChangePitchAndSpeed,
790 AlwaysEnabledFlag, Options { wxT("Ctrl+Shift+P") }),
791 wxT("Edit/Other/Clip")
792};
793
795 Command( L"RenderPitchAndSpeed", XXO("Render Pitch and &Speed"),
797 wxT("Edit/Other/Clip")
798};
799
801 Command( L"PitchUp", XXO("Pitch &Up"),
803 wxT("Edit/Other/Clip")
804};
805
807 Command( L"PitchDown", XXO("Pitch &Down"),
808 OnPitchDown, SomeClipIsSelectedFlag(), Options{ wxT("Alt+Down") }),
809 wxT("Edit/Other/Clip")
810};
811}
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
AttachedItem sAttachment3
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
const auto project
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
std::function< void(double)> ProgressReporter
Definition: Track.h:53
static Settings & settings()
Definition: TrackInfo.cpp:69
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:188
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:159
An AudacityException with no visible message.
static std::once_flag flag
Base class for command in Audacity.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static ChannelView & Get(Channel &channel)
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
Definition: ClientData.h:317
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
std::shared_ptr< Track > FindTrack()
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
static PitchAndSpeedDialog & Get(AudacityProject &project)
PitchAndSpeedDialog & SetFocus(const std::optional< PitchAndSpeedDialogGroup > &group)
PitchAndSpeedDialog & Retarget(const std::shared_ptr< WaveTrack > &track, const WaveTrack::IntervalHolder &wideClip)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
Definition: Registry.h:388
static UIHandlePtr HitTest(std::weak_ptr< SelectHandle > &holder, const TrackPanelMouseState &state, const AudacityProject *pProject, const std::shared_ptr< ChannelView > &pChannelView)
ComponentInterfaceSymbol GetSymbol() const override
static const ComponentInterfaceSymbol Symbol
void PopulateOrExchange(ShuttleGui &S) override
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
static bool IsGoodEditKeyCode(int keyCode)
wxColour & Colour(int iIndex)
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:69
Track * Get()
Definition: TrackFocus.cpp:156
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:233
void RefreshTrack(Track *trk, bool refreshbacking=true)
Definition: TrackPanel.cpp:764
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:36
unsigned Result
Definition: UIHandle.h:39
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static bool ClipDetailsVisible(const ClipTimes &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect)
static bool HitTest(const WaveClip &clip, const ZoomInfo &zoomInfo, const wxRect &rect, const wxPoint &pos)
static UIHandlePtr HitAnywhere(std::weak_ptr< WaveClipAdjustBorderHandle > &holder, const std::shared_ptr< WaveTrack > &waveTrack, const AudacityProject *pProject, const TrackPanelMouseState &state)
WaveClipTitleEditHandle(const std::shared_ptr< TextEditHelper > &helper, const std::shared_ptr< WaveTrack > pTrack)
Result Release(const TrackPanelMouseEvent &event, AudacityProject *project, wxWindow *) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *project) override
std::shared_ptr< TextEditHelper > mHelper
Result Cancel(AudacityProject *project) override
std::shared_ptr< WaveTrack > mpTrack
std::shared_ptr< const Channel > FindChannel() const override
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *project) override
bool OnTextCopy(AudacityProject &project)
void OnTextEditCancelled(AudacityProject *project) override
void OnTrackListEvent(const TrackListEvent &evt)
std::weak_ptr< ClipPitchAndSpeedButtonHandle > mPitchButtonHandle
void OnTextContextMenu(AudacityProject *project, const wxPoint &position) override
std::weak_ptr< WaveClipAdjustBorderHandle > mClipBorderAdjustHandle
unsigned CaptureKey(wxKeyEvent &event, ViewInfo &viewInfo, wxWindow *pParent, AudacityProject *project) override
std::vector< MenuItem > GetMenuItems(const wxRect &rect, const wxPoint *pPosition, AudacityProject *pProject) override
Return a list of items for DoContextMenu() (empties for separators)
void OnTextEditFinished(AudacityProject *project, const wxString &text) override
unsigned LoseFocus(AudacityProject *project) override
bool IsIntervalVisible(const IntervalIterator &it) const noexcept
WaveTrackAffordanceControls(const std::shared_ptr< Track > &pTrack)
void OnSelectionChange(NotifyingSelectedRegionMessage)
bool OnTextSelect(AudacityProject &project)
std::vector< IntervalIterator > mVisibleIntervals
std::weak_ptr< WaveTrackAffordanceHandle > mAffordanceHandle
std::weak_ptr< ClipOverflowButtonHandle > mOverflowButtonHandle
Observer::Subscription mSelectionChangeSubscription
std::shared_ptr< TextEditHelper > mTextEditHelper
std::weak_ptr< ClipPitchAndSpeedButtonHandle > mSpeedButtonHandle
void StartEditSelectedClipName(AudacityProject &project)
std::shared_ptr< TextEditHelper > MakeTextEditHelper(const wxString &text)
void OnRenderClipStretching(AudacityProject &project) const
bool StartEditClipName(AudacityProject &project, IntervalIterator it)
Starts in-place clip name editing or shows a Clip Name Edit dialog, depending on prefs.
std::weak_ptr< SelectHandle > mSelectHandle
unsigned KeyDown(wxKeyEvent &event, ViewInfo &viewInfo, wxWindow *pParent, AudacityProject *project) override
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
unsigned OnAffordanceClick(const TrackPanelMouseEvent &event, AudacityProject *project)
Observer::Subscription mTrackListEventSubscription
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
bool OnTextCut(AudacityProject &project)
IntervalIterator GetSelectedInterval() const
void OnTextModified(AudacityProject *project, const wxString &text) override
bool OnTextPaste(AudacityProject &project)
void StartEditSelectedClipSpeed(AudacityProject &project)
std::weak_ptr< WaveClipTitleEditHandle > mTitleEditHandle
unsigned Char(wxKeyEvent &event, ViewInfo &viewInfo, wxWindow *pParent, AudacityProject *project) override
A Track that contains audio waveform data.
Definition: WaveTrack.h:227
virtual bool Read(const wxString &key, bool *value) const =0
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
constexpr auto Command
Definition: MenuRegistry.h:456
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
AUDACITY_DLL_API bool DrawClipTitle(wxDC &dc, const wxRect &affordanceRect, const wxString &title)
Definition: TrackArt.cpp:289
AUDACITY_DLL_API void DrawClipFolded(wxDC &dc, const wxRect &rect)
Definition: TrackArt.cpp:346
AUDACITY_DLL_API void DrawBackgroundWithSelection(TrackPanelDrawingContext &context, const wxRect &rect, const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush, bool useSelection=true)
Definition: TrackArt.cpp:651
AUDACITY_DLL_API wxRect DrawClipAffordance(wxDC &dc, const wxRect &clipRect, bool highlight=false, bool selected=false)
Definition: TrackArt.cpp:223
void SelectClip(AudacityProject &project, const WaveTrack::Interval &clip)
std::vector< CommonTrackPanelCell::MenuItem > GetWaveClipMenuItems()
WAVE_TRACK_API void WithClipRenderingProgress(std::function< void(const ProgressReporter &)> action, TranslatableString title=defaultStretchRenderingTitle, TranslatableString message=XO("Rendering Clip"))
void OnPitchShift(const CommandContext &context, bool up)
std::pair< std::shared_ptr< WaveTrack >, ChannelGroup::IntervalIterator< WaveTrack::Interval > > SelectedIntervalOfFocusedTrack(AudacityProject &project, bool wholeInterval=true)
static wxRect GetClipRect(const ClipTimes &clip, const ZoomInfo &zoomInfo, const wxRect &viewRect, bool *outShowSamples=nullptr)
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:946
const Type mType
Definition: Track.h:980
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
Definition: Track.h:949