1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 Ruler.h 6 7 Dominic Mazzoni 8 9 **********************************************************************/ 10 11 #ifndef __AUDACITY_RULER__ 12 #define __AUDACITY_RULER__ 13 14 #include "wxPanelWrapper.h" // to inherit 15 #include "NumberScale.h" // member variable 16 17 #include <wx/colour.h> // member variable 18 #include <wx/pen.h> // member variable 19 20 class wxDC; 21 class wxFont; 22 23 class Envelope; 24 class ZoomInfo; 25 26 class AUDACITY_DLL_API Ruler { 27 public: 28 29 enum RulerFormat { 30 IntFormat, 31 RealFormat, 32 RealLogFormat, 33 TimeFormat, 34 LinearDBFormat, 35 }; 36 37 // 38 // Constructor / Destructor 39 // 40 41 Ruler(); 42 ~Ruler(); 43 44 // 45 // Required Ruler Parameters 46 // 47 48 void SetBounds(int left, int top, int right, int bottom); 49 50 // wxHORIZONTAL || wxVERTICAL 51 void SetOrientation(int orient); 52 53 // min is the value at (x, y) 54 // max is the value at (x+width, y+height) 55 // (at the center of the pixel, in both cases) 56 void SetRange(double min, double max); 57 58 // An overload needed for the special case of fisheye 59 // min is the value at (x, y) 60 // max is the value at (x+width, y+height) 61 // hiddenMin, hiddenMax are the values that would be shown without the fisheye. 62 // (at the center of the pixel, in both cases) 63 void SetRange(double min, double max, double hiddenMin, double hiddenMax); 64 65 // 66 // Optional Ruler Parameters 67 // 68 69 // If twoTone is true, cause zero and positive numbers to appear black, negative in another color. 70 void SetTwoTone(bool twoTone); 71 72 // IntFormat, RealFormat, or TimeFormat 73 void SetFormat(RulerFormat format); 74 75 // Specify the name of the units (like "dB") if you 76 // want numbers like "1.6" formatted as "1.6 dB". 77 void SetUnits(const TranslatableString &units); 78 void SetDbMirrorValue( const double d ); 79 80 // Logarithmic 81 void SetLog(bool log); 82 83 // Minimum number of pixels between labels 84 void SetSpacing(int spacing); 85 86 // If this is true, the edges of the ruler will always 87 // receive a label. If not, the nearest round number is 88 // labeled (which may or may not be the edge). 89 void SetLabelEdges(bool labelEdges); 90 91 // Makes a vertical ruler hug the left side (instead of right) 92 // and a horizontal ruler hug the top (instead of bottom) 93 void SetFlip(bool flip); 94 95 // Set it to false if you don't want minor labels. 96 void SetMinor(bool value); 97 98 // Good defaults are provided, but you can override here 99 void SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxFont &minorMinorFont); 100 struct Fonts { 101 wxFont major, minor, minorMinor; 102 int lead; 103 }; 104 Fonts GetFonts() const; 105 106 void SetNumberScale(const NumberScale &scale); 107 108 // The ruler will not draw text within this (pixel) range. 109 // Use this if you have another graphic object obscuring part 110 // of the ruler's area. The values start and end are interpreted 111 // relative to the Ruler's local coordinates. 112 void OfflimitsPixels(int start, int end); 113 114 // 115 // Calculates and returns the maximum size required by the ruler 116 // 117 void GetMaxSize(wxCoord *width, wxCoord *height); 118 119 120 // The following functions should allow a custom ruler setup: 121 // autosize is a GREAT thing, but for some applications it's 122 // useful the definition of a label array and label step by 123 // the user. 124 void SetCustomMode(bool value); 125 // If this is the case, you should provide an array of labels, start 126 // label position, and labels step. The range eventually specified will be 127 // ignored. 128 void SetCustomMajorLabels( 129 const TranslatableStrings &labels, int start, int step); 130 void SetCustomMinorLabels( 131 const TranslatableStrings &labels, int start, int step); 132 133 void SetUseZoomInfo(int leftOffset, const ZoomInfo *zoomInfo); 134 135 // 136 // Drawing 137 // 138 139 // Note that it will not erase for you... 140 void Draw(wxDC& dc) const; 141 void Draw(wxDC& dc, const Envelope* envelope) const; 142 // If length <> 0, draws lines perpendiculars to ruler corresponding 143 // to selected ticks (major, minor, or both), in an adjacent window. 144 // You may need to use the offsets if you are using part of the dc for rulers, borders etc. 145 void DrawGrid(wxDC& dc, int length, bool minor = true, bool major = true, int xOffset = 0, int yOffset = 0) const; 146 147 // So we can have white ticks on black... SetTickColour(const wxColour & colour)148 void SetTickColour( const wxColour & colour) 149 { mTickColour = colour; mPen.SetColour( colour );} 150 151 // Force regeneration of labels at next draw time 152 void Invalidate(); 153 154 private: 155 struct TickSizes; 156 157 class Label { 158 public: 159 double value; 160 int pos; 161 int lx, ly; 162 TranslatableString text; 163 164 void Draw(wxDC &dc, bool twoTone, wxColour c) const; 165 }; 166 using Labels = std::vector<Label>; 167 168 using Bits = std::vector< bool >; 169 170 void ChooseFonts( wxDC &dc ) const; 171 172 void UpdateCache( wxDC &dc, const Envelope* envelope ) const; 173 174 struct Updater; 175 176 public: 177 bool mbTicksOnly; // true => no line the length of the ruler 178 bool mbTicksAtExtremes; 179 180 private: 181 wxColour mTickColour; 182 wxPen mPen; 183 184 int mLeft, mTop, mRight, mBottom; 185 int mLength; 186 187 std::unique_ptr<Fonts> mpUserFonts; 188 mutable std::unique_ptr<Fonts> mpFonts; 189 190 double mMin, mMax; 191 double mHiddenMin, mHiddenMax; 192 193 Bits mUserBits; 194 195 static std::pair< wxRect, Label > MakeTick( 196 Label lab, 197 wxDC &dc, wxFont font, 198 std::vector<bool> &bits, 199 int left, int top, int spacing, int lead, 200 bool flip, int orientation ); 201 202 struct Cache; 203 mutable std::unique_ptr<Cache> mpCache; 204 205 // Returns 'zero' label coordinate (for grid drawing) 206 int FindZero( const Labels &labels ) const; 207 208 int GetZeroPosition() const; 209 210 int mOrientation; 211 int mSpacing; 212 double mDbMirrorValue; 213 bool mHasSetSpacing; 214 bool mLabelEdges; 215 RulerFormat mFormat; 216 bool mLog; 217 bool mFlip; 218 bool mCustom; 219 bool mbMinor; 220 TranslatableString mUnits; 221 bool mTwoTone; 222 const ZoomInfo *mUseZoomInfo; 223 int mLeftOffset; 224 225 NumberScale mNumberScale; 226 }; 227 228 class AUDACITY_DLL_API RulerPanel final : public wxPanelWrapper { 229 DECLARE_DYNAMIC_CLASS(RulerPanel) 230 231 public: 232 using Range = std::pair<double, double>; 233 234 struct Options { 235 bool log { false }; 236 bool flip { false }; 237 bool labelEdges { false }; 238 bool ticksAtExtremes { false }; 239 bool hasTickColour{ false }; 240 wxColour tickColour; 241 OptionsOptions242 Options() {} 243 LogOptions244 Options &Log( bool l ) 245 { log = l; return *this; } 246 FlipOptions247 Options &Flip( bool f ) 248 { flip = f; return *this; } 249 LabelEdgesOptions250 Options &LabelEdges( bool l ) 251 { labelEdges = l; return *this; } 252 TicksAtExtremesOptions253 Options &TicksAtExtremes( bool t ) 254 { ticksAtExtremes = t; return *this; } 255 TickColourOptions256 Options &TickColour( const wxColour c ) 257 { tickColour = c; hasTickColour = true; return *this; } 258 }; 259 260 RulerPanel(wxWindow* parent, wxWindowID id, 261 wxOrientation orientation, 262 const wxSize &bounds, 263 const Range &range, 264 Ruler::RulerFormat format, 265 const TranslatableString &units, 266 const Options &options = {}, 267 const wxPoint& pos = wxDefaultPosition, 268 const wxSize& size = wxDefaultSize); 269 270 ~RulerPanel(); 271 272 void DoSetSize(int x, int y, 273 int width, int height, 274 int sizeFlags = wxSIZE_AUTO) override; 275 276 void OnErase(wxEraseEvent &evt); 277 void OnPaint(wxPaintEvent &evt); 278 void OnSize(wxSizeEvent &evt); SetTickColour(wxColour & c)279 void SetTickColour( wxColour & c){ ruler.SetTickColour( c );} 280 281 // We don't need or want to accept focus. AcceptsFocus()282 bool AcceptsFocus() const override { return false; } 283 // So that wxPanel is not included in Tab traversal - see wxWidgets bug 15581 AcceptsFocusFromKeyboard()284 bool AcceptsFocusFromKeyboard() const override { return false; } 285 286 public: 287 288 Ruler ruler; 289 290 private: 291 DECLARE_EVENT_TABLE() 292 }; 293 294 #endif //define __AUDACITY_RULER__ 295