Files
2026-02-02 04:50:13 +01:00

255 lines
6.3 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_dialog.h"
namespace Ultima {
namespace Nuvie {
GUI_Dialog::GUI_Dialog(int x, int y, int w, int h, uint8 r, uint8 g, uint8 b, bool is_moveable)
: GUI_Widget(nullptr, x, y, w, h), R(r), G(g), B(b), bg_color(0), drag(false),
can_drag(is_moveable), button_x(0), button_y(0), old_x(-1), old_y(-1),
backingstore(nullptr) {
backingstore_rect.setWidth(w);
backingstore_rect.setHeight(h);
loadBorderImages();
}
GUI_Dialog::~GUI_Dialog() {
if (backingstore)
free(backingstore);
for (int i = 0; i < ARRAYSIZE(border); i++)
delete border[i];
}
void GUI_Dialog::loadBorderImages() {
char filename[15]; // BorderU6_x.bmp\0
Common::Path datadir = GUI::get_gui()->get_data_dir();
Common::Path imagefile;
for (int i = 0; i < 8; i++) {
Common::sprintf_s(filename, "Border%s_%d.bmp", "U6", i + 1);
build_path(datadir, filename, imagefile);
border[i] = SDL_LoadBMP(imagefile);
if (border[i] == nullptr) {
DEBUG(0, LEVEL_ERROR, "Failed to load %s from '%s' directory\n", filename, datadir.toString().c_str());
}
}
}
/* Map the color to the display */
void GUI_Dialog::SetDisplay(Screen *s) {
GUI_Widget::SetDisplay(s);
bg_color = surface->format.RGBToColor(R, G, B);
}
/* Show the widget */
void
GUI_Dialog::Display(bool full_redraw) {
int i;
if (old_x != area.left || old_y != area.top) {
if (backingstore) {
screen->restore_area(backingstore, &backingstore_rect, nullptr, nullptr, false);
screen->update(backingstore_rect.left, backingstore_rect.top,
backingstore_rect.width(), backingstore_rect.height());
}
backingstore_rect.moveTo(area.left, area.top);
backingstore = screen->copy_area(&backingstore_rect, backingstore);
old_x = area.left;
old_y = area.top;
}
Common::Rect framerect = area;
framerect.grow(-8);
SDL_FillRect(surface, &framerect, bg_color);
// Draw border corners
Common::Rect dst;
dst = area;
dst.setWidth(8);
dst.setHeight(8);
SDL_BlitSurface(border[0], nullptr, surface, &dst);
dst.left = area.left + area.width() - 8;
dst.top = area.top;
dst.setWidth(8);
dst.setHeight(8);
SDL_BlitSurface(border[2], nullptr, surface, &dst);
dst.left = area.left + area.width() - 8;
dst.top = area.top + area.height() - 8;
dst.setWidth(8);
dst.setHeight(8);
SDL_BlitSurface(border[4], nullptr, surface, &dst);
dst.left = area.left;
dst.top = area.top + area.height() - 8;
dst.setWidth(8);
dst.setHeight(8);
SDL_BlitSurface(border[6], nullptr, surface, &dst);
// Draw top and bottom border lines
for (i = area.left + 8; i < area.left + area.width() - 24; i += 16) {
dst.left = i;
dst.top = area.top;
dst.setWidth(16);
dst.setHeight(8);
SDL_BlitSurface(border[1], nullptr, surface, &dst);
dst.left = i;
dst.top = area.top + area.height() - 8;
dst.setWidth(16);
dst.setHeight(8);
SDL_BlitSurface(border[5], nullptr, surface, &dst);
}
if (i < area.left + area.width() - 8) { // draw partial border images
Common::Rect src;
src.left = 0;
src.top = 0;
src.setWidth(area.left + area.width() - 8 - i);
src.setHeight(8);
dst.left = i;
dst.top = area.top;
dst.setWidth(src.width());
dst.setHeight(8);
SDL_BlitSurface(border[1], &src, surface, &dst);
dst.left = i;
dst.top = area.top + area.height() - 8;
dst.setWidth(src.width());
dst.setHeight(8);
SDL_BlitSurface(border[5], &src, surface, &dst);
}
// Draw left and right sides
for (i = area.top + 8; i < area.top + area.height() - 24; i += 16) {
dst.left = area.left;
dst.top = i;
dst.setWidth(8);
dst.setHeight(16);
SDL_BlitSurface(border[7], nullptr, surface, &dst);
dst.left = area.left + area.width() - 8;
dst.top = i;
dst.setWidth(8);
dst.setHeight(16);
SDL_BlitSurface(border[3], nullptr, surface, &dst);
}
if (i < area.top + area.height() - 8) { // draw partial border images
Common::Rect src;
src.left = 0;
src.top = 0;
src.setWidth(8);
src.setHeight(area.top + area.height() - 8 - i);
dst.left = area.left;
dst.top = i;
dst.setWidth(8);
dst.setHeight(src.height());
SDL_BlitSurface(border[7], &src, surface, &dst);
dst.left = area.left + area.width() - 8;
dst.top = i;
dst.setWidth(8);
dst.setHeight(src.height());
SDL_BlitSurface(border[3], &src, surface, &dst);
}
DisplayChildren();
screen->update(area.left, area.top, area.width(), area.height());
return;
}
GUI_status GUI_Dialog::MouseDown(int x, int y, Events::MouseButton button) {
drag = can_drag;
button_x = x;
button_y = y;
grab_focus();
return GUI_YUM;
}
GUI_status GUI_Dialog::MouseUp(int x, int y, Events::MouseButton button) {
drag = false;
release_focus();
return GUI_YUM;
}
GUI_status GUI_Dialog::MouseMotion(int x, int y, uint8 state) {
if (!drag)
return GUI_PASS;
int dx = x - button_x;
int dy = y - button_y;
button_x = x;
button_y = y;
GUI::get_gui()->moveWidget(this, dx, dy);
// Redraw();
return GUI_YUM;
}
void GUI_Dialog::MoveRelative(int dx, int dy) {
int new_x = area.left + dx;
if (new_x < 0) {
dx = -area.left;
} else if (new_x + area.width() > screen->get_width()) {
dx = screen->get_width() - (area.left + area.width());
}
int new_y = area.top + dy;
if (new_y < 0) {
dy = -area.top;
} else if (new_y + area.height() > screen->get_height()) {
dy = screen->get_height() - (area.top + area.height());
}
GUI_Widget::MoveRelative(dx, dy);
return;
}
} // End of namespace Nuvie
} // End of namespace Ultima