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