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