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,
39 : BC_SubWindow(x, y, 0, 0, -1)
41 this->length = length;
42 this->position = position;
43 this->handlelength = handlelength;
44 this->selection_status = 0;
45 this->highlight_status = 0;
46 this->orientation = orientation;
47 this->pixels = pixels;
52 if(orientation == SCROLL_HORIZ)
53 this->data = BC_WindowBase::get_resources()->hscroll_data;
55 this->data = BC_WindowBase::get_resources()->vscroll_data;
61 memset(images, 0, sizeof(BC_Pixmap*) * SCROLL_IMAGES);
64 BC_ScrollBar::~BC_ScrollBar()
66 for(int i = 0; i < SCROLL_IMAGES; i++)
67 if(images[i]) delete images[i];
70 int BC_ScrollBar::initialize()
72 //printf("BC_ScrollBar::initialize 1\n");
74 //printf("BC_ScrollBar::initialize 1\n");
76 BC_SubWindow::initialize();
77 //printf("BC_ScrollBar::initialize 1\n");
82 void BC_ScrollBar::set_images(VFrame **data)
84 for(int i = 0; i < SCROLL_IMAGES; i++)
86 if(images[i]) delete images[i];
87 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
88 //printf("BC_ScrollBar::set_images %d %p\n", i, data[i]);
90 calculate_dimensions(w, h);
95 void BC_ScrollBar::calculate_dimensions(int &w, int &h)
101 h = data[SCROLL_HANDLE_UP]->get_h();
105 w = data[SCROLL_HANDLE_UP]->get_w();
111 int BC_ScrollBar::get_span(int orientation)
116 return BC_WindowBase::get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
120 return BC_WindowBase::get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
126 int BC_ScrollBar::get_span()
131 return data[SCROLL_HANDLE_UP]->get_h();
135 return data[SCROLL_HANDLE_UP]->get_w();
141 int BC_ScrollBar::get_arrow_pixels()
146 return data[SCROLL_BACKARROW_UP]->get_w();
150 return data[SCROLL_BACKARROW_UP]->get_h();
157 void BC_ScrollBar::draw(int flush)
159 draw_top_background(parent_window, 0, 0, w, h);
160 get_handle_dimensions();
167 //printf("BC_ScrollBar::draw 1 %d %d\n", selection_status, highlight_status == SCROLL_BACKARROW);
168 // Too small to draw anything
169 if(get_w() < get_arrow_pixels() * 2 + 5)
174 images[SCROLL_HANDLE_UP]);
183 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
184 if(selection_status == SCROLL_BACKARROW)
185 draw_pixmap(images[SCROLL_BACKARROW_DN],
189 if(highlight_status == SCROLL_BACKARROW)
190 draw_pixmap(images[SCROLL_BACKARROW_HI],
194 draw_pixmap(images[SCROLL_BACKARROW_UP],
197 //printf("BC_ScrollBar::draw 2\n");
205 if(selection_status == SCROLL_FWDARROW)
206 draw_pixmap(images[SCROLL_FWDARROW_DN],
207 get_w() - get_arrow_pixels(),
210 if(highlight_status == SCROLL_FWDARROW)
211 draw_pixmap(images[SCROLL_FWDARROW_HI],
212 get_w() - get_arrow_pixels(),
215 draw_pixmap(images[SCROLL_FWDARROW_UP],
216 get_w() - get_arrow_pixels(),
223 //printf("BC_ScrollBar::draw 2\n");
226 draw_3segmenth(get_arrow_pixels(),
228 handle_pixel - get_arrow_pixels(),
229 images[SCROLL_HANDLE_BG]);
232 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
233 if(selection_status == SCROLL_HANDLE)
234 draw_3segmenth(handle_pixel,
237 images[SCROLL_HANDLE_DN]);
239 if(highlight_status == SCROLL_HANDLE)
240 draw_3segmenth(handle_pixel,
243 images[SCROLL_HANDLE_HI]);
245 draw_3segmenth(handle_pixel,
248 images[SCROLL_HANDLE_UP]);
249 //printf("BC_ScrollBar::draw 2\n");
252 draw_3segmenth(handle_pixel + handle_pixels,
254 get_w() - get_arrow_pixels() - handle_pixel - handle_pixels,
255 images[SCROLL_HANDLE_BG]);
256 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
268 // Too small to draw anything
269 if(get_h() < get_arrow_pixels() * 2 + 5)
274 images[SCROLL_HANDLE_UP]);
283 //printf("BC_ScrollBar::draw 2 %p\n", images[SCROLL_BACKARROW_HI]);
284 if(selection_status == SCROLL_BACKARROW)
285 draw_pixmap(images[SCROLL_BACKARROW_DN],
289 if(highlight_status == SCROLL_BACKARROW)
290 draw_pixmap(images[SCROLL_BACKARROW_HI],
294 draw_pixmap(images[SCROLL_BACKARROW_UP],
297 //printf("BC_ScrollBar::draw 2\n");
305 if(selection_status == SCROLL_FWDARROW)
306 draw_pixmap(images[SCROLL_FWDARROW_DN],
308 get_h() - get_arrow_pixels());
310 if(highlight_status == SCROLL_FWDARROW)
311 draw_pixmap(images[SCROLL_FWDARROW_HI],
313 get_h() - get_arrow_pixels());
315 draw_pixmap(images[SCROLL_FWDARROW_UP],
317 get_h() - get_arrow_pixels());
323 //printf("BC_ScrollBar::draw 2\n");
328 handle_pixel - get_arrow_pixels(),
329 images[SCROLL_HANDLE_BG]);
332 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
333 if(selection_status == SCROLL_HANDLE)
337 images[SCROLL_HANDLE_DN]);
339 if(highlight_status == SCROLL_HANDLE)
343 images[SCROLL_HANDLE_HI]);
348 images[SCROLL_HANDLE_UP]);
349 //printf("BC_ScrollBar::draw 2\n");
353 handle_pixel + handle_pixels,
354 get_h() - get_arrow_pixels() - handle_pixel - handle_pixels,
355 images[SCROLL_HANDLE_BG]);
356 //printf("BC_ScrollBar::draw 3 %d %d\n", handle_pixel, handle_pixels);
363 void BC_ScrollBar::get_handle_dimensions()
365 int total_pixels = pixels -
366 get_arrow_pixels() * 2;
370 handle_pixels = (int64_t)((double)handlelength /
375 if(handle_pixels < get_resources()->scroll_minhandle)
376 handle_pixels = get_resources()->scroll_minhandle;
379 handle_pixel = (int64_t)((double)position /
384 // Handle pixels is beyond minimum right position. Clamp it.
385 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
387 handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
388 handle_pixels = get_resources()->scroll_minhandle;
390 // Shrink handle_pixels until it fits inside scrollbar
391 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
393 handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
395 if(handle_pixel < get_arrow_pixels())
397 handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
398 handle_pixel = get_arrow_pixels();
400 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
404 handle_pixels = total_pixels;
405 handle_pixel = get_arrow_pixels();
408 CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
409 CLAMP(handle_pixels, 0, total_pixels);
411 // printf("BC_ScrollBar::get_handle_dimensions %d %d %d\n",
417 int BC_ScrollBar::cursor_enter_event()
419 if(top_level->event_win == win)
421 if(!highlight_status)
423 highlight_status = get_cursor_zone(top_level->cursor_x,
424 top_level->cursor_y);
432 int BC_ScrollBar::cursor_leave_event()
436 highlight_status = 0;
442 int BC_ScrollBar::cursor_motion_event()
444 if(top_level->event_win == win)
446 if(highlight_status && !selection_status)
448 int new_highlight_status =
449 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
450 if(new_highlight_status != highlight_status)
452 highlight_status = new_highlight_status;
457 if(selection_status == SCROLL_HANDLE)
459 //printf("BC_ScrollBar::cursor_motion_event 1\n");
460 double total_pixels = pixels - get_arrow_pixels() * 2;
461 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ?
462 top_level->cursor_x :
464 int64_t new_position = (int64_t)((double)(cursor_pixel - min_pixel) /
465 total_pixels * length);
466 //printf("BC_ScrollBar::cursor_motion_event 2\n");
468 if(new_position > length - handlelength)
469 new_position = length - handlelength;
470 if(new_position < 0) new_position = 0;
472 if(new_position != position)
474 //printf("BC_ScrollBar::cursor_motion_event 3\n");
475 position = new_position;
478 //printf("BC_ScrollBar::cursor_motion_event 4\n");
486 int BC_ScrollBar::button_press_event()
488 if(top_level->event_win == win)
490 //printf("BC_ScrollBar::button_press_event %d %p\n", __LINE__, bound_to);
493 top_level->deactivate();
497 if(get_buttonpress() == 4)
499 selection_status = SCROLL_BACKARROW;
500 repeat_event(top_level->get_resources()->scroll_repeat);
503 if(get_buttonpress() == 5)
505 selection_status = SCROLL_FWDARROW;
507 repeat_event(top_level->get_resources()->scroll_repeat);
511 selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
512 if(selection_status == SCROLL_HANDLE)
514 double total_pixels = pixels - get_arrow_pixels() * 2;
515 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ? top_level->cursor_x : top_level->cursor_y;
516 min_pixel = cursor_pixel - (int64_t)((double)position / length * total_pixels + .5);
517 max_pixel = (int)(cursor_pixel + total_pixels);
523 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
525 repeat_event(top_level->get_resources()->scroll_repeat);
534 int BC_ScrollBar::repeat_event(int64_t duration)
536 if(duration == top_level->get_resources()->scroll_repeat &&
539 //printf("BC_ScrollBar::repeat_event %d %d\n", __LINE__, (int)repeat_count);
542 if(repeat_count >= 2 && repeat_count < 5) return 0;
543 int64_t new_position = position;
544 switch(selection_status)
546 case SCROLL_BACKPAGE:
547 new_position -= handlelength;
550 new_position += handlelength;
552 case SCROLL_BACKARROW:
553 new_position -= (handlelength+9) / 10;
555 case SCROLL_FWDARROW:
556 new_position += (handlelength+9) / 10;
560 if(new_position > length - handlelength) new_position = length - handlelength;
561 if(new_position < 0) new_position = 0;
562 if(new_position != position)
564 position = new_position;
573 int BC_ScrollBar::button_release_event()
575 //printf("BC_ScrollBar::button_release_event %d\n", selection_status);
578 if(selection_status != SCROLL_HANDLE)
579 top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
581 selection_status = 0;
588 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
590 if(orientation == SCROLL_VERT)
592 cursor_x ^= cursor_y;
593 cursor_y ^= cursor_x;
594 cursor_x ^= cursor_y;
599 if(cursor_x >= pixels - get_arrow_pixels())
600 return SCROLL_FWDARROW;
602 if(cursor_x >= get_arrow_pixels())
604 if(cursor_x > handle_pixel + handle_pixels)
605 return SCROLL_FWDPAGE;
607 if(cursor_x >= handle_pixel)
608 return SCROLL_HANDLE;
610 return SCROLL_BACKPAGE;
613 return SCROLL_BACKARROW;
621 int BC_ScrollBar::activate()
623 top_level->active_subwindow = this;
624 //printf("BC_ScrollBar::activate %p %p\n", top_level->active_subwindow, this);
628 int64_t BC_ScrollBar::get_value()
633 int64_t BC_ScrollBar::get_position()
638 int64_t BC_ScrollBar::get_length()
643 int BC_ScrollBar::get_pixels()
648 int BC_ScrollBar::in_use()
650 return selection_status != 0;
653 int64_t BC_ScrollBar::get_handlelength()
658 int BC_ScrollBar::update_value(int64_t value)
660 this->position = value;
665 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength, int flush)
667 this->length = length;
668 this->position = position;
669 this->handlelength = handlelength;
674 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
676 if(x != get_x() || y != get_y() || pixels != this->pixels)
678 this->pixels = pixels;
680 calculate_dimensions(new_w, new_h);
681 BC_WindowBase::reposition_window(x, y, new_w, new_h);