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