add view thumbnail size pref, rework vicon view popup, add view popup zoom scale
[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 //printf("BC_Slider::show_value_tooltip %s\n", get_caption());
175         set_tooltip(get_caption());
176         keypress_tooltip_timer = 2000;
177         show_tooltip(50);
178 }
179
180
181 int BC_Slider::repeat_event(int64_t duration)
182 {
183         if(duration == top_level->get_resources()->tooltip_delay)
184         {
185                 if(tooltip_on)
186                 {
187                         if(keypress_tooltip_timer > 0)
188                         {
189                                 keypress_tooltip_timer -= get_resources()->tooltip_delay;
190                         }
191                         else
192                         if(status != SLIDER_HI && status != SLIDER_DN)
193                         {
194                                 hide_tooltip();
195                         }
196                 }
197                 else
198                 if(status == SLIDER_HI && tooltip_text)
199                 {
200                         if(!tooltip_text[0] || isdigit(tooltip_text[0]))
201                         {
202                                 set_tooltip(get_caption());
203                                 show_tooltip(50);
204                         }
205                         else
206                         {
207 //printf("BC_Slider::repeat_event 1 %s\n", tooltip_text);
208                                 set_tooltip(get_caption());
209                                 show_tooltip();
210                         }
211                         return 1;
212                 }
213         }
214         return 0;
215 }
216
217
218 int BC_Slider::keypress_event()
219 {
220         int result = 0;
221         if(!active || !enabled) return 0;
222         if(ctrl_down() || shift_down()) return 0;
223
224         switch(get_keypress())
225         {
226                 case UP:
227                         increase_value_big();
228                         result = 1;
229                         break;
230                 case DOWN:
231                         decrease_value_big();
232                         result = 1;
233                         break;
234                 case LEFT:
235                         decrease_value();
236                         result = 1;
237                         break;
238                 case RIGHT:
239                         increase_value();
240                         result = 1;
241                         break;
242         }
243
244         if(result)
245         {
246                 handle_event();
247                 show_value_tooltip();
248                 draw_face(1);
249         }
250         return result;
251 }
252
253 int BC_Slider::cursor_enter_event()
254 {
255 //printf("BC_Slider::cursor_enter_event 1\n");
256         if(top_level->event_win == win && status == SLIDER_UP)
257         {
258                 status = SLIDER_HI;
259                 draw_face(1);
260         }
261 //printf("BC_Slider::cursor_enter_event 2\n");
262         return 0;
263 }
264
265 int BC_Slider::cursor_leave_event()
266 {
267         if(status == SLIDER_HI)
268         {
269                 status = SLIDER_UP;
270                 draw_face(1);
271                 hide_tooltip();
272         }
273         return 0;
274 }
275
276 int BC_Slider::deactivate()
277 {
278         active = 0;
279         return 0;
280 }
281
282 int BC_Slider::activate()
283 {
284         top_level->active_subwindow = this;
285         active = 1;
286         return 0;
287 }
288
289 void BC_Slider::enable()
290 {
291         enabled = 1;
292         draw_face(1);
293 }
294
295 void BC_Slider::disable()
296 {
297         enabled = 0;
298         draw_face(1);
299 }
300
301 int BC_Slider::button_press_event()
302 {
303         int result = 0;
304         if(is_event_win() && enabled)
305         {
306                 if(!tooltip_on) top_level->hide_tooltip();
307                 if(status == SLIDER_HI)
308                 {
309                         if(get_buttonpress() == 4)
310                         {
311                                 increase_value();
312                                 handle_event();
313                                 show_value_tooltip();
314                                 draw_face(1);
315                         }
316                         else
317                         if(get_buttonpress() == 5)
318                         {
319                                 decrease_value();
320                                 handle_event();
321                                 show_value_tooltip();
322                                 draw_face(1);
323                         }
324                         else
325                         if(get_buttonpress() == 1)
326                         {
327                                 button_down = 1;
328                                 status = SLIDER_DN;
329                                 draw_face(1);
330                                 init_selection(top_level->cursor_x, top_level->cursor_y);
331                                 top_level->deactivate();
332                                 activate();
333                                 show_value_tooltip();
334                         }
335                         result = 1;
336                 }
337         }
338         return result;
339 }
340
341 int BC_Slider::button_release_event()
342 {
343         if(button_down)
344         {
345                 button_down = 0;
346                 if(cursor_inside())
347                         status = SLIDER_HI;
348                 else
349                 {
350                         status = SLIDER_UP;
351                         top_level->hide_tooltip();
352                 }
353                 draw_face(1);
354                 return 1;
355         }
356         return 0;
357 }
358
359 int BC_Slider::cursor_motion_event()
360 {
361         if(button_down)
362         {
363                 int old_pixel = button_pixel;
364                 int result = update_selection(top_level->cursor_x, top_level->cursor_y);
365                 if(button_pixel != old_pixel) draw_face(1);
366                 if(result)
367                 {
368                         handle_event();
369                         set_tooltip(get_caption());
370                 }
371                 return 1;
372         }
373         return 0;
374 }
375
376 int BC_Slider::reposition_window(int x, int y, int w, int h)
377 {
378         BC_SubWindow::reposition_window(x, y, w, h);
379         button_pixel = value_to_pixel();
380         draw_face(0);
381         return 0;
382 }
383
384
385 int BC_Slider::get_pointer_motion_range()
386 {
387         return pointer_motion_range;
388 }
389
390 void BC_Slider::set_pointer_motion_range(int value)
391 {
392         pointer_motion_range = value;
393 }
394
395
396
397
398
399 BC_ISlider::BC_ISlider(int x,
400                         int y,
401                         int vertical,
402                         int pixels,
403                         int pointer_motion_range,
404                         int64_t minvalue,
405                         int64_t maxvalue,
406                         int64_t value,
407                         int use_caption,
408                         VFrame **data,
409                         int *output)
410  : BC_Slider(x,
411                 y,
412                 pixels,
413                 pointer_motion_range,
414                 data,
415                 1,
416                 vertical,
417                 use_caption)
418 {
419         this->minvalue = minvalue;
420         this->maxvalue = maxvalue;
421         this->value = value;
422         this->output = output;
423 }
424
425 int BC_ISlider::value_to_pixel()
426 {
427         if(maxvalue == minvalue) return 0;
428         else
429         {
430                 if(vertical)
431                         return (int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) *
432                                 (get_h() - get_button_pixels()));
433                 else
434                         return (int)((double)(value - minvalue) / (maxvalue - minvalue) *
435                                 (get_w() - get_button_pixels()));
436         }
437 }
438
439 int BC_ISlider::update(int64_t value)
440 {
441         if(this->value != value)
442         {
443                 this->value = value;
444                 int old_pixel = button_pixel;
445                 button_pixel = value_to_pixel();
446                 if(button_pixel != old_pixel) draw_face(1);
447         }
448         return 0;
449 }
450
451 int BC_ISlider::update(int pointer_motion_range,
452         int64_t value,
453         int64_t minvalue,
454         int64_t maxvalue)
455 {
456         this->minvalue = minvalue;
457         this->maxvalue = maxvalue;
458         this->value = value;
459         this->pointer_motion_range = pointer_motion_range;
460
461         int old_pixel = button_pixel;
462         button_pixel = value_to_pixel();
463         if(button_pixel != old_pixel) draw_face(1);
464         return 0;
465 }
466
467
468 int64_t BC_ISlider::get_value()
469 {
470         return value;
471 }
472
473 int64_t BC_ISlider::get_length()
474 {
475         return maxvalue - minvalue;
476 }
477
478 char* BC_ISlider::get_caption()
479 {
480         sprintf(caption, "%jd", value);
481         return caption;
482 }
483
484 int BC_ISlider::increase_value()
485 {
486         value++;
487         if(value > maxvalue) value = maxvalue;
488         button_pixel = value_to_pixel();
489         return 0;
490 }
491
492 int BC_ISlider::decrease_value()
493 {
494         value--;
495         if(value < minvalue) value = minvalue;
496         button_pixel = value_to_pixel();
497         return 0;
498 }
499
500 int BC_ISlider::increase_value_big()
501 {
502         value+=10;
503         if(value > maxvalue) value = maxvalue;
504         button_pixel = value_to_pixel();
505         return 0;
506 }
507
508 int BC_ISlider::decrease_value_big()
509 {
510         value-=10;
511         if(value < minvalue) value = minvalue;
512         button_pixel = value_to_pixel();
513         return 0;
514 }
515
516 int BC_ISlider::init_selection(int cursor_x, int cursor_y)
517 {
518         if(vertical)
519         {
520                 min_pixel = -(int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) * pointer_motion_range);
521                 min_pixel += cursor_y;
522         }
523         else
524         {
525                 min_pixel = -(int)((double)(value - minvalue) / (maxvalue - minvalue) * pointer_motion_range);
526                 min_pixel += cursor_x;
527         }
528         max_pixel = min_pixel + pointer_motion_range;
529         return 0;
530 }
531
532 int BC_ISlider::update_selection(int cursor_x, int cursor_y)
533 {
534         int64_t old_value = value;
535
536         if(vertical)
537         {
538                 value = (int64_t)((1.0 - (double)(cursor_y - min_pixel) /
539                         pointer_motion_range) *
540                         (maxvalue - minvalue) +
541                         minvalue);
542         }
543         else
544         {
545                 value = (int64_t)((double)(cursor_x - min_pixel) /
546                         pointer_motion_range *
547                         (maxvalue - minvalue) +
548                         minvalue);
549         }
550
551         if(value > maxvalue) value = maxvalue;
552         if(value < minvalue) value = minvalue;
553         button_pixel = value_to_pixel();
554
555         if(old_value != value)
556         {
557                 return 1;
558         }
559         return 0;
560 }
561
562 int BC_ISlider::handle_event()
563 {
564         if(output) *output = get_value();
565         return 1;
566 }
567
568
569
570
571
572
573
574
575 BC_FSlider::BC_FSlider(int x,
576                         int y,
577                         int vertical,
578                         int pixels,
579                         int pointer_motion_range,
580                         float minvalue,
581                         float maxvalue,
582                         float value,
583                         int use_caption,
584                         VFrame **data)
585  : BC_Slider(x,
586                 y,
587                 pixels,
588                 pointer_motion_range,
589                 data,
590                 1,
591                 vertical,
592                 use_caption)
593 {
594         this->minvalue = minvalue;
595         this->maxvalue = maxvalue;
596         this->value = value;
597         this->precision = 0.1;
598         this->small_change = 0.1;
599         this->big_change = 1.0;
600 }
601
602 int BC_FSlider::value_to_pixel()
603 {
604 //printf("BC_FSlider::value_to_pixel %f %f\n", maxvalue, minvalue);
605         if(maxvalue == minvalue) return 0;
606         {
607                 if(vertical)
608                         return (int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) *
609                                 (get_h() - get_button_pixels()));
610                 else
611                         return (int)((double)(value - minvalue) / (maxvalue - minvalue) *
612                                 (get_w() - get_button_pixels()));
613         }
614 }
615
616 int BC_FSlider::update(float value)
617 {
618         if(this->value != value)
619         {
620                 this->value = value;
621                 int old_pixel = button_pixel;
622                 button_pixel = value_to_pixel();
623 //printf("BC_FSlider::update 1 %f %d\n", value, button_pixel);
624                 if(button_pixel != old_pixel) draw_face(1);
625         }
626         return 0;
627 }
628
629 int BC_FSlider::update(int pointer_motion_range, float value, float minvalue, float maxvalue)
630 {
631         this->minvalue = minvalue;
632         this->maxvalue = maxvalue;
633         this->value = value;
634         this->pointer_motion_range = pointer_motion_range;
635         int old_pixel = button_pixel;
636         button_pixel = value_to_pixel();
637         if(button_pixel != old_pixel) draw_face(1);
638         return 0;
639 }
640
641
642 float BC_FSlider::get_value()
643 {
644         return value;
645 }
646
647 float BC_FSlider::get_length()
648 {
649         return maxvalue - minvalue;
650 }
651
652 char* BC_FSlider::get_caption()
653 {
654         sprintf(caption, "%.02f", value);
655         return caption;
656 }
657
658 int BC_FSlider::increase_value()
659 {
660         value += small_change;
661         if(value > maxvalue) value = maxvalue;
662         button_pixel = value_to_pixel();
663         return 0;
664 }
665
666 int BC_FSlider::decrease_value()
667 {
668         value -= small_change;
669         if(value < minvalue) value = minvalue;
670         button_pixel = value_to_pixel();
671         return 0;
672 }
673
674 int BC_FSlider::increase_value_big()
675 {
676         value += big_change;
677         if(value > maxvalue) value = maxvalue;
678         button_pixel = value_to_pixel();
679         return 0;
680 }
681
682 int BC_FSlider::decrease_value_big()
683 {
684         value -= big_change;
685         if(value < minvalue) value = minvalue;
686         button_pixel = value_to_pixel();
687         return 0;
688 }
689
690 int BC_FSlider::init_selection(int cursor_x, int cursor_y)
691 {
692         if(vertical)
693         {
694                 min_pixel = -(int)((1.0 - (double)(value - minvalue) / (maxvalue - minvalue)) * pointer_motion_range);
695                 min_pixel += cursor_y;
696         }
697         else
698         {
699                 min_pixel = -(int)((double)(value - minvalue) / (maxvalue - minvalue) * pointer_motion_range);
700                 min_pixel += cursor_x;
701         }
702         max_pixel = min_pixel + pointer_motion_range;
703         return 0;
704 }
705
706 int BC_FSlider::update_selection(int cursor_x, int cursor_y)
707 {
708         float old_value = value;
709
710
711         if(vertical)
712         {
713                 value = ((1.0 - (double)(cursor_y - min_pixel) /
714                         pointer_motion_range) *
715                         (maxvalue - minvalue) +
716                         minvalue);
717         }
718         else
719         {
720                 value = ((double)(cursor_x - min_pixel) /
721                         pointer_motion_range *
722                         (maxvalue - minvalue) +
723                         minvalue);
724         }
725
726         value = Units::quantize(value, precision);
727         if(value > maxvalue) value = maxvalue;
728         if(value < minvalue) value = minvalue;
729         button_pixel = value_to_pixel();
730 // printf("BC_FSlider::update_selection 1 %d %d %d %d %f %f\n",
731 // pointer_motion_range,
732 // min_pixel,
733 // max_pixel,
734 // cursor_x,
735 // precision,
736 // value);
737
738         if(old_value != value)
739         {
740                 return 1;
741         }
742         return 0;
743 }
744
745 void BC_FSlider::set_precision(float value)
746 {
747         this->precision = value;
748 }
749
750 void BC_FSlider::set_pagination(float small_change, float big_change)
751 {
752         this->small_change = small_change;
753         this->big_change = big_change;
754 }
755
756
757 BC_PercentageSlider::BC_PercentageSlider(int x,
758                         int y,
759                         int vertical,
760                         int pixels,
761                         int pointer_motion_range,
762                         float minvalue,
763                         float maxvalue,
764                         float value,
765                         int use_caption,
766                         VFrame **data)
767  : BC_FSlider(x,
768                         y,
769                         vertical,
770                         pixels,
771                         pointer_motion_range,
772                         minvalue,
773                         maxvalue,
774                         value,
775                         use_caption,
776                         data)
777 {
778 }
779
780 char* BC_PercentageSlider::get_caption()
781 {
782         sprintf(caption, "%.0f%%", floor((value - minvalue) / (maxvalue - minvalue) * 100));
783         return caption;
784 }
785