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