26#include <wx/tooltip.h>
34#include "../images/Cursors.h"
66#include <wx/dcclient.h>
74#define SELECT_TOLERANCE_PIXEL 4
76#define PLAY_REGION_TRIANGLE_SIZE 6
77#define PLAY_REGION_RECT_WIDTH 1
78#define PLAY_REGION_RECT_HEIGHT 3
79#define PLAY_REGION_GLOBAL_OFFSET_Y 7
100 return ((width / 2) * 3) / 2;
107 (((height) * 2) / 3) * 2
141 if (oldState.
mX != newState.
mX)
168 const auto pos =
event.event.GetPosition();
177 return viewInfo.PositionToTime(
mX, viewInfo.GetLeftOffset());
189 auto saveMe =
ruler.Target();
192 ruler.StartQPPlay(!event.ShiftDown(),
false, &startTime);
221 size_t numGuides = 1)
233 size_t numGuides = 1)
249 const auto message =
XO(
"Click and drag to define a looping region.");
266 mX =
event.event.m_x;
303 auto &playRegion = viewInfo.playRegion;
319 auto &playRegion = viewInfo.playRegion;
322 playRegion.SetActive(
false);
333 auto identity = [](
auto x){
return x; };
351 bool isSnapped =
ruler.mIsSnapped[ii];
353 ?
ruler.mQuickPlayPos[ii]
354 :
ruler.mQuickPlayPosUnsnapped[ii];
360 for (
size_t ii = 0; ii <
ruler.mNumGuides; ++ii)
361 if (
ruler.mIsSnapped[ii]) {
362 double time0 =
ruler.mQuickPlayPos[ii];
363 double delta = time0 -
ruler.mQuickPlayPosUnsnapped[ii];
364 double time1 =
ruler.mQuickPlayPosUnsnapped[1 - ii] + delta;
366 return { time1, time0 };
368 return { time0, time1 };
371 return {
ruler.mQuickPlayPos[0],
ruler.mQuickPlayPos[1] };
377 std::fill(
ruler.mIsSnapped,
ruler.mIsSnapped +
ruler.mNumGuides,
false );
391 auto &playRegion = viewInfo.playRegion;
393 mOldStart = playRegion.GetLastActiveStart();
394 mOldEnd = playRegion.GetLastActiveEnd();
396 playRegion.SetActive(
true);
478 { std::make_shared<ScrubbingRulerOverlay>(*
this) };
501 return &
Get( *mPartner.mProject );
506 const auto project = mPartner.mProject;
508 auto ruler = GetRuler();
510 bool scrubbing = (scrubber.IsScrubbing()
511 && !scrubber.IsSpeedPlaying()
512 && !scrubber.IsKeyboardScrubbing());
517 mNewQPIndicatorPos = -1;
521 std::max(
ruler->mTracks->GetEndTime(), selectedRegion.t1());
526 mNewIndicatorSnapped = -1;
528 mNewIndicatorSnapped == -1 && ii <
ruler->mNumGuides; ++ii) {
529 if (
ruler->mIsSnapped[ii]) {
530 mNewIndicatorSnapped = ii;
533 mNewQPIndicatorPos =
ruler->Time2Pos(
534 ruler->mQuickPlayPos[std::max(0, mNewIndicatorSnapped)]);
539 !
ruler->IsMouseCaptured() &&
540 (
ruler->LastCell() ==
ruler->mScrubbingCell ||
541 (scrubber.HasMark()));
542 mNewSeek = mNewScrub &&
543 (scrubber.Seeks() || scrubber.TemporarilySeeks());
553std::pair<wxRect, bool>
558 const auto x = mOldQPIndicatorPos;
565 const int indsize = width / 2;
567 auto xx = x - indsize;
572 GetRuler()->GetSize().GetHeight() },
573 (x != mNewQPIndicatorPos
574 || (mOldScrub != mNewScrub)
575 || (mOldSeek != mNewSeek) )
579 return { {}, mNewQPIndicatorPos >= 0 };
585 mOldQPIndicatorPos = mNewQPIndicatorPos;
586 mOldScrub = mNewScrub;
588 if (mOldQPIndicatorPos >= 0) {
589 auto ruler = GetRuler();
591 ruler->DoDrawScrubIndicator(
592 &dc, mOldQPIndicatorPos, width, mOldScrub, mOldSeek);
622 mNewPreviewingScrub =
624 !scrubber.IsScrubbing();
627std::pair<wxRect, bool>
632 wxRect rect(mOldQPIndicatorPos, 0, 1,
size.GetHeight());
633 return std::make_pair(
635 (mOldQPIndicatorPos != mPartner->mNewQPIndicatorPos ||
636 mOldIndicatorSnapped != mPartner->mNewIndicatorSnapped ||
637 mOldPreviewingScrub != mNewPreviewingScrub)
644 mOldQPIndicatorPos = mPartner->mNewQPIndicatorPos;
645 mOldIndicatorSnapped = mPartner->mNewIndicatorSnapped;
646 mOldPreviewingScrub = mNewPreviewingScrub;
648 if (mOldQPIndicatorPos >= 0) {
649 if (!mOldPreviewingScrub && mOldIndicatorSnapped < 0) {
653 pHandle !=
nullptr && pHandle->
Clicked())
660 : (mOldIndicatorSnapped >= 0)
665 auto pCellularPanel =
dynamic_cast<CellularPanel*
>( &panel );
666 if ( !pCellularPanel ) {
672 const auto pChannelView =
dynamic_cast<ChannelView*
>(&cell);
734 , mMenuChoice{ menuChoice }
745 static wxCursor cursor{ wxCURSOR_DEFAULT };
757 mParent->ShowContextMenu(mMenuChoice, pPosition);
766#undef QUICK_PLAY_HANDLE
767#ifdef QUICK_PLAY_HANDLE
790 wxWindow *pParent)
override;
813 mParent->mQuickPlayOffset[0] = 0;
814 mParent->mQuickPlayOffset[1] = 0;
823 mParent->mQuickPlayOffset[0] = playRegion.GetStart() - time;
824 mParent->mQuickPlayOffset[1] = playRegion.GetEnd() - time;
834 playRegion.
SetTimes(times.first, times.second);
864 playRegion.SetEnd(time);
903 auto width = viewInfo.GetTracksUsableWidth();
904 return viewInfo.GetLeftOffset()
911 auto width = viewInfo.GetTracksUsableWidth();
912 auto fraction = (xx - viewInfo.GetLeftOffset()) /
double(width);
913 return std::max(0.0,
std::min(1.0, fraction));
922 : mpParent{ &parent }
932 if (oldState.
mX != newState.
mX)
937 static std::shared_ptr<PlayheadHandle>
942 .IsTransportingPinned() &&
947 return std::make_shared<PlayheadHandle>( parent, xx );
956 if (event.
event.LeftDClick()) {
965 if (!event.
event.LeftIsDown())
985 mpParent->SetNumGuides(1);
986 static wxCursor cursor{ wxCURSOR_SIZEWE };
988 XO(
"Click and drag to adjust, double-click to reset" ),
992 XO(
"Record/Playhead" )
1018 double mOrigPreference {};
1031 std::vector<UIHandlePtr>
HitTest(
1040#ifdef QUICK_PLAY_HANDLE
1041 if (
auto ptr = mHolder.lock())
1042 return ptr->Clicked();
1047#ifdef QUICK_PLAY_HANDLE
1048 std::weak_ptr<QPHandle> mHolder;
1063 mParent->CreateOverlays();
1065 std::vector<UIHandlePtr> results;
1066 auto xx = state.
state.m_x;
1068#ifdef EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
1075 results.push_back( result );
1081 if (!mParent->mIsRecording) {
1082 mParent->UpdateQuickPlayPos( xx );
1085 auto result = std::make_shared<QPHandle>( mParent, xx );
1087 results.push_back( result );
1092 bool hitLeft =
false;
1095 mParent->IsWithinMarker(xx, playRegion.GetLastActiveStart())) ||
1096 mParent->IsWithinMarker(xx, playRegion.GetLastActiveEnd()))
1099 std::make_shared<ResizePlayRegionHandle>( mParent, xx, hitLeft );
1101 results.push_back(result);
1106 if (
auto time = mParent->Pos2Time(xx);
1107 playRegion.Active() &&
1108 time >= playRegion.GetStart() &&
1109 time <= playRegion.GetEnd())
1112 std::make_shared<MovePlayRegionHandle>( mParent, xx );
1114 results.push_back(result);
1119 auto result = std::make_shared<NewPlayRegionHandle>( mParent, xx );
1121 results.push_back(result);
1146 scrubber.CanScrub() &&
1152 if (!scrubber.HasMark()) {
1154 scrubber.MarkScrubStart(
1179 wxWindow *pParent)
override {
1212 std::vector<UIHandlePtr>
HitTest(
1222 if (
auto ptr =
mHolder.lock())
1223 return ptr->Clicked();
1236 mParent->CreateOverlays();
1238 std::vector<UIHandlePtr> results;
1241 if (!mParent->mIsRecording) {
1242 auto xx = state.
state.m_x;
1243 mParent->UpdateQuickPlayPos( xx );
1244 auto result = std::make_shared<ScrubbingHandle>( mParent, xx );
1246 results.push_back( result );
1253AttachedWindows::RegisteredFactory
sKey{
1282 pPanel->wxWindow::Destroy();
1298 SetLayoutDirection(wxLayout_LeftToRight);
1300 mQPCell = std::make_shared<QPCell>(
this );
1308 SetBackgroundStyle(wxBG_STYLE_PAINT);
1317 mOuter = GetClientRect();
1332 wxToolTip::Enable(
true);
1361 CellularPanel::Refresh( eraseBackground, rect );
1404 wxPoint position( 1, 0 );
1409 pGrabber->SetPosition( position );
1418 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1419 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1420 bmpCogwheel, bmpCogwheel, bmpCogwheel,
1424 position.x +=
size.GetWidth();
1439 if(scrubber.Seeks())
1444 return XO(
"Click or drag to begin Seek");
1450 return XO(
"Click or drag to begin Scrub");
1456 return XO(
"Click & move to Scrub. Click & drag to Seek.");
1461 const Scrubber &scrubber,
bool clicked)
1464 if(scrubber.
Seeks())
1469 return XO(
"Move to Seek");
1475 return XO(
"Move to Scrub");
1482 return XO(
"Drag to Seek. Release to stop seeking.");
1485 return XO(
"Drag to Seek. Release and move to Scrub.");
1488 return XO(
"Move to Scrub. Drag to Seek.");
1514 const auto &selectedRegion = viewInfo.selectedRegion;
1515 const auto &playRegion = viewInfo.playRegion;
1520 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() }
1558 const auto &playRegion = viewInfo.playRegion;
1559 const auto playRegionBounds = std::pair{
1560 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() };
1576 rectO = rectP.Intersect(rectS);
1579 const auto top = rectP.GetTop(),
1580 bottom = rectP.GetBottom();
1582 wxPoint{ 0, top }, wxPoint{ this->GetSize().GetWidth() - 1, bottom } };
1584 if (!rectO.IsEmpty()) {
1585 rectR = { wxPoint{ rectO.GetRight() + 1, top }, rectL.GetBottomRight() };
1586 rectL = { rectL.GetTopLeft(), wxPoint{ rectO.GetLeft() - 1, bottom } };
1604 dc.DestroyClippingRegion();
1610 mOuter = GetClientRect();
1661 auto bottom = &inner;
1669 top = &scrubZone, topHeight = scrubHeight;
1671 auto qpHeight = scrubZone.height - scrubHeight;
1672 bottom = &scrubZone, topHeight = qpHeight;
1678 top->height = topHeight;
1679 bottom->height -= topHeight;
1680 bottom->y += topHeight;
1725 int pixelPos =
Time2Pos(markerTime);
1729 return mousePosX >= boundLeft && mousePosX < boundRight;
1732#ifdef QUICK_PLAY_HANDLE
1733auto AdornedRulerPanel::QPHandle::Click(
1736 auto result = CommonRulerHandle::Click(event, pProject);
1738 if (mClicked == Button::Left) {
1743 if(scrubber.HasMark()) {
1751 const auto &playRegion = viewInfo.playRegion;
1752 mParent->mOldPlayRegion = playRegion;
1757 mParent->HandleQPClick( event.event, mX );
1758 mParent->HandleQPDrag( event.event, mX );
1778 if (isWithinStart || isWithinEnd) {
1802auto AdornedRulerPanel::QPHandle::Drag(
1805 auto result = CommonRulerHandle::Drag(event, pProject);
1807 if (mClicked == Button::Left) {
1809 mX =
event.event.m_x;
1810 mParent->UpdateQuickPlayPos( mX );
1811 mParent->HandleQPDrag( event.event, mX );
1820 bool isWithinClick =
1827 auto &playRegion = viewInfo.playRegion;
1833 if (isWithinStart || isWithinEnd) {
1860 if (isWithinStart) {
1880 if (isWithinClick) {
1905 mParent->SetNumGuides(1);
1914#ifdef QUICK_PLAY_HANDLE
1915auto AdornedRulerPanel::QPHandle::Preview(
1919 mParent->SetNumGuides(1);
1923 if (!mParent->mQuickPlayEnabled)
1924 tooltip =
XO(
"Quick-Play disabled");
1926 tooltip =
XO(
"Quick-Play enabled");
1932 const bool scrubbing = scrubber.HasMark();
1940 static wxCursor cursorHand{ wxCURSOR_HAND };
1941 static wxCursor cursorSizeWE{ wxCURSOR_SIZEWE };
1943 bool showArrows =
false;
1946 (mClicked == Button::Left)
1947 || mParent->IsWithinMarker(
1948 state.state.m_x, mParent->mOldPlayRegion.GetStart())
1949 || mParent->IsWithinMarker(
1950 state.state.m_x, mParent->mOldPlayRegion.GetEnd());
1954 showArrows ? &cursorSizeWE : &cursorHand,
1968 auto saveMe = mParent->mQPCell->mHolder.lock();
1972 if (mClicked == Button::Left) {
1974 mParent->HandleQPRelease( event.event );
1977 const auto &playRegion = viewInfo.playRegion;
1978 mParent->mOldPlayRegion = playRegion;
1988 auto &playRegion = viewInfo.playRegion;
1993 const auto &selectedRegion = viewInfo.selectedRegion;
1994 const double sel0 = selectedRegion.t0();
1995 const double sel1 = selectedRegion.t1();
1999 if (evt.ShiftDown() && playRegion.Empty()) {
2003 if (((sel1 < t0) || (sel0 > t1)) &&
2004 ((playRegion.GetStart() < t0) || (playRegion.GetStart() > t1))) {
2009 else if (playRegion.GetStart() >= t1) {
2015 playRegion.GetEnd() - playRegion.GetStart() > 0.0 &&
2016 playRegion.GetEnd() < t0
2025 auto cleanup =
finally( [&] {
2028 SetPlayRegion(mOldPlayRegion.GetStart(), mOldPlayRegion.GetEnd());
2029 SelectUtilities::ActivatePlayRegion(*mProject);
2031 mOldPlayRegion.SetActive( false );
2040 auto result = CommonRulerHandle::Cancel(pProject);
2042 if (mClicked == Button::Left) {
2045 mParent->mMouseEventState = mesNone;
2046 mParent->SetPlayRegion(
2047 mParent->mOldPlayRegion.GetStart(), mParent->mOldPlayRegion.GetEnd());
2048 if (mParent->mOldPlayRegion.Active()) {
2052 mParent->mOldPlayRegion.SetActive(
false );
2062 bool newDefault,
bool cutPreview,
const double *pStartTime)
2067 const auto &playRegion = viewInfo.playRegion;
2068 const auto &selectedRegion = viewInfo.selectedRegion;
2069 const double sel0 = selectedRegion.t0();
2070 const double sel1 = selectedRegion.t1();
2073 bool startPlaying =
true;
2076 bool loopEnabled =
true;
2077 auto oldStart = std::max(0.0, playRegion.GetStart());
2078 double start = oldStart,
end = 0;
2080 if (playRegion.Empty()) {
2082 if (oldStart > sel0 && oldStart < sel1) {
2093 end = std::max(start, playRegion.GetEnd());
2096 loopEnabled = ((
end - start) > 0.001)? true :
false;
2098 newDefault = (loopEnabled && newDefault);
2105 options.pStartTime.emplace(*pStartTime);
2108 options.envelope =
nullptr;
2118 projectAudioManager.Stop();
2135void AdornedRulerPanel::OnToggleScrubRulerFromMenu(wxCommandEvent&)
2138 scrubber.OnToggleScrubRuler(*
mProject);
2145 const auto oldSize = GetSize();
2147 if (
size != oldSize ) {
2150 PostSizeEventToParent();
2159 auto pCellularPanel =
2161 if ( !pCellularPanel ) {
2165 pCellularPanel->DrawOverlays(
false );
2171 auto common = [
this](
2182 timelineOptionsButton->
PopUp();
2185 const auto label =
XO(
"Timeline Options");
2186 common(*timelineOptionsButton,
wxT(
"PinnedHead"),
label);
2209 auto width = viewInfo.GetTracksUsableWidth();
2210 mousePosX = std::max(mousePosX, viewInfo.GetLeftOffset());
2211 mousePosX =
std::min(mousePosX, viewInfo.GetLeftOffset() + width - 1);
2212 const auto time =
Pos2Time(mousePosX);
2226 const auto &playRegion = viewInfo.playRegion;
2231 _(
"Minutes and Seconds"));
2237 _(
"Beats and Measures"));
2241 rulerMenu.AppendSeparator();
2243 auto pDrag = rulerMenu.AppendCheckItem(
OnSyncQuickPlaySelID,
_(
"Setting a loop region also makes an audio selection"));
2245 pDrag->Enable(playRegion.Active());
2250 item->Check(playRegion.Active());
2261 _(
"Set Loop To Selection"));
2264 rulerMenu.AppendSeparator();
2266 rulerMenu.AppendCheckItem(
OnAutoScrollID,
_(
"Scroll view to playhead"))->
2281 PushEventHandler(&scrubber);
2282 auto cleanup =
finally([
this]{ PopEventHandler(); });
2285 scrubber.PopulatePopupMenu(rulerMenu);
2295 const auto &playRegion = viewInfo.playRegion;
2296 auto &selectedRegion = viewInfo.selectedRegion;
2297 selectedRegion.setT0(playRegion.GetStart(),
false);
2298 selectedRegion.setT1(playRegion.GetEnd(),
true);
2312 auto results = snapManager.Snap(
nullptr,
mQuickPlayPos[index],
false);
2319 int id =
event.GetId();
2372 position = *pPosition;
2375 auto rect = GetRect();
2383 position = { rect.GetLeft() + 38, rect.GetHeight()/2 + 1 };
2402 return clrTrackInfo;
2407 return clrTrackPanelText;
2417 return isActive ? clrRulerBackground : clrClipAffordanceInactiveBrush;
2435 dc->DrawRectangle(
mInner );
2442 ScrubRect.Inflate( 1,0 );
2443 dc->DrawRectangle(ScrubRect);
2455 dc->SetPen( *wxBLACK_PEN );
2465 const double hiddenMin =
Pos2Time(0,
true);
2490 const auto &playRegion = viewInfo.playRegion;
2491 const auto t0 = playRegion.GetLastActiveStart(),
2492 t1 = playRegion.GetLastActiveEnd();
2499 const auto &selectedRegion = viewInfo.selectedRegion;
2500 const auto t0 = selectedRegion.t0(), t1 = selectedRegion.t1();
2506 int p0 = -1, p1 = -1;
2515 const int left = p0, top =
mInner.y, right = p1, bottom =
mInner.GetBottom();
2516 return { wxPoint{left, top}, wxPoint{right, bottom} };
2520 wxDC * dc,
const wxRect &rectP,
const wxRect &rectL,
const wxRect &rectR)
2523 const auto& playRegion = viewInfo.playRegion;
2527 if (playRegion.IsLastActiveRegionClear())
2535 dc->DrawRectangle( rectP.Intersect(rectL) );
2536 dc->DrawRectangle( rectP.Intersect(rectR) );
2544 dc->SetPen( { edgeColour } );
2545 dc->SetBrush( { edgeColour } );
2547 constexpr int side = 7;
2548 constexpr int sideLessOne = side - 1;
2551 const auto left = rect.GetLeft(),
2552 right = rect.GetRight(),
2553 bottom = rect.GetBottom(),
2554 top = rect.GetTop();
2557 {left, bottom - sideLessOne},
2558 {left - sideLessOne, bottom},
2562 dc->DrawPolygon( 4, points );
2569 {right + sideLessOne, bottom},
2570 {right, bottom - sideLessOne},
2572 dc->DrawPolygon( 4, points );
2583 dc->SetPen( *wxTRANSPARENT_PEN );
2584 dc->DrawRectangle( rect );
2588 wxDC * dc,
const wxRect &rectS,
const wxRect &rectL,
const wxRect &rectR)
2592 dc->SetPen( *wxTRANSPARENT_PEN );
2593 dc->DrawRectangle( rectS.Intersect(rectL) );
2594 dc->DrawRectangle( rectS.Intersect(rectR) );
2613 wxDC * dc, wxCoord xx,
int width,
bool scrub,
bool seek)
2621 const int TriangleWidth = width * 3 / 8;
2626 : (
mInner.GetBottom() + 1) - 1 - height;
2630 tri[ 1 ].y = yy + height;
2631 tri[ 2 ].x = xx - TriangleWidth;
2632 tri[ 2 ].y = yy + height / 2;
2633 dc->DrawPolygon( 3, tri );
2635 tri[ 0 ].x -= TriangleWidth;
2636 tri[ 1 ].x -= TriangleWidth;
2637 tri[ 2 ].x -= TriangleWidth;
2638 dc->DrawPolygon( 3, tri );
2641 tri[ 2 ].x = xx + TriangleWidth;
2642 dc->DrawPolygon( 3, tri );
2645 tri[ 0 ].x += TriangleWidth;
2646 tri[ 1 ].x += TriangleWidth;
2647 tri[ 2 ].x += TriangleWidth;
2648 dc->DrawPolygon( 3, tri );
2652 const int IndicatorHalfWidth = width / 2;
2657 : (
mInner.GetBottom() + 1) - 1 - height;
2661 tri[ 1 ].y = yy + height;
2662 tri[ 2 ].x = xx - IndicatorHalfWidth;
2663 tri[ 2 ].y = yy + height / 2;
2664 dc->DrawPolygon( 3, tri );
2666 tri[ 2 ].x = xx + IndicatorHalfWidth;
2667 dc->DrawPolygon( 3, tri );
2672 double playRegionStart,
double playRegionEnd)
2681 auto &playRegion = viewInfo.playRegion;
2682 playRegion.SetTimes( playRegionStart, playRegionEnd );
2692 auto &playRegion = viewInfo.playRegion;
2706 s_AcceptsFocus =
true;
2714 for (
size_t ii =
mNumGuides; ii < nn; ++ii) {
2765 return scrubber.ShowsBar();
2772 return std::make_shared< MainGroup >( *
this );
2808 std::make_shared<TrackPanelGuidelineOverlay>(
mProject );
2809 auto pCellularPanel =
2811 if ( !pCellularPanel ) {
2815 pCellularPanel->AddOverlay(
mOverlay );
2831 if (scrubber.HasMark())
2832 scrubber.SetScrollScrubbing(value);
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
ColorId TimelineLimitsColor()
decltype(clrTrackInfo) ColorId
ColorId TimelineLoopRegionColor(bool isActive)
static wxColour AlphaBlend(ColorId fg, ColorId bg, double alpha)
static std::unique_ptr< wxCursor > handOpenCursor
ColorId TimelineBackgroundColor()
@ OnSetPlayRegionToSelectionID
int IndicatorWidthForHeight(int height)
ColorId TimelineTextColor()
wxEVT_COMMAND_BUTTON_CLICKED
int IndicatorHeightForWidth(int width)
#define SELECT_TOLERANCE_PIXEL
constexpr double SelectionOpacity
constexpr CommandFlag AlwaysEnabledFlag
XXO("&Cut/Copy/Paste Toolbar")
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
audacity::BasicSettings * gPrefs
AUDACITY_DLL_API wxWindow & GetProjectPanel(AudacityProject &project)
Get the main sub-window of the project frame that displays track data.
AUDACITY_DLL_API AttachedWindows & GetAttachedWindows(AudacityProject &project)
accessors for certain important windows associated with each project
std::vector< SnapPoint > SnapPointArray
TimeDisplayModeSetting TimeDisplayModePreference
declares abstract base class Track, TrackList, and iterators over TrackList
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
const TranslatableString LoopToggleText
static void IndicatorColor(wxDC *dc, bool bIsNotRecording)
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
static void SnapGuidePen(wxDC *dc)
static void Light(wxDC *dc, bool selected, bool highlight=false)
static void BevelTrackInfo(wxDC &dc, bool up, const wxRect &r, bool highlight=false)
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Makes temporary drawing context changes that you back out of, RAII style.
CommonCell(AdornedRulerPanel *parent, MenuChoice menuChoice)
unsigned DoContextMenu(const wxRect &, wxWindow *, const wxPoint *pPosition, AudacityProject *) final
AdornedRulerPanel * mParent
HitTestPreview DefaultPreview(const TrackPanelMouseState &, const AudacityProject *) override
const MenuChoice mMenuChoice
Result Click(const TrackPanelMouseEvent &event, AudacityProject *) override
Result Drag(const TrackPanelMouseEvent &, AudacityProject *) override
double Time(AudacityProject &project) const
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
CommonRulerHandle(AdornedRulerPanel *pParent, wxCoord xx, MenuChoice menuChoice)
std::shared_ptr< const Channel > FindChannel() const override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *, wxWindow *) override
wxWeakRef< AdornedRulerPanel > mParent
void StartPlay(AudacityProject &project, const wxMouseEvent &event)
Result Cancel(AudacityProject *) override
static UIHandle::Result NeedChangeHighlight(const CommonRulerHandle &oldState, const CommonRulerHandle &newState)
void Enter(bool, AudacityProject *) override
void DoStartAdjust(AudacityProject &project, double) override
MovePlayRegionHandle(AdornedRulerPanel *pParent, wxCoord xx)
void DoAdjust(AudacityProject &project) override
NewPlayRegionHandle(AdornedRulerPanel *pParent, wxCoord xx)
void DoAdjust(AudacityProject &project) override
void DoStartAdjust(AudacityProject &project, double time) override
virtual void DoAdjust(AudacityProject &)=0
virtual void DoStartAdjust(AudacityProject &, double)=0
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
PlayRegionAdjustingHandle(AdornedRulerPanel *pParent, wxCoord xx, MenuChoice menuChoice, wxCursor *cursor, size_t numGuides=1)
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
void SetCursor(wxCursor cursor)
std::pair< double, double > SnappedTimes(AudacityProject &project)
Result Cancel(AudacityProject *pProject) override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
void Unsnap(bool use, AudacityProject *pProject)
SelectedRegion mOldSelectedRegion
double SnappedTime(AudacityProject &project, size_t ii)
bool Escape(AudacityProject *pProject) override
PlayRegionAdjustingHandle(AdornedRulerPanel *pParent, wxCoord xx, MenuChoice menuChoice, wxCursor cursor, size_t numGuides=1)
void SavePlayRegion(AudacityProject &project)
bool HasEscape(AudacityProject *pProject) const override
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
std::weak_ptr< NewPlayRegionHandle > mNewPlayRegionHolder
QPCell(AdornedRulerPanel *parent)
std::weak_ptr< PlayheadHandle > mPlayheadHolder
std::shared_ptr< TrackPanelCell > ContextMenuDelegate() override
std::weak_ptr< ResizePlayRegionHandle > mResizePlayRegionHolder
std::weak_ptr< MovePlayRegionHandle > mMovePlayRegionHolder
ResizePlayRegionHandle(AdornedRulerPanel *pParent, wxCoord xx, bool hitLeft)
void DoStartAdjust(AudacityProject &project, double time) override
void DoAdjust(AudacityProject &project) override
std::shared_ptr< TrackPanelCell > ContextMenuDelegate() override
ScrubbingCell(AdornedRulerPanel *parent)
std::weak_ptr< ScrubbingHandle > mHolder
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
Result Cancel(AudacityProject *pProject) override
ScrubbingHandle(AdornedRulerPanel *pParent, wxCoord xx)
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
AdornedRulerPanel * GetRuler() const
TrackPanelGuidelineOverlay & mPartner
std::pair< wxRect, bool > DoGetRectangle(wxSize size) override
void Draw(OverlayPanel &panel, wxDC &dc) override
unsigned SequenceNumber() const override
This number determines an ordering of overlays, so that those with higher numbers overpaint those wit...
ScrubbingRulerOverlay(TrackPanelGuidelineOverlay &partner)
void Draw(OverlayPanel &panel, wxDC &dc) override
friend ScrubbingRulerOverlay
TrackPanelGuidelineOverlay(AudacityProject *project)
std::shared_ptr< ScrubbingRulerOverlay > mPartner
std::pair< wxRect, bool > DoGetRectangle(wxSize size) override
AudacityProject * mProject
unsigned SequenceNumber() const override
This number determines an ordering of overlays, so that those with higher numbers overpaint those wit...
This is an Audacity Specific ruler panel which additionally has border, selection markers,...
void OnSelectionChange(Observer::Message)
void UpdatePrefs() override
wxRect PlayRegionRectangle() const
void OnPaint(wxPaintEvent &evt)
double mQuickPlayOffset[MAX_GUIDES]
void SetTimeDisplayMode(TimeDisplayMode rulerType)
void OnAudioStartStop(AudioIOEvent)
std::shared_ptr< ScrubbingCell > mScrubbingCell
Observer::Subscription mAudioIOSubscription
void OnTogglePinnedState(wxCommandEvent &event)
void DoSelectionChange(const SelectedRegion &selectedRegion)
void SetPlayRegion(double playRegionStart, double playRegionEnd)
void ShowContextMenu(MenuChoice choice, const wxPoint *pPosition)
PlayRegion mOldPlayRegion
wxRect RegionRectangle(double t0, double t1) const
void SetFocusFromKbd() override
void OnSetPlayRegionToSelection(wxCommandEvent &evt)
void DoDrawOverlap(wxDC *dc, const wxRect &rect)
void OnSize(wxSizeEvent &evt)
void OnTimelineFormatChange(wxCommandEvent &evt)
AudacityProject *const mProject
void DoDrawScrubIndicator(wxDC *dc, wxCoord xx, int width, bool scrub, bool seek)
void GetMaxSize(wxCoord *width, wxCoord *height)
void OnPinnedButton(wxCommandEvent &event)
void UpdateStatusMessage(const TranslatableString &) override
void OnClearPlayRegion(wxCommandEvent &evt)
wxRect SelectedRegionRectangle() const
void OnIdle(wxIdleEvent &evt)
void ShowScrubMenu(const wxPoint &pos)
bool IsWithinMarker(int mousePosX, double markerTime)
void DoDrawMarks(wxDC *dc, bool)
std::shared_ptr< TrackPanelGuidelineOverlay > mOverlay
bool mLastPlayRegionActive
void OnTogglePlayRegion(wxCommandEvent &evt)
static TempAllowFocus TemporarilyAllowFocus()
std::unique_ptr< bool, Resetter > TempAllowFocus
bool mPlayRegionDragsSelection
std::shared_ptr< TrackPanelCell > GetFocusedCell() override
void DoDrawPlayRegion(wxDC *dc, const wxRect &rectP, const wxRect &rectL, const wxRect &rectR)
void OnLeave(wxMouseEvent &evt)
std::pair< double, double > mLastDrawnPlayRegion
void DoDrawSelection(wxDC *dc, const wxRect &rectS, const wxRect &rectL, const wxRect &rectR)
static void DragSelection(AudacityProject &project)
void Refresh(bool eraseBackground=true, const wxRect *rect=(const wxRect *) NULL) override
static bool s_AcceptsFocus
void SetLeftOffset(int offset)
void OnAutoScroll(wxCommandEvent &evt)
void HandleQPClick(wxMouseEvent &event, wxCoord mousePosX)
std::shared_ptr< TrackPanelNode > Root() override
Observer::Subscription mPlayRegionSubscription
void HandleQPRelease(wxMouseEvent &event)
int Time2Pos(double t, bool ignoreFisheye=false) const
void ShowMenu(const wxPoint &pos)
AudacityProject * GetProject() const override
Observer::Subscription mRulerInvalidatedSubscription
TimeDisplayMode mTimeDisplayMode
bool ShowingScrubRuler() const
void UpdateButtonStates()
void HandleQPDrag(wxMouseEvent &event, wxCoord mousePosX)
void StartQPPlay(bool newDefault, bool cutPreview, const double *pStartTime=nullptr)
Observer::Subscription mThemeChangeSubscription
MouseEventState mMouseEventState
bool mIsSnapped[MAX_GUIDES]
TimeDisplayMode GetTimeDisplayMode() const
double mQuickPlayPos[MAX_GUIDES]
void DoDrawBackground(wxDC *dc)
std::shared_ptr< QPCell > mQPCell
void OnSyncSelToQuickPlay(wxCommandEvent &evt)
void UpdateQuickPlayPos(wxCoord &mousePosX)
void DoDrawPlayRegionLimits(wxDC *dc, const wxRect &rect)
static AdornedRulerPanel & Get(AudacityProject &project)
AdornedRulerPanel(AudacityProject *project, wxWindow *parent, wxWindowID id, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, ViewInfo *viewinfo=NULL)
static constexpr size_t MAX_GUIDES
void SetNumGuides(size_t nn)
void HandleSnapping(size_t index)
double mLeftDownClickUnsnapped
void DoDrawEdge(wxDC *dc)
void ProcessUIHandleResult(TrackPanelCell *pClickedTrack, TrackPanelCell *pLatestCell, unsigned refreshResult) override
double Pos2Time(int p, bool ignoreFisheye=false) const
@ mesSelectingPlayRegionRange
@ mesDraggingPlayRegionStart
@ mesDraggingPlayRegionEnd
@ mesSelectingPlayRegionClick
SelectedRegion mLastDrawnSelectedRegion
static void Destroy(AudacityProject &project)
void SetFocusedCell() override
void OnThemeChange(struct ThemeChangeMessage)
double mQuickPlayPosUnsnapped[MAX_GUIDES]
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static AudioIOBase * Get()
wxDC & GetBackingDCForRepaint()
void OnSize(wxSizeEvent &event)
void DisplayBitmap(wxDC &dc)
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
Formerly part of TrackPanel, this abstract base class has no special knowledge of Track objects and i...
bool CancelDragging(bool escaping)
void HandleCursorForPresentMouseState(bool doHit=true)
Subclass * Find(const RegisteredFactory &key)
Get a (bare) pointer to an attachment, or null, down-cast it to Subclass *; will not create on demand...
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
void Assign(const RegisteredFactory &key, ReplacementPointer &&replacement)
Reassign Site's pointer to ClientData.
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
The widget to the left of a ToolBar that allows it to be dragged around to NEW positions.
void SetAsSpacer(bool bIsSpacer)
void SetData(const ZoomInfo *pZoomInfo=nullptr, int leftOffset=0)
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
void DrawOverlays(bool repaint_all, wxDC *pDC=nullptr)
void AddOverlay(const std::weak_ptr< Overlay > &pOverlay)
void SetStart(double start)
void SetTimes(double start, double end)
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
bool IsAudioActive() const
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static ProjectAudioIO & Get(AudacityProject &project)
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
static ProjectWindow & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
void SetTickColour(const wxColour &colour)
void Draw(wxDC &dc) const
void SetTickLengths(const TickLengths &tLengths)
void SetLabelEdges(bool labelEdges)
void GetMaxSize(wxCoord *width, wxCoord *height)
void SetBounds(int left, int top, int right, int bottom)
void SetRange(double min, double max)
static bool ShouldScrubPinned()
static Scrubber & Get(AudacityProject &project)
Defines a selected portion of a project.
wxColour & Colour(int iIndex)
wxSize ImageSize(int iIndex)
bool WriteEnum(TimeDisplayMode value)
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
double GetStartTime() const
Return the least start time of the tracks, or 0 when no tracks.
static TrackList & Get(AudacityProject &project)
std::pair< Axis, Refinement > Subdivision
std::vector< Child > Refinement
static void SetPinnedHeadPreference(bool value, bool flush=false)
static bool GetPinnedHeadPreference()
static double GetPinnedHeadPositionPreference()
static void SetPinnedHeadPositionPreference(double value, bool flush=false)
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
TranslatableString Stripped(unsigned options=MenuCodes) const
non-mutating, constructs another TranslatableString object
Short-lived drawing and event-handling object associated with a TrackPanelCell.
virtual HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject)=0
bool bUpdateTrackIndicator
NotifyingSelectedRegion selectedRegion
static int UpdateScrollPrefsID()
static ViewInfo & Get(AudacityProject &project)
double PositionToTime(int64 position, int64 origin=0, bool ignoreFisheye=false) const
int64 TimeToPosition(double time, int64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
Result Cancel(AudacityProject *) override
AdornedRulerPanel * mpParent
static UIHandle::Result NeedChangeHighlight(const PlayheadHandle &oldState, const PlayheadHandle &newState)
HitTestPreview Preview(const TrackPanelMouseState &, AudacityProject *) override
PlayheadHandle(AdornedRulerPanel &parent, wxCoord xx)
static std::shared_ptr< PlayheadHandle > HitTest(const AudacityProject *pProject, AdornedRulerPanel &parent, wxCoord xx)
void Enter(bool, AudacityProject *) override
std::shared_ptr< const Channel > FindChannel() const override
Result Click(const TrackPanelMouseEvent &event, AudacityProject *) override
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *) override
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
void SetLabel(const TranslatableString &label)
void SetFocus(const WindowPlacement &focus)
Set the window that accepts keyboard input.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
bool Begin(const FilePath &dataDir)
void Release(wxWindow *handler)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Namespace containing an enum 'what to do on a refresh?'.
void SetPlayRegionToSelection(AudacityProject &project)
void ActivatePlayRegion(AudacityProject &project)
void InactivatePlayRegion(AudacityProject &project)
void ClearPlayRegion(AudacityProject &project)
void TogglePlayRegion(AudacityProject &project)
double GetPlayHeadFraction(const AudacityProject *pProject, wxCoord xx)
void OnTogglePinnedHead(const CommandContext &context)
const TranslatableString ScrubbingMessage(const Scrubber &scrubber, bool clicked)
const TranslatableString StartScrubbingMessage(const Scrubber &)
wxCoord GetPlayHeadX(const AudacityProject *pProject)
const TranslatableString ContinueScrubbingMessage(const Scrubber &scrubber, bool clicked)
AttachedWindows::RegisteredFactory sKey
MainGroup(const AdornedRulerPanel &ruler)
Subdivision Children(const wxRect &) override
const AdornedRulerPanel & mRuler
const AdornedRulerPanel & mRuler
Subgroup(const AdornedRulerPanel &ruler)
Subdivision Children(const wxRect &) override
enum AudioIOEvent::Type type
Default message type for Publisher.
std::optional< PreferredSystemAppearance > appearance