Files
scummvm-cursorfix/engines/ultima/ultima4/views/menuitem.cpp
2026-02-02 04:50:13 +01:00

259 lines
7.9 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/ultima4/views/menu.h"
#include "ultima/ultima4/views/menuitem.h"
#include "ultima/ultima4/core/settings.h"
#include "ultima/ultima4/core/utils.h"
namespace Ultima {
namespace Ultima4 {
MenuItem::MenuItem(const Common::String &t, short x, short y, int sc) :
_id(-1), _x(x), _y(y), _text(t), _highlighted(false),
_selected(false), _visible(true), _scOffset(sc), _closesMenu(false) {
// if the sc/scOffset is outside the range of the text string, assert
assertMsg(sc == -1 || (sc >= 0 && sc <= (int)_text.size()), "sc value of %d out of range!", sc);
if (sc != -1) addShortcutKey(tolower(_text[sc]));
}
int MenuItem::getId() const {
return _id;
}
short MenuItem::getX() const {
return _x;
}
short MenuItem::getY() const {
return _y;
}
int MenuItem::getScOffset() const {
return _scOffset;
}
Common::String MenuItem::getText() const {
return _text;
}
bool MenuItem::isHighlighted() const {
return _highlighted;
}
bool MenuItem::isSelected() const {
return _selected;
}
bool MenuItem::isVisible() const {
return _visible;
}
bool MenuItem::hasShortcutKey(int sc) const {
Common::Array<int>::const_iterator begin = _shortcutKeys.begin();
Common::Array<int>::const_iterator end = _shortcutKeys.end();
return (Common::find(begin, end, sc) != end);
}
bool MenuItem::getClosesMenu() const {
return _closesMenu;
}
void MenuItem::setId(int i) {
_id = i;
}
void MenuItem::setX(int x) {
_x = x;
}
void MenuItem::setY(int y) {
_y = y;
}
void MenuItem::setText(const Common::String &t) {
_text = t;
}
void MenuItem::setHighlighted(bool h) {
_highlighted = h;
}
void MenuItem::setSelected(bool s) {
_selected = s;
}
void MenuItem::setVisible(bool v) {
_visible = v;
}
void MenuItem::addShortcutKey(int sc) {
if (!hasShortcutKey(sc))
_shortcutKeys.push_back(sc);
}
void MenuItem::setClosesMenu(bool closesMenu) {
this->_closesMenu = closesMenu;
}
BoolMenuItem::BoolMenuItem(const Common::String &text, short xp, short yp, int shortcutKey, bool *val) :
MenuItem(text, xp, yp, shortcutKey),
_val(val),
_on("On"),
_off("Off") {
}
BoolMenuItem *BoolMenuItem::setValueStrings(const Common::String &onString, const Common::String &offString) {
_on = onString;
_off = offString;
return this;
}
Common::String BoolMenuItem::getText() const {
char buffer[64];
snprintf(buffer, sizeof(buffer), _text.c_str(), *_val ? _on.c_str() : _off.c_str());
return buffer;
}
void BoolMenuItem::activate(MenuEvent &event) {
if (event.getType() == MenuEvent::DECREMENT ||
event.getType() == MenuEvent::INCREMENT ||
event.getType() == MenuEvent::ACTIVATE)
*_val = !(*_val);
}
StringMenuItem::StringMenuItem(const Common::String &text, short xp, short yp, int shortcutKey,
Common::String *val, const Std::vector<Common::String> &validSettings) :
MenuItem(text, xp, yp, shortcutKey),
_val(val),
_validSettings(validSettings) {
}
Common::String StringMenuItem::getText() const {
char buffer[64];
snprintf(buffer, sizeof(buffer), _text.c_str(), _val->c_str());
return buffer;
}
void StringMenuItem::activate(MenuEvent &event) {
Std::vector<Common::String>::const_iterator current =
find(_validSettings.begin(), _validSettings.end(), *_val);
if (current == _validSettings.end())
error("Error: menu Common::String '%s' not a valid choice", _val->c_str());
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
/* move to the next valid choice, wrapping if necessary */
current++;
if (current == _validSettings.end())
current = _validSettings.begin();
*_val = *current;
} else if (event.getType() == MenuEvent::DECREMENT) {
/* move back one, wrapping if necessary */
if (current == _validSettings.begin())
current = _validSettings.end();
current--;
*_val = *current;
}
}
IntMenuItem::IntMenuItem(const Common::String &text, short xp, short yp, int shortcutKey, int *val,
int min, int max, int increment, menuOutputType output) :
MenuItem(text, xp, yp, shortcutKey),
_val(val),
_min(min),
_max(max),
_increment(increment),
_output(output) {
}
Common::String IntMenuItem::getText() const {
// do custom formatting for some menu entries,
// and generate a Common::String of the results
char outputBuffer[20];
switch (_output) {
case MENU_OUTPUT_REAGENT:
snprintf(outputBuffer, sizeof(outputBuffer), "%2d", static_cast<short>(*_val));
break;
case MENU_OUTPUT_GAMMA:
snprintf(outputBuffer, sizeof(outputBuffer), "%.1f", static_cast<float>(*_val) / 100);
break;
case MENU_OUTPUT_SHRINE:
/*
* is this code really necessary? the increments/decrements can be handled by IntMenuItem(),
* as well as the looping once the max is reached. more importantly, the minimum value is
* inconstant, and based upon another setting that can be changed independent of this one.
* This variable could be set to it's minimum value, but when the gameCyclesPerSecond setting
* is changed, the value of this setting could become out of bounds.
*
* settings.shrineTime is only used in one function within shrine.cpp, and that code appears
* to handle the min value, caping the minimum interval at 1.
*
// make sure that the setting we're trying for is even possible
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
settingsChanged.shrineTime++;
if (settingsChanged.shrineTime > MAX_SHRINE_TIME)
settingsChanged.shrineTime = MEDITATION_MANTRAS_PER_CYCLE / settingsChanged.gameCyclesPerSecond;
} else if (event.getType() == MenuEvent::DECREMENT) {
settingsChanged.shrineTime--;
if (settingsChanged.shrineTime < (MEDITATION_MANTRAS_PER_CYCLE / settingsChanged.gameCyclesPerSecond))
settingsChanged.shrineTime = MAX_SHRINE_TIME;
}
*
*/
snprintf(outputBuffer, sizeof(outputBuffer), "%d sec", *_val);
break;
case MENU_OUTPUT_SPELL:
snprintf(outputBuffer, sizeof(outputBuffer), "%3g sec", static_cast<double>(*_val) / 5);
break;
case MENU_OUTPUT_VOLUME:
if (*_val == 0) {
snprintf(outputBuffer, sizeof(outputBuffer), "Disabled");
} else if (*_val == MAX_VOLUME) {
snprintf(outputBuffer, sizeof(outputBuffer), "Full");
} else {
snprintf(outputBuffer, sizeof(outputBuffer), "%d%s%s", *_val * 10, "%", "%");
}
break;
default:
break;
}
// the buffer must contain a field character %d or %s depending
// on the menuOutputType selected. MENU_OUTPUT_INT always uses
// %d, whereas all others use %s
char buffer[64];
if (_output != MENU_OUTPUT_INT)
snprintf(buffer, sizeof(buffer), _text.c_str(), outputBuffer);
else
snprintf(buffer, sizeof(buffer), _text.c_str(), *_val);
return buffer;
}
void IntMenuItem::activate(MenuEvent &event) {
if (event.getType() == MenuEvent::INCREMENT || event.getType() == MenuEvent::ACTIVATE) {
*_val += _increment;
if (*_val > _max)
*_val = _min;
} else if (event.getType() == MenuEvent::DECREMENT) {
*_val -= _increment;
if (*_val < _min)
*_val = _max;
}
}
} // End of namespace Ultima4
} // End of namespace Ultima