void scrollbar::draw_contents() { surface mid_img; surface bottom_img; surface top_img; switch (state_) { case NORMAL: top_img.assign(image::get_image(scrollbar_top)); mid_img.assign(image::get_image(scrollbar_mid)); bottom_img.assign(image::get_image(scrollbar_bottom)); break; case ACTIVE: top_img.assign(image::get_image(scrollbar_top_hl)); mid_img.assign(image::get_image(scrollbar_mid_hl)); bottom_img.assign(image::get_image(scrollbar_bottom_hl)); break; case DRAGGED: top_img.assign(image::get_image(scrollbar_top_pressed)); mid_img.assign(image::get_image(scrollbar_mid_pressed)); bottom_img.assign(image::get_image(scrollbar_bottom_pressed)); break; case UNINIT: default: break; } const surface top_grv(image::get_image(groove_top)); const surface mid_grv(image::get_image(groove_mid)); const surface bottom_grv(image::get_image(groove_bottom)); if (mid_img == NULL || bottom_img == NULL || top_img == NULL || top_grv == NULL || bottom_grv == NULL || mid_grv == NULL) { std::cerr << "Failure to load scrollbar image.\n"; return; } SDL_Rect grip = grip_area(); int mid_height = grip.h - top_img->h - bottom_img->h; if (mid_height <= 0) { // For now, minimum size of the middle piece is 1. // This should never really be encountered, and if it is, // it's a symptom of a larger problem, I think. mid_height = 1; } if(mid_scaled_.null() || mid_scaled_->h != mid_height) { mid_scaled_.assign(scale_surface(mid_img, mid_img->w, mid_height)); } SDL_Rect groove = groove_area(); int groove_height = groove.h - top_grv->h - bottom_grv->h; if (groove_height <= 0) { groove_height = 1; } if (groove_scaled_.null() || groove_scaled_->h != groove_height) { groove_scaled_.assign(scale_surface(mid_grv, mid_grv->w, groove_height)); } if (mid_scaled_.null() || groove_scaled_.null()) { std::cerr << "Failure during scrollbar image scale.\n"; return; } if (grip.h > groove.h) { std::cerr << "abort draw scrollbar: grip too large\n"; return; } // Draw scrollbar "groove" video().blit_surface(groove.x, groove.y, top_grv); video().blit_surface(groove.x, groove.y + top_grv->h, groove_scaled_); video().blit_surface(groove.x, groove.y + top_grv->h + groove_height, bottom_grv); // Draw scrollbar "grip" video().blit_surface(grip.x, grip.y, top_img); video().blit_surface(grip.x, grip.y + top_img->h, mid_scaled_); video().blit_surface(grip.x, grip.y + top_img->h + mid_height, bottom_img); update_rect(groove); }
void scrollbar::handle_event(const SDL_Event& event) { gui::widget::handle_event(event); if (mouse_locked() || hidden()) return; STATE new_state = state_; SDL_Rect const &grip = grip_area(); SDL_Rect const &groove = groove_area(); switch (event.type) { case SDL_MOUSEBUTTONUP: { SDL_MouseButtonEvent const &e = event.button; bool on_grip = sdl::point_in_rect(e.x, e.y, grip); new_state = on_grip ? ACTIVE : NORMAL; break; } case SDL_MOUSEBUTTONDOWN: { SDL_MouseButtonEvent const &e = event.button; bool on_grip = sdl::point_in_rect(e.x, e.y, grip); bool on_groove = sdl::point_in_rect(e.x, e.y, groove); #if !SDL_VERSION_ATLEAST(2,0,0) if (on_groove && e.button == SDL_BUTTON_WHEELDOWN) { move_position(scroll_rate_); } else if (on_groove && e.button == SDL_BUTTON_WHEELUP) { move_position(-scroll_rate_); } else #endif if (on_grip && e.button == SDL_BUTTON_LEFT) { mousey_on_grip_ = e.y - grip.y; new_state = DRAGGED; } else if (on_groove && e.button == SDL_BUTTON_LEFT && groove.h != grip.h) { if (e.y < grip.y) move_position(-static_cast<int>(grip_height_)); else move_position(grip_height_); } else if (on_groove && e.button == SDL_BUTTON_MIDDLE) { int y_dep = e.y - grip.y - grip.h/2; int dep = y_dep * int(full_height_ - grip_height_)/ (groove.h - grip.h); move_position(dep); } break; } case SDL_MOUSEMOTION: { SDL_MouseMotionEvent const &e = event.motion; if (state_ == NORMAL || state_ == ACTIVE) { bool on_grip = sdl::point_in_rect(e.x, e.y, grip); new_state = on_grip ? ACTIVE : NORMAL; } else if (state_ == DRAGGED && groove.h != grip.h) { int y_dep = e.y - grip.y - mousey_on_grip_; int dep = y_dep * static_cast<int>(full_height_ - grip_height_) / (groove.h - grip.h); move_position(dep); } break; } #if SDL_VERSION_ATLEAST(2,0,0) case SDL_MOUSEWHEEL: { const SDL_MouseWheelEvent& e = event.wheel; int x, y; SDL_GetMouseState(&x, &y); bool on_groove = sdl::point_in_rect(x, y, groove); if (on_groove && e.y < 0) { move_position(scroll_rate_); } else if (on_groove && e.y > 0) { move_position(-scroll_rate_); } break; } #endif default: break; } if (new_state != state_) { set_dirty(); mid_scaled_.assign(NULL); state_ = new_state; } }
void scrollbar::handle_event(const SDL_Event& event) { if (mouse_locked() || hidden()) return; STATE new_state = state_; SDL_Rect const &grip = grip_area(); SDL_Rect const &groove = groove_area(); switch (event.type) { case SDL_MOUSEBUTTONUP: { SDL_MouseButtonEvent const &e = event.button; bool on_grip = point_in_rect(e.x, e.y, grip); new_state = on_grip ? ACTIVE : NORMAL; break; } case SDL_MOUSEBUTTONDOWN: { SDL_MouseButtonEvent const &e = event.button; bool on_grip = point_in_rect(e.x, e.y, grip); bool on_groove = point_in_rect(e.x, e.y, groove); if (on_groove && e.button == SDL_BUTTON_WHEELDOWN) { move_position(scroll_rate_); } else if (on_groove && e.button == SDL_BUTTON_WHEELUP) { move_position(-scroll_rate_); } else if (on_grip && e.button == SDL_BUTTON_LEFT) { mousey_on_grip_ = e.y - grip.y; new_state = DRAGGED; } else if (on_groove && e.button == SDL_BUTTON_LEFT && groove.h != grip.h) { if (e.y < grip.y) move_position(-static_cast<int>(grip_height_)); else move_position(grip_height_); } else if (on_groove && e.button == SDL_BUTTON_MIDDLE) { int y_dep = e.y - grip.y - grip.h/2; int dep = y_dep * int(full_height_ - grip_height_)/ int(groove.h - grip.h); move_position(dep); } break; } case SDL_MOUSEMOTION: { SDL_MouseMotionEvent const &e = event.motion; if (state_ == NORMAL || state_ == ACTIVE) { bool on_grip = point_in_rect(e.x, e.y, grip); new_state = on_grip ? ACTIVE : NORMAL; } else if (state_ == DRAGGED && groove.h != grip.h) { int y_dep = e.y - grip.y - mousey_on_grip_; int dep = y_dep * static_cast<int>(full_height_ - grip_height_) / static_cast<int>(groove.h - grip.h); move_position(dep); } break; } default: break; } if ((new_state == NORMAL) ^ (state_ == NORMAL)) { set_dirty(); mid_scaled_.assign(NULL); } state_ = new_state; }