mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-17 08:30:06 +02:00
Reimplement the play/record indicator in the ruler as an overlay...
... fixing the lag between the green line and the triangle for scrolling play
This commit is contained in:
parent
d8e42b0af4
commit
f9dd6b4066
@ -30,30 +30,26 @@ namespace {
|
|||||||
{
|
{
|
||||||
return (m >= l && m < h);
|
return (m >= l && m < h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum { IndicatorMediumWidth = 13 };
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
|
PlayIndicatorOverlayBase::PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster)
|
||||||
: mProject(project)
|
: mProject(project)
|
||||||
, mLastIndicatorX(-1)
|
, mIsMaster(isMaster)
|
||||||
, mNewIndicatorX(-1)
|
|
||||||
{
|
{
|
||||||
mProject->Connect(EVT_TRACK_PANEL_TIMER,
|
|
||||||
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
|
|
||||||
NULL,
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayIndicatorOverlay::~PlayIndicatorOverlay()
|
PlayIndicatorOverlayBase::~PlayIndicatorOverlayBase()
|
||||||
{
|
{
|
||||||
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
|
|
||||||
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
|
|
||||||
NULL,
|
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<wxRect, bool> PlayIndicatorOverlay::DoGetRectangle(wxSize size)
|
std::pair<wxRect, bool> PlayIndicatorOverlayBase::DoGetRectangle(wxSize size)
|
||||||
{
|
{
|
||||||
wxRect rect(mLastIndicatorX, 0, 1, size.GetHeight());
|
auto width = mIsMaster ? 1 : IndicatorMediumWidth;
|
||||||
|
|
||||||
|
// May be excessive height, but little matter
|
||||||
|
wxRect rect(mLastIndicatorX - width / 2, 0, width, size.GetHeight());
|
||||||
return std::make_pair(
|
return std::make_pair(
|
||||||
rect,
|
rect,
|
||||||
mLastIndicatorX != mNewIndicatorX
|
mLastIndicatorX != mNewIndicatorX
|
||||||
@ -61,26 +57,20 @@ std::pair<wxRect, bool> PlayIndicatorOverlay::DoGetRectangle(wxSize size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PlayIndicatorOverlay::Draw(OverlayPanel &panel, wxDC &dc)
|
void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc)
|
||||||
{
|
{
|
||||||
TrackPanel &tp = static_cast<TrackPanel&>(panel);
|
// Set play/record color
|
||||||
TrackPanelCellIterator begin(&tp, true);
|
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
|
||||||
TrackPanelCellIterator end(&tp, false);
|
AColor::IndicatorColor(&dc, !rec);
|
||||||
|
|
||||||
mLastIndicatorX = mNewIndicatorX;
|
mLastIndicatorX = mNewIndicatorX;
|
||||||
if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
|
if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ZoomInfo &viewInfo = mProject->GetZoomInfo();
|
if(auto tp = dynamic_cast<TrackPanel*>(&panel)) {
|
||||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
wxASSERT(mIsMaster);
|
||||||
|
|
||||||
double pos = viewInfo.PositionToTime(mLastIndicatorX, trackPanel->GetLeftOffset());
|
TrackPanelCellIterator begin(tp, true);
|
||||||
|
TrackPanelCellIterator end(tp, false);
|
||||||
// Set play/record color
|
|
||||||
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
|
|
||||||
AColor::IndicatorColor(&dc, !rec);
|
|
||||||
|
|
||||||
mProject->GetRulerPanel()->DrawIndicator(pos, rec);
|
|
||||||
|
|
||||||
// Draw indicator in all visible tracks
|
// Draw indicator in all visible tracks
|
||||||
for (; begin != end; ++begin)
|
for (; begin != end; ++begin)
|
||||||
@ -106,11 +96,36 @@ void PlayIndicatorOverlay::Draw(OverlayPanel &panel, wxDC &dc)
|
|||||||
rect.GetBottom());
|
rect.GetBottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
||||||
|
wxASSERT(!mIsMaster);
|
||||||
|
|
||||||
void PlayIndicatorOverlay::Erase(wxDC &dc, wxDC &src)
|
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wxASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
|
||||||
|
: PlayIndicatorOverlayBase(project, true)
|
||||||
{
|
{
|
||||||
Overlay::Erase(dc, src);
|
mProject->Connect(EVT_TRACK_PANEL_TIMER,
|
||||||
mProject->GetRulerPanel()->ClearIndicator();
|
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
|
||||||
|
NULL,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayIndicatorOverlay::~PlayIndicatorOverlay()
|
||||||
|
{
|
||||||
|
if (mPartner) {
|
||||||
|
auto ruler = mProject->GetRulerPanel();
|
||||||
|
if(ruler)
|
||||||
|
ruler->RemoveOverlay(mPartner.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
mProject->Disconnect(EVT_TRACK_PANEL_TIMER,
|
||||||
|
wxCommandEventHandler(PlayIndicatorOverlay::OnTimer),
|
||||||
|
NULL,
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
||||||
@ -118,6 +133,15 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
|||||||
// Let other listeners get the notification
|
// Let other listeners get the notification
|
||||||
event.Skip();
|
event.Skip();
|
||||||
|
|
||||||
|
// Ensure that there is an overlay attached to the ruler
|
||||||
|
if (!mPartner) {
|
||||||
|
auto ruler = mProject->GetRulerPanel();
|
||||||
|
if (ruler) {
|
||||||
|
mPartner = std::make_unique<PlayIndicatorOverlayBase>(mProject, false);
|
||||||
|
ruler->AddOverlay(mPartner.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mProject->IsAudioActive()) {
|
if (!mProject->IsAudioActive()) {
|
||||||
const auto &scrubber = mProject->GetScrubber();
|
const auto &scrubber = mProject->GetScrubber();
|
||||||
if (scrubber.HasStartedScrubbing())
|
if (scrubber.HasStartedScrubbing())
|
||||||
@ -158,4 +182,7 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
|||||||
|
|
||||||
mNewIndicatorX = viewInfo.TimeToPosition(playPos, mProject->GetTrackPanel()->GetLeftOffset());
|
mNewIndicatorX = viewInfo.TimeToPosition(playPos, mProject->GetTrackPanel()->GetLeftOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mPartner)
|
||||||
|
mPartner->Update(mNewIndicatorX);
|
||||||
}
|
}
|
||||||
|
@ -12,28 +12,44 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#define __AUDACITY_PLAY_INDICATOR_OVERLAY__
|
#define __AUDACITY_PLAY_INDICATOR_OVERLAY__
|
||||||
|
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
|
#include "../../MemoryX.h"
|
||||||
#include "../../widgets/Overlay.h"
|
#include "../../widgets/Overlay.h"
|
||||||
|
|
||||||
class AudacityProject;
|
class AudacityProject;
|
||||||
|
|
||||||
|
|
||||||
class PlayIndicatorOverlay final : public wxEvtHandler, public Overlay
|
// Common class for overlaying track panel or ruler
|
||||||
|
class PlayIndicatorOverlayBase : public wxEvtHandler, public Overlay
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster);
|
||||||
|
virtual ~PlayIndicatorOverlayBase();
|
||||||
|
|
||||||
|
void Update(int newIndicatorX) { mNewIndicatorX = newIndicatorX; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
|
||||||
|
void Draw(OverlayPanel &panel, wxDC &dc) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
AudacityProject *const mProject;
|
||||||
|
const bool mIsMaster;
|
||||||
|
int mLastIndicatorX { -1 };
|
||||||
|
int mNewIndicatorX { -1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Master object for track panel, creates the other object for the ruler
|
||||||
|
class PlayIndicatorOverlay final : public PlayIndicatorOverlayBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlayIndicatorOverlay(AudacityProject *project);
|
PlayIndicatorOverlay(AudacityProject *project);
|
||||||
virtual ~PlayIndicatorOverlay();
|
virtual ~PlayIndicatorOverlay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
|
|
||||||
void Draw(OverlayPanel &panel, wxDC &dc) override;
|
|
||||||
void Erase(wxDC &dc, wxDC &src) override;
|
|
||||||
|
|
||||||
void OnTimer(wxCommandEvent &event);
|
void OnTimer(wxCommandEvent &event);
|
||||||
|
|
||||||
|
std::unique_ptr<PlayIndicatorOverlayBase> mPartner;
|
||||||
AudacityProject *mProject;
|
|
||||||
int mLastIndicatorX;
|
|
||||||
int mNewIndicatorX;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1813,9 +1813,10 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* parent,
|
|||||||
|
|
||||||
mLeftOffset = 0;
|
mLeftOffset = 0;
|
||||||
mIndTime = -1;
|
mIndTime = -1;
|
||||||
mIndType = -1;
|
|
||||||
mQuickPlayInd = false;
|
mQuickPlayInd = false;
|
||||||
mLastQuickPlayX = -1;
|
mLastQuickPlayX = -1;
|
||||||
|
|
||||||
mPlayRegionStart = -1;
|
mPlayRegionStart = -1;
|
||||||
mPlayRegionLock = false;
|
mPlayRegionLock = false;
|
||||||
mPlayRegionEnd = -1;
|
mPlayRegionEnd = -1;
|
||||||
@ -2131,12 +2132,6 @@ void AdornedRulerPanel::OnPaint(wxPaintEvent & WXUNUSED(evt))
|
|||||||
|
|
||||||
DoDrawMarks(&backDC, true);
|
DoDrawMarks(&backDC, true);
|
||||||
|
|
||||||
if (mIndType >= 0)
|
|
||||||
{
|
|
||||||
const bool scrub = mProject->GetScrubber().HasStartedScrubbing();
|
|
||||||
DoDrawIndicator(&backDC, mIndTime, mIndType != 0, IndicatorMediumWidth, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
DoDrawPlayRegion(&backDC);
|
DoDrawPlayRegion(&backDC);
|
||||||
|
|
||||||
DoDrawPushbuttons(&backDC);
|
DoDrawPushbuttons(&backDC);
|
||||||
@ -3466,39 +3461,12 @@ void AdornedRulerPanel::SetLeftOffset(int offset)
|
|||||||
mRuler.SetUseZoomInfo(offset, mViewInfo);
|
mRuler.SetUseZoomInfo(offset, mViewInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
//This draws the little triangular indicator on the
|
|
||||||
//AdornedRulerPanel.
|
|
||||||
//
|
|
||||||
void AdornedRulerPanel::ClearIndicator()
|
|
||||||
{
|
|
||||||
mIndType = -1;
|
|
||||||
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdornedRulerPanel::DrawIndicator( double time, bool rec )
|
|
||||||
{
|
|
||||||
mIndTime = time;
|
|
||||||
|
|
||||||
if (mIndTime < 0)
|
|
||||||
{
|
|
||||||
ClearIndicator();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIndType = ( rec ? 0 : 1 );
|
|
||||||
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draws the play/recording position indicator.
|
// Draws the play/recording position indicator.
|
||||||
void AdornedRulerPanel::DoDrawIndicator
|
void AdornedRulerPanel::DoDrawIndicator
|
||||||
(wxDC * dc, double time, bool playing, int width, bool scrub)
|
(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub)
|
||||||
{
|
{
|
||||||
ADCChanger changer(dc); // Undo pen and brush changes at function exit
|
ADCChanger changer(dc); // Undo pen and brush changes at function exit
|
||||||
|
|
||||||
const int x = Time2Pos(time);
|
|
||||||
AColor::IndicatorColor( dc, playing );
|
AColor::IndicatorColor( dc, playing );
|
||||||
|
|
||||||
wxPoint tri[ 3 ];
|
wxPoint tri[ 3 ];
|
||||||
@ -3510,26 +3478,26 @@ void AdornedRulerPanel::DoDrawIndicator
|
|||||||
auto yy = mShowScrubbing
|
auto yy = mShowScrubbing
|
||||||
? mScrubZone.y
|
? mScrubZone.y
|
||||||
: (mInner.GetBottom() + 1) - 1 /* bevel */ - height;
|
: (mInner.GetBottom() + 1) - 1 /* bevel */ - height;
|
||||||
tri[ 0 ].x = x - IndicatorOffset;
|
tri[ 0 ].x = xx - IndicatorOffset;
|
||||||
tri[ 0 ].y = yy;
|
tri[ 0 ].y = yy;
|
||||||
tri[ 1 ].x = x - IndicatorOffset;
|
tri[ 1 ].x = xx - IndicatorOffset;
|
||||||
tri[ 1 ].y = yy + height;
|
tri[ 1 ].y = yy + height;
|
||||||
tri[ 2 ].x = x - IndicatorHalfWidth;
|
tri[ 2 ].x = xx - IndicatorHalfWidth;
|
||||||
tri[ 2 ].y = yy + height / 2;
|
tri[ 2 ].y = yy + height / 2;
|
||||||
dc->DrawPolygon( 3, tri );
|
dc->DrawPolygon( 3, tri );
|
||||||
tri[ 0 ].x = tri[ 1 ].x = x + IndicatorOffset;
|
tri[ 0 ].x = tri[ 1 ].x = xx + IndicatorOffset;
|
||||||
tri[ 2 ].x = x + IndicatorHalfWidth;
|
tri[ 2 ].x = xx + IndicatorHalfWidth;
|
||||||
dc->DrawPolygon( 3, tri );
|
dc->DrawPolygon( 3, tri );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Down pointing triangle
|
// Down pointing triangle
|
||||||
auto height = IndicatorHeightForWidth(width);
|
auto height = IndicatorHeightForWidth(width);
|
||||||
const int IndicatorHalfWidth = width / 2;
|
const int IndicatorHalfWidth = width / 2;
|
||||||
tri[ 0 ].x = x - IndicatorHalfWidth;
|
tri[ 0 ].x = xx - IndicatorHalfWidth;
|
||||||
tri[ 0 ].y = mInner.y;
|
tri[ 0 ].y = mInner.y;
|
||||||
tri[ 1 ].x = x + IndicatorHalfWidth;
|
tri[ 1 ].x = xx + IndicatorHalfWidth;
|
||||||
tri[ 1 ].y = mInner.y;
|
tri[ 1 ].y = mInner.y;
|
||||||
tri[ 2 ].x = x;
|
tri[ 2 ].x = xx;
|
||||||
tri[ 2 ].y = mInner.y + height;
|
tri[ 2 ].y = mInner.y + height;
|
||||||
dc->DrawPolygon( 3, tri );
|
dc->DrawPolygon( 3, tri );
|
||||||
}
|
}
|
||||||
@ -3591,7 +3559,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc, bool repainting)
|
|||||||
auto scrub = mPrevZone == StatusChoice::EnteringScrubZone ||
|
auto scrub = mPrevZone == StatusChoice::EnteringScrubZone ||
|
||||||
mProject->GetScrubber().HasStartedScrubbing();
|
mProject->GetScrubber().HasStartedScrubbing();
|
||||||
auto width = scrub ? IndicatorBigWidth() : IndicatorSmallWidth;
|
auto width = scrub ? IndicatorBigWidth() : IndicatorSmallWidth;
|
||||||
DoDrawIndicator(dc, mQuickPlayPos, true, width, scrub);
|
DoDrawIndicator(dc, Time2Pos(mQuickPlayPos), true, width, scrub);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdornedRulerPanel::SetPlayRegion(double playRegionStart,
|
void AdornedRulerPanel::SetPlayRegion(double playRegionStart,
|
||||||
|
@ -299,9 +299,7 @@ public:
|
|||||||
|
|
||||||
void SetLeftOffset(int offset);
|
void SetLeftOffset(int offset);
|
||||||
|
|
||||||
void DrawIndicator(double time, bool rec);
|
|
||||||
void DrawSelection();
|
void DrawSelection();
|
||||||
void ClearIndicator();
|
|
||||||
|
|
||||||
void SetPlayRegion(double playRegionStart, double playRegionEnd);
|
void SetPlayRegion(double playRegionStart, double playRegionEnd);
|
||||||
void ClearPlayRegion();
|
void ClearPlayRegion();
|
||||||
@ -380,7 +378,10 @@ private:
|
|||||||
void DoDrawEdge(wxDC *dc);
|
void DoDrawEdge(wxDC *dc);
|
||||||
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
void DoDrawMarks(wxDC * dc, bool /*text */ );
|
||||||
void DoDrawSelection(wxDC * dc);
|
void DoDrawSelection(wxDC * dc);
|
||||||
void DoDrawIndicator(wxDC * dc, double time, bool playing, int width, bool scrub);
|
public:
|
||||||
|
void DoDrawIndicator(wxDC * dc, wxCoord xx, bool playing, int width, bool scrub);
|
||||||
|
|
||||||
|
private:
|
||||||
void DoEraseIndicator(wxDC *dc, int x);
|
void DoEraseIndicator(wxDC *dc, int x);
|
||||||
QuickPlayIndicatorOverlay *GetOverlay();
|
QuickPlayIndicatorOverlay *GetOverlay();
|
||||||
void DrawQuickPlayIndicator(wxDC * dc /*NULL to DELETE old only*/, bool repainting = false);
|
void DrawQuickPlayIndicator(wxDC * dc /*NULL to DELETE old only*/, bool repainting = false);
|
||||||
@ -440,7 +441,6 @@ private:
|
|||||||
int mLeftOffset; // Number of pixels before we hit the 'zero position'.
|
int mLeftOffset; // Number of pixels before we hit the 'zero position'.
|
||||||
|
|
||||||
|
|
||||||
int mIndType; // -1 = No indicator, 0 = Record, 1 = Play
|
|
||||||
double mIndTime;
|
double mIndTime;
|
||||||
bool mQuickPlayInd;
|
bool mQuickPlayInd;
|
||||||
double mQuickPlayPos;
|
double mQuickPlayPos;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user