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 "SurgeStorage.h"
19 #include "CDIBitmap.h"
20 #include "DspUtilities.h"
21 #include "SkinSupport.h"
22 #include "CursorControlGuard.h"
23 
24 #define OSC_MOD_ANIMATION 0
25 
26 class COscillatorDisplay : public VSTGUI::CControl,
27                            public Surge::UI::SkinConsumingComponent,
28                            public Surge::UI::CursorControlAdapter<COscillatorDisplay>
29 {
30   public:
COscillatorDisplay(const VSTGUI::CRect & size,VSTGUI::IControlListener * l,OscillatorStorage * oscdata,SurgeStorage * storage)31     COscillatorDisplay(const VSTGUI::CRect &size, VSTGUI::IControlListener *l,
32                        OscillatorStorage *oscdata, SurgeStorage *storage)
33         : VSTGUI::CControl(size, l, 0, 0), Surge::UI::CursorControlAdapter<COscillatorDisplay>(
34                                                storage)
35     {
36         this->oscdata = oscdata;
37         this->storage = storage;
38         controlstate = 0;
39 
40         this->scene = oscdata->type.scene - 1;
41         this->osc_in_scene = oscdata->type.ctrlgroup_entry;
42 
43         if (storage->getPatch()
44                 .dawExtraState.editor.oscExtraEditState[scene][osc_in_scene]
45                 .hasCustomEditor)
46         {
47             openCustomEditor();
48         }
49     }
~COscillatorDisplay()50     virtual ~COscillatorDisplay() {}
51 
52     /*
53      * Custom Editor Support where I can change this UI based on a type to allow edits
54      * Currently only used by alias oscillator
55      */
56     struct CustomEditor
57     {
CustomEditorCustomEditor58         CustomEditor(COscillatorDisplay *d) : disp(d) {}
59         virtual ~CustomEditor() = default;
60         virtual void draw(VSTGUI::CDrawContext *dc) = 0;
61 
onMouseDownCustomEditor62         virtual VSTGUI::CMouseEventResult onMouseDown(VSTGUI::CPoint &where,
63                                                       const VSTGUI::CButtonState &buttons)
64         {
65             return VSTGUI::kMouseEventNotHandled;
66         };
onMouseUpCustomEditor67         virtual VSTGUI::CMouseEventResult onMouseUp(VSTGUI::CPoint &where,
68                                                     const VSTGUI::CButtonState &buttons)
69         {
70             return VSTGUI::kMouseEventNotHandled;
71         };
onMouseMovedCustomEditor72         virtual VSTGUI::CMouseEventResult onMouseMoved(VSTGUI::CPoint &where,
73                                                        const VSTGUI::CButtonState &buttons)
74         {
75             return VSTGUI::kMouseEventNotHandled;
76         };
onMouseExitedCustomEditor77         virtual VSTGUI::CMouseEventResult onMouseExited(VSTGUI::CPoint &where,
78                                                         const VSTGUI::CButtonState &buttons)
79         {
80             return VSTGUI::kMouseEventNotHandled;
81         };
onMouseEnteredCustomEditor82         virtual VSTGUI::CMouseEventResult onMouseEntered(VSTGUI::CPoint &where,
83                                                          const VSTGUI::CButtonState &buttons)
84         {
85             return VSTGUI::kMouseEventNotHandled;
86         };
87 
onWheelCustomEditor88         virtual bool onWheel(const VSTGUI::CPoint &where, const float &distance,
89                              const VSTGUI::CButtonState &buttons)
90         {
91             return false;
92         }
93 
94         // Entered and Exited too
95         COscillatorDisplay *disp;
96     };
97     bool canHaveCustomEditor();
98     void openCustomEditor();
99     void closeCustomEditor();
100     std::shared_ptr<CustomEditor> customEditor; // I really want unique but that
101     // clashes with the VSTGUI copy semantics
102     bool customEditorActive = false, editButtonHover = false;
103     VSTGUI::CRect customEditButtonRect;
104 
105     virtual void draw(VSTGUI::CDrawContext *dc) override;
106 
107     void drawExtraEditButton(VSTGUI::CDrawContext *dc, const std::string &label);
108 
109     void loadWavetable(int id);
110     void loadWavetableFromFile();
111 
112     // virtual void mouse (CDrawContext *pContext, VSTGUI::CPoint &where, long button = -1);
113     virtual VSTGUI::CMouseEventResult onMouseDown(VSTGUI::CPoint &where,
114                                                   const VSTGUI::CButtonState &buttons) override;
115     virtual VSTGUI::CMouseEventResult onMouseUp(VSTGUI::CPoint &where,
116                                                 const VSTGUI::CButtonState &buttons) override;
117     virtual VSTGUI::CMouseEventResult onMouseMoved(VSTGUI::CPoint &where,
118                                                    const VSTGUI::CButtonState &buttons) override;
119     VSTGUI::CMouseEventResult onMouseExited(VSTGUI::CPoint &where,
120                                             const VSTGUI::CButtonState &buttons) override;
121     VSTGUI::CMouseEventResult onMouseEntered(VSTGUI::CPoint &where,
122                                              const VSTGUI::CButtonState &buttons) override;
123     bool onWheel(const VSTGUI::CPoint &where, const float &distance,
124                  const VSTGUI::CButtonState &buttons) override;
125 
126     void invalidateIfIdIsInRange(int id);
127 
128 #if OSC_MOD_ANIMATION
setIsMod(bool b)129     void setIsMod(bool b)
130     {
131         is_mod = b;
132         mod_time = 0;
133     }
setModSource(modsources m)134     void setModSource(modsources m) { modsource = m; }
tickModTime()135     void tickModTime() { mod_time += 1.0 / 30.0; }
136 #endif
137 
138   protected:
139     void populateMenu(VSTGUI::COptionMenu *m, int selectedItem);
140     bool populateMenuForCategory(VSTGUI::COptionMenu *parent, int categoryId, int selectedItem);
141 
142     OscillatorStorage *oscdata;
143     SurgeStorage *storage;
144     unsigned int controlstate;
145 
146     int scene, osc_in_scene;
147 
148     bool doingDrag = false;
149     enum
150     {
151         NONE,
152         PREV,
153         MENU,
154         NEXT
155     } isWTHover = NONE;
156 
157     static constexpr float scaleDownBy = 0.235;
158 
159 #if OSC_MOD_ANIMATION
160     bool is_mod = false;
161     modsources modsource = ms_original;
162     float mod_time = 0;
163 #endif
164     VSTGUI::CRect rnext, rprev, rmenu;
165     VSTGUI::CPoint lastpos;
166     CLASS_METHODS(COscillatorDisplay, VSTGUI::CControl)
167 };
168