additional Andrew provided Termux mods +
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcpot.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcpot.h"
23 #include "bcresources.h"
24 #include "bccolors.h"
25 #include "keys.h"
26 #include "units.h"
27 #include "vframe.h"
28
29 #include <ctype.h>
30 #include <math.h>
31 #include <string.h>
32 #define MIN_ANGLE 225
33 #define MAX_ANGLE -45
34
35 BC_Pot::BC_Pot(int x, int y, VFrame **data)
36  : BC_SubWindow(x, y, -1, -1, -1)
37 {
38         this->data = data;
39         for(int i = 0; i < POT_STATES; i++)
40                 images[i] = 0;
41         use_caption = 1;
42         enabled = 1;
43 }
44
45 BC_Pot::~BC_Pot()
46 {
47         for(int i = 0; i < POT_STATES; i++)
48                 if(images[i]) delete images[i];
49 }
50
51 int BC_Pot::calculate_h()
52 {
53         return BC_WindowBase::get_resources()->pot_images[0]->get_h();
54 }
55
56 int BC_Pot::calculate_w()
57 {
58         return BC_WindowBase::get_resources()->pot_images[0]->get_w();
59 }
60
61 int BC_Pot::initialize()
62 {
63         if(!data)
64         {
65                 data = get_resources()->pot_images;
66         }
67
68         status = POT_UP;
69         set_data(data);
70         w = data[0]->get_w();
71         h = data[0]->get_h();
72         BC_SubWindow::initialize();
73         draw(0);
74         return 0;
75 }
76
77 int BC_Pot::reposition_window(int x, int y)
78 {
79         BC_WindowBase::reposition_window(x, y);
80         draw(0);
81         return 0;
82 }
83
84 int BC_Pot::set_data(VFrame **data)
85 {
86         for(int i = 0; i < POT_STATES; i++)
87                 if(images[i]) delete images[i];
88
89         for(int i = 0; i < POT_STATES; i++)
90                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
91         return 0;
92 }
93
94
95 void BC_Pot::set_use_caption(int value)
96 {
97         use_caption = value;
98 }
99
100
101 void BC_Pot::enable()
102 {
103         enabled = 1;
104         draw(1);
105 }
106
107 void BC_Pot::disable()
108 {
109         enabled = 0;
110         draw(1);
111 }
112
113
114 int BC_Pot::draw(int flush)
115 {
116         int x1, y1, x2, y2;
117         draw_top_background(parent_window, 0, 0, get_w(), get_h());
118         draw_pixmap(images[status]);
119         set_color(get_resources()->pot_needle_color);
120
121         angle_to_coords(x1, y1, x2, y2, percentage_to_angle(get_percentage()));
122         draw_line(x1, y1, x2, y2);
123
124         flash(flush);
125         return 0;
126 }
127
128 float BC_Pot::percentage_to_angle(float percentage)
129 {
130         return percentage * (MAX_ANGLE - MIN_ANGLE) + MIN_ANGLE;
131 }
132
133 float BC_Pot::angle_to_percentage(float angle)
134 {
135         return (angle - MIN_ANGLE) / (MAX_ANGLE - MIN_ANGLE);
136 }
137
138
139 int BC_Pot::angle_to_coords(int &x1, int &y1, int &x2, int &y2, float angle)
140 {
141         BC_Resources *resources = get_resources();
142         x1 = resources->pot_x1;
143         y1 = resources->pot_y1;
144         if(status == POT_DN)
145         {
146                 x1 += xS(resources->pot_offset);
147                 y1 += yS(resources->pot_offset);
148         }
149
150         while(angle < 0) angle += 360;
151
152         x2 = (int)(cos(angle / 360 * (2 * M_PI)) * resources->pot_r + x1);
153         y2 = (int)(-sin(angle / 360 * (2 * M_PI)) * resources->pot_r + y1);
154         return 0;
155 }
156
157 float BC_Pot::coords_to_angle(int x2, int y2)
158 {
159         int x1, y1, x, y;
160         float angle = 0.;
161
162         x1 = get_resources()->pot_x1;
163         y1 = get_resources()->pot_y1;
164         if(status == POT_DN)
165         {
166                 x1 += 2;
167                 y1 += 2;
168         }
169
170         x = x2 - x1;
171         y = y2 - y1;
172
173         if(x > 0 && y <= 0)
174         {
175                 angle = atan((float)-y / x) / (2 * M_PI) * 360;
176         }
177         else
178         if(x < 0 && y <= 0)
179         {
180                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
181         }
182         else
183         if(x < 0 && y > 0)
184         {
185                 angle = 180 - atan((float)-y / -x) / (2 * M_PI) * 360;
186         }
187         else
188         if(x > 0 && y > 0)
189         {
190                 angle = 360 + atan((float)-y / x) / (2 * M_PI) * 360;
191         }
192         else
193         if(x == 0 && y < 0)
194         {
195                 angle = 90;
196         }
197         else
198         if(x == 0 && y > 0)
199         {
200                 angle = 270;
201         }
202         else
203         if(x == 0 && y == 0)
204         {
205                 angle = 0;
206         }
207
208         return angle;
209 }
210
211
212
213
214 void BC_Pot::show_value_tooltip()
215 {
216         if(use_caption)
217         {
218                 set_tooltip(get_caption());
219                 show_tooltip(50);
220                 keypress_tooltip_timer = 2000;
221         }
222 }
223
224 int BC_Pot::repeat_event(int64_t duration)
225 {
226         if(duration == top_level->get_resources()->tooltip_delay)
227         {
228                 if(tooltip_on)
229                 {
230                         if(keypress_tooltip_timer > 0)
231                         {
232                                 keypress_tooltip_timer -= get_resources()->tooltip_delay;
233                         }
234                         else
235                         if(status != POT_HIGH && status != POT_DN)
236                         {
237                                 hide_tooltip();
238                         }
239                 }
240                 else
241                 if(status == POT_HIGH)
242                 {
243                         if(use_caption && tooltip_text)
244                         {
245                                 if(!tooltip_text[0] || isdigit(tooltip_text[0]))
246                                 {
247                                         set_tooltip(get_caption());
248                                         show_tooltip(50);
249                                 }
250                                 else
251                                         show_tooltip();
252                         }
253                         return 1;
254                 }
255         }
256         return 0;
257 }
258
259 int BC_Pot::keypress_event()
260 {
261         int result = 0;
262         switch(get_keypress())
263         {
264                 case UP:
265                         increase_value();
266                         result = 1;
267                         break;
268                 case DOWN:
269                         decrease_value();
270                         result = 1;
271                         break;
272                 case LEFT:
273                         decrease_value();
274                         result = 1;
275                         break;
276                 case RIGHT:
277                         increase_value();
278                         result = 1;
279                         break;
280         }
281
282         if(result)
283         {
284                 show_value_tooltip();
285                 draw(1);
286                 handle_event();
287                 return result;
288         }
289
290         return context_help_check_and_show();
291 }
292
293 int BC_Pot::cursor_enter_event()
294 {
295         if(top_level->event_win == win && enabled)
296         {
297                 if(!top_level->button_down && status == POT_UP)
298                 {
299                         status = POT_HIGH;
300                 }
301                 draw(1);
302         }
303         return 0;
304 }
305
306 int BC_Pot::cursor_leave_event()
307 {
308         if(status == POT_HIGH)
309         {
310                 status = POT_UP;
311                 draw(1);
312                 hide_tooltip();
313         }
314         return 0;
315 }
316
317 int BC_Pot::button_press_event()
318 {
319         if(!tooltip_on) top_level->hide_tooltip();
320         if(top_level->event_win == win && enabled)
321         {
322                 if(status == POT_HIGH || status == POT_UP)
323                 {
324                         if(get_buttonpress() == 4)
325                         {
326                                 increase_value();
327                                 show_value_tooltip();
328                                 draw(1);
329                                 handle_event();
330                         }
331                         else
332                         if(get_buttonpress() == 5)
333                         {
334                                 decrease_value();
335                                 show_value_tooltip();
336                                 draw(1);
337                                 handle_event();
338                         }
339                         else
340                         {
341                                 status = POT_DN;
342                                 start_cursor_angle = coords_to_angle(get_cursor_x(), get_cursor_y());
343                                 start_needle_angle = percentage_to_angle(get_percentage());
344                                 angle_offset = start_cursor_angle - start_needle_angle;
345                                 prev_angle = start_cursor_angle;
346                                 angle_correction = 0;
347                                 draw(1);
348                                 top_level->deactivate();
349                                 top_level->active_subwindow = this;
350                                 show_value_tooltip();
351                         }
352                         return 1;
353                 }
354         }
355         return 0;
356 }
357
358 int BC_Pot::button_release_event()
359 {
360         if(top_level->event_win == win)
361         {
362                 if(status == POT_DN)
363                 {
364                         if(cursor_inside())
365                                 status = POT_HIGH;
366                         else
367                         {
368                                 status = POT_UP;
369                                 top_level->hide_tooltip();
370                         }
371                 }
372                 draw(1);
373                 return 1;
374         }
375         return 0;
376 }
377
378 int BC_Pot::cursor_motion_event()
379 {
380         if(top_level->button_down &&
381                 top_level->event_win == win &&
382                 status == POT_DN)
383         {
384                 float angle = coords_to_angle(get_cursor_x(), get_cursor_y());
385
386                 if(prev_angle >= 0 && prev_angle < 90 &&
387                         angle >= 270 && angle < 360)
388                 {
389                         angle_correction -= 360;
390                 }
391                 else
392                 if(prev_angle >= 270 && prev_angle < 360 &&
393                         angle >= 0 && angle < 90)
394                 {
395                         angle_correction += 360;
396                 }
397
398                 prev_angle = angle;
399
400                 if(percentage_to_value(
401                         angle_to_percentage(angle + angle_correction - angle_offset)))
402                 {
403                         set_tooltip(get_caption());
404                         draw(1);
405                         handle_event();
406                 }
407                 return 1;
408         }
409         return 0;
410 }
411
412
413 BC_FPot::BC_FPot(int x, int y,
414         float value, float minvalue, float maxvalue, VFrame **data)
415  : BC_Pot(x, y, data)
416 {
417         this->value = value;
418         this->minvalue = minvalue;
419         this->maxvalue = maxvalue;
420         precision = 0.1;
421 }
422
423 BC_FPot::~BC_FPot()
424 {
425 }
426
427 int BC_FPot::increase_value()
428 {
429         value += precision;
430         if(value > maxvalue) value = maxvalue;
431         return 0;
432 }
433
434 int BC_FPot::decrease_value()
435 {
436         value -= precision;
437         if(value < minvalue) value = minvalue;
438         return 0;
439 }
440
441 void BC_FPot::set_precision(float value)
442 {
443         this->precision = value;
444 }
445
446 const char*  BC_FPot::get_caption()
447 {
448         sprintf(caption, "%.2f", value);
449         return caption;
450 }
451
452 float BC_FPot::get_percentage()
453 {
454         float range = maxvalue - minvalue;
455         return range > 0 ? (value - minvalue) / range : minvalue;
456 }
457
458 int BC_FPot::percentage_to_value(float percentage)
459 {
460         float old_value = value;
461         value = percentage * (maxvalue - minvalue) + minvalue;
462         value = Units::quantize(value, precision);
463         if(value < minvalue) value = minvalue;
464         if(value > maxvalue) value = maxvalue;
465         if(value != old_value) return 1;
466         return 0;
467 }
468
469 float BC_FPot::get_value()
470 {
471         return value;
472 }
473
474 void BC_FPot::update(float value)
475 {
476         if(value < minvalue) value= minvalue;
477         if(value > maxvalue) value= maxvalue;
478         if(value != this->value)
479         {
480                 this->value = value;
481                 draw(1);
482         }
483 }
484
485 void BC_FPot::update(float value, float minvalue, float maxvalue)
486 {
487         if(value != this->value ||
488                 minvalue != this->minvalue ||
489                 maxvalue != this->maxvalue)
490         {
491                 this->value = value;
492                 this->minvalue = minvalue;
493                 this->maxvalue = maxvalue;
494                 draw(1);
495         }
496 }
497
498
499 BC_IPot::BC_IPot(int x, int y,
500         int64_t value, int64_t minvalue, int64_t maxvalue, VFrame **data)
501  : BC_Pot(x, y, data)
502 {
503         this->value = value;
504         this->minvalue = minvalue;
505         this->maxvalue = maxvalue;
506 }
507
508 BC_IPot::~BC_IPot()
509 {
510 }
511
512 int BC_IPot::increase_value()
513 {
514         value++;
515         if(value > maxvalue) value = maxvalue;
516         return 0;
517 }
518
519 int BC_IPot::decrease_value()
520 {
521         value--;
522         if(value < minvalue) value = minvalue;
523         return 0;
524 }
525
526 const char* BC_IPot::get_caption()
527 {
528         sprintf(caption, "%jd", value);
529         return caption;
530 }
531
532 float BC_IPot::get_percentage()
533 {
534         float range = maxvalue - minvalue;
535         return range > 0 ? ((float)value - minvalue) / range : minvalue;
536 }
537
538 int BC_IPot::percentage_to_value(float percentage)
539 {
540         int64_t old_value = value;
541         value = (int64_t)(percentage * (maxvalue - minvalue) + minvalue);
542         if(value < minvalue) value = minvalue;
543         if(value > maxvalue) value = maxvalue;
544         if(value != old_value) return 1;
545         return 0;
546 }
547
548 int64_t BC_IPot::get_value()
549 {
550         return value;
551 }
552
553 void BC_IPot::update(int64_t value)
554 {
555         if(value < minvalue) value= minvalue;
556         if(value > maxvalue) value= maxvalue;
557         if(this->value != value)
558         {
559                 this->value = value;
560                 draw(1);
561         }
562 }
563
564 void BC_IPot::update(int64_t value, int64_t minvalue, int64_t maxvalue)
565 {
566         if(this->value != value ||
567                 this->minvalue != minvalue ||
568                 this->maxvalue != maxvalue)
569         {
570                 this->value = value;
571                 this->minvalue = minvalue;
572                 this->maxvalue = maxvalue;
573                 draw(1);
574         }
575 }
576
577
578 BC_QPot::BC_QPot(int x, int y, int64_t value, VFrame **data)
579  : BC_Pot(x, y, data)
580 {
581         this->value = Freq::fromfreq(value);
582         this->minvalue = 0;
583         this->maxvalue = TOTALFREQS;
584 }
585
586 BC_QPot::~BC_QPot()
587 {
588 }
589
590 int BC_QPot::increase_value()
591 {
592         value++;
593         if(value > maxvalue) value = maxvalue;
594         return 0;
595 }
596
597 int BC_QPot::decrease_value()
598 {
599         value--;
600         if(value < minvalue) value = minvalue;
601         return 0;
602 }
603
604 const char* BC_QPot::get_caption()
605 {
606         sprintf(caption, "%d", Freq::tofreq(value));
607         return caption;
608 }
609
610 float BC_QPot::get_percentage()
611 {
612         float range = maxvalue - minvalue;
613         return range > 0 ? ((float)value - minvalue) / range : 0;
614 }
615
616 int BC_QPot::percentage_to_value(float percentage)
617 {
618         int64_t old_value = value;
619         value = (int64_t)(percentage * (maxvalue - minvalue) + minvalue);
620         if(value < minvalue) value = minvalue;
621         if(value > maxvalue) value = maxvalue;
622         if(value != old_value) return 1;
623         return 0;
624 }
625
626 int64_t BC_QPot::get_value()
627 {
628         return Freq::tofreq(value);
629 }
630
631 void BC_QPot::update(int64_t value)
632 {
633         value = Freq::fromfreq(value);
634         if(value < minvalue) value = minvalue;
635         if(value > maxvalue) value = maxvalue;
636         if(this->value != value)
637         {
638                 this->value = value;
639                 draw(1);
640         }
641 }
642
643
644 BC_PercentagePot::BC_PercentagePot(int x, int y,
645         float value, float minvalue, float maxvalue, VFrame **data)
646  : BC_Pot(x, y, data)
647 {
648         this->value = value;
649         this->minvalue = minvalue;
650         this->maxvalue = maxvalue;
651 }
652
653 BC_PercentagePot::~BC_PercentagePot()
654 {
655 }
656
657 int BC_PercentagePot::increase_value()
658 {
659         value++;
660         if(value > maxvalue) value = maxvalue;
661         return 0;
662 }
663
664 int BC_PercentagePot::decrease_value()
665 {
666         value--;
667         if(value < minvalue) value = minvalue;
668         return 0;
669 }
670
671 const char* BC_PercentagePot::get_caption()
672 {
673         sprintf(caption, "%d%%", (int)(get_percentage() * 100 + 0.5));
674         return caption;
675 }
676
677 float BC_PercentagePot::get_percentage()
678 {
679         float range = maxvalue - minvalue;
680         return range > 0 ? (value - minvalue) / range : minvalue;
681 }
682
683 int BC_PercentagePot::percentage_to_value(float percentage)
684 {
685         float old_value = value;
686         value = percentage * (maxvalue - minvalue) + minvalue;
687         if(value < minvalue) value = minvalue;
688         if(value > maxvalue) value = maxvalue;
689         if(value != old_value) return 1;
690         return 0;
691 }
692
693 float BC_PercentagePot::get_value()
694 {
695         return value;
696 }
697
698 void BC_PercentagePot::update(float value)
699 {
700         if(value < minvalue) value= minvalue;
701         if(value > maxvalue) value= maxvalue;
702         if(this->value != value)
703         {
704                 this->value = value;
705                 draw(1);
706         }
707 }
708