1 
2 /*
3  *  Diverse Bristol audio routines.
4  *  Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 3 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*
23  * This will be a highlighted button. Primarily used for the Bit emulators.
24  */
25 
26 #include <math.h>
27 
28 #include "brightoninternals.h"
29 
30 extern int brightonPanelLocation();
31 
32 char  *tbm;
33 
34 int
destroyHButton(brightonDevice * dev)35 destroyHButton(brightonDevice *dev)
36 {
37 	printf("destroyHButton()\n");
38 
39 	if (dev->image)
40 		brightonFreeBitmap(dev->bwin, dev->image);
41 	if (dev->image2)
42 		brightonFreeBitmap(dev->bwin, dev->image2);
43 	dev->image = NULL;
44 	dev->image2 = NULL;
45 
46 	return(0);
47 }
48 
49 static void
displayhbutton(brightonDevice * dev)50 displayhbutton(brightonDevice *dev)
51 {
52 	int flags = dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags;
53 
54 	if (dev->bwin->app->resources[dev->panel].flags & BRIGHTON_WITHDRAWN)
55 		return;
56 
57 	if (flags & BRIGHTON_WITHDRAWN)
58 		return;
59 
60 	/*
61 	 * This is not needed except for moving parts - sliders primarily, but
62 	 * also touch panels. Rotary and hbuttons are located and stay that way.
63 	 */
64 	brightonDevUndraw(dev->bwin, dev->bwin->dlayer,
65 		dev->x + dev->bwin->app->resources[dev->panel].sx,
66 		dev->y + ((int) dev->lastposition)
67 			+ dev->bwin->app->resources[dev->panel].sy,
68 		dev->width, dev->height);
69 
70 	/*
71 	if (dev->value)
72 		id = brightonPut(dev->bwin, "bitmaps/buttons/green.xpm",
73 			dev->x, dev->y, dev->width, dev->height);
74 	else
75 		brightonRemove(dev->bwin, id);
76 	 */
77 	if (dev->value)
78 		brightonStretch(dev->bwin, dev->image2,
79 			dev->bwin->dlayer,
80 			dev->x + dev->bwin->app->resources[dev->panel].sx,
81 			dev->y + dev->bwin->app->resources[dev->panel].sy,
82 			dev->width, dev->height,
83 			flags);
84 	else
85 		brightonStretch(dev->bwin, dev->image,
86 			dev->bwin->dlayer,
87 			dev->x + dev->bwin->app->resources[dev->panel].sx,
88 			dev->y + dev->bwin->app->resources[dev->panel].sy,
89 			dev->width, dev->height,
90 			flags);
91 
92 	brightonFinalRender(dev->bwin,
93 		dev->x + dev->bwin->app->resources[dev->panel].sx,
94 		dev->y + dev->bwin->app->resources[dev->panel].sy,
95 		dev->width, dev->height);
96 
97 	dev->lastvalue = dev->value;
98 	dev->lastposition = dev->position;
99 }
100 
101 /*
102  * This will go into brighton render
103  */
104 static int
renderHighlights(brightonWindow * bwin,brightonDevice * dev)105 renderHighlights(brightonWindow *bwin, brightonDevice *dev)
106 {
107 	float d, streak, dx, dy;
108 	brightonCoord p[8];
109 
110 	if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags &
111 		(BRIGHTON_CHECKBUTTON|BRIGHTON_NOSHADOW|BRIGHTON_WITHDRAWN))
112 		return(0);
113 
114 	dx = dev->x - bwin->lightX;
115 	dy = dev->y - bwin->lightY;
116 
117 	d = sqrt((double) (dx * dx + dy * dy));
118 
119 	streak = (dev->width * 2.0 * d / bwin->lightH)
120 		/ (1 - dev->width * 2.0 / bwin->lightH);
121 
122 	p[0].x = dev->x;
123 	p[0].y = dev->y + dev->height;
124 	p[1].x = dev->x + dev->width;
125 	p[1].y = dev->y;
126 	p[2].x = dev->x + dx * streak / d;
127 	p[2].y = dev->y + dy * streak / d;
128 
129 /*	XFillPolygon(bwin->display, bwin->background, bwin->cheap_shade, */
130 /*		(XPoint *) &p, 3, Complex, CoordModeOrigin); */
131 	return(0);
132 }
133 
considercallback(brightonDevice * dev)134 static int considercallback(brightonDevice *dev)
135 {
136 	brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
137 
138 	if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
139 		& BRIGHTON_WITHDRAWN)
140 		|| (dev->bwin->flags & BRIGHTON_NO_DRAW))
141 		return(0);
142 
143 	if ((dev->lastvalue != dev->value)
144 			|| (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
145 			& BRIGHTON_CHECKBUTTON))
146 	{
147 		if (panel->devlocn[dev->index].callback)
148 		{
149 			panel->devlocn[dev->index].callback(dev->bwin, dev->panel,
150 				dev->index, dev->value);
151 		} else {
152 			if (panel->callback)
153 				panel->callback(dev->bwin, dev->panel, dev->index, dev->value);
154 		}
155 	}
156 	return(0);
157 }
158 
159 static int
configure(brightonDevice * dev,brightonEvent * event)160 configure(brightonDevice *dev, brightonEvent *event)
161 {
162 /*	printf("configureHButton(%i, %f)\n", dev->index, dev->value); */
163 
164 	if (dev->bwin->app->resources[dev->panel].flags & BRIGHTON_WITHDRAWN)
165 		return(0);
166 
167 	if (event->command == -1)
168 		return(-1);
169 
170 	if (event->command == BRIGHTON_RESIZE)
171 	{
172 		dev->x = event->x;
173 		dev->y = event->y;
174 		dev->width = event->w;
175 		dev->height = event->h;
176 		/*
177 		 * We should consider altering the locations structure, so that
178 		 * event dispatching is correct.
179 		 */
180 		if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
181 			& BRIGHTON_CHECKBUTTON) == 0)
182 			considercallback(dev);
183 
184 		brightonPanelLocation(dev->bwin,
185 			dev->panel, dev->index, dev->x, dev->y, dev->width, dev->height);
186 
187 		/*
188 		 * We need to build in some shadow, to prevent the hbutton from looking
189 		 * like it is hanging in mid air.
190 		renderHighlights(dev->bwin, dev);
191 		 */
192 
193 		dev->lastvalue = -1;
194 		displayhbutton(dev);
195 
196 		return(0);
197 	}
198 
199 	if (event->command == BRIGHTON_LEAVE)
200 	{
201 		if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
202 			& BRIGHTON_CHECKBUTTON)
203 		{
204 			dev->value = 0;
205 
206 			displayhbutton(dev);
207 		}
208 		return(0);
209 	}
210 
211 	if (event->command == BRIGHTON_ENTER)
212 	{
213 		if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
214 			& BRIGHTON_CHECKBUTTON)
215 		{
216 			dev->value = 1;
217 
218 			displayhbutton(dev);
219 		}
220 		return(0);
221 	}
222 
223 	if (event->command == BRIGHTON_BUTTONRELEASE)
224 	{
225 		if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
226 			& BRIGHTON_CHECKBUTTON)
227 		{
228 			dev->value = 0;
229 
230 			displayhbutton(dev);
231 
232 			if ((event->x >= dev->x) && (event->y >= dev->y)
233 				&& (event->x < (dev->x + dev->width))
234 				&& (event->y < (dev->y + dev->height)))
235 				considercallback(dev);
236 		}
237 		return(0);
238 	}
239 
240 	if (event->command == BRIGHTON_BUTTONPRESS)
241 	{
242 		brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
243 
244 		if (event->key == BRIGHTON_BUTTON2)
245 		{
246 			brightonRegisterController(dev);
247 
248 			return(0);
249 		}
250 
251 		if (dev->value == 0)
252 			dev->value = panel->devlocn[dev->index].to;
253 		else
254 			dev->value = panel->devlocn[dev->index].from;
255 
256 		if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
257 			& BRIGHTON_CHECKBUTTON) == 0)
258 			considercallback(dev);
259 
260 		displayhbutton(dev);
261 
262 		return(0);
263 	}
264 
265 	if (event->command == BRIGHTON_KEYPRESS)
266 	{
267 		brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
268 
269 		if (event->key == 0x20)
270 		{
271 			if (dev->value == 0)
272 				dev->value = panel->devlocn[dev->index].to;
273 			else
274 				dev->value = panel->devlocn[dev->index].from;
275 
276 			considercallback(dev);
277 
278 			displayhbutton(dev);
279 
280 			return(0);
281 		}
282 		/*
283 		 * If this was not a space bar which we use to activate and de-activate
284 		 * any arbitrary hbutton then it could be that we pressed some key that
285 		 * can otherwise be interpretted.
286 		 * This is awkward since here we are in a single hbutton and I would
287 		 * like to use keypress to emulate a piano keyboard from the computer.
288 		 * These events would have to be delivered to the parent, not to the
289 		 * device, and the parent would then decide to which device the event
290 		 * should be delivered.
291 		 */
292 	}
293 
294 	if (event->command == BRIGHTON_KEYRELEASE)
295 	{
296 		/*
297 		 * This is just to clear the event and repaint the key, we should not
298 		 * be bothered with the callback.
299 		 */
300 		if (event->key == 0x20)
301 		{
302 			if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
303 				& BRIGHTON_CHECKBUTTON)
304 			{
305 				dev->value = 0;
306 
307 				displayhbutton(dev);
308 
309 /*				considercallback(dev); */
310 			}
311 		}
312 		return(0);
313 	}
314 
315 	if (event->command == BRIGHTON_PARAMCHANGE)
316 	{
317 		if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
318 			& BRIGHTON_CHECKBUTTON)
319 		{
320 			dev->value = 0;
321 
322 			displayhbutton(dev);
323 
324 			considercallback(dev);
325 			return(0);
326 		}
327 
328 		dev->value = event->value;
329 		dev->lastvalue = -1;
330 
331 		if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
332 			& BRIGHTON_CHECKBUTTON) == 0)
333 			considercallback(dev);
334 
335 		displayhbutton(dev);
336 
337 		return(0);
338 	}
339 
340 	return(0);
341 }
342 
343 int *
createHButton(brightonWindow * bwin,brightonDevice * dev,int index,char * bitmap)344 createHButton(brightonWindow *bwin, brightonDevice *dev, int index, char *bitmap)
345 {
346 	brightonIResource *panel = &bwin->app->resources[dev->panel];
347 
348 	dev->destroy = destroyHButton;
349 	dev->configure = configure;
350 	dev->bwin = bwin;
351 
352 	if (bitmap == NULL) {
353 		if (dev->image)
354 			brightonFreeBitmap(bwin, dev->image);
355 		/*
356 		 * If we have been passed a specific image name for this device then
357 		 * use it.
358 		 */
359 		if (panel->devlocn[dev->index].image != 0)
360 			dev->image =
361 				bwin->app->resources[dev->panel].devlocn[dev->index].image;
362 		else
363 			dev->image = brightonReadImage(bwin,
364 				"bitmaps/hbuttons/rockerred.xpm");
365 		if (panel->devlocn[dev->index].image2 != 0)
366 			dev->image2 =
367 				bwin->app->resources[dev->panel].devlocn[dev->index].image2;
368 		else
369 			dev->image =
370 				brightonReadImage(bwin, "bitmaps/hbuttons/rockerred.xpm");
371 tbm =  bitmap;
372 	} else {
373 		if (dev->image)
374 			brightonFreeBitmap(bwin, dev->image);
375 
376 		if (panel->devlocn[dev->index].image != 0)
377 			dev->image =
378 				bwin->app->resources[dev->panel].devlocn[dev->index].image;
379 		else
380 			dev->image = brightonReadImage(bwin, bitmap);
381 
382 		if (dev->image2)
383 			brightonFreeBitmap(bwin, dev->image2);
384 
385 		dev->image2 = brightonReadImage(bwin,
386 			bwin->template->resources[dev->panel].devlocn[dev->index].image2);
387 
388 /*
389 		if (panel->devlocn[dev->index].image2 != 0)
390 			dev->image2 =
391 				bwin->app->resources[dev->panel].devlocn[dev->index].image2;
392 */
393 	}
394 
395 	/*
396 	 * These will force an update when we first display ourselves.
397 	 */
398 	dev->value = 0;
399 	dev->lastvalue = -1;
400 	dev->lastposition = -1;
401 
402 	return(0);
403 }
404 
405