aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/tattoo/widget_files.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/tattoo/widget_files.cpp')
-rw-r--r--engines/sherlock/tattoo/widget_files.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/engines/sherlock/tattoo/widget_files.cpp b/engines/sherlock/tattoo/widget_files.cpp
new file mode 100644
index 0000000000..0f5e6793c4
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_files.cpp
@@ -0,0 +1,427 @@
+/* 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 "common/translation.h"
+#include "gui/saveload.h"
+#include "sherlock/tattoo/widget_files.h"
+#include "sherlock/tattoo/tattoo.h"
+#include "sherlock/tattoo/tattoo_fixed_text.h"
+#include "sherlock/tattoo/tattoo_scene.h"
+#include "sherlock/tattoo/tattoo_user_interface.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+#define FILES_LINES_COUNT 5
+
+WidgetFiles::WidgetFiles(SherlockEngine *vm, const Common::String &target) :
+ SaveManager(vm, target), WidgetBase(vm), _vm(vm) {
+ _fileMode = SAVEMODE_NONE;
+ _selector = _oldSelector = -1;
+}
+
+void WidgetFiles::show(SaveMode mode) {
+ Events &events = *_vm->_events;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (_vm->_showOriginalSavesDialog) {
+ // Render and display the file dialog
+ _fileMode = mode;
+ ui._menuMode = FILES_MODE;
+ _selector = _oldSelector = -1;
+ _scroll = true;
+ createSavegameList();
+
+ // Set up the display area
+ _bounds = Common::Rect(SHERLOCK_SCREEN_WIDTH * 2 / 3, (_surface.fontHeight() + 1) *
+ (FILES_LINES_COUNT + 1) + 17);
+ _bounds.moveTo(mousePos.x - _bounds.width() / 2, mousePos.y - _bounds.height() / 2);
+
+ // Create the surface and render its contents
+ _surface.create(_bounds.width(), _bounds.height());
+ render(RENDER_ALL);
+
+ summonWindow();
+ ui._menuMode = FILES_MODE;
+ } else if (mode == SAVEMODE_LOAD) {
+ showScummVMRestoreDialog();
+ } else {
+ showScummVMSaveDialog();
+ }
+}
+
+void WidgetFiles::showScummVMSaveDialog() {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ // create our own description for the saved game, the user didn't enter it
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+
+ _vm->saveGameState(slot, desc);
+ }
+
+ close();
+ delete dialog;
+}
+
+void WidgetFiles::showScummVMRestoreDialog() {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ int slot = dialog->runModalWithCurrentTarget();
+ close();
+ delete dialog;
+
+ if (slot >= 0) {
+ _vm->loadGameState(slot);
+ }
+}
+
+void WidgetFiles::render(FilesRenderMode mode) {
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ ImageFile &images = *ui._interfaceImages;
+ byte color;
+
+ if (mode == RENDER_ALL) {
+ _surface.fill(TRANSPARENCY);
+ makeInfoArea();
+
+ switch (_fileMode) {
+ case SAVEMODE_LOAD:
+ _surface.writeString(FIXED(LoadGame),
+ Common::Point((_surface.w() - _surface.stringWidth(FIXED(LoadGame))) / 2, 5), INFO_TOP);
+ break;
+
+ case SAVEMODE_SAVE:
+ _surface.writeString(FIXED(SaveGame),
+ Common::Point((_surface.w() - _surface.stringWidth(FIXED(SaveGame))) / 2, 5), INFO_TOP);
+ break;
+
+ default:
+ break;
+ }
+
+ _surface.hLine(3, _surface.fontHeight() + 7, _surface.w() - 4, INFO_TOP);
+ _surface.hLine(3, _surface.fontHeight() + 8, _surface.w() - 4, INFO_MIDDLE);
+ _surface.hLine(3, _surface.fontHeight() + 9, _surface.w() - 4, INFO_BOTTOM);
+ _surface.transBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 6));
+ _surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, _surface.fontHeight() + 6));
+
+ int xp = _surface.w() - BUTTON_SIZE - 6;
+ _surface.vLine(xp, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_TOP);
+ _surface.vLine(xp + 1, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_MIDDLE);
+ _surface.vLine(xp + 2, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_BOTTOM);
+ _surface.transBlitFrom(images[6], Common::Point(xp - 1, _surface.fontHeight() + 8));
+ _surface.transBlitFrom(images[7], Common::Point(xp - 1, _bounds.height() - 4));
+ }
+
+ int xp = _surface.stringWidth("00.") + _surface.widestChar() + 5;
+ int yp = _surface.fontHeight() + 14;
+
+ for (int idx = _savegameIndex; idx < (_savegameIndex + FILES_LINES_COUNT); ++idx) {
+ if (OP_NAMES || idx == _selector || idx == _oldSelector) {
+ if (idx == _selector && mode != RENDER_ALL)
+ color = COMMAND_HIGHLIGHTED;
+ else
+ color = INFO_TOP;
+
+ if (mode == RENDER_NAMES_AND_SCROLLBAR)
+ _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
+
+ Common::String numStr = Common::String::format("%d.", idx + 1);
+ _surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
+ _surface.writeString(_savegames[idx], Common::Point(xp, yp), color);
+ }
+
+ yp += _surface.fontHeight() + 1;
+ }
+
+ // Draw the Scrollbar if neccessary
+ if (mode != RENDER_NAMES)
+ drawScrollBar(_savegameIndex, FILES_LINES_COUNT, _savegames.size());
+}
+
+void WidgetFiles::handleEvents() {
+ Events &events = *_vm->_events;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+ Common::KeyState keyState = ui._keyState;
+
+ // Handle scrollbar events
+ ScrollHighlight oldHighlight = ui._scrollHighlight;
+ handleScrollbarEvents(_savegameIndex, FILES_LINES_COUNT, _savegames.size());
+
+ int oldScrollIndex = _savegameIndex;
+ handleScrolling(_savegameIndex, FILES_LINES_COUNT, _savegames.size());
+
+ // See if the mouse is pointing at any filenames in the window
+ if (Common::Rect(_bounds.left, _bounds.top + _surface.fontHeight() + 14,
+ _bounds.right - BUTTON_SIZE - 5, _bounds.bottom - 5).contains(mousePos)) {
+ _selector = (mousePos.y - _bounds.top - _surface.fontHeight() - 14) / (_surface.fontHeight() + 1) +
+ _savegameIndex;
+ } else {
+ _selector = -1;
+ }
+
+ // Check for the Tab key
+ if (keyState.keycode == Common::KEYCODE_TAB) {
+ // If the mouse is not over any of the filenames, move the mouse so that it points to the first one
+ if (_selector == -1) {
+ events.warpMouse(Common::Point(_bounds.right - BUTTON_SIZE - 20,
+ _bounds.top + _surface.fontHeight() * 2 + 8));
+ } else {
+ // See if we're doing Tab or Shift Tab
+ if (keyState.flags & Common::KBD_SHIFT) {
+ // We're doing Shift Tab
+ if (_selector == _savegameIndex)
+ _selector = _savegameIndex + 4;
+ else
+ --_selector;
+ } else {
+ // We're doing Tab
+ ++_selector;
+ if (_selector >= _savegameIndex + 5)
+ _selector = _savegameIndex;
+ }
+
+ events.warpMouse(Common::Point(mousePos.x, _bounds.top + _surface.fontHeight() * 2
+ + 8 + (_selector - _savegameIndex) * (_surface.fontHeight() + 1)));
+ }
+ }
+
+ // Only redraw the window if the the scrollbar position has changed
+ if (ui._scrollHighlight != oldHighlight || oldScrollIndex != _savegameIndex || _selector != _oldSelector)
+ render(RENDER_NAMES_AND_SCROLLBAR);
+ _oldSelector = _selector;
+
+ if (events._firstPress && !_bounds.contains(mousePos))
+ _outsideMenu = true;
+
+ if (events._released || events._rightReleased || keyState.keycode == Common::KEYCODE_ESCAPE) {
+ ui._scrollHighlight = SH_NONE;
+
+ if (_outsideMenu && !_bounds.contains(mousePos)) {
+ close();
+ } else {
+ _outsideMenu = false;
+
+ if (_selector != -1) {
+ if (_fileMode == SAVEMODE_LOAD) {
+ // We're in Load Mode
+ _vm->loadGameState(_selector);
+ } else if (_fileMode == SAVEMODE_SAVE) {
+ // We're in Save Mode
+ if (getFilename())
+ _vm->saveGameState(_selector, _savegames[_selector]);
+ close();
+ }
+ }
+ }
+ }
+}
+
+bool WidgetFiles::getFilename() {
+ Events &events = *_vm->_events;
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ int index = 0;
+ int done = 0;
+ bool blinkFlag = false;
+ int blinkCountdown = 0;
+ int cursorColor = 192;
+ byte color, textColor;
+ bool insert = true;
+
+ assert(_selector != -1);
+ Common::Point pt(_surface.stringWidth("00.") + _surface.widestChar() + 5,
+ _surface.fontHeight() + 14 + (_selector - _savegameIndex) * (_surface.fontHeight() + 1));
+
+ Common::String numStr = Common::String::format("%d.", _selector + 1);
+ _surface.writeString(numStr, Common::Point(_surface.widestChar(), pt.y), COMMAND_HIGHLIGHTED);
+
+ Common::String filename = _savegames[_selector];
+
+ if (isSlotEmpty(_selector)) {
+ index = 0;
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ filename = "";
+ } else {
+ index = filename.size();
+ _surface.writeString(filename, pt, COMMAND_HIGHLIGHTED);
+ pt.x = _surface.stringWidth("00.") + _surface.stringWidth(filename) + _surface.widestChar() + 5;
+ }
+
+ do {
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ char currentChar = (index == (int)filename.size()) ? ' ' : filename[index];
+ Common::String charString = Common::String::format("%c", currentChar);
+ int width = screen.charWidth(currentChar);
+
+ // Wait for keypress
+ while (!events.kbHit()) {
+ events.pollEventsAndWait();
+ events.setButtonState();
+
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ if (--blinkCountdown <= 0) {
+ blinkCountdown = 3;
+ blinkFlag = !blinkFlag;
+ if (blinkFlag) {
+ textColor = 236;
+ color = cursorColor;
+ } else {
+ textColor = COMMAND_HIGHLIGHTED;
+ color = TRANSPARENCY;
+ }
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), color);
+ if (currentChar != ' ')
+ _surface.writeString(charString, pt, textColor);
+ }
+ if (_vm->shouldQuit())
+ return false;
+ }
+
+ Common::KeyState keyState = events.getKey();
+ if (keyState.keycode == Common::KEYCODE_BACKSPACE && index > 0) {
+ pt.x -= _surface.charWidth(filename[index - 1]);
+ --index;
+
+ if (insert) {
+ filename.deleteChar(index);
+ } else {
+ filename.setChar(' ', index);
+ }
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _surface.w() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
+
+ } else if ((keyState.keycode == Common::KEYCODE_LEFT && index > 0)
+ || (keyState.keycode == Common::KEYCODE_RIGHT && index < 49 && pt.x < (_bounds.right - BUTTON_SIZE - 20))
+ || (keyState.keycode == Common::KEYCODE_HOME && index > 0)
+ || (keyState.keycode == Common::KEYCODE_END)) {
+ _surface.fillRect(Common::Rect(pt.x, pt.y, pt.x + width, pt.y + _surface.fontHeight()), TRANSPARENCY);
+ if (currentChar)
+ _surface.writeString(charString, pt, COMMAND_HIGHLIGHTED);
+
+ switch (keyState.keycode) {
+ case Common::KEYCODE_LEFT:
+ pt.x -= _surface.charWidth(filename[index - 1]);
+ --index;
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ pt.x += _surface.charWidth(filename[index]);
+ ++index;
+ break;
+
+ case Common::KEYCODE_HOME:
+ pt.x = _surface.stringWidth("00.") + _surface.widestChar() + 5;
+ index = 0;
+ break;
+
+ case Common::KEYCODE_END:
+ pt.x = _surface.stringWidth("00.") + _surface.stringWidth(filename) + _surface.widestChar() + 5;
+ index = filename.size();
+
+ while (filename[index - 1] == ' ' && index > 0) {
+ pt.x -= _surface.charWidth(filename[index - 1]);
+ --index;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (keyState.keycode == Common::KEYCODE_INSERT) {
+ insert = !insert;
+ if (insert)
+ cursorColor = 192;
+ else
+ cursorColor = 200;
+
+ } else if (keyState.keycode == Common::KEYCODE_DELETE) {
+ filename.deleteChar(index);
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.right - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename + index, pt, COMMAND_HIGHLIGHTED);
+
+ } else if (keyState.keycode == Common::KEYCODE_RETURN) {
+ done = 1;
+
+ } else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
+ _selector = -1;
+ render(RENDER_NAMES_AND_SCROLLBAR);
+ done = -1;
+ }
+
+ if ((keyState.ascii >= ' ') && ((keyState.ascii <= 168) || (keyState.ascii == 225)) && (index < 50)) {
+ if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w() - BUTTON_SIZE - 20) {
+ if (insert)
+ filename.insertChar(keyState.ascii, index);
+ else
+ filename.setChar(keyState.ascii, index);
+
+ _surface.fillRect(Common::Rect(pt.x, pt.y, _bounds.width() - BUTTON_SIZE - 9,
+ pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+ _surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
+ pt.x += _surface.charWidth(keyState.ascii);
+ ++index;
+ }
+ }
+ } while (!done && !_vm->shouldQuit());
+
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return false;
+
+ if (done == 1)
+ _savegames[_selector] = filename;
+
+ return done == 1;
+}
+
+Common::Rect WidgetFiles::getScrollBarBounds() const {
+ Common::Rect scrollRect(BUTTON_SIZE, _bounds.height() - _surface.fontHeight() - 16);
+ scrollRect.moveTo(_bounds.width() - BUTTON_SIZE - 3, _surface.fontHeight() + 13);
+
+ return scrollRect;
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock