1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-09 16:41:14 +02:00

ScrubbingOverlay declared and defined entirely within ScrubUI.cpp

This commit is contained in:
Paul Licameli 2019-07-04 09:22:20 -04:00
parent 24bd7cf571
commit 8414ebffa5
5 changed files with 226 additions and 191 deletions

View File

@ -1079,14 +1079,3 @@ int ProjectManager::GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels) {
int iRecMins = (int)round(dRecTime / 60.0);
return iRecMins;
}
/// This was moved here to eliminate dependency of Scrubbing.cpp on
/// TrackPanel, but perhaps a better home should be found for it in future
#include "tracks/ui/Scrubbing.h"
static const AudacityProject::AttachedObjects::RegisteredFactory sOverlayKey{
[]( AudacityProject &parent ){
auto result = std::make_shared< ScrubbingOverlay >( &parent );
TrackPanel::Get( parent ).AddOverlay( result );
return result;
}
};

View File

@ -0,0 +1,209 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ScrubUI.cpp
Paul Licameli split from Scrubbing.cpp
**********************************************************************/
#include "ScrubUI.h"
#include "Scrubbing.h"
#include "../../widgets/Overlay.h"
#include "../../ClientData.h"
#include "../../AdornedRulerPanel.h"
#include "../../Project.h"
#include "../../TrackPanel.h"
#include <wx/dcclient.h>
#include <wx/event.h>
///////////////////////////////////////////////////////////////////////////////
// class ScrubbingOverlay is responsible for drawing the speed numbers
// Specialist in drawing the scrub speed, and listening for certain events
class ScrubbingOverlay final
: public wxEvtHandler
, public Overlay
, public ClientData::Base
{
public:
explicit
ScrubbingOverlay(AudacityProject *project);
private:
unsigned SequenceNumber() const override;
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw(OverlayPanel &panel, wxDC &dc) override;
void OnTimer(wxCommandEvent &event);
const Scrubber &GetScrubber() const;
Scrubber &GetScrubber();
AudacityProject *mProject;
wxRect mLastScrubRect, mNextScrubRect;
wxString mLastScrubSpeedText, mNextScrubSpeedText;
};
ScrubbingOverlay::ScrubbingOverlay(AudacityProject *project)
: mProject(project)
, mLastScrubRect()
, mNextScrubRect()
, mLastScrubSpeedText()
, mNextScrubSpeedText()
{
mProject->Bind(EVT_TRACK_PANEL_TIMER,
&ScrubbingOverlay::OnTimer,
this);
}
unsigned ScrubbingOverlay::SequenceNumber() const
{
return 40;
}
std::pair<wxRect, bool> ScrubbingOverlay::DoGetRectangle(wxSize)
{
wxRect rect(mLastScrubRect);
const bool outdated =
(mLastScrubRect != mNextScrubRect) ||
(!mLastScrubRect.IsEmpty() && !GetScrubber().ShouldDrawScrubSpeed()) ||
(mLastScrubSpeedText != mNextScrubSpeedText);
return std::make_pair(
rect,
outdated
);
}
void ScrubbingOverlay::Draw(OverlayPanel &, wxDC &dc)
{
mLastScrubRect = mNextScrubRect;
mLastScrubSpeedText = mNextScrubSpeedText;
Scrubber &scrubber = GetScrubber();
if (!scrubber.ShouldDrawScrubSpeed())
return;
static const wxFont labelFont(24, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
dc.SetFont(labelFont);
// These two colors were previously saturated red and green. However
// we have a rule to try to only use red for reserved purposes of
// (a) Recording
// (b) Error alerts
// So they were changed to 'orange' and 'lime'.
static const wxColour clrNoScroll(215, 162, 0), clrScroll(0, 204, 153);
if (scrubber.IsScrollScrubbing())
dc.SetTextForeground(clrScroll);
else
dc.SetTextForeground(clrNoScroll);
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
}
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
{
// Let other listeners get the notification
event.Skip();
Scrubber &scrubber = GetScrubber();
const auto isScrubbing = scrubber.IsScrubbing();
auto &ruler = AdornedRulerPanel::Get( *mProject );
auto position = ::wxGetMousePosition();
if (scrubber.IsSpeedPlaying())
return;
{
if(scrubber.HasMark()) {
auto xx = ruler.ScreenToClient(position).x;
ruler.UpdateQuickPlayPos( xx, false );
if (!isScrubbing)
// Really start scrub if motion is far enough
scrubber.MaybeStartScrubbing(xx);
}
if (!isScrubbing) {
mNextScrubRect = wxRect();
return;
}
else
ruler.DrawBothOverlays();
}
if (!scrubber.ShouldDrawScrubSpeed()) {
mNextScrubRect = wxRect();
}
else {
auto &trackPanel = GetProjectPanel( *mProject );
auto &viewInfo = ViewInfo::Get( *mProject );
int panelWidth, panelHeight;
trackPanel.GetSize(&panelWidth, &panelHeight);
// Where's the mouse?
position = trackPanel.ScreenToClient(position);
const bool seeking = scrubber.Seeks() || scrubber.TemporarilySeeks();
// Find the text
const double maxScrubSpeed = GetScrubber().GetMaxScrubSpeed();
const double speed =
scrubber.IsScrollScrubbing()
? scrubber.FindScrubSpeed( seeking,
ViewInfo::Get( *mProject )
.PositionToTime(position.x, viewInfo.GetLeftOffset()))
: maxScrubSpeed;
const wxChar *format =
scrubber.IsScrollScrubbing()
? seeking
? wxT("%+.2fX")
: wxT("%+.2f")
: wxT("%.2f");
mNextScrubSpeedText = wxString::Format(format, speed);
// Find the origin for drawing text
wxCoord width, height;
{
wxClientDC dc( &trackPanel );
static const wxFont labelFont(24, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
dc.SetFont(labelFont);
dc.GetTextExtent(mNextScrubSpeedText, &width, &height);
}
const auto xx =
std::max(0, std::min(panelWidth - width, position.x - width / 2));
// Put the text above the cursor, if it fits.
enum { offset = 20 };
auto yy = position.y - height + offset;
if (yy < 0)
yy += height + 2 * offset;
yy = std::max(0, std::min(panelHeight - height, yy));
mNextScrubRect = wxRect(xx, yy, width, height);
}
}
const Scrubber &ScrubbingOverlay::GetScrubber() const
{
return Scrubber::Get( *mProject );
}
Scrubber &ScrubbingOverlay::GetScrubber()
{
return Scrubber::Get( *mProject );
}
static const AudacityProject::AttachedObjects::RegisteredFactory sOverlayKey{
[]( AudacityProject &parent ){
auto result = std::make_shared< ScrubbingOverlay >( &parent );
TrackPanel::Get( parent ).AddOverlay( result );
return result;
}
};

View File

@ -0,0 +1,16 @@
/**********************************************************************
Audacity: A Digital Audio Editor
ScrubUI.h
Paul Licameli split from Scrubbing.h
**********************************************************************/
#ifndef __AUDACITY_SCRUB_UI__
#define __AUDACITY_SCRUB_UI__
#endif

View File

@ -913,160 +913,6 @@ void Scrubber::Forwarder::OnMouse(wxMouseEvent &event)
event.Skip();
}
///////////////////////////////////////////////////////////////////////////////
// class ScrubbingOverlay is responsible for drawing the speed numbers
ScrubbingOverlay::ScrubbingOverlay(AudacityProject *project)
: mProject(project)
, mLastScrubRect()
, mNextScrubRect()
, mLastScrubSpeedText()
, mNextScrubSpeedText()
{
mProject->Bind(EVT_TRACK_PANEL_TIMER,
&ScrubbingOverlay::OnTimer,
this);
}
unsigned ScrubbingOverlay::SequenceNumber() const
{
return 40;
}
std::pair<wxRect, bool> ScrubbingOverlay::DoGetRectangle(wxSize)
{
wxRect rect(mLastScrubRect);
const bool outdated =
(mLastScrubRect != mNextScrubRect) ||
(!mLastScrubRect.IsEmpty() && !GetScrubber().ShouldDrawScrubSpeed()) ||
(mLastScrubSpeedText != mNextScrubSpeedText);
return std::make_pair(
rect,
outdated
);
}
void ScrubbingOverlay::Draw(OverlayPanel &, wxDC &dc)
{
mLastScrubRect = mNextScrubRect;
mLastScrubSpeedText = mNextScrubSpeedText;
Scrubber &scrubber = GetScrubber();
if (!scrubber.ShouldDrawScrubSpeed())
return;
static const wxFont labelFont(24, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
dc.SetFont(labelFont);
// These two colors were previously saturated red and green. However
// we have a rule to try to only use red for reserved purposes of
// (a) Recording
// (b) Error alerts
// So they were changed to 'orange' and 'lime'.
static const wxColour clrNoScroll(215, 162, 0), clrScroll(0, 204, 153);
if (scrubber.IsScrollScrubbing())
dc.SetTextForeground(clrScroll);
else
dc.SetTextForeground(clrNoScroll);
dc.DrawText(mLastScrubSpeedText, mLastScrubRect.GetX(), mLastScrubRect.GetY());
}
void ScrubbingOverlay::OnTimer(wxCommandEvent &event)
{
// Let other listeners get the notification
event.Skip();
Scrubber &scrubber = GetScrubber();
const auto isScrubbing = scrubber.IsScrubbing();
auto &ruler = AdornedRulerPanel::Get( *mProject );
auto position = ::wxGetMousePosition();
if (scrubber.IsSpeedPlaying())
return;
{
if(scrubber.HasMark()) {
auto xx = ruler.ScreenToClient(position).x;
ruler.UpdateQuickPlayPos( xx, false );
if (!isScrubbing)
// Really start scrub if motion is far enough
scrubber.MaybeStartScrubbing(xx);
}
if (!isScrubbing) {
mNextScrubRect = wxRect();
return;
}
else
ruler.DrawBothOverlays();
}
if (!scrubber.ShouldDrawScrubSpeed()) {
mNextScrubRect = wxRect();
}
else {
auto &trackPanel = GetProjectPanel( *mProject );
auto &viewInfo = ViewInfo::Get( *mProject );
int panelWidth, panelHeight;
trackPanel.GetSize(&panelWidth, &panelHeight);
// Where's the mouse?
position = trackPanel.ScreenToClient(position);
const bool seeking = scrubber.Seeks() || scrubber.TemporarilySeeks();
// Find the text
const double maxScrubSpeed = GetScrubber().GetMaxScrubSpeed();
const double speed =
scrubber.IsScrollScrubbing()
? scrubber.FindScrubSpeed( seeking,
ViewInfo::Get( *mProject )
.PositionToTime(position.x, viewInfo.GetLeftOffset()))
: maxScrubSpeed;
const wxChar *format =
scrubber.IsScrollScrubbing()
? seeking
? wxT("%+.2fX")
: wxT("%+.2f")
: wxT("%.2f");
mNextScrubSpeedText = wxString::Format(format, speed);
// Find the origin for drawing text
wxCoord width, height;
{
wxClientDC dc( &trackPanel );
static const wxFont labelFont(24, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
dc.SetFont(labelFont);
dc.GetTextExtent(mNextScrubSpeedText, &width, &height);
}
const auto xx =
std::max(0, std::min(panelWidth - width, position.x - width / 2));
// Put the text above the cursor, if it fits.
enum { offset = 20 };
auto yy = position.y - height + offset;
if (yy < 0)
yy += height + 2 * offset;
yy = std::max(0, std::min(panelHeight - height, yy));
mNextScrubRect = wxRect(xx, yy, width, height);
}
}
const Scrubber &ScrubbingOverlay::GetScrubber() const
{
return Scrubber::Get( *mProject );
}
Scrubber &ScrubbingOverlay::GetScrubber()
{
return Scrubber::Get( *mProject );
}
void Scrubber::DoScrub(bool seek)
{
if( !CanScrub() )

View File

@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
#ifndef __AUDACITY_SCRUBBING__
#define __AUDACITY_SCRUBBING__
#include "../../Audacity.h"
#include "../../Experimental.h"
#include <vector>
@ -193,30 +194,4 @@ private:
bool mShowScrubbing { false };
};
// Specialist in drawing the scrub speed, and listening for certain events
class ScrubbingOverlay final
: public wxEvtHandler
, public Overlay
, public ClientData::Base
{
public:
explicit
ScrubbingOverlay(AudacityProject *project);
private:
unsigned SequenceNumber() const override;
std::pair<wxRect, bool> DoGetRectangle(wxSize size) override;
void Draw(OverlayPanel &panel, wxDC &dc) override;
void OnTimer(wxCommandEvent &event);
const Scrubber &GetScrubber() const;
Scrubber &GetScrubber();
AudacityProject *mProject;
wxRect mLastScrubRect, mNextScrubRect;
wxString mLastScrubSpeedText, mNextScrubSpeedText;
};
#endif