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)
90 switch( orientation ) {
92 h = data[SCROLL_HANDLE_UP]->get_h();
96 w = data[SCROLL_HANDLE_UP]->get_w();
101 int BC_ScrollBar::get_span(int orientation)
106 return BC_WindowBase::get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
110 return BC_WindowBase::get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
116 int BC_ScrollBar::get_span()
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();
125 int BC_ScrollBar::get_arrow_pixels()
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();
135 void BC_ScrollBar::draw(int flush)
137 draw_top_background(parent_window, 0, 0, w, h);
138 get_handle_dimensions();
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 + 5)
152 images[SCROLL_HANDLE_UP]);
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],
167 if(highlight_status == SCROLL_BACKARROW)
168 draw_pixmap(images[SCROLL_BACKARROW_HI],
172 draw_pixmap(images[SCROLL_BACKARROW_UP],
175 //printf("BC_ScrollBar::draw 2\n");
183 if(selection_status == SCROLL_FWDARROW)
184 draw_pixmap(images[SCROLL_FWDARROW_DN],
185 get_w() - get_arrow_pixels(),
188 if(highlight_status == SCROLL_FWDARROW)
189 draw_pixmap(images[SCROLL_FWDARROW_HI],
190 get_w() - get_arrow_pixels(),
193 draw_pixmap(images[SCROLL_FWDARROW_UP],
194 get_w() - get_arrow_pixels(),
201 //printf("BC_ScrollBar::draw 2\n");
204 draw_3segmenth(get_arrow_pixels(),
206 handle_pixel - get_arrow_pixels(),
207 images[SCROLL_HANDLE_BG]);
210 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
211 if(selection_status == SCROLL_HANDLE)
212 draw_3segmenth(handle_pixel,
215 images[SCROLL_HANDLE_DN]);
217 if(highlight_status == SCROLL_HANDLE)
218 draw_3segmenth(handle_pixel,
221 images[SCROLL_HANDLE_HI]);
223 draw_3segmenth(handle_pixel,
226 images[SCROLL_HANDLE_UP]);
227 //printf("BC_ScrollBar::draw 2\n");
230 draw_3segmenth(handle_pixel + handle_pixels,
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);
246 // Too small to draw anything
247 if(get_h() < get_arrow_pixels() * 2 + 5)
252 images[SCROLL_HANDLE_UP]);
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],
267 if(highlight_status == SCROLL_BACKARROW)
268 draw_pixmap(images[SCROLL_BACKARROW_HI],
272 draw_pixmap(images[SCROLL_BACKARROW_UP],
275 //printf("BC_ScrollBar::draw 2\n");
283 if(selection_status == SCROLL_FWDARROW)
284 draw_pixmap(images[SCROLL_FWDARROW_DN],
286 get_h() - get_arrow_pixels());
288 if(highlight_status == SCROLL_FWDARROW)
289 draw_pixmap(images[SCROLL_FWDARROW_HI],
291 get_h() - get_arrow_pixels());
293 draw_pixmap(images[SCROLL_FWDARROW_UP],
295 get_h() - get_arrow_pixels());
301 //printf("BC_ScrollBar::draw 2\n");
306 handle_pixel - get_arrow_pixels(),
307 images[SCROLL_HANDLE_BG]);
310 //printf("BC_ScrollBar::draw 2 %d %d\n", handle_pixel, handle_pixels);
311 if(selection_status == SCROLL_HANDLE)
315 images[SCROLL_HANDLE_DN]);
317 if(highlight_status == SCROLL_HANDLE)
321 images[SCROLL_HANDLE_HI]);
326 images[SCROLL_HANDLE_UP]);
327 //printf("BC_ScrollBar::draw 2\n");
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);
341 void BC_ScrollBar::get_handle_dimensions()
343 int total_pixels = pixels -
344 get_arrow_pixels() * 2;
348 handle_pixels = (int64_t)((double)handlelength /
353 if(handle_pixels < get_resources()->scroll_minhandle)
354 handle_pixels = get_resources()->scroll_minhandle;
357 handle_pixel = (int64_t)((double)position /
362 // Handle pixels is beyond minimum right position. Clamp it.
363 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
365 handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
366 handle_pixels = get_resources()->scroll_minhandle;
368 // Shrink handle_pixels until it fits inside scrollbar
369 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
371 handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
373 if(handle_pixel < get_arrow_pixels())
375 handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
376 handle_pixel = get_arrow_pixels();
378 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
382 handle_pixels = total_pixels;
383 handle_pixel = get_arrow_pixels();
386 CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
387 CLAMP(handle_pixels, 0, total_pixels);
389 // printf("BC_ScrollBar::get_handle_dimensions %d %d %d\n",
395 int BC_ScrollBar::cursor_enter_event()
397 if(top_level->event_win == win)
399 if(!highlight_status)
401 highlight_status = get_cursor_zone(top_level->cursor_x,
402 top_level->cursor_y);
410 int BC_ScrollBar::cursor_leave_event()
414 highlight_status = 0;
420 int BC_ScrollBar::cursor_motion_event()
422 if(top_level->event_win == win)
424 if(highlight_status && !selection_status)
426 int new_highlight_status =
427 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
428 if(new_highlight_status != highlight_status)
430 highlight_status = new_highlight_status;
435 if(selection_status == SCROLL_HANDLE)
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 :
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");
446 if(new_position > length - handlelength)
447 new_position = length - handlelength;
448 if(new_position < 0) new_position = 0;
450 if(new_position != position)
452 //printf("BC_ScrollBar::cursor_motion_event 3\n");
453 position = new_position;
456 //printf("BC_ScrollBar::cursor_motion_event 4\n");
464 int BC_ScrollBar::button_press_event()
466 if(top_level->event_win == win)
468 //printf("BC_ScrollBar::button_press_event %d %p\n", __LINE__, bound_to);
471 top_level->deactivate();
475 if(get_buttonpress() == 4)
477 selection_status = SCROLL_BACKARROW;
478 repeat_event(top_level->get_resources()->scroll_repeat);
481 if(get_buttonpress() == 5)
483 selection_status = SCROLL_FWDARROW;
485 repeat_event(top_level->get_resources()->scroll_repeat);
489 selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
490 if(selection_status == SCROLL_HANDLE)
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);
501 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
503 repeat_event(top_level->get_resources()->scroll_repeat);
512 int BC_ScrollBar::repeat_event(int64_t duration)
514 if(duration == top_level->get_resources()->scroll_repeat &&
517 //printf("BC_ScrollBar::repeat_event %d %d\n", __LINE__, (int)repeat_count);
520 if(repeat_count >= 2 && repeat_count < 5) return 0;
521 int64_t new_position = position;
522 switch(selection_status)
524 case SCROLL_BACKPAGE:
525 new_position -= handlelength;
528 new_position += handlelength;
530 case SCROLL_BACKARROW:
531 new_position -= (handlelength+9) / 10;
533 case SCROLL_FWDARROW:
534 new_position += (handlelength+9) / 10;
538 if(new_position > length - handlelength) new_position = length - handlelength;
539 if(new_position < 0) new_position = 0;
540 if(new_position != position)
542 position = new_position;
551 int BC_ScrollBar::button_release_event()
553 //printf("BC_ScrollBar::button_release_event %d\n", selection_status);
556 if(selection_status != SCROLL_HANDLE)
557 top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
559 selection_status = 0;
566 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
568 if(orientation == SCROLL_VERT)
570 cursor_x ^= cursor_y;
571 cursor_y ^= cursor_x;
572 cursor_x ^= cursor_y;
577 if(cursor_x >= pixels - get_arrow_pixels())
578 return SCROLL_FWDARROW;
580 if(cursor_x >= get_arrow_pixels())
582 if(cursor_x > handle_pixel + handle_pixels)
583 return SCROLL_FWDPAGE;
585 if(cursor_x >= handle_pixel)
586 return SCROLL_HANDLE;
588 return SCROLL_BACKPAGE;
591 return SCROLL_BACKARROW;
599 int BC_ScrollBar::activate()
601 top_level->active_subwindow = this;
602 //printf("BC_ScrollBar::activate %p %p\n", top_level->active_subwindow, this);
606 int64_t BC_ScrollBar::get_value()
611 int64_t BC_ScrollBar::get_position()
616 int64_t BC_ScrollBar::get_length()
621 int BC_ScrollBar::get_pixels()
626 int BC_ScrollBar::in_use()
628 return selection_status != 0;
631 int64_t BC_ScrollBar::get_handlelength()
636 int BC_ScrollBar::update_value(int64_t value)
638 this->position = value;
643 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength, int flush)
645 if( stretch ) length += handlelength/4;
646 this->length = length;
647 this->position = position;
648 this->handlelength = handlelength;
653 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
655 if(x != get_x() || y != get_y() || pixels != this->pixels)
657 this->pixels = pixels;
659 calculate_dimensions(new_w, new_h);
660 BC_WindowBase::reposition_window(x, y, new_w, new_h);