upgrade libvpx+lv2, fix dbl tap play bug, add multi nest/unnest clips, add del top...
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcslider.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 "bcpixmap.h"
23 #include "bcresources.h"
24 #include "bcslider.h"
25 #include "bccolors.h"
26 #include "fonts.h"
27 #include "keys.h"
28 #include "units.h"
29 #include "vframe.h"
30
31
32
33 #include <ctype.h>
34 #include <string.h>
35
36
37
38 BC_Slider::BC_Slider(int x,
39                 int y,
40                 int pixels,
41                 int pointer_motion_range,
42                 VFrame **images,
43                 int show_number,
44                 int vertical,
45                 int use_caption)
46  : BC_SubWindow(x, y, 0, 0, -1)
47 {
48         this->images = images;
49         this->show_number = show_number;
50         this->vertical = vertical;
51         this->pointer_motion_range = pointer_motion_range;
52         this->pixels = pixels;
53         this->button_pixel = button_pixel;
54         this->use_caption = use_caption;
55
56         status = SLIDER_UP;
57         pixmaps = new BC_Pixmap*[SLIDER_IMAGES];
58         for(int i = 0; i < SLIDER_IMAGES; i++)
59         {
60                 pixmaps[i] = 0;
61         }
62         button_down = 0;
63         enabled = 1;
64         active = 0;
65 }
66
67 BC_Slider::~BC_Slider()
68 {
69         for(int i = 0; i < SLIDER_IMAGES; i++)
70         {
71                 if(pixmaps[i]) delete pixmaps[i];
72         }
73         if(pixmaps) delete [] pixmaps;
74 }
75
76 int BC_Slider::initialize()
77 {
78         if(!images)
79         {
80                 this->images = vertical ?
81                         BC_WindowBase::get_resources()->vertical_slider_data :
82                         BC_WindowBase::get_resources()->horizontal_slider_data;
83         }
84
85         set_images(images);
86
87         if(vertical)
88         {
89                 w = images[SLIDER_BG_UP]->get_w();
90                 h = pixels;
91         }
92         else
93         {
94                 w = pixels;
95                 h = images[SLIDER_BG_UP]->get_h();
96         }
97
98         text_height = get_text_height(SMALLFONT);
99         button_pixel = value_to_pixel();
100
101         BC_SubWindow::initialize();
102         draw_face(0);
103         show_window(0);
104         return 0;
105 }
106
107 int BC_Slider::get_span(int vertical)
108 {
109         if(vertical)
110         {
111                 return BC_WindowBase::get_resources()->vertical_slider_data[0]->get_w();
112         }
113         else
114         {
115                 return BC_WindowBase::get_resources()->horizontal_slider_data[0]->get_h();
116         }
117 }
118
119 int BC_Slider::draw_face(int flush)
120 {
121 // Clear background
122         draw_top_background(parent_window, 0, 0, get_w(), get_h());
123
124
125         if(vertical)
126         {
127                 draw_3segmentv(0,
128                         0,
129                         get_h(),
130                         pixmaps[SLIDER_IMAGES / 2 + status]);
131                 draw_pixmap(pixmaps[status], 0, button_pixel);
132                 if(use_caption)
133                 {
134                         set_color(RED);
135                         set_font(SMALLFONT);
136                         draw_text(0, h, get_caption());
137                 }
138         }
139         else
140         {
141                 //int y = get_h() / 2 - pixmaps[SLIDER_IMAGES / 2 + status]->get_h() / 2;
142                 draw_3segmenth(0, 0, get_w(), pixmaps[SLIDER_IMAGES / 2 + status]);
143                 draw_pixmap(pixmaps[status], button_pixel, 0);
144                 if(use_caption)
145                 {
146                         set_color(RED);
147                         set_font(SMALLFONT);
148                         draw_text(0, h, get_caption());
149                 }
150         }
151
152         flash(flush);
153         return 0;
154 }
155
156 int BC_Slider::set_images(VFrame **images)
157 {
158         for(int i = 0; i < SLIDER_IMAGES; i++)
159         {
160                 if(pixmaps[i]) delete pixmaps[i];
161                 pixmaps[i] = new BC_Pixmap(parent_window, images[i], PIXMAP_ALPHA);
162         }
163         return 0;
164 }
165
166 int BC_Slider::get_button_pixels()
167 {
168         return vertical ? pixmaps[SLIDER_UP]->get_h() :
169                 pixmaps[SLIDER_UP]->get_w();
170 }
171
172 void BC_Slider::show_value_tooltip()
173 {
174         if( !show_number ) return;
175 //printf("BC_Slider::show_value_tooltip %s\n", get_caption());
176         set_tooltip(get_caption());
177         keypress_tooltip_timer = 2000;
178         show_tooltip(50);
179 }
180
181
182 int BC_Slider::repeat_event(int64_t duration)
183 {
184         if(duration == top_level->get_resources()->tooltip_delay)
185         {
186                 if(tooltip_on)
187                 {
188                         if(keypress_tooltip_timer > 0)
189                         {
190                                 keypress_tooltip_timer -= get_resources()->tooltip_delay;
191                         }
192                         else
193                         if(status != SLIDER_HI && status != SLIDER_DN)
194                         {
195                                 hide_tooltip();
196                         }
197                 }
198                 else
199                 if(status == SLIDER_HI && tooltip_text && show_number)
200                 {
201                         if(!tooltip_text[0] || isdigit(tooltip_text[0]))
202                         {
203                                 set_tooltip(get_caption());
204                                 show_tooltip(50);
205                         }
206                         else
207                         {
208 //printf("BC_Slider::repeat_event 1 %s\n", tooltip_text);
209                                 set_tooltip(get_caption());
210                                 show_tooltip();
211                         }
212                         return 1;
213                 }
214         }
215         return 0;
216 }
217
218
219 int BC_Slider::keypress_event()
220 {
221         int result = 0;
222         if(!active || !enabled) return 0;
223         if(ctrl_down() || shift_down()) return 0;
224
225         switch(get_keypress())
226         {
227                 case UP:
228                         increase_value_big();
229                         result = 1;
230                         break;
231                 case DOWN:
232                         decrease_value_big();
233                         result = 1;
234                         break;
235                 case LEFT:
236                         decrease_value();
237                         result = 1;
238                         break;
239                 case RIGHT:
240                         increase_value();
241                         result = 1;
242                         break;
243         }
244
245         if(result)
246         {
247                 handle_event();
248                 show_value_tooltip();
249                 draw_face(1);
250         }
251         return result;
252 }
253
254 int BC_Slider::cursor_enter_event()
255 {
256 //printf("BC_Slider::cursor_enter_event 1\n");
257         if(top_level->event_win == win && status == SLIDER_UP)
258         {
259                 status = SLIDER_HI;
260                 draw_face(1);
261         }
262 //printf("BC_Slider::cursor_enter_event 2\n");
263         return 0;
264 }
265
266 int BC_Slider::cursor_leave_event()
267 {
268         if(status == SLIDER_HI)
269         {
270                 status = SLIDER_UP;
271                 draw_face(1);
272                 hide_tooltip();
273         }
274         return 0;
275 }
276
277 int BC_Slider::deactivate()
278 {
279         active = 0;
280         return 0;
281 }
282
283 int BC_Slider::activate()
284 {
285         top_level->active_subwindow = this;
286         active = 1;
287         return 0;
288 }
289
290 void BC_Slider::enable()
291 {
292         enabled = 1;
293         draw_face(1);
294 }
295
296 void BC_Slider::disable()
297 {
298         enabled = 0;
299         draw_face(1);
300 }
301
302 void BC_Slider::enable_show_value(int v)
303 {
304         show_number = v;
305 }
306
307 int BC_Slider::button_press_event()
308 {
309         int result = 0;
310         if(is_event_win() && enabled)
311         {
312                 if(!tooltip_on) top_level->hide_tooltip();
313                 if(status == SLIDER_HI)
314                 {
315                         if(get_buttonpress() == 4)
316                         {
317                                 increase_value();
318                                 handle_event();
319                                 show_value_tooltip();
320                                 draw_face(1);
321                         }
322                         else
323                         if(get_buttonpress() == 5)
324                         {
325                                 decrease_value();
326                                 handle_event();
327                                 show_value_tooltip();
328                                 draw_face(1);
329                         }
330                         else
331                         if(get_buttonpress() == 1)
332                         {
333                                 button_down = 1;
334                                 status = SLIDER_DN;
335                                 draw_face(1);
336                                 init_selection(top_level->cursor_x, top_level->cursor_y);
337                                 top_level->deactivate();
338                                 activate();
339                                 show_value_tooltip();
340                         }
341                         result = 1;
342                 }
343         }
344         return result;
345 }
346
347 int BC_Slider::button_release_event()
348 {
349         if(button_down)
350         {
351                 button_down = 0;
352                 if(cursor_inside())
353                         status = SLIDER_HI;
354                 else
355                 {
356                         status = SLIDER_UP;
357                         top_level->hide_tooltip();
358                 }
359                 draw_face(1);
360                 return 1;
361         }
362         return 0;
363 }
364
365 int BC_Slider::cursor_motion_event()
366 {
367         if(button_down)
368         {
369                 int old_pixel = button_pixel;
370                 int result = update_selection(top_level->cursor_x, top_level->cursor_y);
371                 if(button_pixel != old_pixel) draw_face(1);
372                 if(result)
373                 {
374                         handle_event();
375                         set_tooltip(get_caption());
376                 }
377                 return 1;
378         }
379         return 0;
380 }
381
382 int BC_Slider::reposition_window(int x, int y, int w, int h)
383 {
384         BC_SubWindow::reposition_window(x, y, w, h);
385         button_pixel = value_to_pixel();
386         draw_face(0);
387         return 0;
388 }
389
390
391 int BC_Slider::get_pointer_motion_range()
392 {
393         return pointer_motion_range;
394 }
395
396 void BC_Slider::set_pointer_motion_range(int value)
397 {
398         pointer_motion_range = value;
399 }
400
401
402
403
404
405 BC_ISlider::BC_ISlider(int x,
406                         int y,
407                         int vertical,
408                         int pixels,
409                         int pointer_motion_range,
410                         int64_t minvalue,
411                         int64_t maxvalue,
412                         int64_t value,
413                         int use_caption,
414                         VFrame **data,
415                         int *output)
416  : BC_Slider(x,
417                 y,
418                 pixels,
419                 pointer_motion_range,
420                 data,
421                 1,
422                 vertical,
423                 use_caption)
424 {
425         this->minvalue = minvalue;
426         this->maxvalue = maxvalue;
427         this->value = value;
428         this->output = output;
429 }
430
431 int BC_ISlider::value_to_pixel()
432 {
433         if(maxvalue == minvalue) return 0;
434         else
435         {
436                 if(vertical)
437                         return (int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) *
438                                 (get_h() - get_button_pixels()));
439                 else
440                         return (int)((double)(value - minvalue) / (maxvalue - minvalue) *
441                                 (get_w() - get_button_pixels()));
442         }
443 }
444
445 int BC_ISlider::update(int64_t value)
446 {
447         if(this->value != value)
448         {
449                 this->value = value;
450                 int old_pixel = button_pixel;
451                 button_pixel = value_to_pixel();
452                 if(button_pixel != old_pixel) draw_face(1);
453         }
454         return 0;
455 }
456
457 int BC_ISlider::update(int pointer_motion_range,
458         int64_t value,
459         int64_t minvalue,
460         int64_t maxvalue)
461 {
462         this->minvalue = minvalue;
463         this->maxvalue = maxvalue;
464         this->value = value;
465         this->pointer_motion_range = pointer_motion_range;
466
467         int old_pixel = button_pixel;
468         button_pixel = value_to_pixel();
469         if(button_pixel != old_pixel) draw_face(1);
470         return 0;
471 }
472
473
474 int64_t BC_ISlider::get_value()
475 {
476         return value;
477 }
478
479 int64_t BC_ISlider::get_length()
480 {
481         return maxvalue - minvalue;
482 }
483
484 char* BC_ISlider::get_caption()
485 {
486         sprintf(caption, "%jd", value);
487         return caption;
488 }
489
490 int BC_ISlider::increase_value()
491 {
492         value++;
493         if(value > maxvalue) value = maxvalue;
494         button_pixel = value_to_pixel();
495         return 0;
496 }
497
498 int BC_ISlider::decrease_value()
499 {
500         value--;
501         if(value < minvalue) value = minvalue;
502         button_pixel = value_to_pixel();
503         return 0;
504 }
505
506 int BC_ISlider::increase_value_big()
507 {
508         value+=10;
509         if(value > maxvalue) value = maxvalue;
510         button_pixel = value_to_pixel();
511         return 0;
512 }
513
514 int BC_ISlider::decrease_value_big()
515 {
516         value-=10;
517         if(value < minvalue) value = minvalue;
518         button_pixel = value_to_pixel();
519         return 0;
520 }
521
522 int BC_ISlider::init_selection(int cursor_x, int cursor_y)
523 {
524         if(vertical)
525         {
526                 min_pixel = -(int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) * pointer_motion_range);
527                 min_pixel += cursor_y;
528         }
529         else
530         {
531                 min_pixel = -(int)((double)(value - minvalue) / (maxvalue - minvalue) * pointer_motion_range);
532                 min_pixel += cursor_x;
533         }
534         max_pixel = min_pixel + pointer_motion_range;
535         return 0;
536 }
537
538 int BC_ISlider::update_selection(int cursor_x, int cursor_y)
539 {
540         int64_t old_value = value;
541
542         if(vertical)
543         {
544                 value = (int64_t)((1.0 - (double)(cursor_y - min_pixel) /
545                         pointer_motion_range) *
546                         (maxvalue - minvalue) +
547                         minvalue);
548         }
549         else
550         {
551                 value = (int64_t)((double)(cursor_x - min_pixel) /
552                         pointer_motion_range *
553                         (maxvalue - minvalue) +
554                         minvalue);
555         }
556
557         if(value > maxvalue) value = maxvalue;
558         if(value < minvalue) value = minvalue;
559         button_pixel = value_to_pixel();
560
561         if(old_value != value)
562         {
563                 return 1;
564         }
565         return 0;
566 }
567
568 int BC_ISlider::handle_event()
569 {
570         if(output) *output = get_value();
571         return 1;
572 }
573
574
575
576
577
578
579
580
581 BC_FSlider::BC_FSlider(int x,
582                         int y,
583                         int vertical,
584                         int pixels,
585                         int pointer_motion_range,
586                         float minvalue,
587                         float maxvalue,
588                         float value,
589                         int use_caption,
590                         VFrame **data)
591  : BC_Slider(x,
592                 y,
593                 pixels,
594                 pointer_motion_range,
595                 data,
596                 1,
597                 vertical,
598                 use_caption)
599 {
600         this->minvalue = minvalue;
601         this->maxvalue = maxvalue;
602         this->value = value;
603         this->precision = 0.1;
604         this->small_change = 0.1;
605         this->big_change = 1.0;
606 }
607
608 int BC_FSlider::value_to_pixel()
609 {
610 //printf("BC_FSlider::value_to_pixel %f %f\n", maxvalue, minvalue);
611         if(maxvalue == minvalue) return 0;
612         {
613                 if(vertical)
614                         return (int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) *
615                                 (get_h() - get_button_pixels()));
616                 else
617                         return (int)((double)(value - minvalue) / (maxvalue - minvalue) *
618                                 (get_w() - get_button_pixels()));
619         }
620 }
621
622 int BC_FSlider::update(float value)
623 {
624         if(this->value != value)
625         {
626                 this->value = value;
627                 int old_pixel = button_pixel;
628                 button_pixel = value_to_pixel();
629 //printf("BC_FSlider::update 1 %f %d\n", value, button_pixel);
630                 if(button_pixel != old_pixel) draw_face(1);
631         }
632         return 0;
633 }
634
635 int BC_FSlider::update(int pointer_motion_range, float value, float minvalue, float maxvalue)
636 {
637         this->minvalue = minvalue;
638         this->maxvalue = maxvalue;
639         this->value = value;
640         this->pointer_motion_range = pointer_motion_range;
641         int old_pixel = button_pixel;
642         button_pixel = value_to_pixel();
643         if(button_pixel != old_pixel) draw_face(1);
644         return 0;
645 }
646
647
648 float BC_FSlider::get_value()
649 {
650         return value;
651 }
652
653 float BC_FSlider::get_length()
654 {
655         return maxvalue - minvalue;
656 }
657
658 char* BC_FSlider::get_caption()
659 {
660         sprintf(caption, "%.02f", value);
661         return caption;
662 }
663
664 int BC_FSlider::increase_value()
665 {
666         value += small_change;
667         if(value > maxvalue) value = maxvalue;
668         button_pixel = value_to_pixel();
669         return 0;
670 }
671
672 int BC_FSlider::decrease_value()
673 {
674         value -= small_change;
675         if(value < minvalue) value = minvalue;
676         button_pixel = value_to_pixel();
677         return 0;
678 }
679
680 int BC_FSlider::increase_value_big()
681 {
682         value += big_change;
683         if(value > maxvalue) value = maxvalue;
684         button_pixel = value_to_pixel();
685         return 0;
686 }
687
688 int BC_FSlider::decrease_value_big()
689 {
690         value -= big_change;
691         if(value < minvalue) value = minvalue;
692         button_pixel = value_to_pixel();
693         return 0;
694 }
695
696 int BC_FSlider::init_selection(int cursor_x, int cursor_y)
697 {
698         if(vertical)
699         {
700                 min_pixel = -(int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) * pointer_motion_range);
701                 min_pixel += cursor_y;
702         }
703         else
704         {
705                 min_pixel = -(int)((double)(value - minvalue) / (maxvalue - minvalue) * pointer_motion_range);
706                 min_pixel += cursor_x;
707         }
708         max_pixel = min_pixel + pointer_motion_range;
709         return 0;
710 }
711
712 int BC_FSlider::update_selection(int cursor_x, int cursor_y)
713 {
714         float old_value = value;
715
716
717         if(vertical)
718         {
719                 value = ((1.0 - (double)(cursor_y - min_pixel) /
720                         pointer_motion_range) *
721                         (maxvalue - minvalue) +
722                         minvalue);
723         }
724         else
725         {
726                 value = ((double)(cursor_x - min_pixel) /
727                         pointer_motion_range *
728                         (maxvalue - minvalue) +
729                         minvalue);
730         }
731
732         value = Units::quantize(value, precision);
733         if(value > maxvalue) value = maxvalue;
734         if(value < minvalue) value = minvalue;
735         button_pixel = value_to_pixel();
736 // printf("BC_FSlider::update_selection 1 %d %d %d %d %f %f\n",
737 // pointer_motion_range,
738 // min_pixel,
739 // max_pixel,
740 // cursor_x,
741 // precision,
742 // value);
743
744         if(old_value != value)
745         {
746                 return 1;
747         }
748         return 0;
749 }
750
751 void BC_FSlider::set_precision(float value)
752 {
753         this->precision = value;
754 }
755
756 void BC_FSlider::set_pagination(float small_change, float big_change)
757 {
758         this->small_change = small_change;
759         this->big_change = big_change;
760 }
761
762
763 BC_PercentageSlider::BC_PercentageSlider(int x,
764                         int y,
765                         int vertical,
766                         int pixels,
767                         int pointer_motion_range,
768                         float minvalue,
769                         float maxvalue,
770                         float value,
771                         int use_caption,
772                         VFrame **data)
773  : BC_FSlider(x,
774                         y,
775                         vertical,
776                         pixels,
777                         pointer_motion_range,
778                         minvalue,
779                         maxvalue,
780                         value,
781                         use_caption,
782                         data)
783 {
784 }
785
786 char* BC_PercentageSlider::get_caption()
787 {
788         sprintf(caption, "%.0f%%", floor((value - minvalue) / (maxvalue - minvalue) * 100));
789         return caption;
790 }
791