1 /*
2     Wdgts for Foo-YC20 UI
3     Copyright (C) 2010  Sampo Savolainen <v2@iki.fi>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifndef _FOO_YC20_WDGTS_H
20 #define _FOO_YC20_WDGTS_H
21 
22 #include <iostream>
23 #include <stdint.h>
24 #include <math.h>
25 
26 #include <wdgt.h>
27 
28 #define DRAWBAR_BLACK_EMPHASIS_ALPHA 0.333
29 
30 
31 namespace Wdgt
32 {
33 
34 class Draggable : public Wdgt::Object
35 {
36 	public:
Draggable()37 		Draggable()
38 			: minValue(0.0)
39 			, maxValue(1.0)
40 			, value(-99.9)
41 			, zone(NULL)
42 		{
43 		}
44 
45 		virtual bool setValue(float v) = 0;
46 		virtual bool setValueFromDrag(float prevValue, float startY, float y) = 0;
47 
getValue()48 		float getValue() const { return value; };
getMinValue()49 		float getMinValue() const { return minValue; };
getMaxValue()50 		float getMaxValue() const { return maxValue; };
51 
setZone(float * z)52 		void setZone(float *z) { zone = z; };
getZone()53 		float *getZone() const { return zone; };
54 
setPortIndex(uint32_t p)55 		void setPortIndex(uint32_t p) { port = p; }
getPortIndex()56 		uint32_t getPortIndex() const { return port; }
57 
58 	protected:
setValueForZone()59 		void inline setValueForZone()
60 		{
61 			if (zone) {
62 				*zone = value;
63 			}
64 		}
65 
66 		float minValue;
67 		float maxValue;
68 		float value;
69 
70 		float *zone;
71 		uint32_t port;
72 };
73 
74 class Lever : public Draggable
75 {
76 	public:
Lever(bool notches)77 		Lever(bool notches)
78 		{
79 			notched = notches;
80 
81 			value = -1.0;
82 			setValue(0);
83 		}
84 
setValueFromDrag(float prevValue,float startY,float y)85 		bool setValueFromDrag(float prevValue, float startY, float y)
86 		{
87 			return setValue(prevValue + (y-startY)/((y2-y1)/2.0));
88 		}
89 
setValue(float v)90 		virtual bool setValue(float v)
91 		{
92 			if (v < 0.0) {
93 				v = 0.0;
94 			} else if (v > 1.0) {
95 				v = 1.0;
96 			}
97 
98 			imageNum = round(3.0*v);
99 
100 			float newvalue;
101 
102 			if (notched) {
103 				newvalue = (float)imageNum / 3.0;
104 			} else {
105 				newvalue = v;
106 			}
107 
108 			if (value == newvalue) {
109 				return false;
110 			}
111 
112 			value = newvalue;
113 			setValueForZone();
114 
115 			return true;
116 		}
117 
setPosition(float posX,float posY)118 		void setPosition(float posX, float posY)
119 		{
120 			x1 = posX;
121 			y1 = posY;
122 			x2 = x1 + 40;
123 			y2 = y1 + 90 + 5;
124 		}
125 
126 	protected:
127 
128 		bool notched;
129 		int imageNum;
130 
131 };
132 
133 class Drawbar : public Lever
134 {
135 	public:
Drawbar(float posX,float posY,bool notches,cairo_surface_t ** _images)136 		Drawbar(float posX, float posY, bool notches, cairo_surface_t **_images)
137 			: Lever(notches)
138 			, images(_images)
139 			, alpha(0.08)
140 		{
141 			setPosition(posX, posY);
142 		}
143 
Drawbar(float posX,float posY,bool notches,float _alpha,cairo_surface_t ** _images)144 		Drawbar(float posX, float posY, bool notches, float _alpha, cairo_surface_t **_images)
145 			: Lever(notches)
146 			, images(_images)
147 			, alpha(_alpha)
148 		{
149 			setPosition(posX, posY);
150 		}
151 
drawWidget(bool hover,cairo_t * cr)152 		virtual void drawWidget(bool hover, cairo_t *cr) const
153 		{
154 			cairo_set_source_surface(cr, images[imageNum], x1, y1);
155 			cairo_paint(cr);
156 
157 			if (hover) {
158 				cairo_set_source_surface(cr, images[imageNum], x1, y1);
159 				cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
160 				cairo_paint_with_alpha(cr, alpha);
161 				cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
162 
163 			}
164 		}
165 
166 	private:
167 		cairo_surface_t **images;
168 		float alpha;
169 };
170 
171 class Switch : public Drawbar
172 {
173 	public:
Switch(float posX,float posY,float alpha,cairo_surface_t ** images)174 		Switch(float posX, float posY, float alpha, cairo_surface_t **images)
175 			: Drawbar(posX, posY, false, alpha, images)
176 		{
177 		}
178 
setValue(float v)179 		virtual bool setValue(float v)
180 		{
181 			if (v < 0.5) {
182 				v = 0.0;
183 			} else {
184 				v = 1.0;
185 			}
186 			return Drawbar::setValue(v);
187 		}
188 };
189 
190 class Potentiometer : public Draggable
191 {
192 	public:
Potentiometer(float posX,float posY,float min,float max,cairo_surface_t * _image)193 		Potentiometer(float posX, float posY, float min, float max, cairo_surface_t *_image)
194 			: image(_image)
195 		{
196 			minValue = min;
197 			maxValue = max;
198 
199 			value = maxValue / (maxValue - minValue);
200 
201 			setValue( (min+max)/2.0 );
202 
203 			setPosition(posX, posY);
204 		}
205 
setValue(float v)206 		virtual bool setValue(float v)
207 		{
208 			if (v > maxValue) {
209 				v = maxValue;
210 			} else if (v < minValue) {
211 				v = minValue;
212 			}
213 
214 			if (v == value) {
215 				return false;
216 			}
217 
218 			value = v;
219 			setValueForZone();
220 
221 			return true;
222 		}
223 
setPosition(float posX,float posY)224 		void setPosition(float posX, float posY)
225 		{
226 			x1 = posX;
227 			y1 = posY;
228 			x2 = x1 + 72;
229 			y2 = y1 + 90;
230 
231 			origoX = x1 + 72.0/2.0;
232 			origoY = y1 + 37.5 + 5.0;
233 		}
234 
setValueFromDrag(float prevValue,float startY,float y)235 		bool setValueFromDrag(float prevValue, float startY, float y)
236 		{
237 			float v = prevValue + (startY - y)/100.0;
238 
239 			return setValue(v);
240 
241 		}
242 
drawWidget(bool hover,cairo_t * cr)243 		virtual void drawWidget(bool hover, cairo_t *cr) const
244 		{
245 			cairo_set_source_surface(cr, image, x1, y1);
246 			cairo_paint(cr);
247 
248 			if (hover) {
249 				cairo_set_operator(cr, CAIRO_OPERATOR_ADD);
250 				cairo_paint_with_alpha(cr, 0.08);
251 				cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
252 			}
253 
254 			cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
255 			cairo_set_line_width(cr, 2.5);
256 
257 			float relativeValue = -(maxValue - value) / (maxValue - minValue);
258 			relativeValue *= (5.0/6.0);
259 			relativeValue += 1.0/6.0;
260 
261 			float x2offt = 32.0 * cos(M_PI * 2.0 * relativeValue);
262 			float y2offt = 32.0 * sin(M_PI * 2.0 * relativeValue);
263 
264 			float x1offt = 8.0  * cos(M_PI * 2.0 * relativeValue);
265 			float y1offt = 8.0  * sin(M_PI * 2.0 * relativeValue);
266 
267 			cairo_move_to(cr, origoX + x1offt, origoY + y1offt);
268 
269 			cairo_line_to(cr, origoX + x2offt, origoY + y2offt);
270 
271 			cairo_stroke(cr);
272 		}
273 
274 	private:
275 		float origoX;
276 		float origoY;
277 
278 		cairo_surface_t *image;
279 
280 };
281 
282 };
283 
284 
285 #endif /* _FOO_YC20_WDGTS_H */
286 
287