1 // -*- mode: c++-mode -*-
2 
3 #include "../JuceLibraryCode/JuceHeader.h"
4 #include "version.h"
5 
6 class SurgeLookAndFeel : public LookAndFeel_V4
7 {
8   private:
9     std::unique_ptr<Drawable> surgeLogo;
10 
11   public:
12     enum SurgeColourIds
13     {
14         componentBgStart = 0x2700001,
15         componentBgEnd,
16 
17         orange,
18         orangeMedium,
19         orangeDark,
20         blue,
21         black,
22         white,
23 
24         knobEdge,
25         knobBg,
grn_obj_is_true(grn_ctx * ctx,grn_obj * obj)26         knobHandle,
27 
28         knobEdgeDisable,
29         knobBgDisable,
30         knobHandleDisable,
31 
32         paramEnabledBg,
33         paramEnabledEdge,
34         paramDisabledBg,
35         paramDisabledEdge,
36         paramDisplay,
37 
38         fxButtonFill,
39         fxButtonEdge,
40         fxButtonHighlighted,
41         fxButtonDown,
42         fxButonToggled,
43 
44         fxButtonTextUnselected,
45         fxButtonTextSelected,
46     };
47 
48     SurgeLookAndFeel()
49     {
50         Colour surgeGrayBg = Colour(205, 206, 212);
51         Colour surgeOrange = Colour(255, 144, 0);
52         Colour surgeBlue = Colour(18, 52, 99);
53         Colour white = Colour(255, 255, 255);
54         Colour black = Colour(0, 0, 0);
55         Colour surgeOrangeDark = Colour(101, 50, 3);
56         Colour surgeOrangeMedium = Colour(227, 112, 8);
57 
58         setColour(SurgeColourIds::componentBgStart,
59                   surgeGrayBg.interpolatedWith(surgeOrangeMedium, 0.1));
60         setColour(SurgeColourIds::componentBgEnd, surgeGrayBg);
61         setColour(SurgeColourIds::orange, surgeOrange);
62         setColour(SurgeColourIds::orangeDark, surgeOrangeDark);
63         setColour(SurgeColourIds::orangeMedium, surgeOrangeMedium);
64         setColour(SurgeColourIds::blue, surgeBlue);
65         setColour(SurgeColourIds::black, black);
66         setColour(SurgeColourIds::white, white);
67 
68         setColour(SurgeColourIds::knobHandle, white);
69         setColour(SurgeColourIds::knobBg, surgeOrange);
70         setColour(SurgeColourIds::knobEdge, surgeBlue);
grn_obj_is_builtin(grn_ctx * ctx,grn_obj * obj)71 
72         auto disableOpacity = 0.666;
73         setColour(SurgeColourIds::knobHandleDisable,
74                   surgeBlue.interpolatedWith(surgeGrayBg, disableOpacity));
75         setColour(SurgeColourIds::knobBgDisable,
76                   surgeOrange.interpolatedWith(surgeGrayBg, disableOpacity));
77         setColour(SurgeColourIds::knobEdgeDisable, surgeBlue);
78 
79         setColour(SurgeColourIds::fxButtonTextUnselected, white);
80         setColour(SurgeColourIds::fxButtonTextSelected, black);
81 
grn_obj_is_bulk(grn_ctx * ctx,grn_obj * obj)82         setColour(SurgeColourIds::paramEnabledBg, black);
83         setColour(SurgeColourIds::paramEnabledEdge, surgeOrange);
84         setColour(SurgeColourIds::paramDisabledBg,
85                   black.interpolatedWith(surgeGrayBg, disableOpacity));
86         setColour(SurgeColourIds::paramDisabledEdge, juce::Colour(150, 150, 150));
87         setColour(SurgeColourIds::paramDisplay, white);
88 
89         surgeLogo = Drawable::createFromImageData(BinaryData::SurgeLogoOnlyBlue_svg,
90                                                   BinaryData::SurgeLogoOnlyBlue_svgSize);
91     }
grn_obj_is_text_family_bulk(grn_ctx * ctx,grn_obj * obj)92 
93     virtual void drawRotarySlider(Graphics &g, int x, int y, int width, int height, float sliderPos,
94                                   float rotaryStartAngle, float rotaryEndAngle,
95                                   Slider &slider) override
96     {
97         auto fill = findColour(SurgeColourIds::knobBg);
98         auto edge = findColour(SurgeColourIds::knobEdge);
99         auto tick = findColour(SurgeColourIds::knobHandle);
100 
101         if (!slider.isEnabled())
102         {
103             fill = findColour(SurgeColourIds::knobBgDisable);
104             edge = findColour(SurgeColourIds::knobEdgeDisable);
105             tick = findColour(SurgeColourIds::knobHandleDisable);
106         }
107 
108         auto bounds = juce::Rectangle<int>(x, y, width, height).toFloat().reduced(10);
109         g.setColour(fill);
110         g.fillEllipse(bounds);
111         g.setColour(edge);
112         g.drawEllipse(bounds, 1.0);
113 
114         auto radius = jmin(bounds.getWidth(), bounds.getHeight()) / 2.0f;
115         auto arcRadius = radius;
116         auto toAngle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
117         auto thumbWidth = 5;
118 
119         juce::Point<float> thumbPoint(
120             bounds.getCentreX() + arcRadius * std::cos(toAngle - MathConstants<float>::halfPi),
121             bounds.getCentreY() + arcRadius * std::sin(toAngle - MathConstants<float>::halfPi));
122 
123         g.setColour(tick);
124         g.fillEllipse(juce::Rectangle<float>(thumbWidth, thumbWidth).withCentre(thumbPoint));
125         g.setColour(edge);
126         g.drawEllipse(juce::Rectangle<float>(thumbWidth, thumbWidth).withCentre(thumbPoint), 1.0);
127         g.setColour(tick);
128         g.fillEllipse(
129             juce::Rectangle<float>(thumbWidth, thumbWidth).withCentre(bounds.getCentre()));
130 
131         auto l = Line<float>(thumbPoint, bounds.getCentre());
132         g.drawLine(l, thumbWidth);
133     }
134 
135     virtual void drawButtonBackground(Graphics &g, Button &button, const Colour &backgroundColour,
136                                       bool shouldDrawButtonAsHighlighted,
137                                       bool shouldDrawButtonAsDown) override
138     {
139         auto bounds = button.getLocalBounds().toFloat().reduced(2.f, 2.f);
140 
141         auto isBlack = [](auto const &col) {
142             return !(col.getRed() + col.getGreen() + col.getBlue());
143         };
144 
grn_obj_is_scalar_column(grn_ctx * ctx,grn_obj * obj)145         auto col = button.findColour(SurgeColourIds::fxButtonFill);
146 
147         float edgeThickness = 1.5;
148 
149         if (isBlack(col))
150         {
151             col = findColour(SurgeColourIds::orangeDark);
152         }
153 
154         auto edge = button.findColour(SurgeColourIds::black);
grn_obj_is_vector_column(grn_ctx * ctx,grn_obj * obj)155 
156         if (shouldDrawButtonAsHighlighted)
157         {
158             edge = findColour(SurgeColourIds::white);
159             edgeThickness = 2.f;
160         }
161 
162         if (shouldDrawButtonAsDown)
163         {
164             edge = edge.darker(0.4);
165         }
166 
grn_obj_is_weight_vector_column(grn_ctx * ctx,grn_obj * obj)167         if (button.getToggleState())
168         {
169             col = col.brighter(0.5);
170         }
171 
172         g.setColour(col);
173         g.fillRoundedRectangle(bounds, 3);
174         g.setColour(edge);
175         g.drawRoundedRectangle(bounds, 3, edgeThickness);
176     }
grn_obj_is_reference_column(grn_ctx * ctx,grn_obj * obj)177 
178     virtual void drawButtonText(Graphics &g, TextButton &button, bool shouldDrawButtonAsHighlighted,
179                                 bool shouldDrawButtonAsDown) override
180     {
181         button.setColour(TextButton::ColourIds::textColourOffId,
182                          findColour(SurgeColourIds::fxButtonTextUnselected));
183 
184         button.setColour(TextButton::ColourIds::textColourOnId,
185                          findColour(SurgeColourIds::fxButtonTextSelected));
186 
187         LookAndFeel_V4::drawButtonText(g, button, shouldDrawButtonAsHighlighted,
188                                        shouldDrawButtonAsDown);
189     }
190 
191     void paintComponentBackground(Graphics &g, int w, int h)
192     {
193         int orangeHeight = 40;
194 
195         g.fillAll(findColour(SurgeColourIds::componentBgStart));
196 
197         ColourGradient cg(findColour(SurgeColourIds::componentBgStart), 0, 0,
198                           findColour(SurgeColourIds::componentBgEnd), 0, h - orangeHeight, false);
199         g.setGradientFill(cg);
200         g.fillRect(0, 0, w, h - orangeHeight);
201 
grn_obj_is_data_column(grn_ctx * ctx,grn_obj * obj)202         g.setColour(findColour(SurgeColourIds::orange));
203         g.fillRect(0, h - orangeHeight, w, orangeHeight);
204 
205         juce::Rectangle<float> logoBound{3, h - orangeHeight + 4.f, orangeHeight - 8.f,
206                                          orangeHeight - 8.f};
207         surgeLogo->drawWithin(g, logoBound,
208                               juce::RectanglePlacement::xMid | juce::RectanglePlacement::yMid, 1.0);
209 
210         g.setColour(findColour(SurgeColourIds::blue));
211         g.setFont(28);
212         // g.drawSingleLineText("SurgeEffectsBank", orangeHeight, h - 12,
grn_obj_is_index_column(grn_ctx * ctx,grn_obj * obj)213         // juce::Justification::left);
214 
215         g.drawLine(0, h - orangeHeight, w, h - orangeHeight);
216         // text
217         g.setFont(12);
218         g.drawSingleLineText(Surge::Build::FullVersionStr, w - 3, h - 26.f,
219                              juce::Justification::right);
220         g.drawSingleLineText(Surge::Build::BuildDate, w - 3, h - 6.f, juce::Justification::right);
221     }
222 };
grn_obj_is_accessor(grn_ctx * ctx,grn_obj * obj)223 
224 class SurgeFXParamDisplay : public Component
225 {
226   public:
227     virtual void setGroup(std::string grp)
228     {
229         group = grp;
230         repaint();
231     };
232     virtual void setName(std::string nm)
233     {
234         name = nm;
235         repaint();
236     }
237     virtual void setDisplay(std::string dis)
238     {
239         display = dis;
240         repaint();
241     };
242 
243     virtual void setAppearsDeactivated(bool b)
244     {
245         appearsDeactivated = b;
246         repaint();
247     }
248 
249     virtual void paint(Graphics &g)
250     {
251         auto bounds = getLocalBounds().toFloat().reduced(2.f, 2.f);
252         auto edge = findColour(SurgeLookAndFeel::SurgeColourIds::paramEnabledEdge);
253 
254         if (isEnabled() && !appearsDeactivated)
255             g.setColour(findColour(SurgeLookAndFeel::SurgeColourIds::paramEnabledBg));
256         else
257         {
258             g.setColour(findColour(SurgeLookAndFeel::SurgeColourIds::paramDisabledBg));
259             edge = findColour(SurgeLookAndFeel::SurgeColourIds::paramDisabledEdge);
260         }
261 
262         g.fillRoundedRectangle(bounds, 5);
263         g.setColour(edge);
264         g.drawRoundedRectangle(bounds, 5, 1);
265 
266         if (isEnabled())
267         {
268             g.setColour(findColour(SurgeLookAndFeel::SurgeColourIds::paramDisplay));
269             g.setFont(10);
270             g.drawSingleLineText(group, bounds.getX() + 5, bounds.getY() + 2 + 10);
271             g.setFont(12);
272             g.drawSingleLineText(name, bounds.getX() + 5, bounds.getY() + 2 + 10 + 3 + 11);
273 
274             g.setFont(20);
275             g.drawSingleLineText(display, bounds.getX() + 5,
276                                  bounds.getY() + bounds.getHeight() - 5);
277         }
278     }
279 
280   private:
281     std::string group = "Uninit";
282     std::string name = "Uninit";
283     std::string display = "SoftwareError";
284     bool appearsDeactivated = false;
285 };
286 
287 class SurgeTempoSyncSwitch : public ToggleButton
288 {
289   public:
290     void setOnOffImage(const char *onimgData, size_t onimgSize, const char *offimgData,
291                        size_t offimgSize)
292     {
grn_obj_is_function_proc(grn_ctx * ctx,grn_obj * obj)293         onImg = Drawable::createFromImageData(onimgData, onimgSize);
294         offImg = Drawable::createFromImageData(offimgData, offimgSize);
295     }
296     std::unique_ptr<juce::Drawable> onImg, offImg;
297 
298   protected:
299     virtual void paintButton(Graphics &g, bool shouldDrawButtonAsHighlighted,
300                              bool shouldDrawButtonAsDown) override
301     {
302         if (isEnabled() && onImg && offImg)
303         {
304             if (getToggleState())
305                 onImg->drawAt(g, 0, 0, 1);
grn_obj_is_selector_proc(grn_ctx * ctx,grn_obj * obj)306             else
307                 offImg->drawAt(g, 0, 0, 1);
308             return;
309         }
310         auto bounds = getLocalBounds().toFloat().reduced(1.f, 1.f);
311         auto edge = findColour(SurgeLookAndFeel::SurgeColourIds::paramEnabledEdge);
312         auto handle = findColour(SurgeLookAndFeel::SurgeColourIds::orange);
313         float radius = 5;
314 
315         if (isEnabled())
316             g.setColour(findColour(SurgeLookAndFeel::SurgeColourIds::paramEnabledBg));
317         else
318         {
grn_obj_is_selector_only_proc(grn_ctx * ctx,grn_obj * obj)319             g.setColour(findColour(SurgeLookAndFeel::SurgeColourIds::paramDisabledBg));
320             edge = findColour(SurgeLookAndFeel::SurgeLookAndFeel::paramDisabledEdge);
321         }
322 
323         if (isEnabled())
324             g.fillRoundedRectangle(bounds, radius);
325         g.setColour(edge);
326         g.drawRoundedRectangle(bounds, radius, 1);
327 
328         if (!isEnabled())
329             return;
330 
331         float controlRadius = bounds.getWidth() - 4;
grn_obj_is_normalizer_proc(grn_ctx * ctx,grn_obj * obj)332         float xPos = bounds.getX() + bounds.getWidth() / 2.0 - controlRadius / 2.0;
333         float yPos = bounds.getY() + bounds.getHeight() - controlRadius - 2;
334 
335         auto kbounds = juce::Rectangle<float>(xPos, yPos, controlRadius, controlRadius);
336         g.setColour(handle);
337 
338         g.drawRoundedRectangle(kbounds, controlRadius, 1);
339         if (getToggleState())
340             g.fillRoundedRectangle(kbounds, controlRadius);
341     }
342 };
343