4 * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcresources.h"
24 #include "bcscrollbar.h"
31 BC_ScrollBar::BC_ScrollBar(int x, int y, int orientation, int pixels,
32 int64_t length, int64_t position, int64_t handlelength,
34 : BC_SubWindow(x, y, 0, 0, -1)
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;
46 if( !data ) data = orientation == SCROLL_HORIZ ?
47 BC_WindowBase::get_resources()->hscroll_data :
48 BC_WindowBase::get_resources()->vscroll_data ;
55 memset(images, 0, sizeof(BC_Pixmap*) * SCROLL_IMAGES);
58 BC_ScrollBar::~BC_ScrollBar()
60 for(int i = 0; i < SCROLL_IMAGES; i++)
61 if(images[i]) delete images[i];
64 int BC_ScrollBar::initialize()
66 //printf("BC_ScrollBar::initialize 1\n");
68 //printf("BC_ScrollBar::initialize 1\n");
70 BC_SubWindow::initialize();
71 //printf("BC_ScrollBar::initialize 1\n");
76 void BC_ScrollBar::set_images(VFrame **data)
78 for(int i = 0; i < SCROLL_IMAGES; i++)
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]);
84 calculate_dimensions(w, h);
87 void BC_ScrollBar::calculate_dimensions(int &w, int &h)
93 h = data[SCROLL_HANDLE_UP]->get_h();
97 w = data[SCROLL_HANDLE_UP]->get_w();
103 int BC_ScrollBar::get_span(int orientation)
108 return BC_WindowBase::get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
112 return BC_WindowBase::get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
118 int BC_ScrollBar::get_span()
120 switch(orientation) {
121 case SCROLL_HORIZ: return data[SCROLL_HANDLE_UP]->get_h();
122 case SCROLL_VERT: return data[SCROLL_HANDLE_UP]->get_w();
127 int BC_ScrollBar::get_arrow_pixels()
129 switch(orientation) {
130 case SCROLL_HORIZ: return data[SCROLL_BACKARROW_UP]->get_w();
131 case SCROLL_VERT: return data[SCROLL_BACKARROW_UP]->get_h();
137 void BC_ScrollBar::draw(int flush)
139 draw_top_background(parent_window, 0, 0, w, h);
140 get_handle_dimensions();
147 //printf("BC_ScrollBar::draw 1 %d %d\n", selection_status, highlight_status == SCROLL_BACKARROW);
148 // Too small to draw anything
149 if(get_w() < get_arrow_pixels() * 2 + 5)
154 images[SCROLL_HANDLE_UP]);
163 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
164 if(selection_status == SCROLL_BACKARROW)
165 draw_pixmap(images[SCROLL_BACKARROW_DN],
169 if(highlight_status == SCROLL_BACKARROW)
170 draw_pixmap(images[SCROLL_BACKARROW_HI],
174 draw_pixmap(images[SCROLL_BACKARROW_UP],
177 //printf("BC_ScrollBar::draw 2\n");
185 if(selection_status == SCROLL_FWDARROW)
186 draw_pixmap(images[SCROLL_FWDARROW_DN],
187 get_w() - get_arrow_pixels(),
190 if(highlight_status == SCROLL_FWDARROW)
191 draw_pixmap(images[SCROLL_FWDARROW_HI],
192 get_w() - get_arrow_pixels(),
195 draw_pixmap(images[SCROLL_FWDARROW_UP],
196 get_w() - get_arrow_pixels(),
203 //printf("BC_ScrollBar::draw 2\n");
206 draw_3segmenth(get_arrow_pixels(),
208 handle_pixel - get_arrow_pixels(),
209 images[SCROLL_HANDLE_BG]);
212 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
213 if(selection_status == SCROLL_HANDLE)
214 draw_3segmenth(handle_pixel,
217 images[SCROLL_HANDLE_DN]);
219 if(highlight_status == SCROLL_HANDLE)
220 draw_3segmenth(handle_pixel,
223 images[SCROLL_HANDLE_HI]);
225 draw_3segmenth(handle_pixel,
228 images[SCROLL_HANDLE_UP]);
229 //printf("BC_ScrollBar::draw 2\n");
232 draw_3segmenth(handle_pixel + handle_pixels,
234 get_w() - get_arrow_pixels() - handle_pixel - handle_pixels,
235 images[SCROLL_HANDLE_BG]);
236 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
248 // Too small to draw anything
249 if(get_h() < get_arrow_pixels() * 2 + 5)
254 images[SCROLL_HANDLE_UP]);
263 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
264 if(selection_status == SCROLL_BACKARROW)
265 draw_pixmap(images[SCROLL_BACKARROW_DN],
269 if(highlight_status == SCROLL_BACKARROW)
270 draw_pixmap(images[SCROLL_BACKARROW_HI],
274 draw_pixmap(images[SCROLL_BACKARROW_UP],
277 //printf("BC_ScrollBar::draw 2\n");
285 if(selection_status == SCROLL_FWDARROW)
286 draw_pixmap(images[SCROLL_FWDARROW_DN],
288 get_h() - get_arrow_pixels());
290 if(highlight_status == SCROLL_FWDARROW)
291 draw_pixmap(images[SCROLL_FWDARROW_HI],
293 get_h() - get_arrow_pixels());
295 draw_pixmap(images[SCROLL_FWDARROW_UP],
297 get_h() - get_arrow_pixels());
303 //printf("BC_ScrollBar::draw 2\n");
308 handle_pixel - get_arrow_pixels(),
309 images[SCROLL_HANDLE_BG]);
312 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
313 if(selection_status == SCROLL_HANDLE)
317 images[SCROLL_HANDLE_DN]);
319 if(highlight_status == SCROLL_HANDLE)
323 images[SCROLL_HANDLE_HI]);
328 images[SCROLL_HANDLE_UP]);
329 //printf("BC_ScrollBar::draw 2\n");
333 handle_pixel + handle_pixels,
334 get_h() - get_arrow_pixels() - handle_pixel - handle_pixels,
335 images[SCROLL_HANDLE_BG]);
336 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
343 void BC_ScrollBar::get_handle_dimensions()
345 int total_pixels = pixels -
346 get_arrow_pixels() * 2;
350 handle_pixels = (int64_t)((double)handlelength /
355 if(handle_pixels < get_resources()->scroll_minhandle)
356 handle_pixels = get_resources()->scroll_minhandle;
359 handle_pixel = (int64_t)((double)position /
364 // Handle pixels is beyond minimum right position. Clamp it.
365 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
367 handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
368 handle_pixels = get_resources()->scroll_minhandle;
370 // Shrink handle_pixels until it fits inside scrollbar
371 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
373 handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
375 if(handle_pixel < get_arrow_pixels())
377 handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
378 handle_pixel = get_arrow_pixels();
380 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
384 handle_pixels = total_pixels;
385 handle_pixel = get_arrow_pixels();
388 CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
389 CLAMP(handle_pixels, 0, total_pixels);
391 // printf("BC_ScrollBar::get_handle_dimensions %d %d %d\n",
397 int BC_ScrollBar::cursor_enter_event()
399 if(top_level->event_win == win)
401 if(!highlight_status)
403 highlight_status = get_cursor_zone(top_level->cursor_x,
404 top_level->cursor_y);
412 int BC_ScrollBar::cursor_leave_event()
416 highlight_status = 0;
422 int BC_ScrollBar::cursor_motion_event()
424 if(top_level->event_win == win)
426 if(highlight_status && !selection_status)
428 int new_highlight_status =
429 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
430 if(new_highlight_status != highlight_status)
432 highlight_status = new_highlight_status;
437 if(selection_status == SCROLL_HANDLE)
439 //printf("BC_ScrollBar::cursor_motion_event 1\n");
440 double total_pixels = pixels - get_arrow_pixels() * 2;
441 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ?
442 top_level->cursor_x :
444 int64_t new_position = (int64_t)((double)(cursor_pixel - min_pixel) /
445 total_pixels * length);
446 //printf("BC_ScrollBar::cursor_motion_event 2\n");
448 if(new_position > length - handlelength)
449 new_position = length - handlelength;
450 if(new_position < 0) new_position = 0;
452 if(new_position != position)
454 //printf("BC_ScrollBar::cursor_motion_event 3\n");
455 position = new_position;
458 //printf("BC_ScrollBar::cursor_motion_event 4\n");
466 int BC_ScrollBar::button_press_event()
468 if(top_level->event_win == win)
470 //printf("BC_ScrollBar::button_press_event %d %p\n", __LINE__, bound_to);
473 top_level->deactivate();
477 if(get_buttonpress() == 4)
479 selection_status = SCROLL_BACKARROW;
480 repeat_event(top_level->get_resources()->scroll_repeat);
483 if(get_buttonpress() == 5)
485 selection_status = SCROLL_FWDARROW;
487 repeat_event(top_level->get_resources()->scroll_repeat);
491 selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
492 if(selection_status == SCROLL_HANDLE)
494 double total_pixels = pixels - get_arrow_pixels() * 2;
495 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ? top_level->cursor_x : top_level->cursor_y;
496 min_pixel = cursor_pixel - (int64_t)((double)position / length * total_pixels + .5);
497 max_pixel = (int)(cursor_pixel + total_pixels);
503 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
505 repeat_event(top_level->get_resources()->scroll_repeat);
514 int BC_ScrollBar::repeat_event(int64_t duration)
516 if(duration == top_level->get_resources()->scroll_repeat &&
519 //printf("BC_ScrollBar::repeat_event %d %d\n", __LINE__, (int)repeat_count);
522 if(repeat_count >= 2 && repeat_count < 5) return 0;
523 int64_t new_position = position;
524 switch(selection_status)
526 case SCROLL_BACKPAGE:
527 new_position -= handlelength;
530 new_position += handlelength;
532 case SCROLL_BACKARROW:
533 new_position -= (handlelength+9) / 10;
535 case SCROLL_FWDARROW:
536 new_position += (handlelength+9) / 10;
540 if(new_position > length - handlelength) new_position = length - handlelength;
541 if(new_position < 0) new_position = 0;
542 if(new_position != position)
544 position = new_position;
553 int BC_ScrollBar::button_release_event()
555 //printf("BC_ScrollBar::button_release_event %d\n", selection_status);
558 if(selection_status != SCROLL_HANDLE)
559 top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
561 selection_status = 0;
568 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
570 if(orientation == SCROLL_VERT)
572 cursor_x ^= cursor_y;
573 cursor_y ^= cursor_x;
574 cursor_x ^= cursor_y;
579 if(cursor_x >= pixels - get_arrow_pixels())
580 return SCROLL_FWDARROW;
582 if(cursor_x >= get_arrow_pixels())
584 if(cursor_x > handle_pixel + handle_pixels)
585 return SCROLL_FWDPAGE;
587 if(cursor_x >= handle_pixel)
588 return SCROLL_HANDLE;
590 return SCROLL_BACKPAGE;
593 return SCROLL_BACKARROW;
601 int BC_ScrollBar::activate()
603 top_level->active_subwindow = this;
604 //printf("BC_ScrollBar::activate %p %p\n", top_level->active_subwindow, this);
608 int64_t BC_ScrollBar::get_value()
613 int64_t BC_ScrollBar::get_position()
618 int64_t BC_ScrollBar::get_length()
623 int BC_ScrollBar::get_pixels()
628 int BC_ScrollBar::in_use()
630 return selection_status != 0;
633 int64_t BC_ScrollBar::get_handlelength()
638 int BC_ScrollBar::update_value(int64_t value)
640 this->position = value;
645 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength, int flush)
647 if( stretch ) length += handlelength/4;
648 this->length = length;
649 this->position = position;
650 this->handlelength = handlelength;
655 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
657 if(x != get_x() || y != get_y() || pixels != this->pixels)
659 this->pixels = pixels;
661 calculate_dimensions(new_w, new_h);
662 BC_WindowBase::reposition_window(x, y, new_w, new_h);