📄 ruler.cpp
字号:
/********************************************************************** Audacity: A Digital Audio Editor Ruler.cpp Dominic Mazzoni This file contains the implementations of Ruler and RulerPanel. See Ruler.h for information about what these classes are for.**********************************************************************/#include <math.h>#include <wx/dcscreen.h>#include "../Internat.h"#include "Ruler.h"//// Ruler//Ruler::Ruler(){ mMin = 0.0; mMax = 100.0; mOrientation = wxHORIZONTAL; mSpacing = 6; mHasSetSpacing = false; mFormat = RealFormat; mFlip = false; mLog = false; mLabelEdges = false; mUnits = wxT(""); mLeft = -1; mTop = -1; mRight = -1; mBottom = -1; int fontSize = 10;#ifdef __WXMSW__ fontSize = 8;#endif mMinorFont = new wxFont(fontSize, wxSWISS, wxNORMAL, wxNORMAL); mMajorFont = new wxFont(fontSize, wxSWISS, wxNORMAL, wxBOLD); #ifdef __WXMAC__ mMinorFont->SetNoAntiAliasing(true); mMajorFont->SetNoAntiAliasing(true); #endif mMajorLabels = 0; mMinorLabels = 0; mBits = NULL; mUserBits = NULL; mUserBitLen = 0; mValid = false;}Ruler::~Ruler(){ Invalidate(); // frees up our arrays if( mUserBits ) delete [] mUserBits;//JKC delete mMinorFont; delete mMajorFont;}void Ruler::SetFormat(RulerFormat format){ // IntFormat, RealFormat, TimeFormat, or LinearDBFormat if (mFormat != format) { mFormat = format; Invalidate(); }}void Ruler::SetLog(bool log){ // Logarithmic if (mLog != log) { mLog = log; Invalidate(); }}void Ruler::SetUnits(wxString units){ // Specify the name of the units (like "dB") if you // want numbers like "1.6" formatted as "1.6 dB". if (mUnits != units) { mUnits = units; Invalidate(); }}void Ruler::SetOrientation(int orient){ // wxHORIZONTAL || wxVERTICAL if (mOrientation != orient) { mOrientation = orient; if (mOrientation == wxVERTICAL && !mHasSetSpacing) mSpacing = 2; Invalidate(); }}void Ruler::SetRange(double min, double max){ // For a horizontal ruler, // min is the value in the center of pixel "left", // max is the value in the center of pixel "right". if (mMin != min || mMax != max) { mMin = min; mMax = max; Invalidate(); }}void Ruler::SetSpacing(int spacing){ mHasSetSpacing = true; if (mSpacing != spacing) { mSpacing = spacing; Invalidate(); }}void Ruler::SetLabelEdges(bool labelEdges){ // If this is true, the edges of the ruler will always // receive a label. If not, the nearest round number is // labeled (which may or may not be the edge). if (mLabelEdges != labelEdges) { mLabelEdges = labelEdges; Invalidate(); }}void Ruler::SetFlip(bool flip){ // If this is true, the orientation of the tick marks // is reversed from the default; eg. above the line // instead of below if (mFlip != flip) { mFlip = flip; Invalidate(); }}void Ruler::SetFonts(const wxFont &minorFont, const wxFont &majorFont){ *mMinorFont = minorFont; *mMajorFont = majorFont; #ifdef __WXMAC__ mMinorFont->SetNoAntiAliasing(true); mMajorFont->SetNoAntiAliasing(true); #endif Invalidate();}void Ruler::OfflimitsPixels(int start, int end){ int i; if (!mUserBits) { if (mOrientation == wxHORIZONTAL) mLength = mRight-mLeft; else mLength = mBottom-mTop; mUserBits = new int[mLength+1]; for(i=0; i<=mLength; i++) mUserBits[i] = 0; mUserBitLen = mLength+1; } if (end < start) { i = end; end = start; start = i; } if (start < 0) start = 0; if (end > mLength) end = mLength; for(i=start; i<=end; i++) mUserBits[i] = 1;}void Ruler::SetBounds(int left, int top, int right, int bottom){ if (mLeft != left || mTop != top || mRight != right || mBottom != bottom) { mLeft = left; mTop = top; mRight = right; mBottom = bottom; Invalidate(); }}void Ruler::Invalidate(){ mValid = false; if (mOrientation == wxHORIZONTAL) mLength = mRight-mLeft; else mLength = mBottom-mTop; if (mMajorLabels) { delete [] mMajorLabels; mMajorLabels = NULL; } if (mMinorLabels) { delete [] mMinorLabels; mMinorLabels = NULL; } if (mBits) { delete [] mBits; mBits = NULL; } if (mUserBits && mLength+1 != mUserBitLen) { delete[] mUserBits; mUserBits = NULL; mUserBitLen = 0; }}void Ruler::FindLinearTickSizes(double UPP){ // Given the dimensions of the ruler, the range of values it // has to display, and the format (i.e. Int, Real, Time), // figure out how many units are in one Minor tick, and // in one Major tick. // // The goal is to always put tick marks on nice round numbers // that are easy for humans to grok. This is the most tricky // with time. double d; // As a heuristic, we want at least 16 pixels // between each minor tick double units = 16 * fabs(UPP); mDigits = 0; switch(mFormat) { case LinearDBFormat: if (units < 0.1) { mMinor = 0.1; mMajor = 0.5; return; } if (units < 1.0) { mMinor = 1.0; mMajor = 6.0; return; } mMinor = 3.0; mMajor = 12.0; return; case IntFormat: d = 1.0; for(;;) { if (units < d) { mMinor = d; mMajor = d*5.0; return; } d *= 5.0; if (units < d) { mMinor = d; mMajor = d*2.0; return; } d *= 2.0; } break; case TimeFormat: if (units > 0.5) { if (units < 1.0) { // 1 sec mMinor = 1.0; mMajor = 5.0; return; } if (units < 5.0) { // 5 sec mMinor = 5.0; mMajor = 15.0; return; } if (units < 10.0) { mMinor = 10.0; mMajor = 30.0; return; } if (units < 15.0) { mMinor = 15.0; mMajor = 60.0; return; } if (units < 30.0) { mMinor = 30.0; mMajor = 60.0; return; } if (units < 60.0) { // 1 min mMinor = 60.0; mMajor = 300.0; return; } if (units < 300.0) { // 5 min mMinor = 300.0; mMajor = 900.0; return; } if (units < 600.0) { // 10 min mMinor = 600.0; mMajor = 1800.0; return; } if (units < 900.0) { // 15 min mMinor = 900.0; mMajor = 3600.0; return; } if (units < 1800.0) { // 30 min mMinor = 1800.0; mMajor = 3600.0; return; } if (units < 3600.0) { // 1 hr mMinor = 3600.0; mMajor = 6*3600.0; return; } if (units < 6*3600.0) { // 6 hrs mMinor = 6*3600.0; mMajor = 24*3600.0; return; } if (units < 24*3600.0) { // 1 day mMinor = 24*3600.0; mMajor = 7*24*3600.0; return; } mMinor = 24.0 * 7.0 * 3600.0; // 1 week mMajor = 24.0 * 7.0 * 3600.0; } // Otherwise fall through to RealFormat // (fractions of a second should be dealt with // the same way as for RealFormat) case RealFormat: d = 0.000001; mDigits = 6; for(;;) { if (units < d) { mMinor = d; mMajor = d*5.0; return; } d *= 5.0; if (units < d) { mMinor = d; mMajor = d*2.0; return; } d *= 2.0; mDigits--; } break; }}wxString Ruler::LabelString(double d, bool major){ // Given a value, turn it into a string according // to the current ruler format. The number of digits of // accuracy depends on the resolution of the ruler, // i.e. how far zoomed in or out you are. wxString s; // Replace -0 with 0 if (d < 0.0 && d+mMinor > 0.0) d = 0.0; switch(mFormat) { case IntFormat: s.Printf(wxT("%d"), (int)floor(d+0.5)); break; case LinearDBFormat: if (mMinor >= 1.0) s.Printf(wxT("%d"), (int)floor(d+0.5)); else { s.Printf(wxT("%.1f"), d); } break; case RealFormat: if (mMinor >= 1.0) s.Printf(wxT("%d"), (int)floor(d+0.5)); else { s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d); } break; case TimeFormat: if (major) { if (d < 0) { s = wxT("-"); d = -d; } #if ALWAYS_HH_MM_SS int secs = (int)(d + 0.5); if (mMinor >= 1.0) { s.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60); } else { wxString t1, t2, format; t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60); format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits); t2.Printf(format.c_str(), fmod(d, 60.0)); s += t1 + t2; } break; #endif if (mMinor >= 3600.0) { int hrs = (int)(d / 3600.0 + 0.5); wxString h; h.Printf(wxT("%d:00:00"), hrs); s += h; } else if (mMinor >= 60.0) { int minutes = (int)(d / 60.0 + 0.5); wxString m; if (minutes >= 60) m.Printf(wxT("%d:%02d:00"), minutes/60, minutes%60); else m.Printf(wxT("%d:00"), minutes); s += m; } else if (mMinor >= 1.0) { int secs = (int)(d + 0.5); wxString t; if (secs >= 3600) t.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60); else if (secs >= 60) t.Printf(wxT("%d:%02d"), secs/60, secs%60); else t.Printf(wxT("%d"), secs); s += t; } else { int secs = (int)(d); wxString t1, t2, format; if (secs >= 3600) t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60); else if (secs >= 60) t1.Printf(wxT("%d:"), secs/60); if (secs >= 60) format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits); else format.Printf(wxT("%%%d.%dlf"), mDigits+3, mDigits); t2.Printf(format.c_str(), fmod(d, 60.0)); s += t1 + t2; } } else { } } if (mUnits != wxT("")) s = (s + wxT(" ") + mUnits); return s;}void Ruler::Tick(int pos, double d, bool major){ wxString l; wxCoord strW, strH; int strPos, strLen, strLeft, strTop; Label *label; if (major) label = &mMajorLabels[mNumMajor++]; else label = &mMinorLabels[mNumMinor++];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -