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 7
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;
1074 results.push_back( result );
1079 if (!mParent->mIsRecording) {
1080 mParent->UpdateQuickPlayPos( xx );
1083 auto result = std::make_shared<QPHandle>( mParent, xx );
1085 results.push_back( result );
1090 bool hitLeft =
false;
1093 mParent->IsWithinMarker(xx, playRegion.GetLastActiveStart())) ||
1094 mParent->IsWithinMarker(xx, playRegion.GetLastActiveEnd()))
1097 std::make_shared<ResizePlayRegionHandle>( mParent, xx, hitLeft );
1099 results.push_back(result);
1104 if (
auto time = mParent->Pos2Time(xx);
1105 playRegion.Active() &&
1106 time >= playRegion.GetStart() &&
1107 time <= playRegion.GetEnd())
1110 std::make_shared<MovePlayRegionHandle>( mParent, xx );
1112 results.push_back(result);
1117 auto result = std::make_shared<NewPlayRegionHandle>( mParent, xx );
1119 results.push_back(result);
1144 scrubber.CanScrub() &&
1150 if (!scrubber.HasMark()) {
1152 scrubber.MarkScrubStart(
1177 wxWindow *pParent)
override {
1210 std::vector<UIHandlePtr>
HitTest(
1220 if (
auto ptr =
mHolder.lock())
1221 return ptr->Clicked();
1234 mParent->CreateOverlays();
1236 std::vector<UIHandlePtr> results;
1239 if (!mParent->mIsRecording) {
1240 auto xx = state.
state.m_x;
1241 mParent->UpdateQuickPlayPos( xx );
1242 auto result = std::make_shared<ScrubbingHandle>( mParent, xx );
1244 results.push_back( result );
1251AttachedWindows::RegisteredFactory
sKey{
1280 pPanel->wxWindow::Destroy();
1296 SetLayoutDirection(wxLayout_LeftToRight);
1298 mQPCell = std::make_shared<QPCell>(
this );
1306 SetBackgroundStyle(wxBG_STYLE_PAINT);
1315 mOuter = GetClientRect();
1330 wxToolTip::Enable(
true);
1359 CellularPanel::Refresh( eraseBackground, rect );
1388 SetBackgroundColour(GetBackgroundColour());
1402 wxPoint position( 12, 0 );
1411 bmpRecoloredUpSmall, bmpRecoloredDownSmall,
1412 bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
1413 bmpCogwheel, bmpCogwheel, bmpCogwheel,
1417 position.x +=
size.GetWidth();
1432 if(scrubber.Seeks())
1437 return XO(
"Click or drag to begin Seek");
1443 return XO(
"Click or drag to begin Scrub");
1449 return XO(
"Click & move to Scrub. Click & drag to Seek.");
1454 const Scrubber &scrubber,
bool clicked)
1457 if(scrubber.
Seeks())
1462 return XO(
"Move to Seek");
1468 return XO(
"Move to Scrub");
1475 return XO(
"Drag to Seek. Release to stop seeking.");
1478 return XO(
"Drag to Seek. Release and move to Scrub.");
1481 return XO(
"Move to Scrub. Drag to Seek.");
1508 const auto &selectedRegion = viewInfo.selectedRegion;
1509 const auto &playRegion = viewInfo.playRegion;
1514 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() }
1519 if (changed && !isIconized)
1552 const auto &playRegion = viewInfo.playRegion;
1553 const auto playRegionBounds = std::pair{
1554 playRegion.GetLastActiveStart(), playRegion.GetLastActiveEnd() };
1570 rectO = rectP.Intersect(rectS);
1573 const auto top = rectP.GetTop(),
1574 bottom = rectP.GetBottom();
1577 if (!rectO.IsEmpty()) {
1578 rectR = { wxPoint{ rectO.GetRight() + 1, top }, rectL.GetBottomRight() };
1579 rectL = { rectL.GetTopLeft(), wxPoint{ rectO.GetLeft() - 1, bottom } };
1597 dc.DestroyClippingRegion();
1603 mOuter = GetClientRect();
1654 auto bottom = &inner;
1662 top = &scrubZone, topHeight = scrubHeight;
1664 auto qpHeight = scrubZone.height - scrubHeight;
1665 bottom = &scrubZone, topHeight = qpHeight;
1671 top->height = topHeight;
1672 bottom->height -= topHeight;
1673 bottom->y += topHeight;
1718 int pixelPos =
Time2Pos(markerTime);
1722 return mousePosX >= boundLeft && mousePosX < boundRight;
1725#ifdef QUICK_PLAY_HANDLE
1726auto AdornedRulerPanel::QPHandle::Click(
1729 auto result = CommonRulerHandle::Click(event, pProject);
1731 if (mClicked == Button::Left) {
1736 if(scrubber.HasMark()) {
1744 const auto &playRegion = viewInfo.playRegion;
1745 mParent->mOldPlayRegion = playRegion;
1750 mParent->HandleQPClick( event.event, mX );
1751 mParent->HandleQPDrag( event.event, mX );
1771 if (isWithinStart || isWithinEnd) {
1795auto AdornedRulerPanel::QPHandle::Drag(
1798 auto result = CommonRulerHandle::Drag(event, pProject);
1800 if (mClicked == Button::Left) {
1802 mX =
event.event.m_x;
1803 mParent->UpdateQuickPlayPos( mX );
1804 mParent->HandleQPDrag( event.event, mX );
1813 bool isWithinClick =
1820 auto &playRegion = viewInfo.playRegion;
1826 if (isWithinStart || isWithinEnd) {
1853 if (isWithinStart) {
1873 if (isWithinClick) {
1898 mParent->SetNumGuides(1);
1907#ifdef QUICK_PLAY_HANDLE
1908auto AdornedRulerPanel::QPHandle::Preview(
1912 mParent->SetNumGuides(1);
1916 if (!mParent->mQuickPlayEnabled)
1917 tooltip =
XO(
"Quick-Play disabled");
1919 tooltip =
XO(
"Quick-Play enabled");
1925 const bool scrubbing = scrubber.HasMark();
1933 static wxCursor cursorHand{ wxCURSOR_HAND };
1934 static wxCursor cursorSizeWE{ wxCURSOR_SIZEWE };
1936 bool showArrows =
false;
1939 (mClicked == Button::Left)
1940 || mParent->IsWithinMarker(
1941 state.state.m_x, mParent->mOldPlayRegion.GetStart())
1942 || mParent->IsWithinMarker(
1943 state.state.m_x, mParent->mOldPlayRegion.GetEnd());
1947 showArrows ? &cursorSizeWE : &cursorHand,
1961 auto saveMe = mParent->mQPCell->mHolder.lock();
1965 if (mClicked == Button::Left) {
1967 mParent->HandleQPRelease( event.event );
1970 const auto &playRegion = viewInfo.playRegion;
1971 mParent->mOldPlayRegion = playRegion;
1981 auto &playRegion = viewInfo.playRegion;
1986 const auto &selectedRegion = viewInfo.selectedRegion;
1987 const double sel0 = selectedRegion.t0();
1988 const double sel1 = selectedRegion.t1();
1992 if (evt.ShiftDown() && playRegion.Empty()) {
1996 if (((sel1 < t0) || (sel0 > t1)) &&
1997 ((playRegion.GetStart() < t0) || (playRegion.GetStart() > t1))) {
2002 else if (playRegion.GetStart() >= t1) {
2008 playRegion.GetEnd() - playRegion.GetStart() > 0.0 &&
2009 playRegion.GetEnd() < t0
2018 auto cleanup =
finally( [&] {
2021 SetPlayRegion(mOldPlayRegion.GetStart(), mOldPlayRegion.GetEnd());
2022 SelectUtilities::ActivatePlayRegion(*mProject);
2024 mOldPlayRegion.SetActive( false );
2033 auto result = CommonRulerHandle::Cancel(pProject);
2035 if (mClicked == Button::Left) {
2038 mParent->mMouseEventState = mesNone;
2039 mParent->SetPlayRegion(
2040 mParent->mOldPlayRegion.GetStart(), mParent->mOldPlayRegion.GetEnd());
2041 if (mParent->mOldPlayRegion.Active()) {
2045 mParent->mOldPlayRegion.SetActive(
false );
2055 bool newDefault,
bool cutPreview,
const double *pStartTime)
2060 const auto &playRegion = viewInfo.playRegion;
2061 const auto &selectedRegion = viewInfo.selectedRegion;
2062 const double sel0 = selectedRegion.t0();
2063 const double sel1 = selectedRegion.t1();
2066 bool startPlaying =
true;
2069 bool loopEnabled =
true;
2070 auto oldStart = std::max(0.0, playRegion.GetStart());
2071 double start = oldStart,
end = 0;
2073 if (playRegion.Empty()) {
2075 if (oldStart > sel0 && oldStart < sel1) {
2086 end = std::max(start, playRegion.GetEnd());
2089 loopEnabled = ((
end - start) > 0.001)? true :
false;
2091 newDefault = (loopEnabled && newDefault);
2098 options.pStartTime.emplace(*pStartTime);
2101 options.envelope =
nullptr;
2111 projectAudioManager.Stop();
2128void AdornedRulerPanel::OnToggleScrubRulerFromMenu(wxCommandEvent&)
2131 scrubber.OnToggleScrubRuler(*
mProject);
2138 const auto oldSize = GetSize();
2140 if (
size != oldSize ) {
2143 PostSizeEventToParent();
2152 auto pCellularPanel =
2154 if ( !pCellularPanel ) {
2158 pCellularPanel->DrawOverlays(
false );
2164 auto common = [
this](
2175 timelineOptionsButton->
PopUp();
2178 const auto label =
XO(
"Timeline Options");
2179 common(*timelineOptionsButton,
wxT(
"PinnedHead"),
label);
2202 auto width = viewInfo.GetTracksUsableWidth();
2203 mousePosX = std::max(mousePosX, viewInfo.GetLeftOffset());
2204 mousePosX =
std::min(mousePosX, viewInfo.GetLeftOffset() + width - 1);
2205 const auto time =
Pos2Time(mousePosX);
2219 const auto &playRegion = viewInfo.playRegion;
2224 _(
"Minutes and Seconds"));
2230 _(
"Beats and Measures"));
2234 rulerMenu.AppendSeparator();
2236 auto pDrag = rulerMenu.AppendCheckItem(
OnSyncQuickPlaySelID,
_(
"Setting a loop region also makes an audio selection"));
2238 pDrag->Enable(playRegion.Active());
2243 item->Check(playRegion.Active());
2254 _(
"Set Loop To Selection"));
2257 rulerMenu.AppendSeparator();
2259 rulerMenu.AppendCheckItem(
OnAutoScrollID,
_(
"Scroll view to playhead"))->
2274 PushEventHandler(&scrubber);
2275 auto cleanup =
finally([
this]{ PopEventHandler(); });
2278 scrubber.PopulatePopupMenu(rulerMenu);
2288 const auto &playRegion = viewInfo.playRegion;
2289 auto &selectedRegion = viewInfo.selectedRegion;
2290 selectedRegion.setT0(playRegion.GetStart(),
false);
2291 selectedRegion.setT1(playRegion.GetEnd(),
true);
2305 auto results = snapManager.Snap(
nullptr,
mQuickPlayPos[index],
false);
2312 int id =
event.GetId();
2365 position = *pPosition;
2368 auto rect = GetRect();
2376 position = { rect.GetLeft() + 38, rect.GetHeight()/2 + 1 };
2395 return clrTimelineRulerBackground;
2400 return clrTrackPanelText;
2410 return clrRulerSelected;
2415 return isActive ? clrLoopEnabled : clrLoopDisabled;
2433 dc->DrawRectangle(
mOuter );
2440 ScrubRect.Inflate( 1,0 );
2441 dc->DrawRectangle(ScrubRect);
2448 dc->SetPen( *wxBLACK_PEN );
2483 const auto &playRegion = viewInfo.playRegion;
2484 const auto t0 = playRegion.GetLastActiveStart(),
2485 t1 = playRegion.GetLastActiveEnd();
2492 const auto &selectedRegion = viewInfo.selectedRegion;
2493 const auto t0 = selectedRegion.t0(), t1 = selectedRegion.t1();
2509 const int left = p0, top =
mInner.y, right = p1, bottom =
mInner.GetBottom();
2510 return { wxPoint{left, top}, wxPoint{right, bottom} };
2514 wxDC * dc,
const wxRect &rectP,
const wxRect &rectL,
const wxRect &rectR)
2517 const auto& playRegion = viewInfo.playRegion;
2521 if (playRegion.IsLastActiveRegionClear())
2529 dc->DrawRectangle( rectP.Intersect(rectL) );
2530 dc->DrawRectangle( rectP.Intersect(rectR) );
2538 dc->SetPen( { edgeColour } );
2539 dc->SetBrush( { edgeColour } );
2541 constexpr int side = 7;
2542 constexpr int sideLessOne = side - 1;
2545 const auto left = rect.GetLeft(),
2546 right = rect.GetRight(),
2547 bottom = rect.GetBottom(),
2548 top = rect.GetTop();
2551 {left, bottom - sideLessOne},
2552 {left - sideLessOne, bottom},
2556 dc->DrawPolygon( 4, points );
2563 {right + sideLessOne, bottom},
2564 {right, bottom - sideLessOne},
2566 dc->DrawPolygon( 4, points );
2577 dc->SetPen( *wxTRANSPARENT_PEN );
2578 dc->DrawRectangle( rect );
2582 wxDC * dc,
const wxRect &rectS,
const wxRect &rectL,
const wxRect &rectR)
2586 dc->SetPen( *wxTRANSPARENT_PEN );
2587 dc->DrawRectangle( rectS.Intersect(rectL) );
2588 dc->DrawRectangle( rectS.Intersect(rectR) );
2607 wxDC * dc, wxCoord xx,
int width,
bool scrub,
bool seek)
2615 const int TriangleWidth = width * 3 / 8;
2620 : (
mInner.GetBottom() + 1) - 1 - height;
2624 tri[ 1 ].y = yy + height;
2625 tri[ 2 ].x = xx - TriangleWidth;
2626 tri[ 2 ].y = yy + height / 2;
2627 dc->DrawPolygon( 3, tri );
2629 tri[ 0 ].x -= TriangleWidth;
2630 tri[ 1 ].x -= TriangleWidth;
2631 tri[ 2 ].x -= TriangleWidth;
2632 dc->DrawPolygon( 3, tri );
2635 tri[ 2 ].x = xx + TriangleWidth;
2636 dc->DrawPolygon( 3, tri );
2639 tri[ 0 ].x += TriangleWidth;
2640 tri[ 1 ].x += TriangleWidth;
2641 tri[ 2 ].x += TriangleWidth;
2642 dc->DrawPolygon( 3, tri );
2646 const int IndicatorHalfWidth = width / 2;
2651 : (
mInner.GetBottom() + 1) - 1 - height;
2655 tri[ 1 ].y = yy + height;
2656 tri[ 2 ].x = xx - IndicatorHalfWidth;
2657 tri[ 2 ].y = yy + height / 2;
2658 dc->DrawPolygon( 3, tri );
2660 tri[ 2 ].x = xx + IndicatorHalfWidth;
2661 dc->DrawPolygon( 3, tri );
2666 double playRegionStart,
double playRegionEnd)
2675 auto &playRegion = viewInfo.playRegion;
2676 playRegion.SetTimes( playRegionStart, playRegionEnd );
2686 auto &playRegion = viewInfo.playRegion;
2700 s_AcceptsFocus =
true;
2708 for (
size_t ii =
mNumGuides; ii < nn; ++ii) {
2759 return scrubber.ShowsBar();
2766 return std::make_shared< MainGroup >( *
this );
2802 std::make_shared<TrackPanelGuidelineOverlay>(
mProject );
2803 auto pCellularPanel =
2805 if ( !pCellularPanel ) {
2809 pCellularPanel->AddOverlay(
mOverlay );
2825 if (scrubber.HasMark())
2826 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)
#define PLAY_REGION_TRIANGLE_SIZE
ColorId TimelineSelectionColor()
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 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)
Result Release(const TrackPanelMouseEvent &event, AudacityProject *, wxWindow *) override
std::shared_ptr< const Track > FindTrack() const 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,...
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)
bool IsIconized() const override
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
std::shared_ptr< const Track > FindTrack() const override
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
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)
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
const char * end(const char *str) noexcept
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