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