1 #include "SpinBoxChooser.h"
2 #include "ui/FontEngine.h"
3 #include "ui/NanoVGHelpers.h"
4 #include "plugin/ColorPalette.h"
5 #include "Window.hpp"
6 
SpinBoxChooser(Widget * group,const ColorPalette & palette)7 SpinBoxChooser::SpinBoxChooser(Widget *group, const ColorPalette &palette)
8     : NanoWidget(group),
9       fPalette(palette)
10 {
11     updateLayout();
12 }
13 
clearChoices()14 void SpinBoxChooser::clearChoices()
15 {
16     fChoices.clear();
17     fValueIndex = 0;
18 }
19 
addChoice(int32_t value,const char * text)20 void SpinBoxChooser::addChoice(int32_t value, const char *text)
21 {
22     if (text)
23         fChoices.emplace_back(value, text);
24     else
25         fChoices.emplace_back(value, std::to_string(value));
26     setValueIndex(fValueIndex);
27 }
28 
textAtIndex(int32_t index)29 const std::string &SpinBoxChooser::textAtIndex(int32_t index)
30 {
31     if ((uint32_t)index >= fChoices.size()) {
32         static const std::string empty;
33         return empty;
34     }
35     return fChoices[(uint32_t)index].second;
36 }
37 
valueIndex() const38 int32_t SpinBoxChooser::valueIndex() const
39 {
40     return fValueIndex;
41 }
42 
setValueIndex(int32_t index)43 void SpinBoxChooser::setValueIndex(int32_t index)
44 {
45     int32_t count = fChoices.size();
46     index = std::max(0, std::min(count - 1, index));
47 
48     if (index == fValueIndex)
49         return;
50 
51     fValueIndex = index;
52     if (ValueChangedCallback)
53         ValueChangedCallback(value());
54     repaint();
55 }
56 
value() const57 int32_t SpinBoxChooser::value() const
58 {
59     if (fValueIndex < 0 || (uint32_t)fValueIndex >= fChoices.size())
60         return 0;
61 
62     return fChoices[fValueIndex].first;
63 }
64 
setValue(int32_t value)65 void SpinBoxChooser::setValue(int32_t value)
66 {
67     int32_t i = -1;
68 
69     for (uint32_t index = 0, size = fChoices.size(); i == -1 && index < size; ++index) {
70         if (fChoices[index].first == value)
71             i = index;
72     }
73 
74     if (i != -1)
75         setValueIndex(i);
76 }
77 
onNanoDisplay()78 void SpinBoxChooser::onNanoDisplay()
79 {
80     const ColorPalette &cp = fPalette;
81     FontEngine fe(*this, cp);
82 
83     const int h = getHeight();
84 
85     ///
86     Font fontAwesome;
87     fontAwesome.name = "awesome";
88     fontAwesome.size = 0.5 * h;
89     fontAwesome.color = cp[Colors::text_normal];
90     Font fontRegular;
91     fontRegular.name = "regular";
92     fontRegular.size = 12.0;
93     fontRegular.color = cp[Colors::text_normal];
94 
95     ///
96     beginPath();
97     roundedRectWithCorners(*this, fBoundsLeftButton, 10.0, RectangleNW|RectangleSW);
98     fillColor(Colors::fromRGBA8(cp[Colors::spin_box_fill]));
99     fill();
100     fe.drawInBox("\uf053", fontAwesome, fBoundsLeftButton, kAlignCenter|kAlignInside);
101 
102     ///
103     beginPath();
104     roundedRectWithCorners(*this, fBoundsRightButton, 10.0, RectangleNE|RectangleSE);
105     fillColor(Colors::fromRGBA8(cp[Colors::spin_box_fill]));
106     fill();
107     fe.drawInBox("\uf054", fontAwesome, fBoundsRightButton, kAlignCenter|kAlignInside);
108 
109     ///
110     beginPath();
111     ::rect(*this, fBoundsCenterLabel);
112     fillColor(Colors::fromRGBA8(cp[Colors::spin_box_back]));
113     fill();
114     if (!fChoices.empty())
115         fe.drawInBox(fChoices[fValueIndex].second.c_str(), fontRegular, fBoundsCenterLabel, kAlignCenter|kAlignInside);
116 }
117 
onResize(const ResizeEvent & ev)118 void SpinBoxChooser::onResize(const ResizeEvent &ev)
119 {
120     (void)ev;
121     updateLayout();
122 }
123 
onMouse(const MouseEvent & ev)124 bool SpinBoxChooser::onMouse(const MouseEvent &ev)
125 {
126     if (ev.press && ev.button == 1) {
127         if (fBoundsLeftButton.contains(ev.pos.getX(), ev.pos.getY())) {
128             setValueIndex(fValueIndex - 1);
129             return true;
130         }
131         else if (fBoundsRightButton.contains(ev.pos.getX(), ev.pos.getY())) {
132             setValueIndex(fValueIndex + 1);
133             return true;
134         }
135     }
136     return false;
137 }
138 
updateLayout()139 void SpinBoxChooser::updateLayout()
140 {
141     const int w = getWidth();
142     const int h = getHeight();
143 
144     const Rect bounds{0, 0, w, h};
145 
146     fBoundsLeftButton = bounds.from_left(h);
147     fBoundsRightButton = bounds.from_right(h);
148     fBoundsCenterLabel = bounds.reduced({h, 0});
149 }
150