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()
123 return data[SCROLL_HANDLE_UP]->get_h();
127 return data[SCROLL_HANDLE_UP]->get_w();
133 int BC_ScrollBar::get_arrow_pixels()
138 return data[SCROLL_BACKARROW_UP]->get_w();
142 return data[SCROLL_BACKARROW_UP]->get_h();
149 void BC_ScrollBar::draw(int flush)
151 draw_top_background(parent_window, 0, 0, w, h);
152 get_handle_dimensions();
159 //printf("BC_ScrollBar::draw 1 %d %d\n", selection_status, highlight_status == SCROLL_BACKARROW);
160 // Too small to draw anything
161 if(get_w() < get_arrow_pixels() * 2 + 5)
166 images[SCROLL_HANDLE_UP]);
175 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
176 if(selection_status == SCROLL_BACKARROW)
177 draw_pixmap(images[SCROLL_BACKARROW_DN],
181 if(highlight_status == SCROLL_BACKARROW)
182 draw_pixmap(images[SCROLL_BACKARROW_HI],
186 draw_pixmap(images[SCROLL_BACKARROW_UP],
189 //printf("BC_ScrollBar::draw 2\n");
197 if(selection_status == SCROLL_FWDARROW)
198 draw_pixmap(images[SCROLL_FWDARROW_DN],
199 get_w() - get_arrow_pixels(),
202 if(highlight_status == SCROLL_FWDARROW)
203 draw_pixmap(images[SCROLL_FWDARROW_HI],
204 get_w() - get_arrow_pixels(),
207 draw_pixmap(images[SCROLL_FWDARROW_UP],
208 get_w() - get_arrow_pixels(),
215 //printf("BC_ScrollBar::draw 2\n");
218 draw_3segmenth(get_arrow_pixels(),
220 handle_pixel - get_arrow_pixels(),
221 images[SCROLL_HANDLE_BG]);
224 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
225 if(selection_status == SCROLL_HANDLE)
226 draw_3segmenth(handle_pixel,
229 images[SCROLL_HANDLE_DN]);
231 if(highlight_status == SCROLL_HANDLE)
232 draw_3segmenth(handle_pixel,
235 images[SCROLL_HANDLE_HI]);
237 draw_3segmenth(handle_pixel,
240 images[SCROLL_HANDLE_UP]);
241 //printf("BC_ScrollBar::draw 2\n");
244 draw_3segmenth(handle_pixel + handle_pixels,
246 get_w() - get_arrow_pixels() - handle_pixel - handle_pixels,
247 images[SCROLL_HANDLE_BG]);
248 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
260 // Too small to draw anything
261 if(get_h() < get_arrow_pixels() * 2 + 5)
266 images[SCROLL_HANDLE_UP]);
275 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
276 if(selection_status == SCROLL_BACKARROW)
277 draw_pixmap(images[SCROLL_BACKARROW_DN],
281 if(highlight_status == SCROLL_BACKARROW)
282 draw_pixmap(images[SCROLL_BACKARROW_HI],
286 draw_pixmap(images[SCROLL_BACKARROW_UP],
289 //printf("BC_ScrollBar::draw 2\n");
297 if(selection_status == SCROLL_FWDARROW)
298 draw_pixmap(images[SCROLL_FWDARROW_DN],
300 get_h() - get_arrow_pixels());
302 if(highlight_status == SCROLL_FWDARROW)
303 draw_pixmap(images[SCROLL_FWDARROW_HI],
305 get_h() - get_arrow_pixels());
307 draw_pixmap(images[SCROLL_FWDARROW_UP],
309 get_h() - get_arrow_pixels());
315 //printf("BC_ScrollBar::draw 2\n");
320 handle_pixel - get_arrow_pixels(),
321 images[SCROLL_HANDLE_BG]);
324 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
325 if(selection_status == SCROLL_HANDLE)
329 images[SCROLL_HANDLE_DN]);
331 if(highlight_status == SCROLL_HANDLE)
335 images[SCROLL_HANDLE_HI]);
340 images[SCROLL_HANDLE_UP]);
341 //printf("BC_ScrollBar::draw 2\n");
345 handle_pixel + handle_pixels,
346 get_h() - get_arrow_pixels() - handle_pixel - handle_pixels,
347 images[SCROLL_HANDLE_BG]);
348 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
355 void BC_ScrollBar::get_handle_dimensions()
357 int total_pixels = pixels -
358 get_arrow_pixels() * 2;
362 handle_pixels = (int64_t)((double)handlelength /
367 if(handle_pixels < get_resources()->scroll_minhandle)
368 handle_pixels = get_resources()->scroll_minhandle;
371 handle_pixel = (int64_t)((double)position /
376 // Handle pixels is beyond minimum right position. Clamp it.
377 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
379 handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
380 handle_pixels = get_resources()->scroll_minhandle;
382 // Shrink handle_pixels until it fits inside scrollbar
383 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
385 handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
387 if(handle_pixel < get_arrow_pixels())
389 handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
390 handle_pixel = get_arrow_pixels();
392 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
396 handle_pixels = total_pixels;
397 handle_pixel = get_arrow_pixels();
400 CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
401 CLAMP(handle_pixels, 0, total_pixels);
403 // printf("BC_ScrollBar::get_handle_dimensions %d %d %d\n",
409 int BC_ScrollBar::cursor_enter_event()
411 if(top_level->event_win == win)
413 if(!highlight_status)
415 highlight_status = get_cursor_zone(top_level->cursor_x,
416 top_level->cursor_y);
424 int BC_ScrollBar::cursor_leave_event()
428 highlight_status = 0;
434 int BC_ScrollBar::cursor_motion_event()
436 if(top_level->event_win == win)
438 if(highlight_status && !selection_status)
440 int new_highlight_status =
441 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
442 if(new_highlight_status != highlight_status)
444 highlight_status = new_highlight_status;
449 if(selection_status == SCROLL_HANDLE)
451 //printf("BC_ScrollBar::cursor_motion_event 1\n");
452 double total_pixels = pixels - get_arrow_pixels() * 2;
453 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ?
454 top_level->cursor_x :
456 int64_t new_position = (int64_t)((double)(cursor_pixel - min_pixel) /
457 total_pixels * length);
458 //printf("BC_ScrollBar::cursor_motion_event 2\n");
460 if(new_position > length - handlelength)
461 new_position = length - handlelength;
462 if(new_position < 0) new_position = 0;
464 if(new_position != position)
466 //printf("BC_ScrollBar::cursor_motion_event 3\n");
467 position = new_position;
470 //printf("BC_ScrollBar::cursor_motion_event 4\n");
478 int BC_ScrollBar::button_press_event()
480 if(top_level->event_win == win)
482 //printf("BC_ScrollBar::button_press_event %d %p\n", __LINE__, bound_to);
485 top_level->deactivate();
489 if(get_buttonpress() == 4)
491 selection_status = SCROLL_BACKARROW;
492 repeat_event(top_level->get_resources()->scroll_repeat);
495 if(get_buttonpress() == 5)
497 selection_status = SCROLL_FWDARROW;
499 repeat_event(top_level->get_resources()->scroll_repeat);
503 selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
504 if(selection_status == SCROLL_HANDLE)
506 double total_pixels = pixels - get_arrow_pixels() * 2;
507 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ? top_level->cursor_x : top_level->cursor_y;
508 min_pixel = cursor_pixel - (int64_t)((double)position / length * total_pixels + .5);
509 max_pixel = (int)(cursor_pixel + total_pixels);
515 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
517 repeat_event(top_level->get_resources()->scroll_repeat);
526 int BC_ScrollBar::repeat_event(int64_t duration)
528 if(duration == top_level->get_resources()->scroll_repeat &&
531 //printf("BC_ScrollBar::repeat_event %d %d\n", __LINE__, (int)repeat_count);
534 if(repeat_count >= 2 && repeat_count < 5) return 0;
535 int64_t new_position = position;
536 switch(selection_status)
538 case SCROLL_BACKPAGE:
539 new_position -= handlelength;
542 new_position += handlelength;
544 case SCROLL_BACKARROW:
545 new_position -= (handlelength+9) / 10;
547 case SCROLL_FWDARROW:
548 new_position += (handlelength+9) / 10;
552 if(new_position > length - handlelength) new_position = length - handlelength;
553 if(new_position < 0) new_position = 0;
554 if(new_position != position)
556 position = new_position;
565 int BC_ScrollBar::button_release_event()
567 //printf("BC_ScrollBar::button_release_event %d\n", selection_status);
570 if(selection_status != SCROLL_HANDLE)
571 top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
573 selection_status = 0;
580 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
582 if(orientation == SCROLL_VERT)
584 cursor_x ^= cursor_y;
585 cursor_y ^= cursor_x;
586 cursor_x ^= cursor_y;
591 if(cursor_x >= pixels - get_arrow_pixels())
592 return SCROLL_FWDARROW;
594 if(cursor_x >= get_arrow_pixels())
596 if(cursor_x > handle_pixel + handle_pixels)
597 return SCROLL_FWDPAGE;
599 if(cursor_x >= handle_pixel)
600 return SCROLL_HANDLE;
602 return SCROLL_BACKPAGE;
605 return SCROLL_BACKARROW;
613 int BC_ScrollBar::activate()
615 top_level->active_subwindow = this;
616 //printf("BC_ScrollBar::activate %p %p\n", top_level->active_subwindow, this);
620 int64_t BC_ScrollBar::get_value()
625 int64_t BC_ScrollBar::get_position()
630 int64_t BC_ScrollBar::get_length()
635 int BC_ScrollBar::get_pixels()
640 int BC_ScrollBar::in_use()
642 return selection_status != 0;
645 int64_t BC_ScrollBar::get_handlelength()
650 int BC_ScrollBar::update_value(int64_t value)
652 this->position = value;
657 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength, int flush)
659 if( stretch ) length += handlelength/4;
660 this->length = length;
661 this->position = position;
662 this->handlelength = handlelength;
667 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
669 if(x != get_x() || y != get_y() || pixels != this->pixels)
671 this->pixels = pixels;
673 calculate_dimensions(new_w, new_h);
674 BC_WindowBase::reposition_window(x, y, new_w, new_h);