mirror of
https://github.com/cookiengineer/audacity
synced 2025-11-22 00:47:13 +01:00
Mutable cache for ruler updates, so Draw functions can be const
This commit is contained in:
@@ -111,8 +111,6 @@ Ruler::Ruler()
|
|||||||
|
|
||||||
mLength = 0;
|
mLength = 0;
|
||||||
|
|
||||||
mValid = false;
|
|
||||||
|
|
||||||
mCustom = false;
|
mCustom = false;
|
||||||
mbMinor = true;
|
mbMinor = true;
|
||||||
|
|
||||||
@@ -289,6 +287,7 @@ void Ruler::SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxF
|
|||||||
wxCoord height;
|
wxCoord height;
|
||||||
FindFontHeights( height, mpUserFonts->lead, dc, majorFont );
|
FindFontHeights( height, mpUserFonts->lead, dc, majorFont );
|
||||||
|
|
||||||
|
mpFonts.reset();
|
||||||
mpFonts.reset();
|
mpFonts.reset();
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
@@ -346,14 +345,12 @@ void Ruler::SetBounds(int left, int top, int right, int bottom)
|
|||||||
|
|
||||||
void Ruler::Invalidate()
|
void Ruler::Invalidate()
|
||||||
{
|
{
|
||||||
mValid = false;
|
|
||||||
|
|
||||||
if (mOrientation == wxHORIZONTAL)
|
if (mOrientation == wxHORIZONTAL)
|
||||||
mLength = mRight-mLeft;
|
mLength = mRight-mLeft;
|
||||||
else
|
else
|
||||||
mLength = mBottom-mTop;
|
mLength = mBottom-mTop;
|
||||||
|
|
||||||
mBits.clear();
|
mpCache.reset();
|
||||||
mUserBits.clear();
|
mUserBits.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,6 +905,12 @@ struct Ruler::Updater {
|
|||||||
const;
|
const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ruler::Cache {
|
||||||
|
Bits mBits;
|
||||||
|
Labels mMajorLabels, mMinorLabels, mMinorMinorLabels;
|
||||||
|
wxRect mRect;
|
||||||
|
};
|
||||||
|
|
||||||
struct Ruler::Updater::TickOutputs{ Labels &labels; Bits &bits; wxRect &box; };
|
struct Ruler::Updater::TickOutputs{ Labels &labels; Bits &bits; wxRect &box; };
|
||||||
struct Ruler::Updater::UpdateOutputs {
|
struct Ruler::Updater::UpdateOutputs {
|
||||||
Labels &majorLabels, &minorLabels, &minorMinorLabels;
|
Labels &majorLabels, &minorLabels, &minorMinorLabels;
|
||||||
@@ -1328,9 +1331,13 @@ void Ruler::ChooseFonts( wxDC &dc ) const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ruler::Update(
|
void Ruler::UpdateCache(
|
||||||
wxDC &dc, const Envelope* envelope )// Envelope *speedEnv, long minSpeed, long maxSpeed )
|
wxDC &dc, const Envelope* envelope )
|
||||||
|
const // Envelope *speedEnv, long minSpeed, long maxSpeed )
|
||||||
{
|
{
|
||||||
|
if ( mpCache )
|
||||||
|
return;
|
||||||
|
|
||||||
const ZoomInfo *zoomInfo = NULL;
|
const ZoomInfo *zoomInfo = NULL;
|
||||||
if (!mLog && mOrientation == wxHORIZONTAL)
|
if (!mLog && mOrientation == wxHORIZONTAL)
|
||||||
zoomInfo = mUseZoomInfo;
|
zoomInfo = mUseZoomInfo;
|
||||||
@@ -1340,6 +1347,8 @@ void Ruler::Update(
|
|||||||
// tick positions and font size.
|
// tick positions and font size.
|
||||||
|
|
||||||
ChooseFonts( dc );
|
ChooseFonts( dc );
|
||||||
|
mpCache = std::make_unique< Cache >();
|
||||||
|
auto &cache = *mpCache;
|
||||||
|
|
||||||
// If ruler is being resized, we could end up with it being too small.
|
// If ruler is being resized, we could end up with it being too small.
|
||||||
// Values of mLength of zero or below cause bad array allocations and
|
// Values of mLength of zero or below cause bad array allocations and
|
||||||
@@ -1349,33 +1358,31 @@ void Ruler::Update(
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (mOrientation == wxHORIZONTAL)
|
if (mOrientation == wxHORIZONTAL)
|
||||||
mRect = wxRect(0,0, mLength,0);
|
cache.mRect = { 0, 0, mLength, 0 };
|
||||||
else
|
else
|
||||||
mRect = wxRect(0,0, 0,mLength);
|
cache.mRect = { 0, 0, 0, mLength };
|
||||||
|
|
||||||
// FIXME: Surely we do not need to allocate storage for the labels?
|
// FIXME: Surely we do not need to allocate storage for the labels?
|
||||||
// We can just recompute them as we need them? Yes, but only if
|
// We can just recompute them as we need them? Yes, but only if
|
||||||
// mCustom is false!!!!
|
// mCustom is false!!!!
|
||||||
|
|
||||||
if(!mCustom) {
|
if(!mCustom) {
|
||||||
mMajorLabels.clear();
|
cache.mMajorLabels.clear();
|
||||||
mMinorLabels.clear();
|
cache.mMinorLabels.clear();
|
||||||
mMinorMinorLabels.clear();
|
cache.mMinorMinorLabels.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
mBits = mUserBits;
|
cache.mBits = mUserBits;
|
||||||
mBits.resize( static_cast<size_t>(mLength + 1), false );
|
cache.mBits.resize( static_cast<size_t>(mLength + 1), false );
|
||||||
|
|
||||||
// Keep Updater const! We want no hidden state changes affecting its
|
// Keep Updater const! We want no hidden state changes affecting its
|
||||||
// computations.
|
// computations.
|
||||||
const Updater updater{ *this, zoomInfo };
|
const Updater updater{ *this, zoomInfo };
|
||||||
Updater::UpdateOutputs allOutputs{
|
Updater::UpdateOutputs allOutputs{
|
||||||
mMajorLabels, mMinorLabels, mMinorMinorLabels,
|
cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels,
|
||||||
mBits, mRect
|
cache.mBits, cache.mRect
|
||||||
};
|
};
|
||||||
updater.Update(dc, envelope, allOutputs);
|
updater.Update(dc, envelope, allOutputs);
|
||||||
|
|
||||||
mValid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Ruler::GetFonts() const -> Fonts
|
auto Ruler::GetFonts() const -> Fonts
|
||||||
@@ -1388,18 +1395,18 @@ auto Ruler::GetFonts() const -> Fonts
|
|||||||
return *mpFonts;
|
return *mpFonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ruler::Draw(wxDC& dc)
|
void Ruler::Draw(wxDC& dc) const
|
||||||
{
|
{
|
||||||
Draw( dc, NULL);
|
Draw( dc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ruler::Draw(wxDC& dc, const Envelope* envelope)
|
void Ruler::Draw(wxDC& dc, const Envelope* envelope) const
|
||||||
{
|
{
|
||||||
if( mLength <=0 )
|
if( mLength <=0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!mValid)
|
UpdateCache( dc, envelope );
|
||||||
Update( dc, envelope );
|
auto &cache = *mpCache;
|
||||||
|
|
||||||
dc.SetTextForeground( mTickColour );
|
dc.SetTextForeground( mTickColour );
|
||||||
#ifdef EXPERIMENTAL_THEMING
|
#ifdef EXPERIMENTAL_THEMING
|
||||||
@@ -1464,18 +1471,18 @@ void Ruler::Draw(wxDC& dc, const Envelope* envelope)
|
|||||||
label.Draw(dc, mTwoTone, mTickColour);
|
label.Draw(dc, mTwoTone, mTickColour);
|
||||||
};
|
};
|
||||||
|
|
||||||
for( const auto &label : mMajorLabels )
|
for( const auto &label : cache.mMajorLabels )
|
||||||
drawLabel( label, 4 );
|
drawLabel( label, 4 );
|
||||||
|
|
||||||
if( mbMinor ) {
|
if( mbMinor ) {
|
||||||
dc.SetFont( mpFonts->minor );
|
dc.SetFont( mpFonts->minor );
|
||||||
for( const auto &label : mMinorLabels )
|
for( const auto &label : cache.mMinorLabels )
|
||||||
drawLabel( label, 2 );
|
drawLabel( label, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SetFont( mpFonts->minorMinor );
|
dc.SetFont( mpFonts->minorMinor );
|
||||||
|
|
||||||
for( const auto &label : mMinorMinorLabels )
|
for( const auto &label : cache.mMinorMinorLabels )
|
||||||
if ( !label.text.empty() )
|
if ( !label.text.empty() )
|
||||||
drawLabel( label, 2 );
|
drawLabel( label, 2 );
|
||||||
}
|
}
|
||||||
@@ -1484,9 +1491,10 @@ void Ruler::Draw(wxDC& dc, const Envelope* envelope)
|
|||||||
void Ruler::DrawGrid(wxDC& dc,
|
void Ruler::DrawGrid(wxDC& dc,
|
||||||
const int gridLineLength,
|
const int gridLineLength,
|
||||||
const bool minorGrid, const bool majorGrid, int xOffset, int yOffset)
|
const bool minorGrid, const bool majorGrid, int xOffset, int yOffset)
|
||||||
|
const
|
||||||
{
|
{
|
||||||
if ( !mValid )
|
UpdateCache( dc, nullptr );
|
||||||
Update( dc, nullptr );
|
auto &cache = *mpCache;
|
||||||
|
|
||||||
int gridPos;
|
int gridPos;
|
||||||
wxPen gridPen;
|
wxPen gridPen;
|
||||||
@@ -1494,7 +1502,7 @@ void Ruler::DrawGrid(wxDC& dc,
|
|||||||
if(mbMinor && (minorGrid && (gridLineLength != 0 ))) {
|
if(mbMinor && (minorGrid && (gridLineLength != 0 ))) {
|
||||||
gridPen.SetColour(178, 178, 178); // very light grey
|
gridPen.SetColour(178, 178, 178); // very light grey
|
||||||
dc.SetPen(gridPen);
|
dc.SetPen(gridPen);
|
||||||
for( const auto &label : mMinorLabels ) {
|
for( const auto &label : cache.mMinorLabels ) {
|
||||||
gridPos = label.pos;
|
gridPos = label.pos;
|
||||||
if(mOrientation == wxHORIZONTAL) {
|
if(mOrientation == wxHORIZONTAL) {
|
||||||
if((gridPos != 0) && (gridPos != gridLineLength))
|
if((gridPos != 0) && (gridPos != gridLineLength))
|
||||||
@@ -1510,7 +1518,7 @@ void Ruler::DrawGrid(wxDC& dc,
|
|||||||
if(majorGrid && (gridLineLength != 0 )) {
|
if(majorGrid && (gridLineLength != 0 )) {
|
||||||
gridPen.SetColour(127, 127, 127); // light grey
|
gridPen.SetColour(127, 127, 127); // light grey
|
||||||
dc.SetPen(gridPen);
|
dc.SetPen(gridPen);
|
||||||
for( const auto &label : mMajorLabels ) {
|
for( const auto &label : cache.mMajorLabels ) {
|
||||||
gridPos = label.pos;
|
gridPos = label.pos;
|
||||||
if(mOrientation == wxHORIZONTAL) {
|
if(mOrientation == wxHORIZONTAL) {
|
||||||
if((gridPos != 0) && (gridPos != gridLineLength))
|
if((gridPos != 0) && (gridPos != gridLineLength))
|
||||||
@@ -1553,25 +1561,28 @@ int Ruler::FindZero( const Labels &labels ) const
|
|||||||
|
|
||||||
int Ruler::GetZeroPosition() const
|
int Ruler::GetZeroPosition() const
|
||||||
{
|
{
|
||||||
|
wxASSERT( mpCache );
|
||||||
|
auto &cache = *mpCache;
|
||||||
int zero;
|
int zero;
|
||||||
if( (zero = FindZero( mMajorLabels ) ) < 0)
|
if( (zero = FindZero( cache.mMajorLabels ) ) < 0)
|
||||||
zero = FindZero( mMinorLabels );
|
zero = FindZero( cache.mMinorLabels );
|
||||||
// PRL: don't consult minor minor??
|
// PRL: don't consult minor minor??
|
||||||
return zero;
|
return zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ruler::GetMaxSize(wxCoord *width, wxCoord *height)
|
void Ruler::GetMaxSize(wxCoord *width, wxCoord *height)
|
||||||
{
|
{
|
||||||
if (!mValid) {
|
if ( !mpCache ) {
|
||||||
wxScreenDC sdc;
|
wxScreenDC sdc;
|
||||||
Update( sdc, nullptr );
|
UpdateCache( sdc, nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &cache = *mpCache;
|
||||||
if (width)
|
if (width)
|
||||||
*width = mRect.GetWidth();
|
*width = cache.mRect.GetWidth();
|
||||||
|
|
||||||
if (height)
|
if (height)
|
||||||
*height = mRect.GetHeight();
|
*height = cache.mRect.GetHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1583,9 +1594,17 @@ void Ruler::SetCustomMode(bool value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// These two unused functions need reconsideration of their interactions with
|
||||||
|
// the cache and update
|
||||||
void Ruler::SetCustomMajorLabels(
|
void Ruler::SetCustomMajorLabels(
|
||||||
const TranslatableStrings &labels, int start, int step)
|
const TranslatableStrings &labels, int start, int step)
|
||||||
{
|
{
|
||||||
|
SetCustomMode( true );
|
||||||
|
mpCache = std::make_unique<Cache>();
|
||||||
|
auto &cache = *mpCache;
|
||||||
|
auto &mMajorLabels = cache.mMajorLabels;
|
||||||
|
|
||||||
const auto numLabel = labels.size();
|
const auto numLabel = labels.size();
|
||||||
mMajorLabels.resize( numLabel );
|
mMajorLabels.resize( numLabel );
|
||||||
|
|
||||||
@@ -1593,12 +1612,16 @@ void Ruler::SetCustomMajorLabels(
|
|||||||
mMajorLabels[i].text = labels[i];
|
mMajorLabels[i].text = labels[i];
|
||||||
mMajorLabels[i].pos = start + i*step;
|
mMajorLabels[i].pos = start + i*step;
|
||||||
}
|
}
|
||||||
//Remember: DELETE majorlabels....
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ruler::SetCustomMinorLabels(
|
void Ruler::SetCustomMinorLabels(
|
||||||
const TranslatableStrings &labels, int start, int step)
|
const TranslatableStrings &labels, int start, int step)
|
||||||
{
|
{
|
||||||
|
SetCustomMode( true );
|
||||||
|
mpCache = std::make_unique<Cache>();
|
||||||
|
auto &cache = *mpCache;
|
||||||
|
auto &mMinorLabels = cache.mMinorLabels;
|
||||||
|
|
||||||
const auto numLabel = labels.size();
|
const auto numLabel = labels.size();
|
||||||
mMinorLabels.resize( numLabel );
|
mMinorLabels.resize( numLabel );
|
||||||
|
|
||||||
@@ -1606,8 +1629,8 @@ void Ruler::SetCustomMinorLabels(
|
|||||||
mMinorLabels[i].text = labels[i];
|
mMinorLabels[i].text = labels[i];
|
||||||
mMinorLabels[i].pos = start + i*step;
|
mMinorLabels[i].pos = start + i*step;
|
||||||
}
|
}
|
||||||
//Remember: DELETE majorlabels....
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Ruler::Label::Draw(wxDC&dc, bool twoTone, wxColour c) const
|
void Ruler::Label::Draw(wxDC&dc, bool twoTone, wxColour c) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -138,12 +138,12 @@ class AUDACITY_DLL_API Ruler {
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Note that it will not erase for you...
|
// Note that it will not erase for you...
|
||||||
void Draw(wxDC& dc);
|
void Draw(wxDC& dc) const;
|
||||||
void Draw(wxDC& dc, const Envelope* envelope);
|
void Draw(wxDC& dc, const Envelope* envelope) const;
|
||||||
// If length <> 0, draws lines perpendiculars to ruler corresponding
|
// If length <> 0, draws lines perpendiculars to ruler corresponding
|
||||||
// to selected ticks (major, minor, or both), in an adjacent window.
|
// to selected ticks (major, minor, or both), in an adjacent window.
|
||||||
// You may need to use the offsets if you are using part of the dc for rulers, borders etc.
|
// You may need to use the offsets if you are using part of the dc for rulers, borders etc.
|
||||||
void DrawGrid(wxDC& dc, int length, bool minor = true, bool major = true, int xOffset = 0, int yOffset = 0);
|
void DrawGrid(wxDC& dc, int length, bool minor = true, bool major = true, int xOffset = 0, int yOffset = 0) const;
|
||||||
|
|
||||||
// So we can have white ticks on black...
|
// So we can have white ticks on black...
|
||||||
void SetTickColour( const wxColour & colour)
|
void SetTickColour( const wxColour & colour)
|
||||||
@@ -169,14 +169,14 @@ class AUDACITY_DLL_API Ruler {
|
|||||||
using Bits = std::vector< bool >;
|
using Bits = std::vector< bool >;
|
||||||
|
|
||||||
void ChooseFonts( wxDC &dc ) const;
|
void ChooseFonts( wxDC &dc ) const;
|
||||||
void Update( wxDC &dc, const Envelope* envelope );
|
|
||||||
|
void UpdateCache( wxDC &dc, const Envelope* envelope ) const;
|
||||||
|
|
||||||
struct Updater;
|
struct Updater;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool mbTicksOnly; // true => no line the length of the ruler
|
bool mbTicksOnly; // true => no line the length of the ruler
|
||||||
bool mbTicksAtExtremes;
|
bool mbTicksAtExtremes;
|
||||||
wxRect mRect;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxColour mTickColour;
|
wxColour mTickColour;
|
||||||
@@ -192,9 +192,6 @@ private:
|
|||||||
double mHiddenMin, mHiddenMax;
|
double mHiddenMin, mHiddenMax;
|
||||||
|
|
||||||
Bits mUserBits;
|
Bits mUserBits;
|
||||||
Bits mBits;
|
|
||||||
|
|
||||||
bool mValid;
|
|
||||||
|
|
||||||
static std::pair< wxRect, Label > MakeTick(
|
static std::pair< wxRect, Label > MakeTick(
|
||||||
Label lab,
|
Label lab,
|
||||||
@@ -203,17 +200,14 @@ private:
|
|||||||
int left, int top, int spacing, int lead,
|
int left, int top, int spacing, int lead,
|
||||||
bool flip, int orientation );
|
bool flip, int orientation );
|
||||||
|
|
||||||
Labels mMajorLabels;
|
struct Cache;
|
||||||
Labels mMinorLabels;
|
mutable std::unique_ptr<Cache> mpCache;
|
||||||
Labels mMinorMinorLabels;
|
|
||||||
|
|
||||||
// Returns 'zero' label coordinate (for grid drawing)
|
// Returns 'zero' label coordinate (for grid drawing)
|
||||||
int FindZero( const Labels &labels ) const;
|
int FindZero( const Labels &labels ) const;
|
||||||
|
|
||||||
public:
|
|
||||||
int GetZeroPosition() const;
|
int GetZeroPosition() const;
|
||||||
|
|
||||||
private:
|
|
||||||
int mOrientation;
|
int mOrientation;
|
||||||
int mSpacing;
|
int mSpacing;
|
||||||
double mDbMirrorValue;
|
double mDbMirrorValue;
|
||||||
|
|||||||
Reference in New Issue
Block a user