Initial commit
This commit is contained in:
351
engines/bladerunner/ui/ui_dropdown.cpp
Normal file
351
engines/bladerunner/ui/ui_dropdown.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/* 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 "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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user