1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-26 09:28:07 +02:00

Ruler-drawing does not assume uniform zoom, ...

... and AdornedRulerPanel exposes an invalidation function for later use
This commit is contained in:
Paul Licameli 2015-06-09 16:11:02 -04:00
parent 8664c877ba
commit 6b9e7506dd
4 changed files with 94 additions and 46 deletions

View File

@ -156,6 +156,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
bool ZoomOutAvailable() const { return mViewInfo.ZoomOutAvailable(); } bool ZoomOutAvailable() const { return mViewInfo.ZoomOutAvailable(); }
double GetSel0() { return mViewInfo.selectedRegion.t0(); } double GetSel0() { return mViewInfo.selectedRegion.t0(); }
double GetSel1() { return mViewInfo.selectedRegion.t1(); } double GetSel1() { return mViewInfo.selectedRegion.t1(); }
const ZoomInfo &GetZoomInfo() const { return mViewInfo; }
Track *GetFirstVisible(); Track *GetFirstVisible();
void UpdateFirstVisible(); void UpdateFirstVisible();

View File

@ -53,7 +53,8 @@ TimeTrack::TimeTrack(DirManager *projDirManager):
SetDefaultName(_("Time Track")); SetDefaultName(_("Time Track"));
SetName(GetDefaultName()); SetName(GetDefaultName());
mRuler = new Ruler(); mRuler = new Ruler;
mRuler->SetUseZoomInfo(0);
mRuler->SetLabelEdges(false); mRuler->SetLabelEdges(false);
mRuler->SetFormat(Ruler::TimeFormat); mRuler->SetFormat(Ruler::TimeFormat);
@ -77,7 +78,8 @@ TimeTrack::TimeTrack(TimeTrack &orig):
mEnvelope->Paste(0.0, orig.mEnvelope); mEnvelope->Paste(0.0, orig.mEnvelope);
///@TODO: Give Ruler:: a copy-constructor instead of this? ///@TODO: Give Ruler:: a copy-constructor instead of this?
mRuler = new Ruler(); mRuler = new Ruler;
mRuler->SetUseZoomInfo(0);
mRuler->SetLabelEdges(false); mRuler->SetLabelEdges(false);
mRuler->SetFormat(Ruler::TimeFormat); mRuler->SetFormat(Ruler::TimeFormat);

View File

@ -79,6 +79,7 @@ array of Ruler::Label.
#include "../Prefs.h" #include "../Prefs.h"
#include "../Snap.h" #include "../Snap.h"
using std::min;
using std::max; using std::max;
#define SELECT_TOLERANCE_PIXEL 4 #define SELECT_TOLERANCE_PIXEL 4
@ -157,6 +158,8 @@ Ruler::Ruler()
mMinorGrid = false; mMinorGrid = false;
mTwoTone = false; mTwoTone = false;
mUseZoomInfo = false;
} }
Ruler::~Ruler() Ruler::~Ruler()
@ -947,6 +950,10 @@ void Ruler::Update()
void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, long maxSpeed ) void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, long maxSpeed )
{ {
const ZoomInfo *zoomInfo = NULL;
if (mUseZoomInfo && !mLog && mOrientation == wxHORIZONTAL)
zoomInfo = &GetActiveProject()->GetZoomInfo();
// This gets called when something has been changed // This gets called when something has been changed
// (i.e. we've been invalidated). Recompute all // (i.e. we've been invalidated). Recompute all
// tick positions and font size. // tick positions and font size.
@ -1074,8 +1081,14 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
// Zero (if it's in the middle somewhere) // Zero (if it's in the middle somewhere)
if (mMin * mMax < 0.0) { if (mMin * mMax < 0.0) {
int mid = (int)(mLength*(mMin/(mMin-mMax)) + 0.5); int mid;
Tick(mid, 0.0, true, false); if (zoomInfo != NULL)
mid = int(zoomInfo->TimeToPosition(0.0, mLeftOffset));
else
mid = (int)(mLength*(mMin / (mMin - mMax)) + 0.5);
const int iMaxPos = (mOrientation == wxHORIZONTAL) ? mRight : mBottom - 5;
if (mid >= 0 && mid < iMaxPos)
Tick(mid, 0.0, true, false);
} }
double sg = UPP > 0.0? 1.0: -1.0; double sg = UPP > 0.0? 1.0: -1.0;
@ -1083,8 +1096,18 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
// Major and minor ticks // Major and minor ticks
for (int jj = 0; jj < 2; ++jj) { for (int jj = 0; jj < 2; ++jj) {
const double denom = jj == 0 ? mMajor : mMinor; const double denom = jj == 0 ? mMajor : mMinor;
double d, warpedD; i = -1; j = 0;
d = mMin - UPP / 2; double d, warpedD, nextD;
double prevTime = 0.0, time = 0.0;
if (zoomInfo != NULL) {
j = zoomInfo->TimeToPosition(mMin);
prevTime = zoomInfo->PositionToTime(--j);
time = zoomInfo->PositionToTime(++j);
d = (prevTime + time) / 2.0;
}
else
d = mMin - UPP / 2;
if (timetrack) if (timetrack)
warpedD = timetrack->ComputeWarpedLength(0.0, d); warpedD = timetrack->ComputeWarpedLength(0.0, d);
else else
@ -1092,14 +1115,22 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
// using ints doesn't work, as // using ints doesn't work, as
// this will overflow and be negative at high zoom. // this will overflow and be negative at high zoom.
double step = floor(sg * warpedD / denom); double step = floor(sg * warpedD / denom);
i = -1;
while (i <= mLength) { while (i <= mLength) {
i++; i++;
if (timetrack) if (zoomInfo)
warpedD += timetrack->ComputeWarpedLength(d, d + UPP); {
prevTime = time;
time = zoomInfo->PositionToTime(++j);
nextD = (prevTime + time) / 2.0;
// wxASSERT(time >= prevTime);
}
else else
warpedD += UPP; nextD = d + UPP;
d += UPP; if (timetrack)
warpedD += timetrack->ComputeWarpedLength(d, nextD);
else
warpedD = nextD;
d = nextD;
if (floor(sg * warpedD / denom) > step) { if (floor(sg * warpedD / denom) > step) {
step = floor(sg * warpedD / denom); step = floor(sg * warpedD / denom);
@ -1114,7 +1145,6 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo
Tick(0, mMin, true, false); Tick(0, mMin, true, false);
Tick(mLength, mMax, true, false); Tick(mLength, mMax, true, false);
} }
} }
else { else {
// log case // log case
@ -1517,6 +1547,12 @@ void Ruler::Label::Draw(wxDC&dc, bool twoTone) const
} }
} }
void Ruler::SetUseZoomInfo(int leftOffset)
{
mLeftOffset = leftOffset;
mUseZoomInfo = true;
}
// //
// RulerPanel // RulerPanel
// //
@ -1620,8 +1656,8 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent,
SetName(GetLabel()); SetName(GetLabel());
mLeftOffset = 0; mLeftOffset = 0;
mCurPos = -1; mCurTime = -1;
mIndPos = -1; mIndTime = -1;
mIndType = -1; mIndType = -1;
mQuickPlayInd = false; mQuickPlayInd = false;
mPlayRegionStart = -1; mPlayRegionStart = -1;
@ -1644,6 +1680,7 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent,
mInner.width -= 2; // -2 for left and right bevels mInner.width -= 2; // -2 for left and right bevels
mInner.height -= 3; // -3 for top and bottom bevels and bottom line mInner.height -= 3; // -3 for top and bottom bevels and bottom line
ruler.SetUseZoomInfo(mLeftOffset);
ruler.SetBounds( mInner.GetLeft(), ruler.SetBounds( mInner.GetLeft(),
mInner.GetTop(), mInner.GetTop(),
mInner.GetRight(), mInner.GetRight(),
@ -1698,6 +1735,11 @@ void AdornedRulerPanel::UpdatePrefs()
RegenerateTooltips(); RegenerateTooltips();
} }
void AdornedRulerPanel::InvalidateRuler()
{
ruler.Invalidate();
}
void AdornedRulerPanel::RegenerateTooltips() void AdornedRulerPanel::RegenerateTooltips()
{ {
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS
@ -2317,8 +2359,8 @@ void AdornedRulerPanel::DoDrawBorder(wxDC * dc)
void AdornedRulerPanel::DoDrawMarks(wxDC * dc, bool /*text */ ) void AdornedRulerPanel::DoDrawMarks(wxDC * dc, bool /*text */ )
{ {
double min = mViewInfo->h - mLeftOffset / mViewInfo->zoom; const double min = Pos2Time(0);
double max = min + mInner.width / mViewInfo->zoom; const double max = Pos2Time(mInner.width);
ruler.SetTickColour( theTheme.Colour( clrTrackPanelText ) ); ruler.SetTickColour( theTheme.Colour( clrTrackPanelText ) );
ruler.SetRange( min, max ); ruler.SetRange( min, max );
@ -2333,20 +2375,8 @@ void AdornedRulerPanel::DrawSelection()
void AdornedRulerPanel::DoDrawSelection(wxDC * dc) void AdornedRulerPanel::DoDrawSelection(wxDC * dc)
{ {
// Draw selection // Draw selection
double zoom = mViewInfo->zoom; const int p0 = 1 + max(0, Time2Pos(mViewInfo->selectedRegion.t0()));
double sel0 = const int p1 = 2 + min(mInner.width, Time2Pos(mViewInfo->selectedRegion.t1()));
mViewInfo->selectedRegion.t0() - mViewInfo->h + mLeftOffset / zoom;
double sel1 =
mViewInfo->selectedRegion.t1() - mViewInfo->h + mLeftOffset / zoom;
if( sel0 < 0.0 )
sel0 = 0.0;
if( sel1 > ( mInner.width / zoom ) )
sel1 = mInner.width / zoom;
int p0 = int ( sel0 * zoom + 1.5 );
int p1 = int ( sel1 * zoom + 2.5 );
dc->SetBrush( wxBrush( theTheme.Colour( clrRulerBackground )) ); dc->SetBrush( wxBrush( theTheme.Colour( clrRulerBackground )) );
dc->SetPen( wxPen( theTheme.Colour( clrRulerBackground )) ); dc->SetPen( wxPen( theTheme.Colour( clrRulerBackground )) );
@ -2359,16 +2389,22 @@ void AdornedRulerPanel::DoDrawSelection(wxDC * dc)
dc->DrawRectangle( r ); dc->DrawRectangle( r );
} }
void AdornedRulerPanel::DrawCursor(double pos) void AdornedRulerPanel::SetLeftOffset(int offset)
{ {
mCurPos = pos; mLeftOffset = offset;
ruler.SetUseZoomInfo(offset);
}
void AdornedRulerPanel::DrawCursor(double time)
{
mCurTime = time;
Refresh(false); Refresh(false);
} }
void AdornedRulerPanel::DoDrawCursor(wxDC * dc) void AdornedRulerPanel::DoDrawCursor(wxDC * dc)
{ {
int x = mLeftOffset + int ( ( mCurPos - mViewInfo->h ) * mViewInfo->zoom ); const int x = Time2Pos(mCurTime);
// Draw cursor in ruler // Draw cursor in ruler
dc->DrawLine( x, 1, x, mInner.height ); dc->DrawLine( x, 1, x, mInner.height );
@ -2385,11 +2421,11 @@ void AdornedRulerPanel::ClearIndicator()
Refresh(false); Refresh(false);
} }
void AdornedRulerPanel::DrawIndicator( double pos, bool rec ) void AdornedRulerPanel::DrawIndicator( double time, bool rec )
{ {
mIndPos = pos; mIndTime = time;
if( mIndPos < 0 ) if (mIndTime < 0)
{ {
ClearIndicator(); ClearIndicator();
return; return;
@ -2408,7 +2444,7 @@ void AdornedRulerPanel::DoDrawIndicator(wxDC * dc)
} }
int indsize = 6; int indsize = 6;
int x = mLeftOffset + int ( ( mIndPos - mViewInfo->h ) * mViewInfo->zoom ); const int x = Time2Pos(mIndTime);
wxPoint tri[ 3 ]; wxPoint tri[ 3 ];
tri[ 0 ].x = x - indsize; tri[ 0 ].x = x - indsize;
@ -2435,7 +2471,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc, bool clear)
} }
int indsize = 4; int indsize = 4;
int x = mLeftOffset + int((mQuickPlayPos - mViewInfo->h) * mViewInfo->zoom); int x = Time2Pos(mQuickPlayPos);
wxPoint tri[3]; wxPoint tri[3];
tri[0].x = -indsize; tri[0].x = -indsize;

View File

@ -114,6 +114,8 @@ class AUDACITY_DLL_API Ruler {
void SetCustomMajorLabels(wxArrayString *label, int numLabel, int start, int step); void SetCustomMajorLabels(wxArrayString *label, int numLabel, int start, int step);
void SetCustomMinorLabels(wxArrayString *label, int numLabel, int start, int step); void SetCustomMinorLabels(wxArrayString *label, int numLabel, int start, int step);
void SetUseZoomInfo(int leftOffset);
// //
// Drawing // Drawing
// //
@ -130,8 +132,10 @@ class AUDACITY_DLL_API Ruler {
void SetTickColour( const wxColour & colour) void SetTickColour( const wxColour & colour)
{ mTickColour = colour; mPen.SetColour( colour );} { mTickColour = colour; mPen.SetColour( colour );}
private: // Force regeneration of labels at next draw time
void Invalidate(); void Invalidate();
private:
void Update(); void Update();
void Update(TimeTrack* timetrack); void Update(TimeTrack* timetrack);
void FindTickSizes(); void FindTickSizes();
@ -213,6 +217,8 @@ private:
int mGridLineLength; // end int mGridLineLength; // end
wxString mUnits; wxString mUnits;
bool mTwoTone; bool mTwoTone;
bool mUseZoomInfo;
int mLeftOffset;
}; };
class AUDACITY_DLL_API RulerPanel : public wxPanel { class AUDACITY_DLL_API RulerPanel : public wxPanel {
@ -262,10 +268,10 @@ public:
public: public:
static int GetRulerHeight() { return 28; } static int GetRulerHeight() { return 28; }
void SetLeftOffset(int offset){ mLeftOffset = offset; } void SetLeftOffset(int offset);
void DrawCursor(double pos); void DrawCursor(double time);
void DrawIndicator(double pos, bool rec); void DrawIndicator(double time, bool rec);
void DrawSelection(); void DrawSelection();
void ClearIndicator(); void ClearIndicator();
@ -273,9 +279,11 @@ public:
void ClearPlayRegion(); void ClearPlayRegion();
void GetPlayRegion(double* playRegionStart, double* playRegionEnd); void GetPlayRegion(double* playRegionStart, double* playRegionEnd);
void SetProject(AudacityProject* project) {mProject = project;}; void SetProject(AudacityProject* project) {mProject = project;}
void GetMaxSize(wxCoord *width, wxCoord *height); void GetMaxSize(wxCoord *width, wxCoord *height);
void InvalidateRuler();
void UpdatePrefs(); void UpdatePrefs();
void RegenerateTooltips(); void RegenerateTooltips();
@ -313,10 +321,11 @@ private:
int mLeftOffset; // Number of pixels before we hit the 'zero position'. int mLeftOffset; // Number of pixels before we hit the 'zero position'.
double mCurPos; double mCurTime;
int mIndType; // -1 = No indicator, 0 = Play, 1 = Record
double mIndPos; int mIndType; // -1 = No indicator, 0 = Play, 1 = Record
double mIndTime;
bool mQuickPlayInd; bool mQuickPlayInd;
double mQuickPlayPos; double mQuickPlayPos;
SnapManager *mSnapManager; SnapManager *mSnapManager;