1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15 
16 #pragma once
17 #include "vstcontrols.h"
18 #include "SurgeBitmaps.h"
19 #include "SurgeParamConfig.h"
20 #include "SkinSupport.h"
21 #include "CursorControlGuard.h"
22 
23 class CSurgeSlider : public VSTGUI::CControl,
24                      public Surge::UI::CursorControlAdapterWithMouseDelta<CSurgeSlider>,
25                      public Surge::UI::SkinConsumingComponent
26 {
27   public:
28     CSurgeSlider(const VSTGUI::CPoint &loc, long style, VSTGUI::IControlListener *listener,
29                  long tag, bool is_mod, std::shared_ptr<SurgeBitmaps> bitmapStore,
30                  SurgeStorage *storage = nullptr);
31     ~CSurgeSlider();
32     virtual void draw(VSTGUI::CDrawContext *) override;
33     // virtual void mouse (VSTGUI::CDrawContext *pContext, VSTGUI::CPoint &where, long buttons =
34     // -1); virtual bool onWheel (VSTGUI::CDrawContext *pContext, const VSTGUI::CPoint &where, float
35     // distance);
36     virtual bool onWheel(const VSTGUI::CPoint &where, const float &distane,
37                          const VSTGUI::CButtonState &buttons) override;
38 
39     virtual VSTGUI::CMouseEventResult onMouseDown(
40         VSTGUI::CPoint &where,
41         const VSTGUI::CButtonState &buttons) override; ///< called when a mouse down event occurs
42     virtual VSTGUI::CMouseEventResult onMouseUp(
43         VSTGUI::CPoint &where,
44         const VSTGUI::CButtonState &buttons) override; ///< called when a mouse up event occurs
45 
46     virtual VSTGUI::CMouseEventResult onMouseEntered(VSTGUI::CPoint &where,
47                                                      const VSTGUI::CButtonState &buttons) override;
48 
49     virtual VSTGUI::CMouseEventResult onMouseExited(VSTGUI::CPoint &where,
50                                                     const VSTGUI::CButtonState &buttons) override;
51 
52     virtual double getMouseDeltaScaling(const VSTGUI::CPoint &where,
53                                         const VSTGUI::CButtonState &buttons);
onMouseMoved(VSTGUI::CPoint & where,const VSTGUI::CButtonState & buttons)54     virtual VSTGUI::CMouseEventResult onMouseMoved(VSTGUI::CPoint &where,
55                                                    const VSTGUI::CButtonState &buttons) override
56     {
57         return onMouseMovedCursorHelper(where, buttons);
58     }
59 
60     virtual void onMouseMoveDelta(const VSTGUI::CPoint &where, const VSTGUI::CButtonState &buttons,
61                                   double dx, double dy);
62 
63     virtual void setLabel(const char *txt);
setDynamicLabel(std::function<std::string ()> lf)64     virtual void setDynamicLabel(std::function<std::string()> lf)
65     {
66         hasLabFn = true;
67         labfn = lf;
68     }
69     bool hasLabFn = false;
70     std::function<std::string()> labfn;
71 
72     virtual void setModValue(float val);
getModValue()73     virtual float getModValue() { return modval; }
setModMode(int mode)74     virtual void setModMode(int mode)
75     {
76         modmode = mode;
77     } // 0 - absolute pos, 1 - absolute mod, 2 - relative mod
setMoveRate(float rate)78     virtual void setMoveRate(float rate) { moverate = rate; }
setModPresent(bool b)79     virtual void setModPresent(bool b)
80     {
81         has_modulation = b;
82     } // true if the slider has modulation routings assigned to it
setModCurrent(bool isCurrent,bool isBipolarModulator)83     virtual void setModCurrent(bool isCurrent, bool isBipolarModulator)
84     {
85         has_modulation_current = isCurrent;
86         modulation_is_bipolar = isBipolarModulator;
87         invalid();
88     } // - " " - for the currently selected modsource
89     virtual void bounceValue(const bool keeprest = false);
90 
91     virtual bool isInMouseInteraction();
92 
93     virtual void setValue(float val) override;
94 
95     std::function<bool()> isBipolFn = []() { return false; };
setBipolarFunction(std::function<bool ()> f)96     void setBipolarFunction(std::function<bool()> f)
97     {
98         isBipolFn = f;
99         invalid();
100     }
101 
102     std::function<bool()> isDeactivatedFn = []() { return false; };
setDeactivatedFn(std::function<bool ()> f)103     void setDeactivatedFn(std::function<bool()> f)
104     {
105         isDeactivatedFn = f;
106         invalid();
107     }
108 
setTempoSync(bool b)109     virtual void setTempoSync(bool b) { is_temposync = b; }
110 
111     void SetQuantitizedDispValue(float f);
112 
113 #if !TARGET_JUCE_UI
setFont(VSTGUI::CFontRef f)114     void setFont(VSTGUI::CFontRef f)
115     {
116         if (labfont)
117             labfont->forget();
118         labfont = f;
119         labfont->remember();
120     }
121 #endif
122     VSTGUI::CFontRef labfont = nullptr;
123 
124     CLASS_METHODS(CSurgeSlider, CControl)
125 
126     bool in_hover = false;
127     bool is_mod;
128     bool disabled; // means it can't be used unless something else changes
129     bool hasBeenDraggedDuringMouseGesture = false;
130 
131     bool isStepped = false;
132     int intRange = 0;
133 
134     int font_size, text_hoffset, text_voffset;
135     VSTGUI::CHoriTxtAlign text_align;
136     VSTGUI::CTxtFace font_style;
137 
138     SurgeStorage *storage = nullptr;
139 
140     enum MoveRateState
141     {
142         kUnInitialized = 0,
143         kLegacy,
144         kSlow,
145         kMedium,
146         kExact
147     };
148 
149     virtual void onSkinChanged() override;
150 
151     static MoveRateState sliderMoveRateState;
152 
153   private:
154     VSTGUI::CBitmap *pHandle = nullptr, *pTray = nullptr, *pModHandle = nullptr,
155                     *pTempoSyncHandle = nullptr, *pHandleHover = nullptr,
156                     *pTempoSyncHoverHandle = nullptr;
157     VSTGUI::CRect handle_rect, handle_rect_orig;
158     VSTGUI::CPoint offsetHandle;
159     int range;
160     int controlstate;
161     long style;
162     float modval, qdvalue;
163     char label[256];
164     int modmode;
165     float moverate;
166     int typex, typey;
167     int typehx, typehy;
168     bool has_modulation, has_modulation_current, modulation_is_bipolar = false;
169     bool is_temposync = false;
170     VSTGUI::CPoint draghandlecenter;
171     VSTGUI::CPoint startPosition;
172     VSTGUI::CPoint currentPosition;
173     float oldVal, *edit_value;
174     int drawcount_debug;
175 
176     float restvalue, restmodval;
177     bool wheelInitiatedEdit = false;
178 };
179