1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   ASlider.h
6 
7   Dominic Mazzoni
8 
9   This class is a custom slider.
10 
11 **********************************************************************/
12 
13 #ifndef __AUDACITY_SLIDER__
14 #define __AUDACITY_SLIDER__
15 
16 #include <wx/setup.h> // for wxUSE_* macros
17 #include <wx/defs.h>
18 #include <wx/timer.h> // member variable
19 #include "wxPanelWrapper.h" // to inherit
20 
21 class wxBitmap;
22 class wxSize;
23 class wxPoint;
24 class wxTextCtrl;
25 
26 class Ruler;
27 class TipWindow;
28 
29 //
30 // Predefined slider types (mStyle)
31 //
32 #define FRAC_SLIDER 1    // 0.0...1.0
33 #define DB_SLIDER 2      // -36...36 dB
34 #define PAN_SLIDER 3     // -1.0...1.0
35 #define SPEED_SLIDER 4  // 0.01 ..3.0
36 
37 #define VEL_SLIDER 5    // -50..50
38 
39 #define DB_MIN -36.0f
40 #define DB_MAX 36.0f
41 #define FRAC_MIN 0.0f
42 #define FRAC_MAX 1.0f
43 #define SPEED_MIN 0.01f
44 #define SPEED_MAX 3.0f
45 #define VEL_MIN -50.0f
46 #define VEL_MAX 50.0f
47 
48 // Customizable slider only: If stepValue is STEP_CONTINUOUS,
49 // every value on the slider between minValue and maxValue
50 // will be possible
51 //
52 #define STEP_CONTINUOUS 0.0f
53 
54 //
55 // Lightweight slider - i.e. a slider that doesn't appear in
56 // its own window, but rather draws itself inside an existing
57 // window (used inside Track Labels).  The ASlider class,
58 // which uses this class, is below.
59 //
60 
61 class AUDACITY_DLL_API LWSlider
62 {
63    friend class ASlider;
64    friend class ASliderAx;
65 
66  public:
67 
68    // MM: Construct customizable slider
69    LWSlider(wxWindow * parent,
70             const TranslatableString &name,
71             const wxPoint &pos,
72             const wxSize &size,
73             float minValue,
74             float maxValue,
75             float stepValue,
76             bool canUseShift,
77             int style,
78             bool heavyweight=false,
79             bool popup=true,
80             int orientation = wxHORIZONTAL); // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
81 
82    // Construct predefined slider
83    LWSlider(wxWindow * parent,
84             const TranslatableString &name,
85             const wxPoint &pos,
86             const wxSize &size,
87             int style,
88             bool heavyweight=false,
89             bool popup=true,
90             int orientation = wxHORIZONTAL); // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
91 
92    void Init(wxWindow * parent,
93              const TranslatableString &name,
94              const wxPoint &pos,
95              const wxSize &size,
96              float minValue,
97              float maxValue,
98              float stepValue,
99              bool canUseShift,
100              int style,
101              bool heavyweight,
102              bool popup,
103              float speed,
104              int orientation = wxHORIZONTAL); // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
105 
106    virtual ~LWSlider();
107 
108    wxWindowID GetId();
109    void SetId(wxWindowID id);
110 
111    void SetDefaultValue(float value);
112    void SetDefaultShortcut(bool value);
113 
114    void GetScroll(float & line, float & page);
115    void SetScroll(float line, float page);
116 
117    void ShowTip(bool show);
118    void SetToolTipTemplate(const TranslatableString & tip);
119 
120    float Get(bool convert = true);
121    void Set(float value);
122 
123    void Increase(float steps);
124    void Decrease(float steps);
125 
126    // If set to less than 1.0, moving the mouse one pixel will move
127    // the slider by less than 1 unit
128    void SetSpeed(float speed);
129 
130    void Move(const wxPoint &newpos);
131 
132    void AdjustSize(const wxSize & sz);
133 
134    void OnPaint(wxDC &dc, bool highlighted);
135    void OnSize(wxSizeEvent & event);
136    void OnMouseEvent(wxMouseEvent & event);
137    void OnKeyDown(wxKeyEvent & event);
138    void Refresh();
139    void Redraw();
140 
141    bool ShowDialog();
142    bool ShowDialog(wxPoint pos);
143 
144    void SetEnabled(bool enabled);
145    bool GetEnabled() const;
146 
147    float GetMinValue() const;
148    float GetMaxValue() const;
149 
SetParent(wxWindow * parent)150    void SetParent(wxWindow *parent) { mParent = parent; }
151    void SendUpdate(float newValue);
152 
153  private:
154 
155    TranslatableString GetTip(float value) const;
156    TranslatableStrings GetWidestTips() const;
157    void FormatPopWin();
158    void SetPopWinPosition();
159    void CreatePopWin();
160    void DrawToBitmap(wxDC & dc);
161 
162    bool DoShowDialog(wxPoint pos);
163 
164 
165    int ValueToPosition(float val);
166    float DragPositionToValue(int fromPos, bool shiftDown);
167    float ClickPositionToValue(int fromPos, bool shiftDown);
168 
169    wxWindow *mParent;
170 
171    int mStyle;
172    int mOrientation; // wxHORIZONTAL or wxVERTICAL. wxVERTICAL is currently only for DB_SLIDER.
173 
174    bool mHW; // is it really heavyweight (in a window)
175    bool mPopup; // should display dialog on double click
176 
177    int mLeft;
178    int mTop;
179 
180    int mWidth;                  //In pixels
181    int mHeight;                 //In pixels
182 
183    // for (mOrientation == wxHORIZONTAL)
184    int mCenterY;
185 
186    int mLeftX;
187    int mRightX;
188    int mWidthX;
189 
190    // for (mOrientation == wxVERTICAL) //v Vertical PAN_SLIDER currently not handled, forced to horizontal.
191    int mCenterX;
192 
193    int mTopY;
194    int mBottomY; // low values at bottom
195    int mHeightY;
196 
197 
198    int mThumbWidth;             //In pixels
199    int mThumbHeight;            //In pixels
200 
201    float mClickValue;
202    int mClickPos; // position in x if (mOrientation == wxHORIZONTAL), else in y
203 
204    float mMinValue;
205    float mMaxValue;
206    float mStepValue;
207    float mSpeed;
208 
209    float mScrollLine;
210    float mScrollPage;
211 
212    float mCurrentValue;
213 
214    bool mDefaultShortcut;
215    float mDefaultValue;
216 
217    bool mCanUseShift;
218 
219    wxWindowID mID;
220 
221    std::unique_ptr<TipWindow> mTipPanel;
222    TranslatableString mTipTemplate;
223 
224    bool mIsDragging;
225 
226    std::unique_ptr<wxBitmap> mBitmap, mThumbBitmap, mThumbBitmapHilited;
227 
228    TranslatableString mName;
229 
230    bool mEnabled;
231 };
232 
233 class AUDACITY_DLL_API ASlider /* not final */ : public wxPanel
234 {
235    friend class ASliderAx;
236 
237  public:
238    struct Options {
OptionsOptions239       Options() {}
240 
241       int style{ FRAC_SLIDER };
242       wxOrientation orientation{ wxHORIZONTAL };
243       bool popup{ true };
244       bool canUseShift{ true };
245       float stepValue{ STEP_CONTINUOUS };
246 
247       float line{ 1.0 };
248       float page{ 5.0 };
249 
StyleOptions250       Options& Style( int s ) { style = s; return *this; }
OrientationOptions251       Options& Orientation( wxOrientation o )
252          { orientation = o; return *this; }
PopupOptions253       Options& Popup( bool p ) { popup = p; return *this; }
CanUseShiftOptions254       Options& CanUseShift( bool c ) { canUseShift = c; return *this; }
StepValueOptions255       Options& StepValue( float v ) { stepValue = v; return *this; }
256 
LineOptions257       Options& Line( float l ) { line = l; return *this; }
PageOptions258       Options& Page( float p ) { page = p; return *this; }
259    };
260 
261    ASlider( wxWindow * parent,
262             wxWindowID id,
263             const TranslatableString &name,
264             const wxPoint & pos,
265             const wxSize & size,
266             const Options &options = Options{});
267    virtual ~ASlider();
268 
AcceptsFocus()269    bool AcceptsFocus() const override { return s_AcceptsFocus; }
AcceptsFocusFromKeyboard()270    bool AcceptsFocusFromKeyboard() const override { return true; }
271 
272    void SetFocusFromKbd() override;
273 
274    bool SetBackgroundColour(const wxColour& colour) override;
275 
276    void GetScroll(float & line, float & page);
277    void SetScroll(float line, float page);
278 
279    void SetToolTipTemplate(const TranslatableString & tip);
280 
281    float Get( bool convert = true );
282    void Set(float value);
283 
284    void Increase(float steps);
285    void Decrease(float steps);
286    bool ShowDialog(wxPoint pos = wxPoint(-1, -1));
287 
288    void SetSpeed(float speed);
289 
290    void OnErase(wxEraseEvent & event);
291    void OnPaint(wxPaintEvent & event);
292    void OnSize(wxSizeEvent & event);
293    void OnMouseEvent(wxMouseEvent & event);
294    void OnCaptureLost(wxMouseCaptureLostEvent & event);
295    void OnKeyDown(wxKeyEvent &event);
296    void OnSlider(wxCommandEvent &event);
297    void OnSetFocus(wxFocusEvent & event);
298    void OnKillFocus(wxFocusEvent & event);
299    void OnTimer(wxTimerEvent & event);
300 
301    // Overrides of the wxWindow functions with the same semantics
302    bool Enable(bool enable = true) override;
303    bool IsEnabled() const;
304 
305 private:
306    static bool s_AcceptsFocus;
operatorResetter307    struct Resetter { void operator () (bool *p) const { if(p) *p = false; } };
308    using TempAllowFocus = std::unique_ptr<bool, Resetter>;
309 
310 public:
311    static TempAllowFocus TemporarilyAllowFocus();
312 
313  private:
314    std::unique_ptr<LWSlider> mLWSlider;
315    bool mSliderIsFocused;
316    wxTimer mTimer;
317 
318  protected:
319    int mStyle;
320 
321  public:
322     DECLARE_EVENT_TABLE()
323 };
324 
325 
326 
327 #define SLIDER_DIALOG_TEXTCTRL 100
328 
329 
330 // This is a modal dialog that contains an ASlider
331 // and a text-entry box which can be used to set the
332 // value of a slider.
333 class SliderDialog final : public wxDialogWrapper
334 {
335  public:
336    SliderDialog(wxWindow * parent, wxWindowID id,
337                 const TranslatableString & title,
338                 wxPoint position,
339                 wxSize size,
340                 int style,
341                 float value,
342                 float line,
343                 float page,
344                 LWSlider * pSlider=nullptr);
345    ~SliderDialog();
346 
347    float Get();
348 
349  private:
350    bool TransferDataToWindow() override;
351    bool TransferDataFromWindow() override;
352 
353    void OnSlider(wxCommandEvent &event);
354    void OnTextChange(wxCommandEvent &event);
355 
356    ASlider * mSlider;
357    wxTextCtrl * mTextCtrl;
358    int mStyle;
359    LWSlider * mpOrigin;
360    float mValue;
361 
362  public:
363    DECLARE_EVENT_TABLE()
364 };
365 
366 #endif
367