mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-14 16:07:39 +00:00
![Thanasis Antoniou](/assets/img/avatar_default.png)
Current purpose is for text language selection Drop down list for language selection in KIA (early stage)
353 lines
13 KiB
C++
353 lines
13 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "bladerunner/ui/ui_dropdown.h"
|
|
|
|
#include "bladerunner/audio_player.h"
|
|
#include "bladerunner/bladerunner.h"
|
|
#include "bladerunner/ui/kia.h"
|
|
#include "bladerunner/ui/ui_image_picker.h"
|
|
#include "bladerunner/ui/ui_scroll_box.h"
|
|
#include "bladerunner/subtitles.h"
|
|
#include "bladerunner/font.h"
|
|
#include "bladerunner/game_info.h"
|
|
#include "bladerunner/shape.h"
|
|
#include "bladerunner/game_constants.h"
|
|
|
|
#include "common/debug.h"
|
|
|
|
namespace BladeRunner {
|
|
|
|
const Color256 UIDropDown::kColors[] = {
|
|
{ 0, 0, 0 }, // Black - unpressed (framing rectange)
|
|
{ 16, 8, 8 },
|
|
{ 32, 24, 8 },
|
|
{ 56, 32, 16 },
|
|
{ 72, 48, 16 },
|
|
{ 88, 56, 24 }, // Mouse-over (framing rectange)
|
|
{ 104, 72, 32 },
|
|
{ 128, 80, 40 },
|
|
{ 136, 96, 48 },
|
|
{ 152, 112, 56 },
|
|
{ 168, 128, 72 } // Pressed (framing rectange)
|
|
};
|
|
|
|
UIDropDown::UIDropDown(BladeRunnerEngine *vm,
|
|
UIDropDownLineSelectedCallback *ddlLineSelectedCallback,
|
|
UIDropDownGenericCallback *ddlCancelledCallback,
|
|
UIDropDownGenericCallback *ddlTopFrameClickCallback,
|
|
void *callbackData,
|
|
Common::String labelStr,
|
|
int controlLeftX,
|
|
int controlTopY,
|
|
int scrollBoxMaxLineCount) : UIComponent(vm) {
|
|
|
|
_isVisible = false;
|
|
|
|
_labelStr = labelStr;
|
|
_controlLeftX = MAX(controlLeftX, 0);
|
|
// TODO The id should be used to eg. grab info about the selected subtitles from an engine's subtitles object
|
|
_lineSelectedId = -1;
|
|
|
|
_lineSelectorFrameRectColor = 0;
|
|
_lineSelectorFrameRectHasFocus = false;
|
|
// A framing (outlining) rectangle to highlight the selected option field on top of the scrollbox
|
|
controlTopY = CLIP(controlTopY, 0, 600);
|
|
_lineSelectorFrameRect = Common::Rect(0, controlTopY, 0, controlTopY + kDropDownButtonShapeHeight);
|
|
|
|
// TODO This eventually should be set to a default probably by the outside caller class(kia_section_settings)
|
|
// Current explicit assignment only serves as placeholder / proof of concept
|
|
_lineSelectedStr = "English (SCUMMVM) v7 [ENG]";
|
|
_lineSelectorScrollBox = new UIScrollBox(_vm, scrollBoxLineSelectCallback, this, scrollBoxMaxLineCount, 2, false, Common::Rect(0, 0, 0, 55 + kFrameRectPaddingPx), Common::Rect(0, 0, 0, 55));
|
|
_lineSelectorScrollBoxMaxLineWidth = 0;
|
|
|
|
_lineDropdownBtn = new UIImagePicker(_vm, 2);
|
|
|
|
_ddlLineSelectedCallback = ddlLineSelectedCallback;
|
|
_ddlCancelledCallback = ddlCancelledCallback;
|
|
_ddlTopFrameClickCallback = ddlTopFrameClickCallback;
|
|
_callbackData = callbackData;
|
|
|
|
_mouseX = 0;
|
|
_mouseY = 0;
|
|
}
|
|
|
|
UIDropDown::~UIDropDown() {
|
|
delete _lineSelectorScrollBox;
|
|
delete _lineDropdownBtn;
|
|
}
|
|
|
|
void UIDropDown::activate() {
|
|
_lineDropdownBtn->resetImages();
|
|
// Actual button shape
|
|
// defineImage actually increases internally the bottom and right bounds for the rect to be inclusive (for the contains() method)
|
|
_lineDropdownBtn->defineImage(0, Common::Rect(0, _lineSelectorFrameRect.top + 1, kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(73), _vm->_kia->_shapes->get(74), _vm->_kia->_shapes->get(75), nullptr);
|
|
// Clickable Selected/Active Line Description area
|
|
_lineDropdownBtn->defineImage(1, Common::Rect(0, _lineSelectorFrameRect.top, kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), nullptr, nullptr, nullptr, nullptr);
|
|
_lineDropdownBtn->activate(nullptr, nullptr, mouseDownLDBCallback, nullptr, this);
|
|
|
|
_lineSelectorScrollBox->setBoxTop(_lineSelectorFrameRect.bottom);
|
|
_lineSelectorScrollBox->setScrollbarTop(_lineSelectorFrameRect.bottom);
|
|
|
|
_lineSelectorScrollBox->hide(); // show upon click on field or dropdown button
|
|
show();
|
|
}
|
|
|
|
|
|
void UIDropDown::deactivate() {
|
|
_isVisible = false;
|
|
|
|
_lineDropdownBtn->deactivate();
|
|
_lineSelectorScrollBox->hide();
|
|
}
|
|
|
|
void UIDropDown::draw(Graphics::Surface &surface) {
|
|
if (!_isVisible) {
|
|
return;
|
|
}
|
|
|
|
int posStartOfSelectedLineDesc = _controlLeftX + _vm->_mainFont->getStringWidth(_labelStr) + _vm->_mainFont->getCharWidth(' ');
|
|
_vm->_mainFont->drawString(&surface, _labelStr, _controlLeftX, _lineSelectorFrameRect.top, surface.w, surface.format.RGBToColor(232, 208, 136));
|
|
_vm->_mainFont->drawString(&surface, _lineSelectedStr,
|
|
posStartOfSelectedLineDesc,
|
|
_lineSelectorFrameRect.top, surface.w, surface.format.RGBToColor(240, 232, 192));
|
|
|
|
// TODO add a clipping for description field here
|
|
int posEndOfSelectedLineDesc = posStartOfSelectedLineDesc + _vm->_mainFont->getStringWidth(_lineSelectedStr) + _vm->_mainFont->getCharWidth(' ');
|
|
|
|
_lineDropdownBtn->setImageLeft(0, posEndOfSelectedLineDesc );
|
|
|
|
_lineDropdownBtn->setImageLeft(1, posStartOfSelectedLineDesc - kFrameRectPaddingPx);
|
|
_lineDropdownBtn->setImageWidth(1, posEndOfSelectedLineDesc + kFrameRectPaddingPx - posStartOfSelectedLineDesc);
|
|
|
|
_lineDropdownBtn->draw(surface);
|
|
// _lineDropdownBtn->drawTooltip(surface, _mouseX, _mouseY);
|
|
|
|
_lineSelectorFrameRect.moveTo(posStartOfSelectedLineDesc - kFrameRectPaddingPx, _lineSelectorFrameRect.top);
|
|
_lineSelectorFrameRect.setWidth(posEndOfSelectedLineDesc + kDropDownButtonShapeWidth + kFrameRectPaddingPx - posStartOfSelectedLineDesc);
|
|
|
|
_lineSelectorScrollBox->draw(surface);
|
|
|
|
int lineSelectorFrameRectTargetColor;
|
|
if (_lineSelectorScrollBox->isVisible()) {
|
|
lineSelectorFrameRectTargetColor = 10;
|
|
} else if (_lineSelectorFrameRectHasFocus) {
|
|
lineSelectorFrameRectTargetColor = 5;
|
|
} else {
|
|
lineSelectorFrameRectTargetColor = 0;
|
|
}
|
|
|
|
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
|
if (_lineSelectorFrameRectColor < lineSelectorFrameRectTargetColor) {
|
|
++_lineSelectorFrameRectColor;
|
|
}
|
|
|
|
// Ensures animated transition of the frame's (outlining rectangle's) color to the new one
|
|
if (_lineSelectorFrameRectColor > lineSelectorFrameRectTargetColor) {
|
|
--_lineSelectorFrameRectColor;
|
|
}
|
|
surface.frameRect(_lineSelectorFrameRect,
|
|
surface.format.RGBToColor(kColors[_lineSelectorFrameRectColor].r,
|
|
kColors[_lineSelectorFrameRectColor].g,
|
|
kColors[_lineSelectorFrameRectColor].b));
|
|
}
|
|
|
|
void UIDropDown::show() {
|
|
_isVisible = true;
|
|
}
|
|
|
|
void UIDropDown::hide() {
|
|
_isVisible = false;
|
|
}
|
|
|
|
bool UIDropDown::isVisible() {
|
|
return _isVisible;
|
|
}
|
|
|
|
bool UIDropDown::isDropDownMenuExpanded() {
|
|
return _lineSelectorScrollBox->isVisible();
|
|
}
|
|
|
|
void UIDropDown::clearLines() {
|
|
_lineSelectorScrollBox->clearLines();
|
|
_lineSelectorScrollBoxMaxLineWidth = 0;
|
|
}
|
|
|
|
void UIDropDown::addLine(const Common::String &text, int lineData) {
|
|
_lineSelectorScrollBox->addLine(text, lineData, 0x08);
|
|
_lineSelectorScrollBoxMaxLineWidth = MAX(_vm->_mainFont->getStringWidth(text), _lineSelectorScrollBoxMaxLineWidth);
|
|
}
|
|
|
|
void UIDropDown::addLine(const char *text, int lineData) {
|
|
_lineSelectorScrollBox->addLine(text, lineData, 0x08);
|
|
_lineSelectorScrollBoxMaxLineWidth = MAX(_vm->_mainFont->getStringWidth(text), _lineSelectorScrollBoxMaxLineWidth);
|
|
}
|
|
|
|
void UIDropDown::sortLines() {
|
|
_lineSelectorScrollBox->sortLines();
|
|
}
|
|
|
|
void UIDropDown::handleMouseMove(int mouseX, int mouseY) {
|
|
if (!_isVisible) {
|
|
return;
|
|
}
|
|
|
|
_mouseX = mouseX;
|
|
_mouseY = mouseY;
|
|
|
|
// contains() does not include right or bottom boundary "line"
|
|
if (_lineSelectorFrameRect.contains(mouseX, mouseY)) {
|
|
if (!_lineSelectorFrameRectHasFocus && !_lineSelectorScrollBox->isVisible()) {
|
|
_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(kSfxTEXT3), 100, 0, 0, 50, 0);
|
|
}
|
|
_lineSelectorFrameRectHasFocus = true;
|
|
} else {
|
|
_lineSelectorFrameRectHasFocus = false;
|
|
}
|
|
|
|
_lineSelectorScrollBox->handleMouseMove(mouseX, mouseY);
|
|
_lineDropdownBtn->handleMouseAction(mouseX, mouseY, false, false, false);
|
|
}
|
|
|
|
void UIDropDown::handleMouseDown(bool alternateButton) {
|
|
if (!_isVisible) {
|
|
return;
|
|
}
|
|
|
|
if (!alternateButton) {
|
|
_lineSelectorScrollBox->handleMouseDown(false);
|
|
_lineDropdownBtn->handleMouseAction(_mouseX, _mouseY, true, false, false);
|
|
if (!_lineSelectorFrameRectHasFocus
|
|
&& _lineSelectorScrollBox->isVisible()
|
|
&& !_lineSelectorScrollBox->hasFocus()
|
|
) {
|
|
_ddlCancelledCallback(_callbackData, this);
|
|
showSelectionDropdown(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UIDropDown::handleMouseScroll(int direction) {
|
|
if (!_isVisible) {
|
|
return;
|
|
}
|
|
|
|
if (_lineSelectorScrollBox->isVisible()) {
|
|
_lineSelectorScrollBox->handleMouseScroll(direction);
|
|
}
|
|
}
|
|
|
|
void UIDropDown::handleMouseUp(bool alternateButton) {
|
|
if (!_isVisible) {
|
|
return;
|
|
}
|
|
|
|
if (!alternateButton) {
|
|
_lineSelectorScrollBox->handleMouseUp(false);
|
|
_lineDropdownBtn->handleMouseAction(_mouseX, _mouseY, false, true, false);
|
|
}
|
|
}
|
|
|
|
void UIDropDown::scrollBoxLineSelectCallback(void *callbackData, void *source, int lineData, int mouseButton) {
|
|
UIDropDown *self = (UIDropDown *)callbackData;
|
|
|
|
if (source == self->_lineSelectorScrollBox && lineData >= 0) {
|
|
Common::String selectedLangDescStr = self->_lineSelectorScrollBox->getLineText(lineData);
|
|
self->_lineSelectedId = lineData;
|
|
self->_lineSelectedStr = selectedLangDescStr;
|
|
self->_vm->_audioPlayer->playAud(self->_vm->_gameInfo->getSfxTrack(kSfxELECBP1), 90, 0, 0, 50, 0);
|
|
self->_ddlLineSelectedCallback(self->_callbackData, self, lineData, mouseButton);
|
|
self->showSelectionDropdown(false);
|
|
//debug("text selected: %s", selectedLangDescStr.c_str());
|
|
}
|
|
}
|
|
|
|
// Callback from _lineDropdownBtn items
|
|
void UIDropDown::mouseDownLDBCallback(int buttonId, void *callbackData) {
|
|
UIDropDown *self = (UIDropDown *)callbackData;
|
|
self->onButtonPressed(buttonId);
|
|
}
|
|
|
|
void UIDropDown::onButtonPressed(int buttonId) {
|
|
switch (buttonId) {
|
|
case 0:
|
|
// Pressed DDL dropdown button (0)
|
|
// fall through
|
|
case 1:
|
|
// if (buttonId == 1) {
|
|
// // Pressed DDL clickable area (1)
|
|
// debug("Pressed DDL clickable area (1)");
|
|
// }
|
|
_ddlTopFrameClickCallback(_callbackData, this);
|
|
showSelectionDropdown(!_lineSelectorScrollBox->isVisible());
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
void UIDropDown::showSelectionDropdown(bool showToggle) {
|
|
int prevDropdownBtnLeft = _lineDropdownBtn->getImageLeft(0);
|
|
if (showToggle) {
|
|
_lineSelectorScrollBox->setBoxTop(_lineSelectorFrameRect.bottom);
|
|
_lineSelectorScrollBox->setBoxLeft(_lineDropdownBtn->getImageLeft(1));
|
|
// TODO width should be retrieved from the maximum width of a language description in SUBTITLES.MIX (or a max width to clip to)
|
|
_lineSelectorScrollBox->setBoxWidth(MAX(_lineDropdownBtn->getImageWidth(1), _lineSelectorScrollBoxMaxLineWidth + _vm->_mainFont->getCharWidth(' ')));
|
|
|
|
if (_lineDropdownBtn->getImageLeft(0) < kFurthestLeftForScrollBar) {
|
|
// CLIP expects the first boundary argument to be the min of the two.
|
|
_lineSelectorScrollBox->setScrollbarLeft(CLIP( _lineSelectorScrollBox->getBoxLeft() + _lineSelectorScrollBox->getBoxWidth(), _lineDropdownBtn->getImageLeft(0), kFurthestLeftForScrollBar));
|
|
} else {
|
|
_lineSelectorScrollBox->setScrollbarLeft(MAX( _lineSelectorScrollBox->getBoxLeft() + _lineSelectorScrollBox->getBoxWidth(), kFurthestLeftForScrollBar));
|
|
}
|
|
|
|
_lineSelectorScrollBox->setScrollbarTop(_lineSelectorFrameRect.bottom);
|
|
_lineSelectorScrollBox->setScrollbarWidth(kDropDownButtonShapeWidth);
|
|
_lineSelectorScrollBox->show();
|
|
// change dropdown button icon too
|
|
_lineDropdownBtn->resetActiveImage(0);
|
|
_lineDropdownBtn->defineImage(0, Common::Rect(prevDropdownBtnLeft, _lineSelectorFrameRect.top + 1, prevDropdownBtnLeft + kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(70), _vm->_kia->_shapes->get(71), _vm->_kia->_shapes->get(72), nullptr);
|
|
_lineSelectorFrameRectColor = 10;
|
|
} else {
|
|
// hide scrollable area
|
|
_lineSelectorScrollBox->hide();
|
|
// change dropdown button icon too
|
|
_lineDropdownBtn->resetActiveImage(0);
|
|
_lineDropdownBtn->defineImage(0, Common::Rect(prevDropdownBtnLeft, _lineSelectorFrameRect.top + 1, prevDropdownBtnLeft + kDropDownButtonShapeWidth - 1, _lineSelectorFrameRect.bottom - 1), _vm->_kia->_shapes->get(73), _vm->_kia->_shapes->get(74), _vm->_kia->_shapes->get(75), nullptr);
|
|
_lineSelectorFrameRectColor = 0;
|
|
}
|
|
}
|
|
|
|
void UIDropDown::setLabelStr(Common::String newLabel) {
|
|
_labelStr = newLabel;
|
|
}
|
|
|
|
void UIDropDown::setControlLeft(int controlLeftX) {
|
|
_controlLeftX = controlLeftX;
|
|
}
|
|
|
|
Common::String UIDropDown::getLineSelectedStr() {
|
|
return _lineSelectedStr;
|
|
}
|
|
|
|
}
|