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 simple pushbutton, initially it will function as 2 throw,
24 * but may incorporate capabilities to support pure contact switches.
25 * radio buttons will probably have to be separate.
26 */
27
28 #include <math.h>
29
30 #include "brightoninternals.h"
31
32 extern int brightonPanelLocation();
33
34 int
destroyButton(brightonDevice * dev)35 destroyButton(brightonDevice *dev)
36 {
37 printf("destroyButton()\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
displaybutton(brightonDevice * dev)50 displaybutton(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 (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
58 & BRIGHTON_WITHDRAWN)
59 return;
60
61 /*
62 * This is not needed except for moving parts - sliders primarily, but
63 * also touch panels. Rotary and buttons are located and stay that way.
64 */
65 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
66 & BRIGHTON_REDRAW)
67 brightonDevUndraw(dev->bwin, dev->bwin->dlayer,
68 dev->x + dev->bwin->app->resources[dev->panel].sx,
69 dev->y + + dev->bwin->app->resources[dev->panel].sy,
70 dev->width, dev->height);
71
72 brightonRenderShadow(dev, 1);
73
74 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
75 & (BRIGHTON_THREEWAY|BRIGHTON_FIVEWAY))
76 {
77 if ((dev->value >= 0) && (dev->value <= 0.5))
78 {
79 brightonStretch(dev->bwin, dev->imagec,
80 dev->bwin->dlayer,
81 dev->x + dev->bwin->app->resources[dev->panel].sx,
82 dev->y + dev->bwin->app->resources[dev->panel].sy,
83 dev->width, dev->height, flags);
84 } else if ((dev->value > 0.5) && (dev->value <= 1.5)) {
85 brightonStretch(dev->bwin, dev->image2,
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, flags);
90 } else if ((dev->value > 1.5) && (dev->value <= 2.5)) {
91 brightonStretch(dev->bwin, dev->image,
92 dev->bwin->dlayer,
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, flags);
96 } else if ((dev->value > 2.5) && (dev->value <= 3.5)) {
97 brightonStretch(dev->bwin, dev->image3,
98 dev->bwin->dlayer,
99 dev->x + dev->bwin->app->resources[dev->panel].sx,
100 dev->y + dev->bwin->app->resources[dev->panel].sy,
101 dev->width, dev->height, flags);
102 } else if ((dev->value > 3.5) && (dev->value <= 4.5)) {
103 brightonStretch(dev->bwin, dev->image4,
104 dev->bwin->dlayer,
105 dev->x + dev->bwin->app->resources[dev->panel].sx,
106 dev->y + dev->bwin->app->resources[dev->panel].sy,
107 dev->width, dev->height, flags);
108 }
109 } else if (dev->image2) {
110 if (dev->value)
111 brightonStretch(dev->bwin, dev->image2,
112 dev->bwin->dlayer,
113 dev->x + dev->bwin->app->resources[dev->panel].sx,
114 dev->y + dev->bwin->app->resources[dev->panel].sy,
115 dev->width, dev->height,
116 dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags);
117 else
118 brightonStretch(dev->bwin, dev->image,
119 dev->bwin->dlayer,
120 dev->x + dev->bwin->app->resources[dev->panel].sx,
121 dev->y + dev->bwin->app->resources[dev->panel].sy,
122 dev->width, dev->height,
123 dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags);
124 } else {
125 if ((~dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
126 & BRIGHTON_CHECKBUTTON))
127 {
128 if (dev->value == 0)
129 flags = 0;
130 else
131 flags = BRIGHTON_REVERSE|BRIGHTON_HALF_REVERSE;
132
133 flags |= (BRIGHTON_VERTICAL
134 & dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags);
135 }
136
137 brightonStretch(dev->bwin, dev->image,
138 /*dev->bwin->app->resources[dev->panel].canvas, */
139 dev->bwin->dlayer,
140 dev->x + dev->bwin->app->resources[dev->panel].sx,
141 dev->y + dev->bwin->app->resources[dev->panel].sy,
142 dev->width, dev->height, flags);
143 }
144
145 brightonRenderShadow(dev, 0);
146
147 brightonFinalRender(dev->bwin,
148 dev->x + dev->bwin->app->resources[dev->panel].sx,
149 dev->y + dev->bwin->app->resources[dev->panel].sy,
150 dev->width, dev->height);
151
152 dev->lastvalue = dev->value;
153 dev->lastposition = dev->position;
154 }
155
156 /*
157 * This will go into brighton render
158 */
159 static int
renderHighlights(brightonWindow * bwin,brightonDevice * dev)160 renderHighlights(brightonWindow *bwin, brightonDevice *dev)
161 {
162 float d, streak, dx, dy;
163 brightonCoord p[8];
164
165 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags &
166 (BRIGHTON_CHECKBUTTON|BRIGHTON_NOSHADOW|BRIGHTON_WITHDRAWN))
167 return(0);
168
169 dx = dev->x - bwin->lightX;
170 dy = dev->y - bwin->lightY;
171
172 d = sqrt((double) (dx * dx + dy * dy));
173
174 streak = (dev->width * 2.0 * d / bwin->lightH)
175 / (1 - dev->width * 2.0 / bwin->lightH);
176
177 p[0].x = dev->x;
178 p[0].y = dev->y + dev->height;
179 p[1].x = dev->x + dev->width;
180 p[1].y = dev->y;
181 p[2].x = dev->x + dx * streak / d;
182 p[2].y = dev->y + dy * streak / d;
183
184 /* XFillPolygon(bwin->display, bwin->background, bwin->cheap_shade, */
185 /* (XPoint *) &p, 3, Complex, CoordModeOrigin); */
186 return(0);
187 }
188
considercallback(brightonDevice * dev)189 static int considercallback(brightonDevice *dev)
190 {
191 brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
192
193 if (dev->bwin->flags & BRIGHTON_NO_DRAW)
194 return(0);
195
196 if ((dev->lastvalue != dev->value)
197 || (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
198 & BRIGHTON_CHECKBUTTON))
199 {
200 if (panel->devlocn[dev->index].callback)
201 {
202 panel->devlocn[dev->index].callback(dev->bwin, dev->panel,
203 dev->index, dev->value);
204 } else {
205 if (panel->callback)
206 panel->callback(dev->bwin, dev->panel, dev->index, dev->value);
207 }
208 }
209 return(0);
210 }
211
212 static int
configure(brightonDevice * dev,brightonEvent * event)213 configure(brightonDevice *dev, brightonEvent *event)
214 {
215 /* printf("configureButton(%i, %f)\n", dev->index, dev->value); */
216
217 /*
218 * We had to do this for some withdrawn panels
219 if (dev->bwin->app->resources[dev->panel].flags & BRIGHTON_WITHDRAWN)
220 return(0);
221 */
222
223 if (event->command == -1)
224 return(-1);
225
226 if (event->command == BRIGHTON_RESIZE)
227 {
228 dev->x = event->x;
229 dev->y = event->y;
230 dev->width = event->w;
231 dev->height = event->h;
232 /*
233 * We should consider altering the locations structure, so that
234 * event dispatching is correct.
235 */
236 if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
237 & BRIGHTON_CHECKBUTTON) == 0)
238 considercallback(dev);
239
240 brightonPanelLocation(dev->bwin,
241 dev->panel, dev->index, dev->x, dev->y, dev->width, dev->height);
242
243 /*
244 * We need to build in some shadow, to prevent the button from looking
245 * like it is hanging in mid air.
246 */
247 renderHighlights(dev->bwin, dev);
248
249 dev->lastvalue = -1;
250 displaybutton(dev);
251
252 return(0);
253 }
254
255 if (event->command == BRIGHTON_LEAVE)
256 {
257 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
258 & BRIGHTON_CHECKBUTTON)
259 {
260 dev->value = 0;
261
262 displaybutton(dev);
263 }
264 return(0);
265 }
266
267 if (event->command == BRIGHTON_ENTER)
268 {
269 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
270 & BRIGHTON_CHECKBUTTON)
271 {
272 dev->value = 1;
273
274 displaybutton(dev);
275 }
276 return(0);
277 }
278
279 if (event->command == BRIGHTON_BUTTONRELEASE)
280 {
281 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
282 & BRIGHTON_CHECKBUTTON)
283 {
284 dev->value = 0;
285
286 displaybutton(dev);
287
288 if ((event->x >= dev->x) && (event->y >= dev->y)
289 && (event->x < (dev->x + dev->width))
290 && (event->y < (dev->y + dev->height)))
291 considercallback(dev);
292 } else {
293 brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
294
295 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
296 & BRIGHTON_NO_TOGGLE)
297 {
298 if (dev->value == 0)
299 dev->value = panel->devlocn[dev->index].to;
300 else
301 dev->value = panel->devlocn[dev->index].from;
302
303 considercallback(dev);
304
305 displaybutton(dev);
306 }
307 }
308
309 return(0);
310 }
311
312 if (event->command == BRIGHTON_BUTTONPRESS)
313 {
314 brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
315
316 if (event->key == BRIGHTON_BUTTON2)
317 {
318 brightonRegisterController(dev);
319
320 return(0);
321 }
322 /*
323 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
324 & BRIGHTON_CHECKBUTTON)
325 return(0);
326 */
327 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags &
328 BRIGHTON_THREEWAY)
329 {
330 if (--dev->value < 0)
331 dev->value = 2;
332 } else if
333 (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags &
334 BRIGHTON_FIVEWAY)
335 {
336 if (--dev->value < 0)
337 dev->value = 4;
338 } else if (dev->value == 0)
339 dev->value = panel->devlocn[dev->index].to;
340 else
341 dev->value = panel->devlocn[dev->index].from;
342
343 if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
344 & BRIGHTON_CHECKBUTTON) == 0)
345 considercallback(dev);
346
347 displaybutton(dev);
348
349 return(0);
350 }
351
352 if (event->command == BRIGHTON_KEYPRESS)
353 {
354 brightonIResource *panel = &dev->bwin->app->resources[dev->panel];
355
356 if (event->key == 0x20)
357 {
358 if (dev->value == 0)
359 dev->value = panel->devlocn[dev->index].to;
360 else
361 dev->value = panel->devlocn[dev->index].from;
362
363 considercallback(dev);
364
365 displaybutton(dev);
366
367 return(0);
368 }
369 /*
370 * If this was not a space bar which we use to activate and de-activate
371 * any arbitrary button then it could be that we pressed some key that
372 * can otherwise be interpretted.
373 * This is awkward since here we are in a single button and I would
374 * like to use keypress to emulate a piano keyboard from the computer.
375 * These events would have to be delivered to the parent, not to the
376 * device, and the parent would then decide to which device the event
377 * should be delivered.
378 */
379 }
380
381 if (event->command == BRIGHTON_KEYRELEASE)
382 {
383 /*
384 * This is just to clear the event and repaint the key, we should not
385 * be bothered with the callback.
386 */
387 if (event->key == 0x20)
388 {
389 if (dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
390 & BRIGHTON_CHECKBUTTON)
391 {
392 dev->value = 0;
393
394 displaybutton(dev);
395
396 /* considercallback(dev); */
397 }
398 }
399 return(0);
400 }
401
402 if (event->command == BRIGHTON_PARAMCHANGE)
403 {
404 dev->value = event->value;
405 dev->lastvalue = -1;
406
407 if ((dev->bwin->app->resources[dev->panel].devlocn[dev->index].flags
408 & BRIGHTON_CHECKBUTTON) == 0)
409 considercallback(dev);
410
411 displaybutton(dev);
412
413 return(0);
414 }
415
416 return(0);
417 }
418
419 int *
createButton(brightonWindow * bwin,brightonDevice * dev,int index,char * bitmap)420 createButton(brightonWindow *bwin, brightonDevice *dev, int index, char *bitmap)
421 {
422 brightonIResource *panel = &bwin->app->resources[dev->panel];
423
424 /*printf("createButton(%s, %x)\n", bitmap, panel->devlocn[dev->index].image); */
425
426 dev->destroy = destroyButton;
427 dev->configure = configure;
428 dev->bwin = bwin;
429
430 if (bwin->app->resources[dev->panel].devlocn[dev->index].flags
431 & BRIGHTON_THREEWAY)
432 {
433 char path[256];
434
435 if (dev->image)
436 brightonFreeBitmap(bwin, dev->image);
437 if (dev->image2)
438 brightonFreeBitmap(bwin, dev->image2);
439 if (dev->imagec)
440 brightonFreeBitmap(bwin, dev->imagec);
441
442 sprintf(path, "bitmaps/buttons/%s1.xpm", bitmap);
443 if ((dev->image = brightonReadImage(bwin, path)) != 0)
444 {
445 sprintf(path, "bitmaps/buttons/%s2.xpm", bitmap);
446 if ((dev->image2 = brightonReadImage(bwin, path)) == 0)
447 dev->image2 =
448 brightonReadImage(bwin, "bitmaps/buttons/sw4.xpm");
449 sprintf(path, "bitmaps/buttons/%s3.xpm", bitmap);
450 if ((dev->imagec = brightonReadImage(bwin, path)) == 0)
451 dev->image2 =
452 brightonReadImage(bwin, "bitmaps/buttons/sw4.xpm");
453 } else {
454 dev->image = brightonReadImage(bwin, "bitmaps/buttons/sw5.xpm");
455 dev->image2 = brightonReadImage(bwin, "bitmaps/buttons/sw4.xpm");
456 dev->imagec = brightonReadImage(bwin, "bitmaps/buttons/sw3.xpm");
457 }
458 } else if (bwin->app->resources[dev->panel].devlocn[dev->index].flags
459 & BRIGHTON_FIVEWAY)
460 {
461 char path[256];
462
463 if (dev->image)
464 brightonFreeBitmap(bwin, dev->image);
465 if (dev->image2)
466 brightonFreeBitmap(bwin, dev->image2);
467 if (dev->image3)
468 brightonFreeBitmap(bwin, dev->image3);
469 if (dev->image4)
470 brightonFreeBitmap(bwin, dev->image4);
471 if (dev->imagec)
472 brightonFreeBitmap(bwin, dev->imagec);
473
474 sprintf(path, "bitmaps/buttons/%s1.xpm", bitmap);
475
476 if ((dev->image = brightonReadImage(bwin, path)) != 0)
477 {
478 sprintf(path, "bitmaps/buttons/%s2.xpm", bitmap);
479 if ((dev->image2 = brightonReadImage(bwin, path)) == 0)
480 dev->image2 =
481 brightonReadImage(bwin, "bitmaps/buttons/sw2.xpm");
482 sprintf(path, "bitmaps/buttons/%s3.xpm", bitmap);
483 if ((dev->image3 = brightonReadImage(bwin, path)) == 0)
484 dev->image3 =
485 brightonReadImage(bwin, "bitmaps/buttons/sw3.xpm");
486 sprintf(path, "bitmaps/buttons/%s4.xpm", bitmap);
487 if ((dev->image4 = brightonReadImage(bwin, path)) == 0)
488 dev->image4 =
489 brightonReadImage(bwin, "bitmaps/buttons/sw4.xpm");
490 sprintf(path, "bitmaps/buttons/%s5.xpm", bitmap);
491 if ((dev->imagec = brightonReadImage(bwin, path)) == 0)
492 dev->imagec =
493 brightonReadImage(bwin, "bitmaps/buttons/sw5.xpm");
494 } else {
495 dev->image = brightonReadImage(bwin, "bitmaps/buttons/sw1.xpm");
496 dev->image2 = brightonReadImage(bwin, "bitmaps/buttons/sw2.xpm");
497 dev->image3 = brightonReadImage(bwin, "bitmaps/buttons/sw3.xpm");
498 dev->image4 = brightonReadImage(bwin, "bitmaps/buttons/sw4.xpm");
499 dev->imagec = brightonReadImage(bwin, "bitmaps/buttons/sw5.xpm");
500 }
501
502 } else if (bitmap == NULL) {
503 if (dev->image)
504 brightonFreeBitmap(bwin, dev->image);
505 /*
506 * If we have been passed a specific image name for this device then
507 * use it.
508 */
509 if (panel->devlocn[dev->index].image != 0)
510 dev->image =
511 bwin->app->resources[dev->panel].devlocn[dev->index].image;
512 else
513 dev->image = brightonReadImage(bwin,
514 "bitmaps/buttons/rockerred.xpm");
515 if (panel->devlocn[dev->index].image2 != 0)
516 dev->image2 =
517 bwin->app->resources[dev->panel].devlocn[dev->index].image2;
518 else
519 dev->image =
520 brightonReadImage(bwin, "bitmaps/buttons/rockerred.xpm");
521 } else {
522 if (dev->image)
523 brightonFreeBitmap(bwin, dev->image);
524
525 if (panel->devlocn[dev->index].image != 0)
526 dev->image =
527 bwin->app->resources[dev->panel].devlocn[dev->index].image;
528 else
529 dev->image = brightonReadImage(bwin, bitmap);
530
531 if (dev->image2)
532 brightonFreeBitmap(bwin, dev->image2);
533
534 dev->image2 = brightonReadImage(bwin,
535 bwin->template->resources[dev->panel].devlocn[dev->index].image2);
536
537 /*
538 if (panel->devlocn[dev->index].image2 != 0)
539 dev->image2 =
540 bwin->app->resources[dev->panel].devlocn[dev->index].image2;
541 */
542 }
543
544 /*
545 * These will force an update when we first display ourselves.
546 */
547 dev->value = 0;
548 dev->lastvalue = -1;
549 dev->lastposition = -1;
550
551 return(0);
552 }
553
554