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