diff --git a/src/Project.h b/src/Project.h index 3121f63fa..8793bde25 100644 --- a/src/Project.h +++ b/src/Project.h @@ -156,6 +156,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, bool ZoomOutAvailable() const { return mViewInfo.ZoomOutAvailable(); } double GetSel0() { return mViewInfo.selectedRegion.t0(); } double GetSel1() { return mViewInfo.selectedRegion.t1(); } + const ZoomInfo &GetZoomInfo() const { return mViewInfo; } Track *GetFirstVisible(); void UpdateFirstVisible(); diff --git a/src/TimeTrack.cpp b/src/TimeTrack.cpp index 5bf349ffc..ea121cf4a 100644 --- a/src/TimeTrack.cpp +++ b/src/TimeTrack.cpp @@ -53,7 +53,8 @@ TimeTrack::TimeTrack(DirManager *projDirManager): SetDefaultName(_("Time Track")); SetName(GetDefaultName()); - mRuler = new Ruler(); + mRuler = new Ruler; + mRuler->SetUseZoomInfo(0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); @@ -77,7 +78,8 @@ TimeTrack::TimeTrack(TimeTrack &orig): mEnvelope->Paste(0.0, orig.mEnvelope); ///@TODO: Give Ruler:: a copy-constructor instead of this? - mRuler = new Ruler(); + mRuler = new Ruler; + mRuler->SetUseZoomInfo(0); mRuler->SetLabelEdges(false); mRuler->SetFormat(Ruler::TimeFormat); diff --git a/src/widgets/Ruler.cpp b/src/widgets/Ruler.cpp index 7b6ac4c4b..49ce486f3 100644 --- a/src/widgets/Ruler.cpp +++ b/src/widgets/Ruler.cpp @@ -79,6 +79,7 @@ array of Ruler::Label. #include "../Prefs.h" #include "../Snap.h" +using std::min; using std::max; #define SELECT_TOLERANCE_PIXEL 4 @@ -157,6 +158,8 @@ Ruler::Ruler() mMinorGrid = false; mTwoTone = false; + + mUseZoomInfo = false; } Ruler::~Ruler() @@ -947,6 +950,10 @@ void Ruler::Update() 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 // (i.e. we've been invalidated). Recompute all // 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) if (mMin * mMax < 0.0) { - int mid = (int)(mLength*(mMin/(mMin-mMax)) + 0.5); - Tick(mid, 0.0, true, false); + int mid; + 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; @@ -1083,8 +1096,18 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo // Major and minor ticks for (int jj = 0; jj < 2; ++jj) { const double denom = jj == 0 ? mMajor : mMinor; - double d, warpedD; - d = mMin - UPP / 2; + i = -1; j = 0; + 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) warpedD = timetrack->ComputeWarpedLength(0.0, d); else @@ -1092,14 +1115,22 @@ void Ruler::Update(TimeTrack* timetrack)// Envelope *speedEnv, long minSpeed, lo // using ints doesn't work, as // this will overflow and be negative at high zoom. double step = floor(sg * warpedD / denom); - i = -1; while (i <= mLength) { i++; - if (timetrack) - warpedD += timetrack->ComputeWarpedLength(d, d + UPP); + if (zoomInfo) + { + prevTime = time; + time = zoomInfo->PositionToTime(++j); + nextD = (prevTime + time) / 2.0; + // wxASSERT(time >= prevTime); + } else - warpedD += UPP; - d += UPP; + nextD = d + UPP; + if (timetrack) + warpedD += timetrack->ComputeWarpedLength(d, nextD); + else + warpedD = nextD; + d = nextD; if (floor(sg * warpedD / denom) > step) { 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(mLength, mMax, true, false); } - } else { // 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 // @@ -1620,8 +1656,8 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent, SetName(GetLabel()); mLeftOffset = 0; - mCurPos = -1; - mIndPos = -1; + mCurTime = -1; + mIndTime = -1; mIndType = -1; mQuickPlayInd = false; mPlayRegionStart = -1; @@ -1644,6 +1680,7 @@ AdornedRulerPanel::AdornedRulerPanel(wxWindow* parent, mInner.width -= 2; // -2 for left and right bevels mInner.height -= 3; // -3 for top and bottom bevels and bottom line + ruler.SetUseZoomInfo(mLeftOffset); ruler.SetBounds( mInner.GetLeft(), mInner.GetTop(), mInner.GetRight(), @@ -1698,6 +1735,11 @@ void AdornedRulerPanel::UpdatePrefs() RegenerateTooltips(); } +void AdornedRulerPanel::InvalidateRuler() +{ + ruler.Invalidate(); +} + void AdornedRulerPanel::RegenerateTooltips() { #if wxUSE_TOOLTIPS @@ -2317,8 +2359,8 @@ void AdornedRulerPanel::DoDrawBorder(wxDC * dc) void AdornedRulerPanel::DoDrawMarks(wxDC * dc, bool /*text */ ) { - double min = mViewInfo->h - mLeftOffset / mViewInfo->zoom; - double max = min + mInner.width / mViewInfo->zoom; + const double min = Pos2Time(0); + const double max = Pos2Time(mInner.width); ruler.SetTickColour( theTheme.Colour( clrTrackPanelText ) ); ruler.SetRange( min, max ); @@ -2333,20 +2375,8 @@ void AdornedRulerPanel::DrawSelection() void AdornedRulerPanel::DoDrawSelection(wxDC * dc) { // Draw selection - double zoom = mViewInfo->zoom; - double sel0 = - 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 ); + const int p0 = 1 + max(0, Time2Pos(mViewInfo->selectedRegion.t0())); + const int p1 = 2 + min(mInner.width, Time2Pos(mViewInfo->selectedRegion.t1())); dc->SetBrush( wxBrush( theTheme.Colour( clrRulerBackground )) ); dc->SetPen( wxPen( theTheme.Colour( clrRulerBackground )) ); @@ -2359,16 +2389,22 @@ void AdornedRulerPanel::DoDrawSelection(wxDC * dc) 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); } void AdornedRulerPanel::DoDrawCursor(wxDC * dc) { - int x = mLeftOffset + int ( ( mCurPos - mViewInfo->h ) * mViewInfo->zoom ); + const int x = Time2Pos(mCurTime); // Draw cursor in ruler dc->DrawLine( x, 1, x, mInner.height ); @@ -2385,11 +2421,11 @@ void AdornedRulerPanel::ClearIndicator() 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(); return; @@ -2408,7 +2444,7 @@ void AdornedRulerPanel::DoDrawIndicator(wxDC * dc) } int indsize = 6; - int x = mLeftOffset + int ( ( mIndPos - mViewInfo->h ) * mViewInfo->zoom ); + const int x = Time2Pos(mIndTime); wxPoint tri[ 3 ]; tri[ 0 ].x = x - indsize; @@ -2435,7 +2471,7 @@ void AdornedRulerPanel::DrawQuickPlayIndicator(wxDC * dc, bool clear) } int indsize = 4; - int x = mLeftOffset + int((mQuickPlayPos - mViewInfo->h) * mViewInfo->zoom); + int x = Time2Pos(mQuickPlayPos); wxPoint tri[3]; tri[0].x = -indsize; diff --git a/src/widgets/Ruler.h b/src/widgets/Ruler.h index 0e14cba94..5d52cda2b 100644 --- a/src/widgets/Ruler.h +++ b/src/widgets/Ruler.h @@ -114,6 +114,8 @@ class AUDACITY_DLL_API Ruler { void SetCustomMajorLabels(wxArrayString *label, int numLabel, int start, int step); void SetCustomMinorLabels(wxArrayString *label, int numLabel, int start, int step); + void SetUseZoomInfo(int leftOffset); + // // Drawing // @@ -130,8 +132,10 @@ class AUDACITY_DLL_API Ruler { void SetTickColour( const wxColour & colour) { mTickColour = colour; mPen.SetColour( colour );} - private: + // Force regeneration of labels at next draw time void Invalidate(); + + private: void Update(); void Update(TimeTrack* timetrack); void FindTickSizes(); @@ -213,6 +217,8 @@ private: int mGridLineLength; // end wxString mUnits; bool mTwoTone; + bool mUseZoomInfo; + int mLeftOffset; }; class AUDACITY_DLL_API RulerPanel : public wxPanel { @@ -262,10 +268,10 @@ public: public: static int GetRulerHeight() { return 28; } - void SetLeftOffset(int offset){ mLeftOffset = offset; } + void SetLeftOffset(int offset); - void DrawCursor(double pos); - void DrawIndicator(double pos, bool rec); + void DrawCursor(double time); + void DrawIndicator(double time, bool rec); void DrawSelection(); void ClearIndicator(); @@ -273,9 +279,11 @@ public: void ClearPlayRegion(); 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 InvalidateRuler(); + void UpdatePrefs(); void RegenerateTooltips(); @@ -313,10 +321,11 @@ private: 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; double mQuickPlayPos; SnapManager *mSnapManager;