00001 #include "bcpixmap.h"
00002 #include "bcresources.h"
00003 #include "bcscrollbar.h"
00004 #include "clip.h"
00005 #include "colors.h"
00006 #include "vframe.h"
00007
00008 #include <string.h>
00009
00010 BC_ScrollBar::BC_ScrollBar(int x,
00011 int y,
00012 int orientation,
00013 int pixels,
00014 int64_t length,
00015 int64_t position,
00016 int64_t handlelength,
00017 VFrame **data)
00018 : BC_SubWindow(x, y, 0, 0, -1)
00019 {
00020 this->length = length;
00021 this->position = position;
00022 this->handlelength = handlelength;
00023 this->selection_status = 0;
00024 this->highlight_status = 0;
00025 this->orientation = orientation;
00026 this->pixels = pixels;
00027
00028 if(data)
00029 this->data = data;
00030 else
00031 if(orientation == SCROLL_HORIZ)
00032 this->data = BC_WindowBase::get_resources()->hscroll_data;
00033 else
00034 this->data = BC_WindowBase::get_resources()->vscroll_data;
00035
00036 handle_pixel = 0;
00037 handle_pixels = 0;
00038 bound_to = 0;
00039 repeat_count = 0;
00040 memset(images, 0, sizeof(BC_Pixmap*) * SCROLL_IMAGES);
00041 }
00042
00043 BC_ScrollBar::~BC_ScrollBar()
00044 {
00045 for(int i = 0; i < SCROLL_IMAGES; i++)
00046 if(images[i]) delete images[i];
00047 }
00048
00049 int BC_ScrollBar::initialize()
00050 {
00051
00052 set_images(data);
00053
00054
00055 BC_SubWindow::initialize();
00056
00057 draw();
00058 return 0;
00059 }
00060
00061 void BC_ScrollBar::set_images(VFrame **data)
00062 {
00063 for(int i = 0; i < SCROLL_IMAGES; i++)
00064 {
00065 if(images[i]) delete images[i];
00066 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
00067
00068 }
00069 calculate_dimensions(w, h);
00070 }
00071
00072
00073
00074 void BC_ScrollBar::calculate_dimensions(int &w, int &h)
00075 {
00076 switch(orientation)
00077 {
00078 case SCROLL_HORIZ:
00079 w = pixels;
00080 h = data[SCROLL_HANDLE_UP]->get_h();
00081 break;
00082
00083 case SCROLL_VERT:
00084 w = data[SCROLL_HANDLE_UP]->get_w();
00085 h = pixels;
00086 break;
00087 }
00088 }
00089
00090 int BC_ScrollBar::get_span(int orientation)
00091 {
00092 switch(orientation)
00093 {
00094 case SCROLL_HORIZ:
00095 return BC_WindowBase::get_resources()->hscroll_data[SCROLL_HANDLE_UP]->get_h();
00096 break;
00097
00098 case SCROLL_VERT:
00099 return BC_WindowBase::get_resources()->vscroll_data[SCROLL_HANDLE_UP]->get_w();
00100 break;
00101 }
00102 return 0;
00103 }
00104
00105 int BC_ScrollBar::get_span()
00106 {
00107 switch(orientation)
00108 {
00109 case SCROLL_HORIZ:
00110 return data[SCROLL_HANDLE_UP]->get_h();
00111 break;
00112
00113 case SCROLL_VERT:
00114 return data[SCROLL_HANDLE_UP]->get_w();
00115 break;
00116 }
00117 return 0;
00118 }
00119
00120 int BC_ScrollBar::get_arrow_pixels()
00121 {
00122 switch(orientation)
00123 {
00124 case SCROLL_HORIZ:
00125 return data[SCROLL_BACKARROW_UP]->get_w();
00126 break;
00127
00128 case SCROLL_VERT:
00129 return data[SCROLL_BACKARROW_UP]->get_h();
00130 break;
00131 }
00132 return 0;
00133 }
00134
00135
00136 void BC_ScrollBar::draw()
00137 {
00138 draw_top_background(parent_window, 0, 0, w, h);
00139 get_handle_dimensions();
00140
00141 switch(orientation)
00142 {
00143 case SCROLL_HORIZ:
00144
00145
00146
00147
00148 if(get_w() < get_arrow_pixels() * 2 + 5)
00149 {
00150 draw_3segmenth(0,
00151 0,
00152 get_w(),
00153 images[SCROLL_HANDLE_UP]);
00154 }
00155 else
00156 {
00157
00158
00159
00160
00161
00162
00163 if(selection_status == SCROLL_BACKARROW)
00164 draw_pixmap(images[SCROLL_BACKARROW_DN],
00165 0,
00166 0);
00167 else
00168 if(highlight_status == SCROLL_BACKARROW)
00169 draw_pixmap(images[SCROLL_BACKARROW_HI],
00170 0,
00171 0);
00172 else
00173 draw_pixmap(images[SCROLL_BACKARROW_UP],
00174 0,
00175 0);
00176
00177
00178
00179
00180
00181
00182
00183
00184 if(selection_status == SCROLL_FWDARROW)
00185 draw_pixmap(images[SCROLL_FWDARROW_DN],
00186 get_w() - get_arrow_pixels(),
00187 0);
00188 else
00189 if(highlight_status == SCROLL_FWDARROW)
00190 draw_pixmap(images[SCROLL_FWDARROW_HI],
00191 get_w() - get_arrow_pixels(),
00192 0);
00193 else
00194 draw_pixmap(images[SCROLL_FWDARROW_UP],
00195 get_w() - get_arrow_pixels(),
00196 0);
00197
00198
00199
00200
00201
00202
00203
00204
00205 draw_3segmenth(get_arrow_pixels(),
00206 0,
00207 handle_pixel - get_arrow_pixels(),
00208 images[SCROLL_HANDLE_BG]);
00209
00210
00211
00212 if(selection_status == SCROLL_HANDLE)
00213 draw_3segmenth(handle_pixel,
00214 0,
00215 handle_pixels,
00216 images[SCROLL_HANDLE_DN]);
00217 else
00218 if(highlight_status == SCROLL_HANDLE)
00219 draw_3segmenth(handle_pixel,
00220 0,
00221 handle_pixels,
00222 images[SCROLL_HANDLE_HI]);
00223 else
00224 draw_3segmenth(handle_pixel,
00225 0,
00226 handle_pixels,
00227 images[SCROLL_HANDLE_UP]);
00228
00229
00230
00231 draw_3segmenth(handle_pixel + handle_pixels,
00232 0,
00233 get_w() - get_arrow_pixels() - handle_pixel - handle_pixels,
00234 images[SCROLL_HANDLE_BG]);
00235
00236 }
00237 break;
00238
00239
00240
00241
00242
00243
00244
00245
00246 case SCROLL_VERT:
00247
00248 if(get_h() < get_arrow_pixels() * 2 + 5)
00249 {
00250 draw_3segmentv(0,
00251 0,
00252 get_w(),
00253 images[SCROLL_HANDLE_UP]);
00254 }
00255 else
00256 {
00257
00258
00259
00260
00261
00262
00263 if(selection_status == SCROLL_BACKARROW)
00264 draw_pixmap(images[SCROLL_BACKARROW_DN],
00265 0,
00266 0);
00267 else
00268 if(highlight_status == SCROLL_BACKARROW)
00269 draw_pixmap(images[SCROLL_BACKARROW_HI],
00270 0,
00271 0);
00272 else
00273 draw_pixmap(images[SCROLL_BACKARROW_UP],
00274 0,
00275 0);
00276
00277
00278
00279
00280
00281
00282
00283
00284 if(selection_status == SCROLL_FWDARROW)
00285 draw_pixmap(images[SCROLL_FWDARROW_DN],
00286 0,
00287 get_h() - get_arrow_pixels());
00288 else
00289 if(highlight_status == SCROLL_FWDARROW)
00290 draw_pixmap(images[SCROLL_FWDARROW_HI],
00291 0,
00292 get_h() - get_arrow_pixels());
00293 else
00294 draw_pixmap(images[SCROLL_FWDARROW_UP],
00295 0,
00296 get_h() - get_arrow_pixels());
00297
00298
00299
00300
00301
00302
00303
00304
00305 draw_3segmentv(0,
00306 get_arrow_pixels(),
00307 handle_pixel - get_arrow_pixels(),
00308 images[SCROLL_HANDLE_BG]);
00309
00310
00311
00312 if(selection_status == SCROLL_HANDLE)
00313 draw_3segmentv(0,
00314 handle_pixel,
00315 handle_pixels,
00316 images[SCROLL_HANDLE_DN]);
00317 else
00318 if(highlight_status == SCROLL_HANDLE)
00319 draw_3segmentv(0,
00320 handle_pixel,
00321 handle_pixels,
00322 images[SCROLL_HANDLE_HI]);
00323 else
00324 draw_3segmentv(0,
00325 handle_pixel,
00326 handle_pixels,
00327 images[SCROLL_HANDLE_UP]);
00328
00329
00330
00331 draw_3segmentv(0,
00332 handle_pixel + handle_pixels,
00333 get_h() - get_arrow_pixels() - handle_pixel - handle_pixels,
00334 images[SCROLL_HANDLE_BG]);
00335
00336 }
00337 break;
00338 }
00339 flash();
00340 }
00341
00342 void BC_ScrollBar::get_handle_dimensions()
00343 {
00344 int total_pixels = pixels -
00345 get_arrow_pixels() * 2;
00346
00347 if(length > 0)
00348 {
00349 handle_pixels = (int64_t)((double)handlelength /
00350 length *
00351 total_pixels +
00352 .5);
00353
00354 if(handle_pixels < get_resources()->scroll_minhandle)
00355 handle_pixels = get_resources()->scroll_minhandle;
00356
00357
00358 handle_pixel = (int64_t)((double)position /
00359 length *
00360 total_pixels + .5) +
00361 get_arrow_pixels();
00362
00363
00364 if(handle_pixel > pixels - get_arrow_pixels() - get_resources()->scroll_minhandle)
00365 {
00366 handle_pixel = pixels - get_arrow_pixels() - get_resources()->scroll_minhandle;
00367 handle_pixels = get_resources()->scroll_minhandle;
00368 }
00369
00370 if(handle_pixel > pixels - get_arrow_pixels() - handle_pixels)
00371 {
00372 handle_pixels = pixels - get_arrow_pixels() - handle_pixel;
00373 }
00374 if(handle_pixel < get_arrow_pixels())
00375 {
00376 handle_pixels = handle_pixel + handle_pixels - get_arrow_pixels();
00377 handle_pixel = get_arrow_pixels();
00378 }
00379 if(handle_pixels < get_resources()->scroll_minhandle) handle_pixels = get_resources()->scroll_minhandle;
00380 }
00381 else
00382 {
00383 handle_pixels = total_pixels;
00384 handle_pixel = get_arrow_pixels();
00385 }
00386
00387 CLAMP(handle_pixel, get_arrow_pixels(), (int)(pixels - get_arrow_pixels()));
00388 CLAMP(handle_pixels, 0, total_pixels);
00389
00390
00391
00392
00393
00394 }
00395
00396 int BC_ScrollBar::cursor_enter_event()
00397 {
00398 if(top_level->event_win == win)
00399 {
00400 if(!highlight_status)
00401 {
00402 highlight_status = get_cursor_zone(top_level->cursor_x,
00403 top_level->cursor_y);
00404 draw();
00405 }
00406 return 1;
00407 }
00408 return 0;
00409 }
00410
00411 int BC_ScrollBar::cursor_leave_event()
00412 {
00413 if(highlight_status)
00414 {
00415 highlight_status = 0;
00416 draw();
00417 }
00418 return 0;
00419 }
00420
00421 int BC_ScrollBar::cursor_motion_event()
00422 {
00423 if(top_level->event_win == win)
00424 {
00425 if(highlight_status && !selection_status)
00426 {
00427 int new_highlight_status =
00428 get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
00429 if(new_highlight_status != highlight_status)
00430 {
00431 highlight_status = new_highlight_status;
00432 draw();
00433 }
00434 }
00435 else
00436 if(selection_status == SCROLL_HANDLE)
00437 {
00438
00439 double total_pixels = pixels - get_arrow_pixels() * 2;
00440 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ?
00441 top_level->cursor_x :
00442 top_level->cursor_y;
00443 int64_t new_position = (int64_t)((double)(cursor_pixel - min_pixel) /
00444 total_pixels * length);
00445
00446
00447 if(new_position > length - handlelength)
00448 new_position = length - handlelength;
00449 if(new_position < 0) new_position = 0;
00450
00451 if(new_position != position)
00452 {
00453
00454 position = new_position;
00455 draw();
00456 handle_event();
00457
00458 }
00459 }
00460 return 1;
00461 }
00462 return 0;
00463 }
00464
00465 int BC_ScrollBar::button_press_event()
00466 {
00467 if(top_level->event_win == win)
00468 {
00469 if(!bound_to)
00470 {
00471 top_level->deactivate();
00472 activate();
00473 }
00474
00475 if(get_buttonpress() == 4)
00476 {
00477 selection_status = SCROLL_BACKARROW;
00478 repeat_event(top_level->get_resources()->scroll_repeat);
00479 }
00480 else
00481 if(get_buttonpress() == 5)
00482 {
00483 selection_status = SCROLL_FWDARROW;
00484 repeat_count = 0;
00485 repeat_event(top_level->get_resources()->scroll_repeat);
00486 }
00487 else
00488 {
00489 selection_status = get_cursor_zone(top_level->cursor_x, top_level->cursor_y);
00490 if(selection_status == SCROLL_HANDLE)
00491 {
00492 double total_pixels = pixels - get_arrow_pixels() * 2;
00493 int64_t cursor_pixel = (orientation == SCROLL_HORIZ) ? top_level->cursor_x : top_level->cursor_y;
00494 min_pixel = cursor_pixel - (int64_t)((double)position / length * total_pixels + .5);
00495 max_pixel = (int)(cursor_pixel + total_pixels);
00496 draw();
00497 }
00498 else
00499 if(selection_status)
00500 {
00501 top_level->set_repeat(top_level->get_resources()->scroll_repeat);
00502 repeat_count = 0;
00503 repeat_event(top_level->get_resources()->scroll_repeat);
00504 draw();
00505 }
00506 }
00507 return 1;
00508 }
00509 return 0;
00510 }
00511
00512 int BC_ScrollBar::repeat_event(int64_t duration)
00513 {
00514 if(duration == top_level->get_resources()->scroll_repeat &&
00515 selection_status)
00516 {
00517 repeat_count++;
00518 if(repeat_count == 2) return 0;
00519 int64_t new_position = position;
00520 switch(selection_status)
00521 {
00522 case SCROLL_BACKPAGE:
00523 new_position -= handlelength;
00524 break;
00525 case SCROLL_FWDPAGE:
00526 new_position += handlelength;
00527 break;
00528 case SCROLL_BACKARROW:
00529 new_position -= handlelength / 10;
00530 break;
00531 case SCROLL_FWDARROW:
00532 new_position += handlelength / 10;
00533 break;
00534 }
00535
00536 if(new_position > length - handlelength) new_position = length - handlelength;
00537 if(new_position < 0) new_position = 0;
00538 if(new_position != position)
00539 {
00540 position = new_position;
00541 draw();
00542 handle_event();
00543 }
00544 return 1;
00545 }
00546 return 0;
00547 }
00548
00549 int BC_ScrollBar::button_release_event()
00550 {
00551
00552 if(selection_status)
00553 {
00554 if(selection_status != SCROLL_HANDLE)
00555 top_level->unset_repeat(top_level->get_resources()->scroll_repeat);
00556
00557 selection_status = 0;
00558 draw();
00559 return 1;
00560 }
00561 return 0;
00562 }
00563
00564 int BC_ScrollBar::get_cursor_zone(int cursor_x, int cursor_y)
00565 {
00566 if(orientation == SCROLL_VERT)
00567 {
00568 cursor_x ^= cursor_y;
00569 cursor_y ^= cursor_x;
00570 cursor_x ^= cursor_y;
00571 }
00572
00573
00574
00575 if(cursor_x >= pixels - get_arrow_pixels())
00576 return SCROLL_FWDARROW;
00577 else
00578 if(cursor_x >= get_arrow_pixels())
00579 {
00580 if(cursor_x > handle_pixel + handle_pixels)
00581 return SCROLL_FWDPAGE;
00582 else
00583 if(cursor_x >= handle_pixel)
00584 return SCROLL_HANDLE;
00585 else
00586 return SCROLL_BACKPAGE;
00587 }
00588 else
00589 return SCROLL_BACKARROW;
00590
00591
00592
00593
00594 return 0;
00595 }
00596
00597 int BC_ScrollBar::activate()
00598 {
00599 top_level->active_subwindow = this;
00600
00601 return 0;
00602 }
00603
00604 int64_t BC_ScrollBar::get_value()
00605 {
00606 return position;
00607 }
00608
00609 int64_t BC_ScrollBar::get_position()
00610 {
00611 return position;
00612 }
00613
00614 int64_t BC_ScrollBar::get_length()
00615 {
00616 return length;
00617 }
00618
00619 int BC_ScrollBar::get_pixels()
00620 {
00621 return pixels;
00622 }
00623
00624 int BC_ScrollBar::in_use()
00625 {
00626 return selection_status != 0;
00627 }
00628
00629 int64_t BC_ScrollBar::get_handlelength()
00630 {
00631 return handlelength;
00632 }
00633
00634 int BC_ScrollBar::update_value(int64_t value)
00635 {
00636 this->position = value;
00637 draw();
00638 return 0;
00639 }
00640
00641 int BC_ScrollBar::update_length(int64_t length, int64_t position, int64_t handlelength)
00642 {
00643 this->length = length;
00644 this->position = position;
00645 this->handlelength = handlelength;
00646 draw();
00647 return 0;
00648 }
00649
00650 int BC_ScrollBar::reposition_window(int x, int y, int pixels)
00651 {
00652 if(x != get_x() || y != get_y() || pixels != this->pixels)
00653 {
00654 this->pixels = pixels;
00655 int new_w, new_h;
00656 calculate_dimensions(new_w, new_h);
00657 BC_WindowBase::reposition_window(x, y, new_w, new_h);
00658 }
00659 draw();
00660 return 0;
00661 }
00662