mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-14 17:14:07 +01: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:
@@ -30,30 +30,26 @@ namespace {
|
||||
{
|
||||
return (m >= l && m < h);
|
||||
}
|
||||
|
||||
enum { IndicatorMediumWidth = 13 };
|
||||
}
|
||||
|
||||
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
|
||||
: mProject(project)
|
||||
, mLastIndicatorX(-1)
|
||||
, mNewIndicatorX(-1)
|
||||
PlayIndicatorOverlayBase::PlayIndicatorOverlayBase(AudacityProject *project, bool isMaster)
|
||||
: mProject(project)
|
||||
, mIsMaster(isMaster)
|
||||
{
|
||||
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(
|
||||
rect,
|
||||
mLastIndicatorX != mNewIndicatorX
|
||||
@@ -61,56 +57,75 @@ 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);
|
||||
TrackPanelCellIterator begin(&tp, true);
|
||||
TrackPanelCellIterator end(&tp, false);
|
||||
|
||||
// Set play/record color
|
||||
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
|
||||
AColor::IndicatorColor(&dc, !rec);
|
||||
mLastIndicatorX = mNewIndicatorX;
|
||||
if (!between_incexc(0, mLastIndicatorX, dc.GetSize().GetWidth()))
|
||||
return;
|
||||
|
||||
const ZoomInfo &viewInfo = mProject->GetZoomInfo();
|
||||
TrackPanel *const trackPanel = mProject->GetTrackPanel();
|
||||
if(auto tp = dynamic_cast<TrackPanel*>(&panel)) {
|
||||
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
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
TrackPanelCellIterator::value_type data(*begin);
|
||||
Track *const pTrack = data.first;
|
||||
if (!pTrack)
|
||||
continue;
|
||||
|
||||
// Don't draw the indicator in label tracks
|
||||
if (pTrack->GetKind() == Track::Label)
|
||||
// Draw indicator in all visible tracks
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TrackPanelCellIterator::value_type data(*begin);
|
||||
Track *const pTrack = data.first;
|
||||
if (!pTrack)
|
||||
continue;
|
||||
|
||||
// Draw the NEW indicator in its NEW location
|
||||
// AColor::Line includes both endpoints so use GetBottom()
|
||||
const wxRect &rect = data.second;
|
||||
AColor::Line(dc,
|
||||
mLastIndicatorX,
|
||||
rect.GetTop(),
|
||||
mLastIndicatorX,
|
||||
rect.GetBottom());
|
||||
// Don't draw the indicator in label tracks
|
||||
if (pTrack->GetKind() == Track::Label)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Draw the NEW indicator in its NEW location
|
||||
// AColor::Line includes both endpoints so use GetBottom()
|
||||
const wxRect &rect = data.second;
|
||||
AColor::Line(dc,
|
||||
mLastIndicatorX,
|
||||
rect.GetTop(),
|
||||
mLastIndicatorX,
|
||||
rect.GetBottom());
|
||||
}
|
||||
}
|
||||
else if(auto ruler = dynamic_cast<AdornedRulerPanel*>(&panel)) {
|
||||
wxASSERT(!mIsMaster);
|
||||
|
||||
ruler->DoDrawIndicator(&dc, mLastIndicatorX, !rec, IndicatorMediumWidth, false);
|
||||
}
|
||||
else
|
||||
wxASSERT(false);
|
||||
}
|
||||
|
||||
void PlayIndicatorOverlay::Erase(wxDC &dc, wxDC &src)
|
||||
PlayIndicatorOverlay::PlayIndicatorOverlay(AudacityProject *project)
|
||||
: PlayIndicatorOverlayBase(project, true)
|
||||
{
|
||||
Overlay::Erase(dc, src);
|
||||
mProject->GetRulerPanel()->ClearIndicator();
|
||||
mProject->Connect(EVT_TRACK_PANEL_TIMER,
|
||||
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)
|
||||
@@ -118,6 +133,15 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
||||
// Let other listeners get the notification
|
||||
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()) {
|
||||
const auto &scrubber = mProject->GetScrubber();
|
||||
if (scrubber.HasStartedScrubbing())
|
||||
@@ -158,4 +182,7 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event)
|
||||
|
||||
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__
|
||||
|
||||
#include <wx/event.h>
|
||||
#include "../../MemoryX.h"
|
||||
#include "../../widgets/Overlay.h"
|
||||
|
||||
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:
|
||||
PlayIndicatorOverlay(AudacityProject *project);
|
||||
virtual ~PlayIndicatorOverlay();
|
||||
|
||||
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);
|
||||
|
||||
|
||||
AudacityProject *mProject;
|
||||
int mLastIndicatorX;
|
||||
int mNewIndicatorX;
|
||||
std::unique_ptr<PlayIndicatorOverlayBase> mPartner;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user