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 }
744 if (mParent->mTimelineToolTip)
745 tooltip =
XO(
"Timeline actions disabled during recording");
747 static wxCursor cursor{ wxCURSOR_DEFAULT };
759 mParent->ShowContextMenu(mMenuChoice, pPosition);
768#undef QUICK_PLAY_HANDLE
769#ifdef QUICK_PLAY_HANDLE
792 wxWindow *pParent)
override;
815 mParent->mQuickPlayOffset[0] = 0;
816 mParent->mQuickPlayOffset[1] = 0;
825 mParent->mQuickPlayOffset[0] = playRegion.GetStart() - time;
826 mParent->mQuickPlayOffset[1] = playRegion.GetEnd() - time;
836 playRegion.
SetTimes(times.first, times.second);
866 playRegion.SetEnd(time);
905 auto width = viewInfo.GetTracksUsableWidth();
906 return viewInfo.GetLeftOffset()
913 auto width = viewInfo.GetTracksUsableWidth();
914 auto fraction = (xx - viewInfo.GetLeftOffset()) /
double(width);
915 return std::max(0.0,
std::min(1.0, fraction));
924 : mpParent{ &parent }
934 if (oldState.
mX != newState.
mX)
939 static std::shared_ptr<PlayheadHandle>
944 .IsTransportingPinned() &&
949 return std::make_shared<PlayheadHandle>( parent, xx );
958 if (event.
event.LeftDClick()) {
967 if (!event.
event.LeftIsDown())
987 mpParent->SetNumGuides(1);
988 static wxCursor cursor{ wxCURSOR_SIZEWE };
990 XO(
"Click and drag to adjust, double-click to reset" ),
994 XO(
"Record/Play head" )
1000 wxWindow *)
override
1020 double mOrigPreference {};
1033 std::vector<UIHandlePtr>
HitTest(
1042#ifdef QUICK_PLAY_HANDLE
1043 if (
auto ptr = mHolder.lock())
1044 return ptr->Clicked();
1049#ifdef QUICK_PLAY_HANDLE
1050 std::weak_ptr<QPHandle> mHolder;
1065 mParent->CreateOverlays();
1067 std::vector<UIHandlePtr> results;
1068 auto xx = state.
state.m_x;
1070#ifdef EXPERIMENTAL_DRAGGABLE_PLAY_HEAD
1074 auto result = PlayheadHandle::HitTest( pProject, *mParent, xx );
1077 results.push_back( result );
1083 if (!mParent->mIsRecording) {
1084 mParent->UpdateQuickPlayPos( xx );
1087 auto result = std::make_shared<QPHandle>( mParent, xx );
1089 results.push_back( result );
1094 bool hitLeft =
false;
1097 mParent->IsWithinMarker(xx, playRegion.GetLastActiveStart())) ||
1098 mParent->IsWithinMarker(xx, playRegion.GetLastActiveEnd()))
1101 std::make_shared<ResizePlayRegionHandle>( mParent, xx, hitLeft );
1103 results.push_back(result);
1108 if (
auto time = mParent->Pos2Time(xx);
1109 playRegion.Active() &&
1110 time >= playRegion.GetStart() &&
1111 time <= playRegion.GetEnd())
1114 std::make_shared<MovePlayRegionHandle>( mParent, xx );
1116 results.push_back(result);
1121 auto result = std::make_shared<NewPlayRegionHandle>( mParent, xx );
1123 results.push_back(result);
1148 scrubber.CanScrub() &&
1154 if (!scrubber.HasMark()) {
1156 scrubber.MarkScrubStart(
1181 wxWindow *pParent)
override {
1214 std::vector<UIHandlePtr>
HitTest(
1224 if (
auto ptr =
mHolder.lock())
1225 return ptr->Clicked();
1238 mParent->CreateOverlays();
1240 std::vector<UIHandlePtr> results;
1243 if (!mParent->mIsRecording) {
1244 auto xx = state.
state.m_x;
1245 mParent->UpdateQuickPlayPos( xx );
1246 auto result = std::make_shared<ScrubbingHandle>( mParent, xx );
1248 results.push_back( result );
1255AttachedWindows::RegisteredFactory
sKey{
1284 pPanel->wxWindow::Destroy();
1300 SetLayoutDirection(wxLayout_LeftToRight);
1302 mQPCell = std::make_shared<QPCell>(
this );
1310 SetBackgroundStyle(wxBG_STYLE_PAINT);
1319 mOuter = GetClientRect();
1335 wxToolTip::Enable(
true);
1364 CellularPanel::Refresh( eraseBackground, rect );
1383#ifdef EXPERIMENTAL_SCROLLING_LIMITS
1384#ifdef EXPERIMENTAL_TWO_TONE_TIME_RULER
1418 wxPoint position( 1, 0 );
1423 pGrabber->SetPosition( position );
1430 auto buttonMaker = [&]
1431 (wxWindowID
id,
teBmps bitmap,
bool toggle)
1436 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1437 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1438 bitmap, bitmap, bitmap,
1439 id, position, toggle,
size
1442 position.x +=
size.GetWidth();
1449 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1450 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1452 bmpRecordPointer, bmpRecordPointer, bmpRecordPointer,
1456 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1457 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1459 bmpRecordPointerPinned, bmpRecordPointerPinned, bmpRecordPointerPinned,
1463 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1464 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1466 bmpPlayPointer, bmpPlayPointer, bmpPlayPointer,
1481 if(scrubber.Seeks())
1486 return XO(
"Click or drag to begin Seek");
1492 return XO(
"Click or drag to begin Scrub");
1498 return XO(
"Click & move to Scrub. Click & drag to Seek.");
1503 const Scrubber &scrubber,
bool clicked)
1506 if(scrubber.
Seeks())
1511 return XO(
"Move to Seek");
1517 return XO(
"Move to Scrub");
1524 return XO(
"Drag to Seek. Release to stop seeking.");
1527 return XO(
"Drag to Seek. Release and move to Scrub.");
1530 return XO(
"Move to Scrub. Drag to Seek.");
1556 const auto &selectedRegion = viewInfo.selectedRegion;
1557 const auto &playRegion = viewInfo.playRegion;
1562 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() }
1600 const auto &playRegion = viewInfo.playRegion;
1601 const auto playRegionBounds = std::pair{
1602 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() };
1618 rectO = rectP.Intersect(rectS);
1621 const auto top = rectP.GetTop(),
1622 bottom = rectP.GetBottom();
1624 wxPoint{ 0, top }, wxPoint{ this->GetSize().GetWidth() - 1, bottom } };
1626 if (!rectO.IsEmpty()) {
1627 rectR = { wxPoint{ rectO.GetRight() + 1, top }, rectL.GetBottomRight() };
1628 rectL = { rectL.GetTopLeft(), wxPoint{ rectO.GetLeft() - 1, bottom } };
1646 dc.DestroyClippingRegion();
1652 mOuter = GetClientRect();
1703 auto bottom = &inner;
1711 top = &scrubZone, topHeight = scrubHeight;
1713 auto qpHeight = scrubZone.height - scrubHeight;
1714 bottom = &scrubZone, topHeight = qpHeight;
1720 top->height = topHeight;
1721 bottom->height -= topHeight;
1722 bottom->y += topHeight;
1767 int pixelPos =
Time2Pos(markerTime);
1771 return mousePosX >= boundLeft && mousePosX < boundRight;
1774#ifdef QUICK_PLAY_HANDLE
1775auto AdornedRulerPanel::QPHandle::Click(
1778 auto result = CommonRulerHandle::Click(event, pProject);
1780 if (mClicked == Button::Left) {
1785 if(scrubber.HasMark()) {
1793 const auto &playRegion = viewInfo.playRegion;
1794 mParent->mOldPlayRegion = playRegion;
1799 mParent->HandleQPClick( event.event, mX );
1800 mParent->HandleQPDrag( event.event, mX );
1820 if (isWithinStart || isWithinEnd) {
1844auto AdornedRulerPanel::QPHandle::Drag(
1847 auto result = CommonRulerHandle::Drag(event, pProject);
1849 if (mClicked == Button::Left) {
1851 mX =
event.event.m_x;
1852 mParent->UpdateQuickPlayPos( mX );
1853 mParent->HandleQPDrag( event.event, mX );
1862 bool isWithinClick =
1869 auto &playRegion = viewInfo.playRegion;
1875 if (isWithinStart || isWithinEnd) {
1902 if (isWithinStart) {
1922 if (isWithinClick) {
1947 mParent->SetNumGuides(1);
1956#ifdef QUICK_PLAY_HANDLE
1957auto AdornedRulerPanel::QPHandle::Preview(
1961 mParent->SetNumGuides(1);
1964 if (mParent && mParent->mTimelineToolTip) {
1965 if (!mParent->mQuickPlayEnabled)
1966 tooltip =
XO(
"Quick-Play disabled");
1968 tooltip =
XO(
"Quick-Play enabled");
1974 const bool scrubbing = scrubber.HasMark();
1982 static wxCursor cursorHand{ wxCURSOR_HAND };
1983 static wxCursor cursorSizeWE{ wxCURSOR_SIZEWE };
1985 bool showArrows =
false;
1988 (mClicked == Button::Left)
1989 || mParent->IsWithinMarker(
1990 state.state.m_x, mParent->mOldPlayRegion.GetStart())
1991 || mParent->IsWithinMarker(
1992 state.state.m_x, mParent->mOldPlayRegion.GetEnd());
1996 showArrows ? &cursorSizeWE : &cursorHand,
2010 auto saveMe = mParent->mQPCell->mHolder.lock();
2014 if (mClicked == Button::Left) {
2016 mParent->HandleQPRelease( event.event );
2019 const auto &playRegion = viewInfo.playRegion;
2020 mParent->mOldPlayRegion = playRegion;
2030 auto &playRegion = viewInfo.playRegion;
2035 const auto &selectedRegion = viewInfo.selectedRegion;
2036 const double sel0 = selectedRegion.t0();
2037 const double sel1 = selectedRegion.t1();
2041 if (evt.ShiftDown() && playRegion.Empty()) {
2045 if (((sel1 < t0) || (sel0 > t1)) &&
2046 ((playRegion.GetStart() < t0) || (playRegion.GetStart() > t1))) {
2051 else if (playRegion.GetStart() >= t1) {
2057 playRegion.GetEnd() - playRegion.GetStart() > 0.0 &&
2058 playRegion.GetEnd() < t0
2067 auto cleanup =
finally( [&] {
2070 SetPlayRegion(mOldPlayRegion.GetStart(), mOldPlayRegion.GetEnd());
2071 SelectUtilities::ActivatePlayRegion(*mProject);
2073 mOldPlayRegion.SetActive( false );
2082 auto result = CommonRulerHandle::Cancel(pProject);
2084 if (mClicked == Button::Left) {
2087 mParent->mMouseEventState = mesNone;
2088 mParent->SetPlayRegion(
2089 mParent->mOldPlayRegion.GetStart(), mParent->mOldPlayRegion.GetEnd());
2090 if (mParent->mOldPlayRegion.Active()) {
2094 mParent->mOldPlayRegion.SetActive(
false );
2104 bool newDefault,
bool cutPreview,
const double *pStartTime)
2109 const auto &playRegion = viewInfo.playRegion;
2110 const auto &selectedRegion = viewInfo.selectedRegion;
2111 const double sel0 = selectedRegion.t0();
2112 const double sel1 = selectedRegion.t1();
2115 bool startPlaying =
true;
2118 bool loopEnabled =
true;
2119 auto oldStart = std::max(0.0, playRegion.GetStart());
2120 double start = oldStart,
end = 0;
2122 if (playRegion.Empty()) {
2124 if (oldStart > sel0 && oldStart < sel1) {
2135 end = std::max(start, playRegion.GetEnd());
2138 loopEnabled = ((
end - start) > 0.001)? true :
false;
2140 newDefault = (loopEnabled && newDefault);
2147 options.pStartTime.emplace(*pStartTime);
2150 options.envelope =
nullptr;
2160 projectAudioManager.Stop();
2177void AdornedRulerPanel::OnToggleScrubRulerFromMenu(wxCommandEvent&)
2180 scrubber.OnToggleScrubRuler(*
mProject);
2187 const auto oldSize = GetSize();
2189 if (
size != oldSize ) {
2192 PostSizeEventToParent();
2201 auto pCellularPanel =
2203 if ( !pCellularPanel ) {
2207 pCellularPanel->DrawOverlays(
false );
2213 auto common = [
this](
2230 pinButton->PushDown();
2232 pinButton->SetAlternateIdx(
2233 (gAudioIO->IsCapturing() ? 2 : 0) + (state ? 0 : 1));
2236 const auto label =
XO(
"Timeline Options");
2237 common(*pinButton,
wxT(
"PinnedHead"),
label);
2260 auto width = viewInfo.GetTracksUsableWidth();
2261 mousePosX = std::max(mousePosX, viewInfo.GetLeftOffset());
2262 mousePosX =
std::min(mousePosX, viewInfo.GetLeftOffset() + width - 1);
2263 const auto time =
Pos2Time(mousePosX);
2277 const auto &playRegion = viewInfo.playRegion;
2282 _(
"Minutes and Seconds"));
2288 _(
"Beats and Measures"));
2292 rulerMenu.AppendSeparator();
2294 auto pDrag = rulerMenu.AppendCheckItem(
OnSyncQuickPlaySelID,
_(
"Setting a loop region also makes an audio selection"));
2296 pDrag->Enable(playRegion.Active());
2298 rulerMenu.AppendCheckItem(
OnAutoScrollID,
_(
"Update display while playing"))->
2304 item->Check(playRegion.Active());
2315 _(
"Set Loop To Selection"));
2318 rulerMenu.AppendSeparator();
2331 PushEventHandler(&scrubber);
2332 auto cleanup =
finally([
this]{ PopEventHandler(); });
2335 scrubber.PopulatePopupMenu(rulerMenu);
2345 const auto &playRegion = viewInfo.playRegion;
2346 auto &selectedRegion = viewInfo.selectedRegion;
2347 selectedRegion.setT0(playRegion.GetStart(),
false);
2348 selectedRegion.setT1(playRegion.GetEnd(),
true);
2362 auto results = snapManager.Snap(
nullptr,
mQuickPlayPos[index],
false);
2369 int id =
event.GetId();
2389void AdornedRulerPanel::OnTimelineToolTips(wxCommandEvent&)
2432 position = *pPosition;
2435 auto rect = GetRect();
2443 position = { rect.GetLeft() + 38, rect.GetHeight()/2 + 1 };
2462 return clrTrackInfo;
2467 return clrTrackPanelText;
2477 return isActive ? clrRulerBackground : clrClipAffordanceInactiveBrush;
2495 dc->DrawRectangle(
mInner );
2502 ScrubRect.Inflate( 1,0 );
2503 dc->DrawRectangle(ScrubRect);
2515 dc->SetPen( *wxBLACK_PEN );
2525 const double hiddenMin =
Pos2Time(0,
true);
2550 const auto &playRegion = viewInfo.playRegion;
2551 const auto t0 = playRegion.GetLastActiveStart(),
2552 t1 = playRegion.GetLastActiveEnd();
2559 const auto &selectedRegion = viewInfo.selectedRegion;
2560 const auto t0 = selectedRegion.t0(), t1 = selectedRegion.t1();
2566 int p0 = -1, p1 = -1;
2575 const int left = p0, top =
mInner.y, right = p1, bottom =
mInner.GetBottom();
2576 return { wxPoint{left, top}, wxPoint{right, bottom} };
2580 wxDC * dc,
const wxRect &rectP,
const wxRect &rectL,
const wxRect &rectR)
2583 const auto& playRegion = viewInfo.playRegion;
2587 if (playRegion.IsLastActiveRegionClear())
2595 dc->DrawRectangle( rectP.Intersect(rectL) );
2596 dc->DrawRectangle( rectP.Intersect(rectR) );
2604 dc->SetPen( { edgeColour } );
2605 dc->SetBrush( { edgeColour } );
2607 constexpr int side = 7;
2608 constexpr int sideLessOne = side - 1;
2611 const auto left = rect.GetLeft(),
2612 right = rect.GetRight(),
2613 bottom = rect.GetBottom(),
2614 top = rect.GetTop();
2617 {left, bottom - sideLessOne},
2618 {left - sideLessOne, bottom},
2622 dc->DrawPolygon( 4, points );
2629 {right + sideLessOne, bottom},
2630 {right, bottom - sideLessOne},
2632 dc->DrawPolygon( 4, points );
2643 dc->SetPen( *wxTRANSPARENT_PEN );
2644 dc->DrawRectangle( rect );
2648 wxDC * dc,
const wxRect &rectS,
const wxRect &rectL,
const wxRect &rectR)
2652 dc->SetPen( *wxTRANSPARENT_PEN );
2653 dc->DrawRectangle( rectS.Intersect(rectL) );
2654 dc->DrawRectangle( rectS.Intersect(rectR) );
2673 wxDC * dc, wxCoord xx,
int width,
bool scrub,
bool seek)
2681 const int TriangleWidth = width * 3 / 8;
2686 : (
mInner.GetBottom() + 1) - 1 - height;
2690 tri[ 1 ].y = yy + height;
2691 tri[ 2 ].x = xx - TriangleWidth;
2692 tri[ 2 ].y = yy + height / 2;
2693 dc->DrawPolygon( 3, tri );
2695 tri[ 0 ].x -= TriangleWidth;
2696 tri[ 1 ].x -= TriangleWidth;
2697 tri[ 2 ].x -= TriangleWidth;
2698 dc->DrawPolygon( 3, tri );
2701 tri[ 2 ].x = xx + TriangleWidth;
2702 dc->DrawPolygon( 3, tri );
2705 tri[ 0 ].x += TriangleWidth;
2706 tri[ 1 ].x += TriangleWidth;
2707 tri[ 2 ].x += TriangleWidth;
2708 dc->DrawPolygon( 3, tri );
2712 const int IndicatorHalfWidth = width / 2;
2717 : (
mInner.GetBottom() + 1) - 1 - height;
2721 tri[ 1 ].y = yy + height;
2722 tri[ 2 ].x = xx - IndicatorHalfWidth;
2723 tri[ 2 ].y = yy + height / 2;
2724 dc->DrawPolygon( 3, tri );
2726 tri[ 2 ].x = xx + IndicatorHalfWidth;
2727 dc->DrawPolygon( 3, tri );
2732 double playRegionStart,
double playRegionEnd)
2741 auto &playRegion = viewInfo.playRegion;
2742 playRegion.SetTimes( playRegionStart, playRegionEnd );
2752 auto &playRegion = viewInfo.playRegion;
2766 s_AcceptsFocus =
true;
2774 for (
size_t ii =
mNumGuides; ii < nn; ++ii) {
2825 return scrubber.ShowsBar();
2832 return std::make_shared< MainGroup >( *
this );
2871 std::make_shared<TrackPanelGuidelineOverlay>(
mProject );
2872 auto pCellularPanel =
2874 if ( !pCellularPanel ) {
2878 pCellularPanel->AddOverlay(
mOverlay );
2894 if (scrubber.HasMark())
2895 scrubber.SetScrollScrubbing(value);
2926 Command(
wxT(
"PinnedHead"),
XXO(
"Enable pinned play &head"),
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)
BoolSetting ScrollingPreference
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
TrackPanelCell * GetFocusedCell() 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
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)
void SetTwoTone(bool twoTone)
static bool ShouldScrubPinned()
static Scrubber & Get(AudacityProject &project)
Defines a selected portion of a project.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
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