Files
scummvm-cursorfix/engines/ultima/nuvie/gui/gui_scroll_bar.cpp
2026-02-02 04:50:13 +01:00

316 lines
8.7 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/shared/std/string.h"
#include "ultima/nuvie/core/nuvie_defs.h"
#include "ultima/nuvie/misc/u6_misc.h"
#include "ultima/nuvie/gui/gui.h"
#include "ultima/nuvie/gui/gui_button.h"
#include "ultima/nuvie/gui/gui_scroll_bar.h"
namespace Ultima {
namespace Nuvie {
// Colours
#define SLIDER_HIGHLIGHT_R 245
#define SLIDER_HIGHLIGHT_G 247
#define SLIDER_HIGHLIGHT_B 201
#define SLIDER_SHADOW_R 115
#define SLIDER_SHADOW_G 116
#define SLIDER_SHADOW_B 94
#define SLIDER_BASE_R 183
#define SLIDER_BASE_G 185
#define SLIDER_BASE_B 150
#define TRACK_BORDER_R 76
#define TRACK_BORDER_G 75
#define TRACK_BORDER_B 71
#define TRACK_BASE_R 137
#define TRACK_BASE_G 139
#define TRACK_BASE_B 113
GUI_ScrollBar::GUI_ScrollBar(int x, int y, int h, GUI_CallBack *callback)
: GUI_Widget(nullptr, x, y, SCROLLBAR_WIDTH, h), callback_object(callback),
drag(false), slider_highlight_c(0), slider_shadow_c(0), slider_base_c(0),
track_border_c(0), track_base_c(0), slider_click_offset(0) {
loadButtons();
track_length = area.height() - 2 * button_height;
slider_length = track_length / 2;
slider_y = 5;
}
void GUI_ScrollBar::loadButtons() {
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
Graphics::ManagedSurface *image, *image1;
build_path(datadir, "ScrollBarUp_1.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
build_path(datadir, "ScrollBarUp_2.bmp", imagefile);
image1 = SDL_LoadBMP(imagefile);
up_button = new GUI_Button(nullptr, 0, 0, image, image1, this);
this->AddWidget(up_button);
build_path(datadir, "ScrollBarDown_1.bmp", imagefile);
image = SDL_LoadBMP(imagefile);
build_path(datadir, "ScrollBarDown_2.bmp", imagefile);
image1 = SDL_LoadBMP(imagefile);
button_height = image->h;
down_button = new GUI_Button(nullptr, 0, area.height() - button_height, image, image1, this);
this->AddWidget(down_button);
return;
}
/* Map the color to the display */
void GUI_ScrollBar::SetDisplay(Screen *s) {
GUI_Widget::SetDisplay(s);
slider_highlight_c = surface->format.RGBToColor(SLIDER_HIGHLIGHT_R, SLIDER_HIGHLIGHT_G, SLIDER_HIGHLIGHT_B);
slider_shadow_c = surface->format.RGBToColor(SLIDER_SHADOW_R, SLIDER_SHADOW_G, SLIDER_SHADOW_B);
slider_base_c = surface->format.RGBToColor(SLIDER_BASE_R, SLIDER_BASE_G, SLIDER_BASE_B);
track_border_c = surface->format.RGBToColor(TRACK_BORDER_R, TRACK_BORDER_G, TRACK_BORDER_B);
track_base_c = surface->format.RGBToColor(TRACK_BASE_R, TRACK_BASE_G, TRACK_BASE_B);
}
void GUI_ScrollBar::set_slider_length(float percentage) {
slider_length = (int)((float)track_length * percentage);
}
void GUI_ScrollBar::set_slider_position(float percentage) {
move_slider((int)((float)track_length * percentage));
}
/* Show the widget */
void GUI_ScrollBar::Display(bool full_redraw) {
Common::Rect framerect;
// Common::Rect src, dst;
if (slider_y > 0) {
framerect.left = area.left;
framerect.top = area.top + button_height;
framerect.setWidth(SCROLLBAR_WIDTH);
framerect.setHeight(slider_y);
SDL_FillRect(surface, &framerect, track_base_c);
// Draw Border
framerect.left = area.left;
framerect.top = area.top + button_height;
framerect.setHeight(SCROLLBAR_WIDTH);
framerect.setHeight(1);
SDL_FillRect(surface, &framerect, track_border_c);
framerect.left = area.left;
framerect.top = area.top + button_height;
framerect.setWidth(1);
framerect.setHeight(slider_y);
SDL_FillRect(surface, &framerect, track_border_c);
framerect.left = area.left + SCROLLBAR_WIDTH - 1;
framerect.top = area.top + button_height;
framerect.setWidth(1);
framerect.setHeight(slider_y);
SDL_FillRect(surface, &framerect, track_border_c);
}
DisplaySlider();
if (slider_y + slider_length < track_length) {
framerect.left = area.left;
framerect.top = area.top + button_height + slider_y + slider_length;
framerect.setWidth(SCROLLBAR_WIDTH);
framerect.setHeight(track_length - (slider_y + slider_length));
SDL_FillRect(surface, &framerect, track_base_c);
// Draw Border
framerect.left = area.left;
framerect.top = area.top + area.height() - button_height - 1;
framerect.setWidth(SCROLLBAR_WIDTH);
framerect.setHeight(1);
SDL_FillRect(surface, &framerect, track_border_c);
framerect.left = area.left;
framerect.top = area.top + button_height + slider_y + slider_length;
framerect.setWidth(1);
framerect.setHeight(track_length - slider_y - slider_length);
SDL_FillRect(surface, &framerect, track_border_c);
framerect.left = area.left + SCROLLBAR_WIDTH - 1;
framerect.top = area.top + button_height + slider_y + slider_length;
framerect.setWidth(1);
framerect.setHeight(track_length - slider_y - slider_length);
SDL_FillRect(surface, &framerect, track_border_c);
}
DisplayChildren();
screen->update(area.left, area.top, area.width(), area.height());
return;
}
inline void GUI_ScrollBar::DisplaySlider() {
Common::Rect rect;
rect.left = area.left;
rect.top = area.top + button_height + slider_y;
rect.setWidth(SCROLLBAR_WIDTH);
rect.setHeight(slider_length);
SDL_FillRect(surface, &rect, slider_base_c);
rect.left = area.left;
rect.top = area.top + button_height + slider_y;
rect.setWidth(1);
rect.setHeight(slider_length - 1);
SDL_FillRect(surface, &rect, slider_highlight_c);
rect.left = area.left + 1;
rect.top = area.top + button_height + slider_y;
rect.setWidth(SCROLLBAR_WIDTH - 1);
rect.setHeight(1);
SDL_FillRect(surface, &rect, slider_highlight_c);
rect.left = area.left + SCROLLBAR_WIDTH - 1;
rect.top = area.top + button_height + slider_y;
rect.setWidth(1);
rect.setHeight(slider_length);
SDL_FillRect(surface, &rect, slider_shadow_c);
rect.left = area.left;
rect.top = area.top + button_height + slider_y + slider_length - 1;
rect.setWidth(SCROLLBAR_WIDTH - 1);
rect.setHeight(1);
SDL_FillRect(surface, &rect, slider_shadow_c);
}
GUI_status GUI_ScrollBar::MouseWheel(sint32 x, sint32 y) {
if (y > 0) {
send_up_button_msg();
} else if (y < 0) {
send_down_button_msg();
}
return GUI_YUM;
}
GUI_status GUI_ScrollBar::MouseDown(int x, int y, Events::MouseButton button) {
if (y >= area.top + button_height + slider_y && y <= area.top + button_height + slider_y + slider_length) {
drag = true;
slider_click_offset = y - area.top - button_height - slider_y;
grab_focus();
} else if (y < area.top + button_height + slider_y)
callback_object->callback(SCROLLBAR_CB_PAGE_UP, this, nullptr);
else
callback_object->callback(SCROLLBAR_CB_PAGE_DOWN, this, nullptr);
return GUI_YUM;
}
GUI_status GUI_ScrollBar::MouseUp(int x, int y, Events::MouseButton button) {
drag = false;
release_focus();
return GUI_YUM;
}
GUI_status GUI_ScrollBar::MouseMotion(int x, int y, uint8 state) {
int new_slider_y;
if (!drag)
return GUI_PASS;
new_slider_y = y - slider_click_offset - (area.top + button_height);
if (move_slider(new_slider_y)) {
send_slider_moved_msg();
}
// Redraw();
return GUI_YUM;
}
inline bool GUI_ScrollBar::move_slider(int new_slider_y) {
if (new_slider_y < 0 || new_slider_y + slider_length > track_length) { //new slider position is out of bounds.
if (new_slider_y < 0)
new_slider_y = 0;
else
new_slider_y = track_length - slider_length;
}
if (slider_y == new_slider_y)
return false;
slider_y = new_slider_y;
return true;
}
void GUI_ScrollBar::send_slider_moved_msg() {
float slider_percentage;
slider_percentage = slider_y / (float)track_length;
callback_object->callback(SCROLLBAR_CB_SLIDER_MOVED, this, &slider_percentage);
return;
}
void GUI_ScrollBar::send_up_button_msg() {
callback_object->callback(SCROLLBAR_CB_UP_BUTTON, this, nullptr);
}
void GUI_ScrollBar::send_down_button_msg() {
callback_object->callback(SCROLLBAR_CB_DOWN_BUTTON, this, nullptr);
}
GUI_status GUI_ScrollBar::callback(uint16 msg, GUI_CallBack *caller, void *data) {
if (msg == BUTTON_CB) {
if (caller == up_button)
send_up_button_msg();
if (caller == down_button)
send_down_button_msg();
}
return GUI_YUM;
}
} // End of namespace Nuvie
} // End of namespace Ultima