no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcscrollbar.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 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 "bcscrollbar.h"
25 #include "clip.h"
26 #include "bccolors.h"
27 #include "vframe.h"
28
29 #include <string.h>
30
31 BC_ScrollBar::BC_ScrollBar(int x, int y, int orientation, int pixels,
32         int64_t length, int64_t position, int64_t handlelength,
33         VFrame **data)
34  : BC_SubWindow(x, y, 0, 0, -1)
35 {
36         this->length = length;
37         this->position = position;
38         this->handlelength = handlelength;
39         this->selection_status = 0;
40         this->highlight_status = 0;
41         this->stretch = orientation & SCROLL_STRETCH ? 1 : 0;
42         orientation &= ~SCROLL_STRETCH;
43         this->orientation = orientation;
44         this->pixels = pixels;
45
46         if( !data ) data = orientation == SCROLL_HORIZ ?
47                 BC_WindowBase::get_resources()->hscroll_data :
48                 BC_WindowBase::get_resources()->vscroll_data ;
49         this->data = data;
50
51         handle_pixel = 0;
52         handle_pixels = 0;
53         bound_to = 0;
54         repeat_count = 0;
55         memset(images, 0, sizeof(BC_Pixmap*) * SCROLL_IMAGES);
56 }
57
58 BC_ScrollBar::~BC_ScrollBar()
59 {
60         for(int i = 0; i < SCROLL_IMAGES; i++)
61                 if(images[i]) delete images[i];
62 }
63
64 int BC_ScrollBar::initialize()
65 {
66 //printf("BC_ScrollBar::initialize 1\n");
67         set_images(data);
68 //printf("BC_ScrollBar::initialize 1\n");
69
70         BC_SubWindow::initialize();
71 //printf("BC_ScrollBar::initialize 1\n");
72         draw(0);
73         return 0;
74 }
75
76 void BC_ScrollBar::set_images(VFrame **data)
77 {
78         for(int i = 0; i < SCROLL_IMAGES; i++)
79         {
80                 if(images[i]) delete images[i];
81                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
82 //printf("BC_ScrollBar::set_images %d %p\n", i, data[i]);
83         }
84         calculate_dimensions(w, h);
85 }
86
87 void BC_ScrollBar::calculate_dimensions(int &w, int &h)
88 {
89         w = h = pixels;
90         switch( orientation ) {
91                 case SCROLL_HORIZ:
92                         h = data[SCROLL_HANDLE_UP]->get_h();
93                         break;
94
95                 case SCROLL_VERT:
96                         w = data[SCROLL_HANDLE_UP]->get_w();
97                         break;
98         }
99 }
100
101 int BC_ScrollBar::get_span(int orientation)
102 {
103         switch(orientation)
104         {
105                 case SCROLL_HORIZ:
106                         return BC_WindowBase::get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
107                         break;
108
109                 case SCROLL_VERT:
110                         return BC_WindowBase::get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
111                         break;
112         }
113         return 0;
114 }
115
116 int BC_ScrollBar::get_span()
117 {
118         switch(orientation) {
119         case SCROLL_HORIZ: return data[SCROLL_HANDLE_UP]->get_h();
120         case SCROLL_VERT:  return data[SCROLL_HANDLE_UP]->get_w();
121         }
122         return 0;
123 }
124
125 int BC_ScrollBar::get_arrow_pixels()
126 {
127         switch(orientation) {
128         case SCROLL_HORIZ: return data[SCROLL_BACKARROW_UP]->get_w();
129         case SCROLL_VERT:  return data[SCROLL_BACKARROW_UP]->get_h();
130         }
131         return 0;
132 }
133
134
135 void BC_ScrollBar::draw(int flush)
136 {
137         draw_top_background(parent_window, 0, 0, w, h);
138         get_handle_dimensions();
139
140         switch(orientation)
141         {
142                 case SCROLL_HORIZ:
143
144
145 //printf("BC_ScrollBar::draw 1 %d %d\n", selection_status, highlight_status == SCROLL_BACKARROW);
146 // Too small to draw anything
147                         if(get_w() < get_arrow_pixels() * 2 + xS(5))
148                         {
149                                 draw_3segmenth(0,
150                                         0,
151                                         get_w(),
152                                         images[SCROLL_HANDLE_UP]);
153                         }
154                         else
155                         {
156
157
158
159
160 // back arrow
161 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
162                                 if(selection_status == SCROLL_BACKARROW)
163                                         draw_pixmap(images[SCROLL_BACKARROW_DN],
164                                                 0,
165                                                 0);
166                                 else
167                                 if(highlight_status == SCROLL_BACKARROW)
168                                         draw_pixmap(images[SCROLL_BACKARROW_HI],
169                                                 0,
170                                                 0);
171                                 else
172                                         draw_pixmap(images[SCROLL_BACKARROW_UP],
173                                                 0,
174                                                 0);
175 //printf("BC_ScrollBar::draw 2\n");
176
177
178
179
180
181
182 // forward arrow
183                                 if(selection_status == SCROLL_FWDARROW)
184                                         draw_pixmap(images[SCROLL_FWDARROW_DN],
185                                                 get_w() - get_arrow_pixels(),
186                                                 0);
187                                 else
188                                 if(highlight_status == SCROLL_FWDARROW)
189                                         draw_pixmap(images[SCROLL_FWDARROW_HI],
190                                                 get_w() - get_arrow_pixels(),
191                                                 0);
192                                 else
193                                         draw_pixmap(images[SCROLL_FWDARROW_UP],
194                                                 get_w() - get_arrow_pixels(),
195                                                 0);
196
197
198
199
200
201 //printf("BC_ScrollBar::draw 2\n");
202
203 // handle background
204                                 draw_3segmenth(get_arrow_pixels(),
205                                         0,
206                                         handle_pixel - get_arrow_pixels(),
207                                         images[SCROLL_HANDLE_BG]);
208
209 // handle foreground
210 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
211                                 if(selection_status == SCROLL_HANDLE)
212                                         draw_3segmenth(handle_pixel,
213                                                 0,
214                                                 handle_pixels,
215                                                 images[SCROLL_HANDLE_DN]);
216                                 else
217                                 if(highlight_status == SCROLL_HANDLE)
218                                         draw_3segmenth(handle_pixel,
219                                                 0,
220                                                 handle_pixels,
221                                                 images[SCROLL_HANDLE_HI]);
222                                 else
223                                         draw_3segmenth(handle_pixel,
224                                                 0,
225                                                 handle_pixels,
226                                                 images[SCROLL_HANDLE_UP]);
227 //printf("BC_ScrollBar::draw 2\n");
228
229 // handle background
230                                 draw_3segmenth(handle_pixel + handle_pixels,
231                                         0,
232                                         get_w() - get_arrow_pixels() - handle_pixel - handle_pixels,
233                                         images[SCROLL_HANDLE_BG]);
234 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
235                         }
236                         break;
237
238
239
240
241
242
243
244
245                 case SCROLL_VERT:
246 // Too small to draw anything
247                         if(get_h() < get_arrow_pixels() * 2 + yS(5))
248                         {
249                                 draw_3segmentv(0,
250                                         0,
251                                         get_w(),
252                                         images[SCROLL_HANDLE_UP]);
253                         }
254                         else
255                         {
256
257
258
259
260 // back arrow
261 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
262                                 if(selection_status == SCROLL_BACKARROW)
263                                         draw_pixmap(images[SCROLL_BACKARROW_DN],
264                                                 0,
265                                                 0);
266                                 else
267                                 if(highlight_status == SCROLL_BACKARROW)
268                                         draw_pixmap(images[SCROLL_BACKARROW_HI],
269                                                 0,
270                                                 0);
271                                 else
272                                         draw_pixmap(images[SCROLL_BACKARROW_UP],
273                                                 0,
274                                                 0);
275 //printf("BC_ScrollBar::draw 2\n");
276
277
278
279
280
281
282 // forward arrow
283                                 if(selection_status == SCROLL_FWDARROW)
284                                         draw_pixmap(images[SCROLL_FWDARROW_DN],
285                                                 0,
286                                                 get_h() - get_arrow_pixels());
287                                 else
288                                 if(highlight_status == SCROLL_FWDARROW)
289                                         draw_pixmap(images[SCROLL_FWDARROW_HI],
290                                                 0,
291                                                 get_h() - get_arrow_pixels());
292                                 else
293                                         draw_pixmap(images[SCROLL_FWDARROW_UP],
294                                                 0,
295                                                 get_h() - get_arrow_pixels());
296
297
298
299
300
301 //printf("BC_ScrollBar::draw 2\n");
302
303 // handle background
304                                 draw_3segmentv(0,
305                                         get_arrow_pixels(),
306                                         handle_pixel - get_arrow_pixels(),
307                                         images[SCROLL_HANDLE_BG]);
308
309 // handle foreground
310 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
311                                 if(selection_status == SCROLL_HANDLE)
312                                         draw_3segmentv(0,
313                                                 handle_pixel,
314                                                 handle_pixels,
315                                                 images[SCROLL_HANDLE_DN]);
316                                 else
317                                 if(highlight_status == SCROLL_HANDLE)
318                                         draw_3segmentv(0,
319                                                 handle_pixel,
320                                                 handle_pixels,
321                                                 images[SCROLL_HANDLE_HI]);
322                                 else
323                                         draw_3segmentv(0,
324                                                 handle_pixel,
325                                                 handle_pixels,
326                                                 images[SCROLL_HANDLE_UP]);
327 //printf("BC_ScrollBar::draw 2\n");
328
329 // handle background
330                                 draw_3segmentv(0,
331                                         handle_pixel + handle_pixels,
332                                         get_h() - get_arrow_pixels() - handle_pixel - handle_pixels,
333                                         images[SCROLL_HANDLE_BG]);
334 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
335                         }
336                         break;
337         }
338         flash(flush);
339 }
340
341 void BC_ScrollBar::get_handle_dimensions()
342 {
343         int total_pixels = pixels -
344                 get_arrow_pixels() * 2;
345
346         if(length > 0)
347         {
348                 handle_pixels = (int64_t)((double)handlelength /
349                         length *
350                         total_pixels +
351                         .5);
352
353                 if(handle_pixels < get_resources()->scroll_minhandle)
354                         handle_pixels = get_resources()->scroll_minhandle;
355
356
357                 handle_pixel = (int64_t)((double)position /
358                                 length *
359                                 total_pixels + .5) +
360                         get_arrow_pixels();
361
362 // Handle pixels is beyond minimum right position.  Clamp it.
363                 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
364                 {
365                         handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
366                         handle_pixels = get_resources()->scroll_minhandle;
367                 }
368 // Shrink handle_pixels until it fits inside scrollbar
369                 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
370                 {
371                         handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
372                 }
373                 if(handle_pixel < get_arrow_pixels())
374                 {
375                         handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
376                         handle_pixel = get_arrow_pixels();
377                 }
378                 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
379         }
380         else
381         {
382                 handle_pixels = total_pixels;
383                 handle_pixel = get_arrow_pixels();
384         }
385
386         CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
387         CLAMP(handle_pixels, 0, total_pixels);
388
389 // printf("BC_ScrollBar::get_handle_dimensions %d %d %d\n",
390 // total_pixels,
391 // handle_pixel,
392 // handle_pixels);
393 }
394
395 int BC_ScrollBar::cursor_enter_event()
396 {
397         if(top_level->event_win == win)
398         {
399                 if(!highlight_status)
400                 {
401                         highlight_status = get_cursor_zone(top_level->cursor_x,
402                                 top_level->cursor_y);
403                         draw(1);
404                 }
405                 return 1;
406         }
407         return 0;
408 }
409
410 int BC_ScrollBar::cursor_leave_event()
411 {
412         if(highlight_status)
413         {
414                 highlight_status = 0;
415                 draw(1);
416         }
417         return 0;
418 }
419
420 int BC_ScrollBar::cursor_motion_event()
421 {
422         if(top_level->event_win == win)
423         {
424                 if(highlight_status && !selection_status)
425                 {
426                         int new_highlight_status =
427                                 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
428                         if(new_highlight_status != highlight_status)
429                         {
430                                 highlight_status = new_highlight_status;
431                                 draw(1);
432                         }
433                 }
434                 else
435                 if(selection_status == SCROLL_HANDLE)
436                 {
437 //printf("BC_ScrollBar::cursor_motion_event 1\n");
438                         double total_pixels = pixels - get_arrow_pixels() * 2;
439                         int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ?
440                                 top_level->cursor_x :
441                                 top_level->cursor_y;
442                         int64_t new_position = (int64_t)((double)(cursor_pixel - min_pixel) /
443                                 total_pixels * length);
444 //printf("BC_ScrollBar::cursor_motion_event 2\n");
445
446                         if(new_position > length - handlelength)
447                                 new_position = length - handlelength;
448                         if(new_position < 0) new_position = 0;
449
450                         if(new_position != position)
451                         {
452 //printf("BC_ScrollBar::cursor_motion_event 3\n");
453                                 position = new_position;
454                                 draw(1);
455                                 handle_event();
456 //printf("BC_ScrollBar::cursor_motion_event 4\n");
457                         }
458                 }
459                 return 1;
460         }
461         return 0;
462 }
463
464 int BC_ScrollBar::button_press_event()
465 {
466         if(top_level->event_win == win)
467         {
468 //printf("BC_ScrollBar::button_press_event %d %p\n", __LINE__, bound_to);
469                 if(!bound_to)
470                 {
471                         top_level->deactivate();
472                         activate();
473                 }
474
475                 if(get_buttonpress() == 4)
476                 {
477                         selection_status = SCROLL_BACKARROW;
478                         repeat_event(top_level->get_resources()->scroll_repeat);
479                 }
480                 else
481                 if(get_buttonpress() == 5)
482                 {
483                         selection_status = SCROLL_FWDARROW;
484                         repeat_count = 0;
485                         repeat_event(top_level->get_resources()->scroll_repeat);
486                 }
487                 else
488                 {
489                         selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
490                         if(selection_status == SCROLL_HANDLE)
491                         {
492                                 double total_pixels = pixels - get_arrow_pixels() * 2;
493                                 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ? top_level->cursor_x : top_level->cursor_y;
494                                 min_pixel = cursor_pixel - (int64_t)((double)position / length * total_pixels + .5);
495                                 max_pixel = (int)(cursor_pixel + total_pixels);
496                                 draw(1);
497                         }
498                         else
499                         if(selection_status)
500                         {
501                                 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
502                                 repeat_count = 0;
503                                 repeat_event(top_level->get_resources()->scroll_repeat);
504                                 draw(1);
505                         }
506                 }
507                 return 1;
508         }
509         return 0;
510 }
511
512 int BC_ScrollBar::repeat_event(int64_t duration)
513 {
514         if(duration == top_level->get_resources()->scroll_repeat &&
515                 selection_status)
516         {
517 //printf("BC_ScrollBar::repeat_event %d %d\n", __LINE__, (int)repeat_count);
518                 repeat_count++;
519 // delay 1st repeat
520                 if(repeat_count >= 2 && repeat_count < 5) return 0;
521                 int64_t new_position = position;
522                 switch(selection_status)
523                 {
524                         case SCROLL_BACKPAGE:
525                                 new_position -= handlelength;
526                                 break;
527                         case SCROLL_FWDPAGE:
528                                 new_position += handlelength;
529                                 break;
530                         case SCROLL_BACKARROW:
531                                 new_position -= (handlelength+9) / 10;
532                                 break;
533                         case SCROLL_FWDARROW:
534                                 new_position += (handlelength+9) / 10;
535                                 break;
536                 }
537
538                 if(new_position > length - handlelength) new_position = length - handlelength;
539                 if(new_position < 0) new_position = 0;
540                 if(new_position != position)
541                 {
542                         position = new_position;
543                         draw(1);
544                         handle_event();
545                 }
546                 return 1;
547         }
548         return 0;
549 }
550
551 int BC_ScrollBar::button_release_event()
552 {
553 //printf("BC_ScrollBar::button_release_event %d\n", selection_status);
554         if(selection_status)
555         {
556                 if(selection_status != SCROLL_HANDLE)
557                         top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
558
559                 selection_status = 0;
560                 draw(1);
561                 return 1;
562         }
563         return 0;
564 }
565
566 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
567 {
568         if(orientation == SCROLL_VERT)
569         {
570                 cursor_x ^= cursor_y;
571                 cursor_y ^= cursor_x;
572                 cursor_x ^= cursor_y;
573         }
574
575
576
577         if(cursor_x >= pixels - get_arrow_pixels())
578                 return SCROLL_FWDARROW;
579         else
580         if(cursor_x >= get_arrow_pixels())
581         {
582                 if(cursor_x > handle_pixel + handle_pixels)
583                         return SCROLL_FWDPAGE;
584                 else
585                 if(cursor_x >= handle_pixel)
586                         return SCROLL_HANDLE;
587                 else
588                         return SCROLL_BACKPAGE;
589         }
590         else
591                 return SCROLL_BACKARROW;
592
593
594
595
596         return 0;
597 }
598
599 int BC_ScrollBar::activate()
600 {
601         top_level->active_subwindow = this;
602 //printf("BC_ScrollBar::activate %p %p\n", top_level->active_subwindow, this);
603         return 0;
604 }
605
606 int64_t BC_ScrollBar::get_value()
607 {
608         return position;
609 }
610
611 int64_t BC_ScrollBar::get_position()
612 {
613         return position;
614 }
615
616 int64_t BC_ScrollBar::get_length()
617 {
618         return length;
619 }
620
621 int BC_ScrollBar::get_pixels()
622 {
623         return pixels;
624 }
625
626 int BC_ScrollBar::in_use()
627 {
628         return selection_status != 0;
629 }
630
631 int64_t BC_ScrollBar::get_handlelength()
632 {
633         return handlelength;
634 }
635
636 int BC_ScrollBar::update_value(int64_t value)
637 {
638         this->position = value;
639         draw(1);
640         return 0;
641 }
642
643 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength, int flush)
644 {
645         if( stretch ) length += handlelength/4;
646         this->length = length;
647         this->position = position;
648         this->handlelength = handlelength;
649         draw(flush);
650         return 0;
651 }
652
653 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
654 {
655         if(x != get_x() || y != get_y() || pixels != this->pixels)
656         {
657                 this->pixels = pixels;
658                 int new_w, new_h;
659                 calculate_dimensions(new_w, new_h);
660                 BC_WindowBase::reposition_window(x, y, new_w, new_h);
661         }
662         draw(0);
663         return 0;
664 }
665