1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-10 17:11:17 +02:00

Preparations for scattering TrackArt functions to better places

This commit is contained in:
Paul Licameli 2018-11-05 09:35:05 -05:00
commit 9bb235c274
12 changed files with 373 additions and 282 deletions

View File

@ -319,11 +319,14 @@ static void DrawPoint(wxDC & dc, const wxRect & r, int x, int y, bool top)
/// TODO: This should probably move to track artist. /// TODO: This should probably move to track artist.
void Envelope::DrawPoints void Envelope::DrawPoints
(TrackPanelDrawingContext &context, const wxRect & r, const ZoomInfo &zoomInfo, (TrackPanelDrawingContext &context, const wxRect & r,
bool dB, double dBRange, bool dB, double dBRange,
float zoomMin, float zoomMax, bool mirrored) const float zoomMin, float zoomMax, bool mirrored) const
{ {
auto &dc = context.dc; auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
bool highlight = false; bool highlight = false;
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
auto target = dynamic_cast<EnvelopeHandle*>(context.target.get()); auto target = dynamic_cast<EnvelopeHandle*>(context.target.get());
@ -357,7 +360,7 @@ void Envelope::DrawPoints
true, dBRange, false); true, dBRange, false);
// This follows the same logic as the envelop drawing in // This follows the same logic as the envelop drawing in
// TrackArtist::DrawEnvelope(). // TrackArt::DrawEnvelope().
// TODO: make this calculation into a reusable function. // TODO: make this calculation into a reusable function.
if (y2 - y < 9) { if (y2 - y < 9) {
int value = (int)((zoomMax / (zoomMax - zoomMin)) * r.height); int value = (int)((zoomMax / (zoomMax - zoomMin)) * r.height);

View File

@ -119,7 +119,7 @@ public:
void DrawPoints( void DrawPoints(
TrackPanelDrawingContext &context, TrackPanelDrawingContext &context,
const wxRect & r, const ZoomInfo &zoomInfo, const wxRect & r,
bool dB, double dBRange, bool dB, double dBRange,
float zoomMin, float zoomMax, bool mirrored) const; float zoomMin, float zoomMax, bool mirrored) const;

View File

@ -782,11 +782,12 @@ namespace {
/// @param dc the device context /// @param dc the device context
/// @param r the LabelTrack rectangle. /// @param r the LabelTrack rectangle.
void LabelTrack::Draw void LabelTrack::Draw
(TrackPanelDrawingContext &context, const wxRect & r, ( TrackPanelDrawingContext &context, const wxRect & r ) const
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo) const
{ {
auto &dc = context.dc; auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
auto pHit = findHit(); auto pHit = findHit();
if(msFont.Ok()) if(msFont.Ok())
@ -795,9 +796,9 @@ void LabelTrack::Draw
if (mFontHeight == -1) if (mFontHeight == -1)
calculateFontHeight(dc); calculateFontHeight(dc);
TrackArtist::DrawBackgroundWithSelection(&dc, r, this, TrackArt::DrawBackgroundWithSelection( context, r, this,
AColor::labelSelectedBrush, AColor::labelUnselectedBrush, AColor::labelSelectedBrush, AColor::labelUnselectedBrush,
selectedRegion, zoomInfo); ( GetSelected() || IsSyncLockSelected() ) );
wxCoord textWidth, textHeight; wxCoord textWidth, textHeight;

View File

@ -153,9 +153,7 @@ class AUDACITY_DLL_API LabelTrack final : public Track
static wxFont GetFont(const wxString &faceName, int size = DefaultFontSize); static wxFont GetFont(const wxString &faceName, int size = DefaultFontSize);
static void ResetFont(); static void ResetFont();
void Draw(TrackPanelDrawingContext &context, const wxRect & r, void Draw( TrackPanelDrawingContext &context, const wxRect & r ) const;
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo) const;
int getSelectedIndex() const { return mSelIndex; } int getSelectedIndex() const { return mSelIndex; }

View File

@ -88,7 +88,10 @@ bool AudacityPrintout::OnPrintPage(int WXUNUSED(page))
artist.SetBackgroundBrushes(*wxWHITE_BRUSH, *wxWHITE_BRUSH, artist.SetBackgroundBrushes(*wxWHITE_BRUSH, *wxWHITE_BRUSH,
*wxWHITE_PEN, *wxWHITE_PEN); *wxWHITE_PEN, *wxWHITE_PEN);
const double screenDuration = mTracks->GetEndTime(); const double screenDuration = mTracks->GetEndTime();
SelectedRegion region{};
artist.pSelectedRegion = &region;
ZoomInfo zoomInfo(0.0, width / screenDuration); ZoomInfo zoomInfo(0.0, width / screenDuration);
artist.pZoomInfo = &zoomInfo;
int y = rulerPageHeight; int y = rulerPageHeight;
for (auto n : mTracks->Any()) { for (auto n : mTracks->Any()) {
@ -98,9 +101,10 @@ bool AudacityPrintout::OnPrintPage(int WXUNUSED(page))
r.width = width; r.width = width;
r.height = (int)(n->GetHeight() * scale); r.height = (int)(n->GetHeight() * scale);
TrackPanelDrawingContext context{ *dc, {}, {} }; TrackPanelDrawingContext context{
artist.DrawTrack( *dc, {}, {}, &artist
context, n, r, SelectedRegion(), zoomInfo, false, false, false, false); };
TrackArt::DrawTrack( context, n, r );
dc->SetPen(*wxBLACK_PEN); dc->SetPen(*wxBLACK_PEN);
AColor::Line(*dc, 0, r.y, width, r.y); AColor::Line(*dc, 0, r.y, width, r.y);

View File

@ -24,6 +24,7 @@
#include "Envelope.h" #include "Envelope.h"
#include "Prefs.h" #include "Prefs.h"
#include "Project.h" #include "Project.h"
#include "TrackArtist.h"
#include "Internat.h" #include "Internat.h"
#include "ViewInfo.h" #include "ViewInfo.h"
#include "AllThemeResources.h" #include "AllThemeResources.h"
@ -265,9 +266,12 @@ void TimeTrack::WriteXML(XMLWriter &xmlFile) const
#include "tracks/ui/EnvelopeHandle.h" #include "tracks/ui/EnvelopeHandle.h"
void TimeTrack::Draw void TimeTrack::Draw
(TrackPanelDrawingContext &context, const wxRect & r, const ZoomInfo &zoomInfo) const ( TrackPanelDrawingContext &context, const wxRect & r ) const
{ {
auto &dc = context.dc; auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
bool highlight = false; bool highlight = false;
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
auto target = dynamic_cast<EnvelopeHandle*>(context.target.get()); auto target = dynamic_cast<EnvelopeHandle*>(context.target.get());

View File

@ -66,8 +66,7 @@ class TimeTrack final : public Track {
double GetEndTime() const override { return 0.0; } double GetEndTime() const override { return 0.0; }
void Draw void Draw
(TrackPanelDrawingContext &context, ( TrackPanelDrawingContext &context, const wxRect & r ) const;
const wxRect & r, const ZoomInfo &zoomInfo) const;
// XMLTagHandler callback methods for loading and saving // XMLTagHandler callback methods for loading and saving

View File

@ -153,7 +153,7 @@ const int notePos[12] = { 1, 6, 11, 16, 21, 27,
// IPITCH_TO_Y above, which computes coordinates relative to GetBottom() // IPITCH_TO_Y above, which computes coordinates relative to GetBottom()
// Note the -NOTE_MARGIN, which leaves a little margin to draw notes that // Note the -NOTE_MARGIN, which leaves a little margin to draw notes that
// are out of bounds. I'm not sure why the -2 is necessary. // are out of bounds. I'm not sure why the -2 is necessary.
int TrackArtist::GetBottom(NoteTrack *t, const wxRect &rect) int TrackArt::GetBottom(NoteTrack *t, const wxRect &rect)
{ {
int bottomNote = t->GetBottomNote(); int bottomNote = t->GetBottomNote();
int bottom = rect.y + rect.height - 2 - t->GetNoteMargin() + int bottom = rect.y + rect.height - 2 - t->GetNoteMargin() +
@ -173,12 +173,19 @@ TrackArtist::TrackArtist()
SetColours(0); SetColours(0);
vruler = std::make_unique<Ruler>(); vruler = std::make_unique<Ruler>();
UpdatePrefs();
} }
TrackArtist::~TrackArtist() TrackArtist::~TrackArtist()
{ {
} }
TrackArtist * TrackArtist::Get( TrackPanelDrawingContext &context )
{
return static_cast< TrackArtist* >( context.pUserData );
}
void TrackArtist::SetColours( int iColorIndex) void TrackArtist::SetColours( int iColorIndex)
{ {
theTheme.SetBrushColour( blankBrush, clrBlank ); theTheme.SetBrushColour( blankBrush, clrBlank );
@ -226,32 +233,19 @@ void TrackArtist::SetColours( int iColorIndex)
} }
} }
void TrackArtist::DrawTracks(TrackPanelDrawingContext &context, void TrackArt::DrawTracks(TrackPanelDrawingContext &context,
const TrackList * tracks, const TrackList * tracks,
const wxRegion & reg, const wxRegion & reg,
const wxRect & clip, int leftOffset, const wxRect & clip)
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo,
bool drawEnvelope,
bool bigPoints,
bool drawSliders)
{ {
// Fix the horizontal extent; will later change only the vertical extent. // Fix the horizontal extent; will later change only the vertical extent.
const auto artist = TrackArtist::Get( context );
const auto leftOffset = artist->leftOffset;
wxRect teamRect{ wxRect teamRect{
clip.x + leftOffset, 0, clip.width - (leftOffset + kRightMargin), 0 clip.x + leftOffset, 0, clip.width - (leftOffset + kRightMargin), 0
}; };
bool hasSolo = false; const auto &zoomInfo = *artist->pZoomInfo;
for (const Track *t : *tracks) {
t = t->SubstitutePendingChangedTrack().get();
auto pt = dynamic_cast<const PlayableTrack *>(t);
if (pt && pt->GetSolo()) {
hasSolo = true;
break;
}
}
gPrefs->Read(wxT("/GUI/ShowTrackNameInWaveform"), &mbShowTrackNameInWaveform, false);
for(auto leader : tracks->Leaders()) { for(auto leader : tracks->Leaders()) {
auto group = TrackList::Channels( leader ); auto group = TrackList::Channels( leader );
@ -285,31 +279,26 @@ void TrackArtist::DrawTracks(TrackPanelDrawingContext &context,
teamRect.width, teamRect.width,
t->GetHeight() - (kTopMargin + kBottomMargin) t->GetHeight() - (kTopMargin + kBottomMargin)
}; };
DrawTrack(context, t, trackRect, DrawTrack( context, t, trackRect );
selectedRegion, zoomInfo,
drawEnvelope, bigPoints, drawSliders, hasSolo);
} }
} }
} }
} }
void TrackArtist::DrawTrack(TrackPanelDrawingContext &context, void TrackArt::DrawTrack(TrackPanelDrawingContext &context,
const Track * t, const Track * t,
const wxRect & rect, const wxRect & rect)
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo,
bool drawEnvelope,
bool bigPoints,
bool drawSliders,
bool hasSolo)
{ {
auto &dc = context.dc; auto &dc = context.dc;
t->TypeSwitch( t->TypeSwitch(
[&](const WaveTrack *wt) { [&](const WaveTrack *wt) {
for (const auto &clip : wt->GetClips()) { for (const auto &clip : wt->GetClips()) {
clip->ClearDisplayRect(); clip->ClearDisplayRect();
} }
const auto artist = TrackArtist::Get( context );
const auto hasSolo = artist->hasSolo;
bool muted = (hasSolo || wt->GetMute()) && bool muted = (hasSolo || wt->GetMute()) &&
!wt->GetSolo(); !wt->GetSolo();
@ -320,11 +309,10 @@ void TrackArtist::DrawTrack(TrackPanelDrawingContext &context,
switch (wt->GetDisplay()) { switch (wt->GetDisplay()) {
case WaveTrack::Waveform: case WaveTrack::Waveform:
DrawWaveform(context, wt, rect, selectedRegion, zoomInfo, DrawWaveform(context, wt, rect, muted);
drawEnvelope, bigPoints, drawSliders, muted);
break; break;
case WaveTrack::Spectrum: case WaveTrack::Spectrum:
DrawSpectrum(wt, dc, rect, selectedRegion, zoomInfo); DrawSpectrum( context, wt, rect );
break; break;
default: default:
wxASSERT(false); wxASSERT(false);
@ -334,7 +322,9 @@ void TrackArtist::DrawTrack(TrackPanelDrawingContext &context,
dc.GetGraphicsContext()->SetAntialiasMode(aamode); dc.GetGraphicsContext()->SetAntialiasMode(aamode);
#endif #endif
if (mbShowTrackNameInWaveform && const auto bShowTrackNameInWaveform =
artist->mbShowTrackNameInWaveform;
if (bShowTrackNameInWaveform &&
wt->IsLeader() && wt->IsLeader() &&
// Exclude empty name. // Exclude empty name.
!wt->GetName().IsEmpty()) { !wt->GetName().IsEmpty()) {
@ -354,21 +344,23 @@ void TrackArtist::DrawTrack(TrackPanelDrawingContext &context,
[&](const NoteTrack *nt) { [&](const NoteTrack *nt) {
bool muted = false; bool muted = false;
#ifdef EXPERIMENTAL_MIDI_OUT #ifdef EXPERIMENTAL_MIDI_OUT
const auto artist = TrackArtist::Get( context );
const auto hasSolo = artist->hasSolo;
muted = (hasSolo || nt->GetMute()) && !nt->GetSolo(); muted = (hasSolo || nt->GetMute()) && !nt->GetSolo();
#endif #endif
DrawNoteTrack(nt, dc, rect, selectedRegion, zoomInfo, muted); DrawNoteTrack( context, nt, rect, muted );
}, },
#endif // USE_MIDI #endif // USE_MIDI
[&](const LabelTrack *lt) { [&](const LabelTrack *lt) {
DrawLabelTrack(context, lt, rect, selectedRegion, zoomInfo); lt->Draw( context, rect );
}, },
[&](const TimeTrack *tt) { [&](const TimeTrack *tt) {
DrawTimeTrack(context, tt, rect, zoomInfo); DrawTimeTrack( context, tt, rect );
} }
); );
} }
void TrackArtist::DrawVRuler void TrackArt::DrawVRuler
( TrackPanelDrawingContext &context, const Track *t, const wxRect & rect_, ( TrackPanelDrawingContext &context, const Track *t, const wxRect & rect_,
bool bSelected ) bool bSelected )
{ {
@ -418,8 +410,10 @@ void TrackArtist::DrawVRuler
rr.width -= adj; rr.width -= adj;
} }
UpdateVRuler(t, rr); const auto artist = TrackArtist::Get( context );
artist->UpdateVRuler(t, rr);
const auto &vruler = artist->vruler;
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText )); vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
vruler->Draw(*dc); vruler->Draw(*dc);
}, },
@ -441,8 +435,10 @@ void TrackArtist::DrawVRuler
rr.width -= adj; rr.width -= adj;
} }
UpdateVRuler(t, rr); const auto artist = TrackArtist::Get( context );
artist->UpdateVRuler(t, rr);
const auto &vruler = artist->vruler;
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText )); vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
vruler->Draw(*dc); vruler->Draw(*dc);
} }
@ -451,7 +447,8 @@ void TrackArtist::DrawVRuler
, ,
[&](const NoteTrack *track) { [&](const NoteTrack *track) {
// The note track draws a vertical keyboard to label pitches // The note track draws a vertical keyboard to label pitches
UpdateVRuler(t, rect); const auto artist = TrackArtist::Get( context );
artist->UpdateVRuler(t, rect);
dc->SetPen(highlight ? AColor::uglyPen : *wxTRANSPARENT_PEN); dc->SetPen(highlight ? AColor::uglyPen : *wxTRANSPARENT_PEN);
dc->SetBrush(*wxWHITE_BRUSH); dc->SetBrush(*wxWHITE_BRUSH);
@ -899,8 +896,11 @@ float ValueOfPixel(int yy, int height, bool offset,
return v; return v;
} }
void TrackArtist::DrawNegativeOffsetTrackArrows(wxDC &dc, const wxRect &rect) void TrackArt::DrawNegativeOffsetTrackArrows(
TrackPanelDrawingContext &context, const wxRect &rect )
{ {
auto &dc = context.dc;
// Draws two black arrows on the left side of the track to // Draws two black arrows on the left side of the track to
// indicate the user that the track has been time-shifted // indicate the user that the track has been time-shifted
// to the left beyond t=0.0. // to the left beyond t=0.0.
@ -926,16 +926,19 @@ void TrackArtist::DrawNegativeOffsetTrackArrows(wxDC &dc, const wxRect &rect)
rect.x + 6, rect.y + rect.height - 12); rect.x + 6, rect.y + rect.height - 12);
} }
void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect &rect, void TrackArt::DrawWaveformBackground(TrackPanelDrawingContext &context,
int leftOffset, const wxRect &rect,
const double env[], const double env[],
float zoomMin, float zoomMax, float zoomMin, float zoomMax,
int zeroLevelYCoordinate, int zeroLevelYCoordinate,
bool dB, float dBRange, bool dB, float dBRange,
double t0, double t1, double t0, double t1,
const ZoomInfo &zoomInfo, bool bIsSyncLockSelected,
bool drawEnvelope, bool bIsSyncLockSelected,
bool highlightEnvelope) bool highlightEnvelope)
{ {
auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
// Visually (one vertical slice of the waveform background, on its side; // Visually (one vertical slice of the waveform background, on its side;
// the "*" is the actual waveform background we're drawing // the "*" is the actual waveform background we're drawing
@ -956,6 +959,10 @@ void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect
int xx, lx = 0; int xx, lx = 0;
int l, w; int l, w;
const auto &blankBrush = artist->blankBrush;
const auto &selectedBrush = artist->selectedBrush;
const auto &unselectedBrush = artist->unselectedBrush;
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(blankBrush); dc.SetBrush(blankBrush);
dc.DrawRectangle(rect); dc.DrawRectangle(rect);
@ -981,6 +988,7 @@ void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect
mintop +=1; mintop +=1;
minbot +=1; minbot +=1;
const auto drawEnvelope = artist->drawEnvelope;
if (!drawEnvelope || maxbot > mintop) { if (!drawEnvelope || maxbot > mintop) {
maxbot = halfHeight; maxbot = halfHeight;
mintop = halfHeight; mintop = halfHeight;
@ -1041,7 +1049,8 @@ void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect
if (bIsSyncLockSelected && t0 < t1) { if (bIsSyncLockSelected && t0 < t1) {
const int begin = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t0, -leftOffset)))); const int begin = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t0, -leftOffset))));
const int end = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t1, -leftOffset)))); const int end = std::max(0, std::min(rect.width, (int)(zoomInfo.TimeToPosition(t1, -leftOffset))));
DrawSyncLockTiles(&dc, wxRect(rect.x + begin, rect.y, end - 1 - begin, rect.height)); DrawSyncLockTiles( context,
{ rect.x + begin, rect.y, end - 1 - begin, rect.height } );
} }
//OK, the display bounds are between min and max, which //OK, the display bounds are between min and max, which
@ -1055,12 +1064,15 @@ void TrackArtist::DrawWaveformBackground(wxDC &dc, int leftOffset, const wxRect
} }
void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[], void TrackArt::DrawMinMaxRMS(
TrackPanelDrawingContext &context, const wxRect & rect, const double env[],
float zoomMin, float zoomMax, float zoomMin, float zoomMax,
bool dB, float dBRange, bool dB, float dBRange,
const float *min, const float *max, const float *rms, const int *bl, const float *min, const float *max, const float *rms, const int *bl,
bool /* showProgress */, bool muted) bool /* showProgress */, bool muted)
{ {
auto &dc = context.dc;
// Display a line representing the // Display a line representing the
// min and max of the samples in this region // min and max of the samples in this region
int lasth1 = std::numeric_limits<int>::max(); int lasth1 = std::numeric_limits<int>::max();
@ -1072,7 +1084,9 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
ArrayOf<int> clipped; ArrayOf<int> clipped;
int clipcnt = 0; int clipcnt = 0;
if (mShowClipping) { const auto artist = TrackArtist::Get( context );
const auto bShowClipping = artist->mShowClipping;
if (bShowClipping) {
clipped.reinit( size_t(rect.width) ); clipped.reinit( size_t(rect.width) );
} }
@ -1082,12 +1096,15 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
bool drawStripes = true; bool drawStripes = true;
bool drawWaveform = true; bool drawWaveform = true;
const auto &muteSamplePen = artist->muteSamplePen;
const auto &samplePen = artist->samplePen;
dc.SetPen(muted ? muteSamplePen : samplePen); dc.SetPen(muted ? muteSamplePen : samplePen);
for (int x0 = 0; x0 < rect.width; ++x0) { for (int x0 = 0; x0 < rect.width; ++x0) {
int xx = rect.x + x0; int xx = rect.x + x0;
double v; double v;
v = min[x0] * env[x0]; v = min[x0] * env[x0];
if (clipped && mShowClipping && (v <= -MAX_AUDIO)) if (clipped && bShowClipping && (v <= -MAX_AUDIO))
{ {
if (clipcnt == 0 || clipped[clipcnt - 1] != xx) { if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
clipped[clipcnt++] = xx; clipped[clipcnt++] = xx;
@ -1097,7 +1114,7 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
rect.height, dB, true, dBRange, true); rect.height, dB, true, dBRange, true);
v = max[x0] * env[x0]; v = max[x0] * env[x0];
if (clipped && mShowClipping && (v >= MAX_AUDIO)) if (clipped && bShowClipping && (v >= MAX_AUDIO))
{ {
if (clipcnt == 0 || clipped[clipcnt - 1] != xx) { if (clipcnt == 0 || clipped[clipcnt - 1] != xx) {
clipped[clipcnt++] = xx; clipped[clipcnt++] = xx;
@ -1170,6 +1187,9 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
} }
// Stroke rms over the min-max // Stroke rms over the min-max
const auto &muteRmsPen = artist->muteRmsPen;
const auto &rmsPen = artist->rmsPen;
dc.SetPen(muted ? muteRmsPen : rmsPen); dc.SetPen(muted ? muteRmsPen : rmsPen);
for (int x0 = 0; x0 < rect.width; ++x0) { for (int x0 = 0; x0 < rect.width; ++x0) {
int xx = rect.x + x0; int xx = rect.x + x0;
@ -1182,6 +1202,9 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
// Draw the clipping lines // Draw the clipping lines
if (clipcnt) { if (clipcnt) {
const auto &muteClippedPen = artist->muteClippedPen;
const auto &clippedPen = artist->clippedPen;
dc.SetPen(muted ? muteClippedPen : clippedPen); dc.SetPen(muted ? muteClippedPen : clippedPen);
while (--clipcnt >= 0) { while (--clipcnt >= 0) {
int xx = clipped[clipcnt]; int xx = clipped[clipcnt];
@ -1190,14 +1213,18 @@ void TrackArtist::DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[
} }
} }
void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &rect, void TrackArt::DrawIndividualSamples(TrackPanelDrawingContext &context,
int leftOffset, const wxRect &rect,
float zoomMin, float zoomMax, float zoomMin, float zoomMax,
bool dB, float dBRange, bool dB, float dBRange,
const WaveClip *clip, const WaveClip *clip,
const ZoomInfo &zoomInfo, bool showPoints, bool muted,
bool bigPoints, bool showPoints, bool muted,
bool highlight) bool highlight)
{ {
auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
const double toffset = clip->GetOffset(); const double toffset = clip->GetOffset();
double rate = clip->GetRate(); double rate = clip->GetRate();
const double t0 = std::max(0.0, zoomInfo.PositionToTime(0, -leftOffset) - toffset); const double t0 = std::max(0.0, zoomInfo.PositionToTime(0, -leftOffset) - toffset);
@ -1226,9 +1253,12 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
ArrayOf<int> clipped; ArrayOf<int> clipped;
int clipcnt = 0; int clipcnt = 0;
if (mShowClipping) const auto bShowClipping = artist->mShowClipping;
if (bShowClipping)
clipped.reinit( size_t(slen) ); clipped.reinit( size_t(slen) );
const auto &muteSamplePen = artist->muteSamplePen;
const auto &samplePen = artist->samplePen;
auto &pen = highlight ? AColor::uglyPen : muted ? muteSamplePen : samplePen; auto &pen = highlight ? AColor::uglyPen : muted ? muteSamplePen : samplePen;
dc.SetPen( pen ); dc.SetPen( pen );
@ -1244,7 +1274,7 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
clip->GetEnvelope()->GetValue( time, 1.0 / clip->GetRate() ); clip->GetEnvelope()->GetValue( time, 1.0 / clip->GetRate() );
const double tt = buffer[s] * value; const double tt = buffer[s] * value;
if (clipped && mShowClipping && ((tt <= -MAX_AUDIO) || (tt >= MAX_AUDIO))) if (clipped && bShowClipping && ((tt <= -MAX_AUDIO) || (tt >= MAX_AUDIO)))
clipped[clipcnt++] = xx; clipped[clipcnt++] = xx;
ypos[s] = ypos[s] =
std::max(-1, std::max(-1,
@ -1256,11 +1286,14 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
if (showPoints) { if (showPoints) {
// Draw points where spacing is enough // Draw points where spacing is enough
const auto bigPoints = artist->bigPoints;
const int tickSize = bigPoints ? 4 : 3;// Bigger ellipses when draggable. const int tickSize = bigPoints ? 4 : 3;// Bigger ellipses when draggable.
wxRect pr; wxRect pr;
pr.width = tickSize; pr.width = tickSize;
pr.height = tickSize; pr.height = tickSize;
//different colour when draggable. //different colour when draggable.
const auto &dragsampleBrush = artist->dragsampleBrush;
const auto &sampleBrush = artist->sampleBrush;
auto &brush = highlight auto &brush = highlight
? AColor::uglyBrush ? AColor::uglyBrush
: bigPoints ? dragsampleBrush : sampleBrush; : bigPoints ? dragsampleBrush : sampleBrush;
@ -1274,7 +1307,8 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
} }
} }
if (showPoints && (mSampleDisplay == (int) WaveTrack::StemPlot)) { const auto sampleDisplay = artist->mSampleDisplay;
if (showPoints && (sampleDisplay == (int) WaveTrack::StemPlot)) {
// Draw vertical lines // Draw vertical lines
int yZero = GetWaveYPos(0.0, zoomMin, zoomMax, rect.height, dB, true, dBRange, false); int yZero = GetWaveYPos(0.0, zoomMin, zoomMax, rect.height, dB, true, dBRange, false);
yZero = rect.y + std::max(-1, std::min(rect.height, yZero)); yZero = rect.y + std::max(-1, std::min(rect.height, yZero));
@ -1295,6 +1329,8 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
// Draw clipping // Draw clipping
if (clipcnt) { if (clipcnt) {
const auto &muteClippedPen = artist->muteClippedPen;
const auto &clippedPen = artist->clippedPen;
dc.SetPen(muted ? muteClippedPen : clippedPen); dc.SetPen(muted ? muteClippedPen : clippedPen);
while (--clipcnt >= 0) { while (--clipcnt >= 0) {
auto s = clipped[clipcnt]; auto s = clipped[clipcnt];
@ -1303,10 +1339,13 @@ void TrackArtist::DrawIndividualSamples(wxDC &dc, int leftOffset, const wxRect &
} }
} }
void TrackArtist::DrawEnvelope(wxDC &dc, const wxRect &rect, const double env[], void TrackArt::DrawEnvelope(TrackPanelDrawingContext &context,
const wxRect &rect, const double env[],
float zoomMin, float zoomMax, float zoomMin, float zoomMax,
bool dB, float dBRange, bool highlight) bool dB, float dBRange, bool highlight)
{ {
auto &dc = context.dc;
int h = rect.height; int h = rect.height;
auto &pen = highlight ? AColor::uglyPen : AColor::envelopePen; auto &pen = highlight ? AColor::uglyPen : AColor::envelopePen;
@ -1332,13 +1371,17 @@ void TrackArtist::DrawEnvelope(wxDC &dc, const wxRect &rect, const double env[],
cenvBot = value + 4; cenvBot = value + 4;
} }
DrawEnvLine(dc, rect, x0, envTop, cenvTop, true); DrawEnvLine( context, rect, x0, envTop, cenvTop, true );
DrawEnvLine(dc, rect, x0, envBot, cenvBot, false); DrawEnvLine( context, rect, x0, envBot, cenvBot, false );
} }
} }
void TrackArtist::DrawEnvLine(wxDC &dc, const wxRect &rect, int x0, int y0, int cy, bool top) void TrackArt::DrawEnvLine(
TrackPanelDrawingContext &context,
const wxRect &rect, int x0, int y0, int cy, bool top )
{ {
auto &dc = context.dc;
int xx = rect.x + x0; int xx = rect.x + x0;
int yy = rect.y + cy; int yy = rect.y + cy;
@ -1364,17 +1407,13 @@ void TrackArtist::DrawEnvLine(wxDC &dc, const wxRect &rect, int x0, int y0, int
#include "tracks/ui/TimeShiftHandle.h" #include "tracks/ui/TimeShiftHandle.h"
#include "tracks/playabletrack/wavetrack/ui/CutlineHandle.h" #include "tracks/playabletrack/wavetrack/ui/CutlineHandle.h"
void TrackArtist::DrawWaveform(TrackPanelDrawingContext &context, void TrackArt::DrawWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track, const WaveTrack *track,
const wxRect & rect, const wxRect & rect,
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo,
bool drawEnvelope,
bool bigPoints,
bool drawSliders,
bool muted) bool muted)
{ {
auto &dc = context.dc; auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
bool highlight = false; bool highlight = false;
bool gripHit = false; bool gripHit = false;
@ -1386,17 +1425,20 @@ void TrackArtist::DrawWaveform(TrackPanelDrawingContext &context,
const bool dB = !track->GetWaveformSettings().isLinear(); const bool dB = !track->GetWaveformSettings().isLinear();
DrawBackgroundWithSelection(&dc, rect, track, blankSelectedBrush, blankBrush, const auto &blankSelectedBrush = artist->blankSelectedBrush;
selectedRegion, zoomInfo); const auto &blankBrush = artist->blankBrush;
DrawBackgroundWithSelection(
context, rect, track, blankSelectedBrush, blankBrush );
for (const auto &clip: track->GetClips()) for (const auto &clip: track->GetClips())
DrawClipWaveform(context, track, clip.get(), rect, selectedRegion, zoomInfo, DrawClipWaveform(context, track, clip.get(), rect,
drawEnvelope, bigPoints,
dB, muted); dB, muted);
// Update cache for locations, e.g. cutlines and merge points // Update cache for locations, e.g. cutlines and merge points
track->UpdateLocationsCache(); track->UpdateLocationsCache();
const auto &zoomInfo = *artist->pZoomInfo;
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
auto target2 = dynamic_cast<CutlineHandle*>(context.target.get()); auto target2 = dynamic_cast<CutlineHandle*>(context.target.get());
#endif #endif
@ -1428,9 +1470,10 @@ void TrackArtist::DrawWaveform(TrackPanelDrawingContext &context,
} }
} }
const auto drawSliders = artist->drawSliders;
if (drawSliders) { if (drawSliders) {
DrawTimeSlider(dc, rect, true, highlight && gripHit); // directed right DrawTimeSlider( context, rect, true, highlight && gripHit ); // directed right
DrawTimeSlider(dc, rect, false, highlight && gripHit); // directed left DrawTimeSlider( context, rect, false, highlight && gripHit ); // directed left
} }
} }
@ -1651,18 +1694,18 @@ void FindWavePortions
#include "tracks/playabletrack/wavetrack/ui/SampleHandle.h" #include "tracks/playabletrack/wavetrack/ui/SampleHandle.h"
#include "tracks/ui/EnvelopeHandle.h" #include "tracks/ui/EnvelopeHandle.h"
void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context, void TrackArt::DrawClipWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track, const WaveTrack *track,
const WaveClip *clip, const WaveClip *clip,
const wxRect & rect, const wxRect & rect,
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo,
bool drawEnvelope,
bool bigPoints,
bool dB, bool dB,
bool muted) bool muted)
{ {
auto &dc = context.dc; auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &selectedRegion = *artist->pSelectedRegion;
const auto &zoomInfo = *artist->pZoomInfo;
#ifdef PROFILE_WAVEFORM #ifdef PROFILE_WAVEFORM
Profiler profiler; Profiler profiler;
#endif #endif
@ -1673,7 +1716,8 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
highlightEnvelope = target && target->GetEnvelope() == clip->GetEnvelope(); highlightEnvelope = target && target->GetEnvelope() == clip->GetEnvelope();
#endif #endif
const ClipParameters params(false, track, clip, rect, selectedRegion, zoomInfo); const ClipParameters params{
false, track, clip, rect, selectedRegion, zoomInfo };
const wxRect &hiddenMid = params.hiddenMid; const wxRect &hiddenMid = params.hiddenMid;
// The "hiddenMid" rect contains the part of the display actually // The "hiddenMid" rect contains the part of the display actually
// containing the waveform, as it appears without the fisheye. If it's empty, we're done. // containing the waveform, as it appears without the fisheye. If it's empty, we're done.
@ -1696,7 +1740,7 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
int iColorIndex = clip->GetColourIndex(); int iColorIndex = clip->GetColourIndex();
SetColours( iColorIndex ); artist->SetColours( iColorIndex );
// If we get to this point, the clip is actually visible on the // If we get to this point, the clip is actually visible on the
// screen, so remember the display rectangle. // screen, so remember the display rectangle.
@ -1729,12 +1773,12 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
} }
else else
tt0 = tt1 = 0.0; tt0 = tt1 = 0.0;
DrawWaveformBackground(dc, leftOffset, mid, DrawWaveformBackground(context, leftOffset, mid,
env, env,
zoomMin, zoomMax, zoomMin, zoomMax,
track->ZeroLevelYCoordinate(mid), track->ZeroLevelYCoordinate(mid),
dB, dBRange, dB, dBRange,
tt0, tt1, zoomInfo, drawEnvelope, tt0, tt1,
!track->GetSelected(), highlightEnvelope); !track->GetSelected(), highlightEnvelope);
} }
@ -1857,7 +1901,7 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
0, // 1.0 / rate, 0, // 1.0 / rate,
env2, rectPortion.width, leftOffset, zoomInfo ); env2, rectPortion.width, leftOffset, zoomInfo );
DrawMinMaxRMS(dc, rectPortion, env2, DrawMinMaxRMS( context, rectPortion, env2,
zoomMin, zoomMax, zoomMin, zoomMax,
dB, dBRange, dB, dBRange,
useMin, useMax, useRms, useBl, useMin, useMax, useRms, useBl,
@ -1869,26 +1913,29 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
auto target = dynamic_cast<SampleHandle*>(context.target.get()); auto target = dynamic_cast<SampleHandle*>(context.target.get());
highlight = target && target->GetTrack().get() == track; highlight = target && target->GetTrack().get() == track;
#endif #endif
DrawIndividualSamples(dc, leftOffset, rectPortion, zoomMin, zoomMax, DrawIndividualSamples(
context, leftOffset, rectPortion, zoomMin, zoomMax,
dB, dBRange, dB, dBRange,
clip, zoomInfo, clip,
bigPoints, showPoints, muted, highlight); showPoints, muted, highlight );
} }
} }
leftOffset += rectPortion.width + skippedRight; leftOffset += rectPortion.width + skippedRight;
} }
const auto drawEnvelope = artist->drawEnvelope;
if (drawEnvelope) { if (drawEnvelope) {
DrawEnvelope(dc, mid, env, zoomMin, zoomMax, dB, dBRange, highlightEnvelope); DrawEnvelope(
context, mid, env, zoomMin, zoomMax, dB, dBRange, highlightEnvelope );
clip->GetEnvelope()->DrawPoints clip->GetEnvelope()->DrawPoints
(context, rect, zoomInfo, dB, dBRange, zoomMin, zoomMax, true); ( context, rect, dB, dBRange, zoomMin, zoomMax, true );
} }
// Draw arrows on the left side if the track extends to the left of the // Draw arrows on the left side if the track extends to the left of the
// beginning of time. :) // beginning of time. :)
if (h == 0.0 && tOffset < 0.0) { if (h == 0.0 && tOffset < 0.0) {
DrawNegativeOffsetTrackArrows(dc, rect); DrawNegativeOffsetTrackArrows( context, rect );
} }
// Draw clip edges // Draw clip edges
@ -1906,10 +1953,12 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
} }
void TrackArtist::DrawTimeSlider(wxDC & dc, void TrackArt::DrawTimeSlider( TrackPanelDrawingContext &context,
const wxRect & rect, const wxRect & rect,
bool rightwards, bool highlight ) bool rightwards, bool highlight )
{ {
auto &dc = context.dc;
const int border = 3; // 3 pixels all round. const int border = 3; // 3 pixels all round.
const int width = 6; // width of the drag box. const int width = 6; // width of the drag box.
const int taper = 6; // how much the box tapers by. const int taper = 6; // how much the box tapers by.
@ -1962,19 +2011,19 @@ void TrackArtist::DrawTimeSlider(wxDC & dc,
} }
} }
void TrackArtist::DrawSpectrum(const WaveTrack *track, void TrackArt::DrawSpectrum( TrackPanelDrawingContext &context,
wxDC & dc, const WaveTrack *track,
const wxRect & rect, const wxRect & rect )
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo)
{ {
DrawBackgroundWithSelection(&dc, rect, track, blankSelectedBrush, blankBrush, const auto artist = TrackArtist::Get( context );
selectedRegion, zoomInfo); const auto &blankSelectedBrush = artist->blankSelectedBrush;
const auto &blankBrush = artist->blankBrush;
DrawBackgroundWithSelection(
context, rect, track, blankSelectedBrush, blankBrush );
WaveTrackCache cache(Track::Pointer<const WaveTrack>(track)); WaveTrackCache cache(Track::Pointer<const WaveTrack>(track));
for (const auto &clip: track->GetClips()) { for (const auto &clip: track->GetClips())
DrawClipSpectrum(cache, clip.get(), dc, rect, selectedRegion, zoomInfo); DrawClipSpectrum( context, cache, clip.get(), rect );
}
} }
static inline float findValue static inline float findValue
@ -2058,13 +2107,16 @@ AColor::ColorGradientChoice ChooseColorSet( float bin0, float bin1, float selBin
} }
void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache, void TrackArt::DrawClipSpectrum(TrackPanelDrawingContext &context,
WaveTrackCache &waveTrackCache,
const WaveClip *clip, const WaveClip *clip,
wxDC & dc, const wxRect & rect)
const wxRect & rect,
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo)
{ {
auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &selectedRegion = *artist->pSelectedRegion;
const auto &zoomInfo = *artist->pZoomInfo;
#ifdef PROFILE_WAVEFORM #ifdef PROFILE_WAVEFORM
Profiler profiler; Profiler profiler;
#endif #endif
@ -2075,7 +2127,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrackCache &waveTrackCache,
enum { DASH_LENGTH = 10 /* pixels */ }; enum { DASH_LENGTH = 10 /* pixels */ };
const ClipParameters params(true, track, clip, rect, selectedRegion, zoomInfo); const ClipParameters params{
true, track, clip, rect, selectedRegion, zoomInfo };
const wxRect &hiddenMid = params.hiddenMid; const wxRect &hiddenMid = params.hiddenMid;
// The "hiddenMid" rect contains the part of the display actually // The "hiddenMid" rect contains the part of the display actually
// containing the waveform, as it appears without the fisheye. If it's empty, we're done. // containing the waveform, as it appears without the fisheye. If it's empty, we're done.
@ -2676,13 +2729,17 @@ int PitchToY(double p, int bottom)
sel is equal to rect, and the entire region is drawn with unselected sel is equal to rect, and the entire region is drawn with unselected
background colors. background colors.
*/ */
void TrackArtist::DrawNoteBackground(const NoteTrack *track, wxDC &dc, void TrackArt::DrawNoteBackground(TrackPanelDrawingContext &context,
const NoteTrack *track,
const wxRect &rect, const wxRect &sel, const wxRect &rect, const wxRect &sel,
const ZoomInfo &zoomInfo,
const wxBrush &wb, const wxPen &wp, const wxBrush &wb, const wxPen &wp,
const wxBrush &bb, const wxPen &bp, const wxBrush &bb, const wxPen &bp,
const wxPen &mp) const wxPen &mp)
{ {
auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &zoomInfo = *artist->pZoomInfo;
dc.SetBrush(wb); dc.SetBrush(wb);
dc.SetPen(wp); dc.SetPen(wp);
#ifndef EXPERIMENTAL_NOTETRACK_OVERLAY #ifndef EXPERIMENTAL_NOTETRACK_OVERLAY
@ -2772,13 +2829,16 @@ graphics. Since there may be notes outside of the display region,
reserve a half-note-height margin at the top and bottom of the reserve a half-note-height margin at the top and bottom of the
window and draw out-of-bounds notes here instead. window and draw out-of-bounds notes here instead.
*/ */
void TrackArtist::DrawNoteTrack(const NoteTrack *track, void TrackArt::DrawNoteTrack(TrackPanelDrawingContext &context,
wxDC & dc, const NoteTrack *track,
const wxRect & rect, const wxRect & rect,
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo,
bool muted) bool muted)
{ {
auto &dc = context.dc;
const auto artist = TrackArtist::Get( context );
const auto &selectedRegion = *artist->pSelectedRegion;
const auto &zoomInfo = *artist->pZoomInfo;
SonifyBeginNoteBackground(); SonifyBeginNoteBackground();
double sel0 = selectedRegion.t0(); double sel0 = selectedRegion.t0();
double sel1 = selectedRegion.t1(); double sel1 = selectedRegion.t1();
@ -2803,9 +2863,8 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
track->PrepareIPitchToY(rect); track->PrepareIPitchToY(rect);
#ifdef EXPERIMENTAL_NOTETRACK_OVERLAY #ifdef EXPERIMENTAL_NOTETRACK_OVERLAY
DrawBackgroundWithSelection(&dc, rect, track, DrawBackgroundWithSelection(context, rect, track,
AColor::labelSelectedBrush, AColor::labelUnselectedBrush, AColor::labelSelectedBrush, AColor::labelUnselectedBrush);
selectedRegion, zoomInfo);
#endif #endif
// Background comes in 4 colors, that are now themed. // Background comes in 4 colors, that are now themed.
@ -2821,7 +2880,9 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
wxPen barLinePen; wxPen barLinePen;
barLinePen.SetColour(theTheme.Colour( clrMidiLines)); barLinePen.SetColour(theTheme.Colour( clrMidiLines));
DrawNoteBackground(track, dc, rect, rect, zoomInfo, blankBrush, blankPen, const auto &blankBrush = artist->blankBrush;
const auto &blankPen = artist->blankPen;
DrawNoteBackground(context, track, rect, rect, blankBrush, blankPen,
blackStripeBrush, blackStripePen, barLinePen); blackStripeBrush, blackStripePen, barLinePen);
dc.SetClippingRegion(rect); dc.SetClippingRegion(rect);
@ -2849,7 +2910,7 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
wxPen selectedBarLinePen; wxPen selectedBarLinePen;
selectedBarLinePen.SetColour(theTheme.Colour( clrMidiLines)); selectedBarLinePen.SetColour(theTheme.Colour( clrMidiLines));
DrawNoteBackground(track, dc, rect, selBG, zoomInfo, DrawNoteBackground(context, track, rect, selBG,
selectedWhiteKeyBrush, selectedWhiteKeyPen, selectedWhiteKeyBrush, selectedWhiteKeyPen,
selectedBlackKeyBrush, selectedBlackKeyPen, selectedBlackKeyBrush, selectedBlackKeyPen,
selectedBarLinePen); selectedBarLinePen);
@ -3124,7 +3185,7 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
rect.x + rect.width, rect.y + rect.height - marg - 1); // top of line rect.x + rect.width, rect.y + rect.height - marg - 1); // top of line
if (h == 0.0 && track->GetOffset() < 0.0) { if (h == 0.0 && track->GetOffset() < 0.0) {
DrawNegativeOffsetTrackArrows(dc, rect); DrawNegativeOffsetTrackArrows( context, rect );
} }
dc.DestroyClippingRegion(); dc.DestroyClippingRegion();
@ -3133,38 +3194,24 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
#endif // USE_MIDI #endif // USE_MIDI
void TrackArtist::DrawLabelTrack(TrackPanelDrawingContext &context, void TrackArt::DrawTimeTrack(TrackPanelDrawingContext &context,
const LabelTrack *track,
const wxRect & rect,
const SelectedRegion &selectedRegion,
const ZoomInfo &zoomInfo)
{
double sel0 = selectedRegion.t0();
double sel1 = selectedRegion.t1();
if (!track->GetSelected() && !track->IsSyncLockSelected())
sel0 = sel1 = 0.0;
track->Draw(context, rect, SelectedRegion(sel0, sel1), zoomInfo);
}
void TrackArtist::DrawTimeTrack(TrackPanelDrawingContext &context,
const TimeTrack *track, const TimeTrack *track,
const wxRect & rect, const wxRect & rect)
const ZoomInfo &zoomInfo)
{ {
track->Draw(context, rect, zoomInfo); track->Draw( context, rect );
wxRect envRect = rect; wxRect envRect = rect;
envRect.height -= 2; envRect.height -= 2;
double lower = track->GetRangeLower(), upper = track->GetRangeUpper(); double lower = track->GetRangeLower(), upper = track->GetRangeUpper();
const auto artist = TrackArtist::Get( context );
const auto dbRange = artist->mdBrange;
if(track->GetDisplayLog()) { if(track->GetDisplayLog()) {
// MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale // MB: silly way to undo the work of GetWaveYPos while still getting a logarithmic scale
lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / mdBrange + 1.0; lower = LINEAR_TO_DB(std::max(1.0e-7, lower)) / dbRange + 1.0;
upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / mdBrange + 1.0; upper = LINEAR_TO_DB(std::max(1.0e-7, upper)) / dbRange + 1.0;
} }
track->GetEnvelope()->DrawPoints track->GetEnvelope()->DrawPoints
(context, envRect, zoomInfo, ( context, envRect,
track->GetDisplayLog(), mdBrange, lower, upper, false); track->GetDisplayLog(), dbRange, lower, upper, false );
} }
void TrackArtist::UpdatePrefs() void TrackArtist::UpdatePrefs()
@ -3172,6 +3219,10 @@ void TrackArtist::UpdatePrefs()
mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange); mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange);
mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping); mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
mSampleDisplay = TracksPrefs::SampleViewChoice(); mSampleDisplay = TracksPrefs::SampleViewChoice();
mbShowTrackNameInWaveform =
gPrefs->ReadBool(wxT("/GUI/ShowTrackNameInWaveform"), false);
SetColours(0); SetColours(0);
} }
@ -3188,8 +3239,11 @@ void TrackArtist::UpdatePrefs()
// 5x5 box. // 5x5 box.
// //
// There may be a better way to do this, or a more appealing pattern. // There may be a better way to do this, or a more appealing pattern.
void TrackArtist::DrawSyncLockTiles(wxDC *dc, const wxRect &rect) void TrackArt::DrawSyncLockTiles(
TrackPanelDrawingContext &context, const wxRect &rect )
{ {
const auto dc = &context.dc;
wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockSelTile)); wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockSelTile));
// Grid spacing is a bit smaller than actual image size // Grid spacing is a bit smaller than actual image size
@ -3295,13 +3349,19 @@ void TrackArtist::DrawSyncLockTiles(wxDC *dc, const wxRect &rect)
} }
} }
void TrackArtist::DrawBackgroundWithSelection(wxDC *dc, const wxRect &rect, void TrackArt::DrawBackgroundWithSelection(
TrackPanelDrawingContext &context, const wxRect &rect,
const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush, const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo) bool useSelection)
{ {
const auto dc = &context.dc;
const auto artist = TrackArtist::Get( context );
const auto &selectedRegion = *artist->pSelectedRegion;
const auto &zoomInfo = *artist->pZoomInfo;
//MM: Draw background. We should optimize that a bit more. //MM: Draw background. We should optimize that a bit more.
const double sel0 = selectedRegion.t0(); const double sel0 = useSelection ? selectedRegion.t0() : 0.0;
const double sel1 = selectedRegion.t1(); const double sel1 = useSelection ? selectedRegion.t1() : 0.0;
dc->SetPen(*wxTRANSPARENT_PEN); dc->SetPen(*wxTRANSPARENT_PEN);
if (track->GetSelected() || track->IsSyncLockSelected()) if (track->GetSelected() || track->IsSyncLockSelected())
@ -3337,7 +3397,7 @@ void TrackArtist::DrawBackgroundWithSelection(wxDC *dc, const wxRect &rect,
// Per condition above, track must be sync-lock selected // Per condition above, track must be sync-lock selected
dc->SetBrush(unselBrush); dc->SetBrush(unselBrush);
dc->DrawRectangle(within); dc->DrawRectangle(within);
DrawSyncLockTiles(dc, within); DrawSyncLockTiles( context, within );
} }
after.x = 1 + within.GetRight(); after.x = 1 + within.GetRight();

View File

@ -24,7 +24,6 @@
#include "Experimental.h" #include "Experimental.h"
#include "audacity/Types.h" #include "audacity/Types.h"
class wxDC;
class wxRect; class wxRect;
class wxHashTable; class wxHashTable;
@ -47,33 +46,114 @@ struct TrackPanelDrawingContext;
typedef unsigned char uchar; typedef unsigned char uchar;
#endif #endif
namespace TrackArt {
void DrawTracks(TrackPanelDrawingContext &context,
const TrackList *tracks,
const wxRegion & reg,
const wxRect &clip);
void DrawTrack(TrackPanelDrawingContext &context,
const Track *t,
const wxRect & rect);
void DrawVRuler(TrackPanelDrawingContext &context,
const Track *t, const wxRect & rect, bool bSelected );
// Helper: draws the "sync-locked" watermark tiled to a rectangle
void DrawSyncLockTiles(
TrackPanelDrawingContext &context, const wxRect &rect );
// Helper: draws background with selection rect
void DrawBackgroundWithSelection(TrackPanelDrawingContext &contex,
const wxRect &rect, const Track *track,
const wxBrush &selBrush, const wxBrush &unselBrush,
bool useSelection = true);
//
// Lower-level drawing functions
//
void DrawWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track,
const wxRect & rect,
bool muted);
void DrawSpectrum(TrackPanelDrawingContext &context,
const WaveTrack *track,
const wxRect & rect);
#ifdef USE_MIDI
int GetBottom(NoteTrack *t, const wxRect &rect);
void DrawNoteBackground(TrackPanelDrawingContext &context,
const NoteTrack *track,
const wxRect &rect, const wxRect &sel,
const wxBrush &wb, const wxPen &wp,
const wxBrush &bb, const wxPen &bp,
const wxPen &mp);
void DrawNoteTrack(TrackPanelDrawingContext &context,
const NoteTrack *track,
const wxRect & rect,
bool muted);
#endif // USE_MIDI
void DrawTimeTrack(TrackPanelDrawingContext &context,
const TimeTrack *track,
const wxRect & rect);
void DrawTimeSlider(TrackPanelDrawingContext &context,
const wxRect & rect,
bool rightwards, bool highlight);
void DrawClipWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track, const WaveClip *clip,
const wxRect & rect,
bool dB, bool muted);
void DrawClipSpectrum(TrackPanelDrawingContext &context,
WaveTrackCache &cache, const WaveClip *clip,
const wxRect & rect);
// Waveform utility functions
void DrawWaveformBackground(TrackPanelDrawingContext &context,
int leftOffset, const wxRect &rect,
const double env[],
float zoomMin, float zoomMax,
int zeroLevelYCoordinate,
bool dB, float dBRange,
double t0, double t1,
bool bIsSyncLockSelected,
bool highlightEnvelope);
void DrawMinMaxRMS(TrackPanelDrawingContext &context,
const wxRect & rect, const double env[],
float zoomMin, float zoomMax,
bool dB, float dBRange,
const float *min, const float *max, const float *rms, const int *bl,
bool /* showProgress */, bool muted);
void DrawIndividualSamples(TrackPanelDrawingContext &context,
int leftOffset, const wxRect & rect,
float zoomMin, float zoomMax,
bool dB, float dBRange,
const WaveClip *clip,
bool showPoints, bool muted,
bool highlight);
void DrawNegativeOffsetTrackArrows( TrackPanelDrawingContext &context,
const wxRect & rect );
void DrawEnvelope(TrackPanelDrawingContext &context,
const wxRect & rect, const double env[],
float zoomMin, float zoomMax,
bool dB, float dBRange, bool highlight);
void DrawEnvLine(TrackPanelDrawingContext &context,
const wxRect & rect, int x0, int y0, int cy, bool top);
}
class AUDACITY_DLL_API TrackArtist { class AUDACITY_DLL_API TrackArtist {
public: public:
TrackArtist(); TrackArtist();
~TrackArtist(); ~TrackArtist();
static TrackArtist *Get( TrackPanelDrawingContext & );
void SetColours(int iColorIndex);
void DrawTracks(TrackPanelDrawingContext &context,
const TrackList *tracks,
const wxRegion & reg,
const wxRect &clip, int leftOffset,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
bool drawEnvelope, bool bigPoints, bool drawSliders);
void DrawTrack(TrackPanelDrawingContext &context,
const Track *t,
const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
bool drawEnvelope, bool bigPoints, bool drawSliders,
bool hasSolo);
void DrawVRuler(TrackPanelDrawingContext &context,
const Track *t, const wxRect & rect, bool bSelected );
void UpdateVRuler(const Track *t, const wxRect & rect);
void UpdatePrefs();
void SetBackgroundBrushes(wxBrush unselectedBrushIn, wxBrush selectedBrushIn, void SetBackgroundBrushes(wxBrush unselectedBrushIn, wxBrush selectedBrushIn,
wxPen unselectedPenIn, wxPen selectedPenIn) { wxPen unselectedPenIn, wxPen selectedPenIn) {
@ -83,96 +163,11 @@ class AUDACITY_DLL_API TrackArtist {
this->selectedPen = selectedPenIn; this->selectedPen = selectedPenIn;
} }
// Helper: draws the "sync-locked" watermark tiled to a rectangle void SetColours(int iColorIndex);
static void DrawSyncLockTiles(wxDC *dc, const wxRect &rect);
// Helper: draws background with selection rect void UpdatePrefs();
static void DrawBackgroundWithSelection(wxDC *dc, const wxRect &rect,
const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo);
private: void UpdateVRuler(const Track *t, const wxRect & rect);
//
// Lower-level drawing functions
//
void DrawWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track,
const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
bool drawEnvelope, bool bigPoints, bool drawSliders,
bool muted);
void DrawSpectrum(const WaveTrack *track,
wxDC & dc, const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo);
#ifdef USE_MIDI
int GetBottom(NoteTrack *t, const wxRect &rect);
void DrawNoteBackground(const NoteTrack *track, wxDC &dc,
const wxRect &rect, const wxRect &sel,
const ZoomInfo &zoomInfo,
const wxBrush &wb, const wxPen &wp,
const wxBrush &bb, const wxPen &bp,
const wxPen &mp);
void DrawNoteTrack(const NoteTrack *track,
wxDC & dc, const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
bool muted);
#endif // USE_MIDI
void DrawLabelTrack(TrackPanelDrawingContext &context,
const LabelTrack *track,
const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo);
void DrawTimeTrack(TrackPanelDrawingContext &context,
const TimeTrack *track,
const wxRect & rect, const ZoomInfo &zoomInfo);
void DrawTimeSlider(wxDC & dc, const wxRect & rect,
bool rightwards, bool highlight);
void DrawClipWaveform(TrackPanelDrawingContext &context,
const WaveTrack *track, const WaveClip *clip,
const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo,
bool drawEnvelope, bool bigPoints,
bool dB, bool muted);
void DrawClipSpectrum(WaveTrackCache &cache, const WaveClip *clip,
wxDC & dc, const wxRect & rect,
const SelectedRegion &selectedRegion, const ZoomInfo &zoomInfo);
// Waveform utility functions
void DrawWaveformBackground(wxDC & dc, int leftOffset, const wxRect &rect,
const double env[],
float zoomMin, float zoomMax,
int zeroLevelYCoordinate,
bool dB, float dBRange,
double t0, double t1, const ZoomInfo &zoomInfo,
bool drawEnvelope, bool bIsSyncLockSelected,
bool highlightEnvelope);
void DrawMinMaxRMS(wxDC &dc, const wxRect & rect, const double env[],
float zoomMin, float zoomMax,
bool dB, float dBRange,
const float *min, const float *max, const float *rms, const int *bl,
bool /* showProgress */, bool muted);
void DrawIndividualSamples(wxDC & dc, int leftOffset, const wxRect & rect,
float zoomMin, float zoomMax,
bool dB, float dBRange,
const WaveClip *clip,
const ZoomInfo &zoomInfo,
bool bigPoints, bool showPoints, bool muted,
bool highlight);
void DrawNegativeOffsetTrackArrows(wxDC & dc, const wxRect & rect);
void DrawEnvelope(wxDC & dc, const wxRect & rect, const double env[],
float zoomMin, float zoomMax,
bool dB, float dBRange, bool highlight);
void DrawEnvLine(wxDC & dc, const wxRect & rect, int x0, int y0, int cy, bool top);
// Preference values // Preference values
float mdBrange; // "/GUI/EnvdBRange" float mdBrange; // "/GUI/EnvdBRange"
@ -215,6 +210,15 @@ class AUDACITY_DLL_API TrackArtist {
int findNotesNOld; int findNotesNOld;
bool findNotesQuantizeOld; bool findNotesQuantizeOld;
#endif #endif
SelectedRegion *pSelectedRegion{};
ZoomInfo *pZoomInfo{};
int leftOffset{ 0 };
bool drawEnvelope{ false };
bool bigPoints{ false };
bool drawSliders{ false };
bool hasSolo{ false };
}; };
extern int GetWaveYPos(float value, float min, float max, extern int GetWaveYPos(float value, float min, float max,

View File

@ -1048,7 +1048,11 @@ void TrackPanel::DrawTracks(wxDC * dc)
const wxRect clip = GetRect(); const wxRect clip = GetRect();
TrackPanelDrawingContext context{ *dc, Target(), mLastMouseState }; mTrackArtist->pSelectedRegion = &mViewInfo->selectedRegion;
mTrackArtist->pZoomInfo = mViewInfo;
TrackPanelDrawingContext context {
*dc, Target(), mLastMouseState, mTrackArtist.get()
};
// Draw margins on two or three sides. // Draw margins on two or three sides.
ClearLeftAndRightMargins(context, clip); ClearLeftAndRightMargins(context, clip);
@ -1064,11 +1068,19 @@ void TrackPanel::DrawTracks(wxDC * dc)
bool bigPointsFlag = pTtb->IsDown(drawTool) || bMultiToolDown; bool bigPointsFlag = pTtb->IsDown(drawTool) || bMultiToolDown;
bool sliderFlag = bMultiToolDown; bool sliderFlag = bMultiToolDown;
// The track artist actually draws the stuff inside each track const bool hasSolo = GetTracks()->Any< PlayableTrack >()
mTrackArtist->DrawTracks(context, GetTracks(), .any_of( []( const PlayableTrack *pt ) {
region, clip, GetLeftOffset(), pt = static_cast< const PlayableTrack * >(
mViewInfo->selectedRegion, *mViewInfo, pt->SubstitutePendingChangedTrack().get() );
envelopeFlag, bigPointsFlag, sliderFlag); return (pt && pt->GetSolo());
} );
mTrackArtist->leftOffset = GetLeftOffset();
mTrackArtist->drawEnvelope = envelopeFlag;
mTrackArtist->bigPoints = bigPointsFlag;
mTrackArtist->drawSliders = sliderFlag;
mTrackArtist->hasSolo = hasSolo;
TrackArt::DrawTracks( context, GetTracks(), region, clip );
// Draw the rest, including the click-to-deselect blank area below all // Draw the rest, including the click-to-deselect blank area below all
// tracks // tracks
@ -1142,7 +1154,7 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context,
GetVRulerWidth() + 1, GetVRulerWidth() + 1,
trackRect.height - kSeparatorThickness trackRect.height - kSeparatorThickness
}; };
mTrackArtist->DrawVRuler(context, channel, rect, bSelected); TrackArt::DrawVRuler(context, channel, rect, bSelected);
} }
} }
} }
@ -1638,7 +1650,7 @@ void TrackPanel::DrawOutside
// wxRect tileFill = rect; // wxRect tileFill = rect;
// tileFill.x = GetVRulerOffset(); // tileFill.x = GetVRulerOffset();
// tileFill.width = GetVRulerWidth(); // tileFill.width = GetVRulerWidth();
// TrackArtist::DrawSyncLockTiles(dc, tileFill); // TrackArt::DrawSyncLockTiles(dc, tileFill);
//} //}
DrawBordersAroundTrack( dc, rect ); DrawBordersAroundTrack( dc, rect );

View File

@ -24,6 +24,8 @@ struct TrackPanelDrawingContext {
UIHandlePtr target; UIHandlePtr target;
wxMouseState lastState; wxMouseState lastState;
void *pUserData;
// This redundancy fixes an MSVC compiler warning: // This redundancy fixes an MSVC compiler warning:
TrackPanelDrawingContext() = delete; TrackPanelDrawingContext() = delete;
}; };

View File

@ -90,6 +90,7 @@
#include "../FFT.h" #include "../FFT.h"
#include "../Prefs.h" #include "../Prefs.h"
#include "../Project.h" #include "../Project.h"
#include "../TrackArtist.h"
#include "../WaveTrack.h" #include "../WaveTrack.h"
#include "../widgets/Ruler.h" #include "../widgets/Ruler.h"
#include "../xml/XMLFileReader.h" #include "../xml/XMLFileReader.h"
@ -3049,9 +3050,12 @@ void EqualizationPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
memDC.SetPen(*wxBLACK_PEN); memDC.SetPen(*wxBLACK_PEN);
if( mEffect->mDraw->GetValue() ) if( mEffect->mDraw->GetValue() )
{ {
TrackPanelDrawingContext context{ memDC, {}, {} }; ZoomInfo zoomInfo( 0.0, mEnvRect.width-1 );
TrackArtist artist;
artist.pZoomInfo = &zoomInfo;
TrackPanelDrawingContext context{ memDC, {}, {}, &artist };
mEffect->mEnvelope->DrawPoints( mEffect->mEnvelope->DrawPoints(
context, mEnvRect, ZoomInfo(0.0, mEnvRect.width-1), false, 0.0, context, mEnvRect, false, 0.0,
mEffect->mdBMin, mEffect->mdBMax, false); mEffect->mdBMin, mEffect->mdBMax, false);
} }