aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/ThemeEngine.cpp2
-rw-r--r--gui/ThemeEngine.h4
-rw-r--r--gui/Tooltip.cpp2
-rw-r--r--gui/gui-manager.cpp2
-rw-r--r--gui/module.mk1
-rw-r--r--gui/saveload-dialog.cpp881
-rw-r--r--gui/saveload-dialog.h210
-rw-r--r--gui/saveload.cpp392
-rw-r--r--gui/saveload.h47
-rw-r--r--gui/themes/default.inc67
-rw-r--r--gui/themes/scummclassic.zipbin93390 -> 95181 bytes
-rw-r--r--gui/themes/scummclassic/THEMERC2
-rw-r--r--gui/themes/scummclassic/classic_layout.stx45
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx31
-rw-r--r--gui/themes/scummmodern.zipbin1449870 -> 1453476 bytes
-rw-r--r--gui/themes/scummmodern/THEMERC2
-rw-r--r--gui/themes/scummmodern/grid.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/list.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx2
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx45
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx31
-rw-r--r--gui/widget.cpp35
-rw-r--r--gui/widget.h10
23 files changed, 1418 insertions, 393 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index 2fff92c263..e2fa2580f5 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -48,6 +48,8 @@ const char * const ThemeEngine::kImageLogoSmall = "logo_small.bmp";
const char * const ThemeEngine::kImageSearch = "search.bmp";
const char * const ThemeEngine::kImageEraser = "eraser.bmp";
const char * const ThemeEngine::kImageDelbtn = "delbtn.bmp";
+const char * const ThemeEngine::kImageList = "list.bmp";
+const char * const ThemeEngine::kImageGrid = "grid.bmp";
struct TextDrawData {
const Graphics::Font *_fontPtr;
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 21711e2955..6fb93d3b46 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -35,7 +35,7 @@
#include "graphics/pixelformat.h"
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.13"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.16"
class OSystem;
@@ -232,6 +232,8 @@ public:
static const char *const kImageSearch; ///< Search tool image used in the launcher
static const char *const kImageEraser; ///< Clear input image used in the launcher
static const char *const kImageDelbtn; ///< Delete characters in the predictive dialog
+ static const char *const kImageList; ///< List image used in save/load chooser selection
+ static const char *const kImageGrid; ///< Grid image used in save/load chooser selection
/**
* Graphics mode enumeration.
diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp
index 85e5856cff..88124e782b 100644
--- a/gui/Tooltip.cpp
+++ b/gui/Tooltip.cpp
@@ -37,7 +37,7 @@ Tooltip::Tooltip() :
}
void Tooltip::setup(Dialog *parent, Widget *widget, int x, int y) {
- assert(widget->getTooltip());
+ assert(widget->hasTooltip());
_maxWidth = g_gui.xmlEval()->getVar("Globals.Tooltip.MaxWidth", 100);
_xdelta = g_gui.xmlEval()->getVar("Globals.Tooltip.XDelta", 0);
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index abd781e1a3..a0ef4216aa 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -381,7 +381,7 @@ void GuiManager::runLoop() {
if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
- if (wdg && wdg->getTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
+ if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
Tooltip *tooltip = new Tooltip();
tooltip->setup(activeDialog, wdg, _lastMousePosition.x, _lastMousePosition.y);
tooltip->runModal();
diff --git a/gui/module.mk b/gui/module.mk
index d272bb0313..a435d8cca7 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -15,6 +15,7 @@ MODULE_OBJS := \
options.o \
predictivedialog.o \
saveload.o \
+ saveload-dialog.o \
themebrowser.o \
ThemeEngine.o \
ThemeEval.o \
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp
new file mode 100644
index 0000000000..0b36ff5d59
--- /dev/null
+++ b/gui/saveload-dialog.cpp
@@ -0,0 +1,881 @@
+/* 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 "gui/saveload-dialog.h"
+#include "common/translation.h"
+#include "common/config-manager.h"
+
+#include "gui/message.h"
+#include "gui/gui-manager.h"
+#include "gui/ThemeEval.h"
+#include "gui/widgets/edittext.h"
+
+#include "graphics/scaler.h"
+
+namespace GUI {
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) {
+ const Common::String &userConfig = ConfMan.get("gui_saveload_chooser", Common::ConfigManager::kApplicationDomain);
+ if (g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400
+ && metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo)
+ && metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail)
+ && userConfig.equalsIgnoreCase("grid")) {
+ // In case we are 640x400 or higher, this dialog is not in save mode,
+ // the user requested the grid dialog and the engines supports it we
+ // try to set it up.
+ return kSaveLoadDialogGrid;
+ } else {
+ // In all other cases we want to use the list dialog.
+ return kSaveLoadDialogList;
+ }
+}
+
+enum {
+ kListSwitchCmd = 'LIST',
+ kGridSwitchCmd = 'GRID'
+};
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+SaveLoadChooserDialog::SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode)
+ : Dialog(dialogName), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
+ _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode)
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ , _listButton(0), _gridButton(0)
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+}
+
+SaveLoadChooserDialog::SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode)
+ : Dialog(x, y, w, h), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
+ _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode)
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ , _listButton(0), _gridButton(0)
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+}
+
+void SaveLoadChooserDialog::open() {
+ Dialog::open();
+
+ // So that quitting ScummVM will not cause the dialog result to say a
+ // savegame was selected.
+ setResult(-1);
+}
+
+int SaveLoadChooserDialog::run(const Common::String &target, const MetaEngine *metaEngine) {
+ _metaEngine = metaEngine;
+ _target = target;
+ _delSupport = _metaEngine->hasFeature(MetaEngine::kSupportsDeleteSave);
+ _metaInfoSupport = _metaEngine->hasFeature(MetaEngine::kSavesSupportMetaInfo);
+ _thumbnailSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportThumbnail);
+ _saveDateSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportCreationDate);
+ _playTimeSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportPlayTime);
+
+ return runIntern();
+}
+
+void SaveLoadChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ switch (cmd) {
+ case kListSwitchCmd:
+ setResult(kSwitchSaveLoadDialog);
+ // We save the requested dialog type here to avoid the setting to be
+ // overwritten when our reflowLayout logic selects a different dialog
+ // type.
+ ConfMan.set("gui_saveload_chooser", "list", Common::ConfigManager::kApplicationDomain);
+ close();
+ break;
+
+ case kGridSwitchCmd:
+ setResult(kSwitchSaveLoadDialog);
+ // See above.
+ ConfMan.set("gui_saveload_chooser", "grid", Common::ConfigManager::kApplicationDomain);
+ close();
+ break;
+
+ default:
+ break;
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ return Dialog::handleCommand(sender, cmd, data);
+}
+
+void SaveLoadChooserDialog::reflowLayout() {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+
+ const SaveLoadChooserType currentType = getType();
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
+
+ // Change the dialog type if there is any need for it.
+ if (requestedType != currentType) {
+ setResult(kSwitchSaveLoadDialog);
+ close();
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ Dialog::reflowLayout();
+}
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+void SaveLoadChooserDialog::addChooserButtons() {
+ if (_listButton) {
+ removeWidget(_listButton);
+ delete _listButton;
+ }
+
+ if (_gridButton) {
+ removeWidget(_gridButton);
+ delete _gridButton;
+ }
+
+ _listButton = createSwitchButton("SaveLoadChooser.ListSwitch", "L", _("List view"), ThemeEngine::kImageList, kListSwitchCmd);
+ _gridButton = createSwitchButton("SaveLoadChooser.GridSwitch", "G", _("Grid view"), ThemeEngine::kImageGrid, kGridSwitchCmd);
+ if (!_metaInfoSupport || !_thumbnailSupport || !(g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400)) {
+ _gridButton->setEnabled(false);
+ _listButton->setEnabled(false);
+ }
+}
+
+ButtonWidget *SaveLoadChooserDialog::createSwitchButton(const Common::String &name, const char *desc, const char *tooltip, const char *image, uint32 cmd) {
+ ButtonWidget *button;
+
+#ifndef DISABLE_FANCY_THEMES
+ if (g_gui.xmlEval()->getVar("Globals.ShowChooserPics") == 1 && g_gui.theme()->supportsImages()) {
+ button = new PicButtonWidget(this, name, tooltip, cmd);
+ ((PicButtonWidget *)button)->useThemeTransparency(true);
+ ((PicButtonWidget *)button)->setGfx(g_gui.theme()->getImageSurface(image));
+ } else
+#endif
+ button = new ButtonWidget(this, name, desc, tooltip, cmd);
+
+ return button;
+}
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+// SaveLoadChooserSimple implementation
+
+enum {
+ kChooseCmd = 'CHOS',
+ kDelCmd = 'DEL '
+};
+
+SaveLoadChooserSimple::SaveLoadChooserSimple(const String &title, const String &buttonLabel, bool saveMode)
+ : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) {
+ _fillR = _fillG = _fillB = 0;
+
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", title);
+
+ // Add choice list
+ _list = new ListWidget(this, "SaveLoadChooser.List");
+ _list->setNumberingMode(kListNumberingZero);
+ _list->setEditable(saveMode);
+
+ _gfxWidget = new GraphicsWidget(this, 0, 0, 10, 10);
+
+ _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
+ _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
+ _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
+
+ // Buttons
+ new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
+ _chooseButton = new ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
+ _chooseButton->setEnabled(false);
+
+ _deleteButton = new ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
+ _deleteButton->setEnabled(false);
+
+ _delSupport = _metaInfoSupport = _thumbnailSupport = false;
+
+ _container = new ContainerWidget(this, 0, 0, 10, 10);
+// _container->setHints(THEME_HINT_USE_SHADOW);
+}
+
+int SaveLoadChooserSimple::runIntern() {
+ if (_gfxWidget)
+ _gfxWidget->setGfx(0);
+
+ _resultString.clear();
+ reflowLayout();
+ updateSaveList();
+
+ return Dialog::runModal();
+}
+
+const Common::String &SaveLoadChooserSimple::getResultString() const {
+ int selItem = _list->getSelected();
+ return (selItem >= 0) ? _list->getSelectedString() : _resultString;
+}
+
+void SaveLoadChooserSimple::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ int selItem = _list->getSelected();
+
+ switch (cmd) {
+ case kListItemActivatedCmd:
+ case kListItemDoubleClickedCmd:
+ if (selItem >= 0 && _chooseButton->isEnabled()) {
+ if (_list->isEditable() || !_list->getSelectedString().empty()) {
+ _list->endEditMode();
+ if (!_saveList.empty()) {
+ setResult(_saveList[selItem].getSaveSlot());
+ _resultString = _list->getSelectedString();
+ }
+ close();
+ }
+ }
+ break;
+ case kChooseCmd:
+ _list->endEditMode();
+ if (!_saveList.empty()) {
+ setResult(_saveList[selItem].getSaveSlot());
+ _resultString = _list->getSelectedString();
+ }
+ close();
+ break;
+ case kListSelectionChangedCmd:
+ updateSelection(true);
+ break;
+ case kDelCmd:
+ if (selItem >= 0 && _delSupport) {
+ MessageDialog alert(_("Do you really want to delete this savegame?"),
+ _("Delete"), _("Cancel"));
+ if (alert.runModal() == kMessageOK) {
+ _metaEngine->removeSaveState(_target.c_str(), _saveList[selItem].getSaveSlot());
+
+ setResult(-1);
+ _list->setSelected(-1);
+
+ updateSaveList();
+ updateSelection(true);
+ }
+ }
+ break;
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ SaveLoadChooserDialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void SaveLoadChooserSimple::reflowLayout() {
+ if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && _thumbnailSupport) {
+ int16 x, y;
+ uint16 w, h;
+
+ if (!g_gui.xmlEval()->getWidgetData("SaveLoadChooser.Thumbnail", x, y, w, h))
+ error("Error when loading position data for Save/Load Thumbnails");
+
+ int thumbW = kThumbnailWidth;
+ int thumbH = kThumbnailHeight2;
+ int thumbX = x + (w >> 1) - (thumbW >> 1);
+ int thumbY = y + kLineHeight;
+
+ int textLines = 0;
+ if (!_saveDateSupport)
+ textLines++;
+ if (!_playTimeSupport)
+ textLines++;
+
+ _container->resize(x, y, w, h - (kLineHeight * textLines));
+ _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
+
+ int height = thumbY + thumbH + kLineHeight;
+
+ if (_saveDateSupport) {
+ _date->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ _time->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ }
+
+ if (_playTimeSupport)
+ _playtime->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+
+ _container->setVisible(true);
+ _gfxWidget->setVisible(true);
+
+ _date->setVisible(_saveDateSupport);
+ _time->setVisible(_saveDateSupport);
+
+ _playtime->setVisible(_playTimeSupport);
+
+ _fillR = 0;
+ _fillG = 0;
+ _fillB = 0;
+ updateSelection(false);
+ } else {
+ _container->setVisible(false);
+ _gfxWidget->setVisible(false);
+ _date->setVisible(false);
+ _time->setVisible(false);
+ _playtime->setVisible(false);
+ }
+
+ SaveLoadChooserDialog::reflowLayout();
+}
+
+void SaveLoadChooserSimple::updateSelection(bool redraw) {
+ int selItem = _list->getSelected();
+
+ bool isDeletable = _delSupport;
+ bool isWriteProtected = false;
+ bool startEditMode = _list->isEditable();
+
+ _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
+ _date->setLabel(_("No date saved"));
+ _time->setLabel(_("No time saved"));
+ _playtime->setLabel(_("No playtime saved"));
+
+ if (selItem >= 0 && _metaInfoSupport) {
+ SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot());
+
+ isDeletable = desc.getDeletableFlag() && _delSupport;
+ isWriteProtected = desc.getWriteProtectedFlag();
+
+ // Don't allow the user to change the description of write protected games
+ if (isWriteProtected)
+ startEditMode = false;
+
+ if (_thumbnailSupport) {
+ const Graphics::Surface *thumb = desc.getThumbnail();
+ if (thumb) {
+ _gfxWidget->setGfx(thumb);
+ _gfxWidget->useAlpha(256);
+ }
+ }
+
+ if (_saveDateSupport) {
+ const Common::String &saveDate = desc.getSaveDate();
+ if (!saveDate.empty())
+ _date->setLabel(_("Date: ") + saveDate);
+
+ const Common::String &saveTime = desc.getSaveTime();
+ if (!saveTime.empty())
+ _time->setLabel(_("Time: ") + saveTime);
+ }
+
+ if (_playTimeSupport) {
+ const Common::String &playTime = desc.getPlayTime();
+ if (!playTime.empty())
+ _playtime->setLabel(_("Playtime: ") + playTime);
+ }
+ }
+
+
+ if (_list->isEditable()) {
+ // Disable the save button if nothing is selected, or if the selected
+ // game is write protected
+ _chooseButton->setEnabled(selItem >= 0 && !isWriteProtected);
+
+ if (startEditMode) {
+ _list->startEditMode();
+
+ if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") &&
+ _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
+ _list->setEditString("");
+ _list->setEditColor(ThemeEngine::kFontColorNormal);
+ }
+ }
+ } else {
+ // Disable the load button if nothing is selected, or if an empty
+ // list item is selected.
+ _chooseButton->setEnabled(selItem >= 0 && !_list->getSelectedString().empty());
+ }
+
+ // Delete will always be disabled if the engine doesn't support it.
+ _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
+
+ if (redraw) {
+ _gfxWidget->draw();
+ _date->draw();
+ _time->draw();
+ _playtime->draw();
+ _chooseButton->draw();
+ _deleteButton->draw();
+
+ draw();
+ }
+}
+
+void SaveLoadChooserSimple::close() {
+ _metaEngine = 0;
+ _target.clear();
+ _saveList.clear();
+ _list->setList(StringArray());
+
+ SaveLoadChooserDialog::close();
+}
+
+void SaveLoadChooserSimple::updateSaveList() {
+ _saveList = _metaEngine->listSaves(_target.c_str());
+
+ int curSlot = 0;
+ int saveSlot = 0;
+ StringArray saveNames;
+ ListWidget::ColorList colors;
+ for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
+ // Handle gaps in the list of save games
+ saveSlot = x->getSaveSlot();
+ if (curSlot < saveSlot) {
+ while (curSlot < saveSlot) {
+ SaveStateDescriptor dummySave(curSlot, "");
+ _saveList.insert_at(curSlot, dummySave);
+ saveNames.push_back(dummySave.getDescription());
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ curSlot++;
+ }
+
+ // Sync the save list iterator
+ for (x = _saveList.begin(); x != _saveList.end(); ++x) {
+ if (x->getSaveSlot() == saveSlot)
+ break;
+ }
+ }
+
+ // Show "Untitled savestate" for empty/whitespace savegame descriptions
+ Common::String description = x->getDescription();
+ Common::String trimmedDescription = description;
+ trimmedDescription.trim();
+ if (trimmedDescription.empty()) {
+ description = _("Untitled savestate");
+ colors.push_back(ThemeEngine::kFontColorAlternate);
+ } else {
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ }
+
+ saveNames.push_back(description);
+ curSlot++;
+ }
+
+ // Fill the rest of the save slots with empty saves
+
+ int maximumSaveSlots = _metaEngine->getMaximumSaveSlot();
+
+#ifdef __DS__
+ // Low memory on the DS means too many save slots are impractical, so limit
+ // the maximum here.
+ if (maximumSaveSlots > 99) {
+ maximumSaveSlots = 99;
+ }
+#endif
+
+ Common::String emptyDesc;
+ for (int i = curSlot; i <= maximumSaveSlots; i++) {
+ saveNames.push_back(emptyDesc);
+ SaveStateDescriptor dummySave(i, "");
+ _saveList.push_back(dummySave);
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ }
+
+ _list->setList(saveNames, &colors);
+}
+
+// SaveLoadChooserGrid implementation
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+
+enum {
+ kNextCmd = 'NEXT',
+ kPrevCmd = 'PREV',
+ kNewSaveCmd = 'SAVE'
+};
+
+SaveLoadChooserGrid::SaveLoadChooserGrid(const Common::String &title, bool saveMode)
+ : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _lines(0), _columns(0), _entriesPerPage(0),
+ _curPage(0), _newSaveContainer(0), _nextFreeSaveSlot(0), _buttons() {
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", title);
+
+ // Buttons
+ new ButtonWidget(this, "SaveLoadChooser.Delete", _("Cancel"), 0, kCloseCmd);
+ _nextButton = new ButtonWidget(this, "SaveLoadChooser.Choose", _("Next"), 0, kNextCmd);
+ _nextButton->setEnabled(false);
+
+ _prevButton = new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Prev"), 0, kPrevCmd);
+ _prevButton->setEnabled(false);
+
+ // Page display
+ _pageDisplay = new StaticTextWidget(this, "SaveLoadChooser.PageDisplay", Common::String());
+ _pageDisplay->setAlign(Graphics::kTextAlignRight);
+}
+
+SaveLoadChooserGrid::~SaveLoadChooserGrid() {
+ removeWidget(_pageDisplay);
+ delete _pageDisplay;
+}
+
+const Common::String &SaveLoadChooserGrid::getResultString() const {
+ return _resultString;
+}
+
+void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ if (cmd <= _entriesPerPage) {
+ const SaveStateDescriptor &desc = _saveList[cmd - 1 + _curPage * _entriesPerPage];
+
+ if (_saveMode) {
+ _resultString = desc.getDescription();
+ }
+
+ setResult(desc.getSaveSlot());
+ close();
+ }
+
+ switch (cmd) {
+ case kNextCmd:
+ ++_curPage;
+ updateSaves();
+ draw();
+ break;
+
+ case kPrevCmd:
+ --_curPage;
+ updateSaves();
+ draw();
+ break;
+
+ case kNewSaveCmd:
+ setResult(_nextFreeSaveSlot);
+ close();
+ break;
+
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ SaveLoadChooserDialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
+ if (direction > 0) {
+ if (_nextButton->isEnabled()) {
+ ++_curPage;
+ updateSaves();
+ draw();
+ }
+ } else {
+ if (_prevButton->isEnabled()) {
+ --_curPage;
+ updateSaves();
+ draw();
+ }
+ }
+}
+
+void SaveLoadChooserGrid::open() {
+ SaveLoadChooserDialog::open();
+
+ _curPage = 0;
+ _saveList = _metaEngine->listSaves(_target.c_str());
+ _resultString.clear();
+
+ // Determine the next free save slot for save mode
+ if (_saveMode) {
+ int lastSlot = -1;
+ _nextFreeSaveSlot = -1;
+ for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
+ const int curSlot = x->getSaveSlot();
+
+ // In case there was a gap found use the slot.
+ if (lastSlot + 1 < curSlot) {
+ _nextFreeSaveSlot = lastSlot + 1;
+ break;
+ }
+
+ lastSlot = curSlot;
+ }
+
+ // Use the next available slot otherwise.
+ if (_nextFreeSaveSlot == -1 && lastSlot + 1 < _metaEngine->getMaximumSaveSlot()) {
+ _nextFreeSaveSlot = lastSlot + 1;
+ }
+ }
+
+ updateSaves();
+}
+
+void SaveLoadChooserGrid::reflowLayout() {
+ removeWidget(_pageDisplay);
+ if (g_gui.xmlEval()->getVar("Globals.ShowChooserPageDisplay") == 1) {
+ _pageDisplay->init();
+ }
+
+ SaveLoadChooserDialog::reflowLayout();
+ destroyButtons();
+
+ const uint16 availableWidth = getWidth() - 20;
+ uint16 availableHeight;
+
+ int16 x, y;
+ uint16 w;
+ g_gui.xmlEval()->getWidgetData("SaveLoadChooser.List", x, y, w, availableHeight);
+
+ const int16 buttonWidth = kThumbnailWidth + 6;
+ const int16 buttonHeight = kThumbnailHeight2 + 6;
+
+ const int16 containerFrameWidthAdd = 10;
+ const int16 containerFrameHeightAdd = 0;
+ const int16 containerWidth = buttonWidth + containerFrameWidthAdd;
+ const int16 containerHeight = buttonHeight + kLineHeight + containerFrameHeightAdd;
+
+ const int16 defaultSpacingHorizontal = 4;
+ const int16 defaultSpacingVertical = 8;
+ const int16 slotAreaWidth = containerWidth + defaultSpacingHorizontal;
+ const int16 slotAreaHeight = containerHeight + defaultSpacingVertical;
+
+ const uint oldEntriesPerPage = _entriesPerPage;
+ _columns = MAX<uint>(1, availableWidth / slotAreaWidth);
+ _lines = MAX<uint>(1, availableHeight / slotAreaHeight);
+ _entriesPerPage = _columns * _lines;
+
+ // In save mode the first button is always "New Save", thus we need to
+ // adjust the entries per page here.
+ if (_saveMode) {
+ --_entriesPerPage;
+ }
+
+ // Recalculate the page number
+ if (!_saveList.empty() && oldEntriesPerPage != 0) {
+ if (_entriesPerPage != 0) {
+ _curPage = (_curPage * oldEntriesPerPage) / _entriesPerPage;
+ } else {
+ _curPage = 0;
+ }
+ }
+
+ const uint addX = _columns > 1 ? (availableWidth % slotAreaWidth) / (_columns - 1) : 0;
+ //const uint addY = _lines > 1 ? (availableHeight % slotAreaHeight) / (_lines - 1) : 0;
+
+ _buttons.reserve(_lines * _columns);
+ y += defaultSpacingVertical / 2;
+ for (uint curLine = 0; curLine < _lines; ++curLine, y += slotAreaHeight/* + addY*/) {
+ for (uint curColumn = 0, curX = x + defaultSpacingHorizontal / 2; curColumn < _columns; ++curColumn, curX += slotAreaWidth + addX) {
+ int dstY = containerFrameHeightAdd / 2;
+ int dstX = containerFrameWidthAdd / 2;
+
+ // In the save mode we will always create a new save button as the first button.
+ if (_saveMode && curLine == 0 && curColumn == 0) {
+ _newSaveContainer = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
+ ButtonWidget *newSave = new ButtonWidget(_newSaveContainer, dstX, dstY, buttonWidth, buttonHeight, _("New Save"), _("Create a new save game"), kNewSaveCmd);
+ // In case no more slots are free, we will disable the new save button
+ if (_nextFreeSaveSlot == -1) {
+ newSave->setEnabled(false);
+ }
+ continue;
+ }
+
+ ContainerWidget *container = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
+ container->setVisible(false);
+
+ // Command 0 cannot be used, since it won't be send. Thus we will adjust
+ // command number here, if required. This is only the case for load mode
+ // since for save mode, the first button used is index 1 anyway.
+ uint buttonCmd = curLine * _columns + curColumn;
+ if (!_saveMode) {
+ buttonCmd += 1;
+ }
+
+ PicButtonWidget *button = new PicButtonWidget(container, dstX, dstY, buttonWidth, buttonHeight, 0, buttonCmd);
+ dstY += buttonHeight;
+
+ StaticTextWidget *description = new StaticTextWidget(container, dstX, dstY, buttonWidth, kLineHeight, Common::String(), Graphics::kTextAlignLeft);
+
+ _buttons.push_back(SlotButton(container, button, description));
+ }
+ }
+
+ if (!_target.empty())
+ updateSaves();
+}
+
+void SaveLoadChooserGrid::close() {
+ SaveLoadChooserDialog::close();
+ hideButtons();
+}
+
+int SaveLoadChooserGrid::runIntern() {
+ int slot;
+ do {
+ const SaveLoadChooserType currentType = getType();
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
+
+ // Catch resolution changes when the save name dialog was open.
+ if (currentType != requestedType) {
+ setResult(kSwitchSaveLoadDialog);
+ return kSwitchSaveLoadDialog;
+ }
+
+ slot = runModal();
+ } while (_saveMode && slot >= 0 && !selectDescription());
+
+ return slot;
+}
+
+bool SaveLoadChooserGrid::selectDescription() {
+ _savenameDialog.setDescription(_resultString);
+ _savenameDialog.setTargetSlot(getResult());
+ if (_savenameDialog.runModal() == 0) {
+ _resultString = _savenameDialog.getDescription();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SaveLoadChooserGrid::destroyButtons() {
+ if (_newSaveContainer) {
+ removeWidget(_newSaveContainer);
+ delete _newSaveContainer;
+ _newSaveContainer = 0;
+ }
+
+ for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
+ removeWidget(i->container);
+ delete i->container;
+ }
+
+ _buttons.clear();
+}
+
+void SaveLoadChooserGrid::hideButtons() {
+ for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
+ i->button->setGfx(0);
+ i->setVisible(false);
+ }
+}
+
+void SaveLoadChooserGrid::updateSaves() {
+ hideButtons();
+
+ for (uint i = _curPage * _entriesPerPage, curNum = 0; i < _saveList.size() && curNum < _entriesPerPage; ++i, ++curNum) {
+ const uint saveSlot = _saveList[i].getSaveSlot();
+
+ SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), saveSlot);
+ SlotButton &curButton = _buttons[curNum];
+ curButton.setVisible(true);
+ const Graphics::Surface *thumbnail = desc.getThumbnail();
+ if (thumbnail) {
+ curButton.button->setGfx(desc.getThumbnail());
+ } else {
+ curButton.button->setGfx(kThumbnailWidth, kThumbnailHeight2, 0, 0, 0);
+ }
+ curButton.description->setLabel(Common::String::format("%d. %s", saveSlot, desc.getDescription().c_str()));
+
+ Common::String tooltip(_("Name: "));
+ tooltip += desc.getDescription();
+
+ if (_saveDateSupport) {
+ const Common::String &saveDate = desc.getSaveDate();
+ if (!saveDate.empty()) {
+ tooltip += "\n";
+ tooltip += _("Date: ") + saveDate;
+ }
+
+ const Common::String &saveTime = desc.getSaveTime();
+ if (!saveTime.empty()) {
+ tooltip += "\n";
+ tooltip += _("Time: ") + saveTime;
+ }
+ }
+
+ if (_playTimeSupport) {
+ const Common::String &playTime = desc.getPlayTime();
+ if (!playTime.empty()) {
+ tooltip += "\n";
+ tooltip += _("Playtime: ") + playTime;
+ }
+ }
+
+ curButton.button->setTooltip(tooltip);
+
+ // In save mode we disable the button, when it's write protected.
+ // TODO: Maybe we should not display it at all then?
+ if (_saveMode && desc.getWriteProtectedFlag()) {
+ curButton.button->setEnabled(false);
+ } else {
+ curButton.button->setEnabled(true);
+ }
+ }
+
+ const uint numPages = (_entriesPerPage != 0) ? (_saveList.size() / _entriesPerPage + 1) : 1;
+ _pageDisplay->setLabel(Common::String::format("%u/%u", _curPage + 1, numPages));
+
+ if (_curPage > 0)
+ _prevButton->setEnabled(true);
+ else
+ _prevButton->setEnabled(false);
+
+ if ((_curPage + 1) * _entriesPerPage < _saveList.size())
+ _nextButton->setEnabled(true);
+ else
+ _nextButton->setEnabled(false);
+}
+
+SavenameDialog::SavenameDialog()
+ : Dialog("SavenameDialog") {
+ _title = new StaticTextWidget(this, "SavenameDialog.DescriptionText", Common::String());
+
+ new ButtonWidget(this, "SavenameDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "SavenameDialog.Ok", _("OK"), 0, kOKCmd);
+
+ _description = new EditTextWidget(this, "SavenameDialog.Description", Common::String(), 0, 0, kOKCmd);
+}
+
+void SavenameDialog::setDescription(const Common::String &desc) {
+ _description->setEditString(desc);
+}
+
+const Common::String &SavenameDialog::getDescription() {
+ return _description->getEditString();
+}
+
+void SavenameDialog::open() {
+ Dialog::open();
+ setResult(-1);
+
+ _title->setLabel(Common::String::format(_("Enter a description for slot %d:"), _targetSlot));
+}
+
+void SavenameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kOKCmd:
+ setResult(0);
+ close();
+ break;
+
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+} // End of namespace GUI
diff --git a/gui/saveload-dialog.h b/gui/saveload-dialog.h
new file mode 100644
index 0000000000..50b7d419b7
--- /dev/null
+++ b/gui/saveload-dialog.h
@@ -0,0 +1,210 @@
+/* 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.
+ */
+
+#ifndef GUI_SAVELOAD_DIALOG_H
+#define GUI_SAVELOAD_DIALOG_H
+
+#include "gui/dialog.h"
+#include "gui/widgets/list.h"
+
+#include "engines/metaengine.h"
+
+namespace GUI {
+
+#define kSwitchSaveLoadDialog -2
+
+// TODO: We might want to disable the grid based save/load chooser for more
+// platforms, than those which define DISABLE_FANCY_THEMES. But those are
+// probably not able to handle the grid chooser anyway, so disabling it
+// for them is a good start.
+#ifdef DISABLE_FANCY_THEMES
+#define DISABLE_SAVELOADCHOOSER_GRID
+#endif // DISABLE_FANCY_THEMES
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+enum SaveLoadChooserType {
+ kSaveLoadDialogList = 0,
+ kSaveLoadDialogGrid = 1
+};
+
+SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine);
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+class SaveLoadChooserDialog : protected Dialog {
+public:
+ SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode);
+ SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode);
+
+ virtual void open();
+
+ virtual void reflowLayout();
+
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ virtual SaveLoadChooserType getType() const = 0;
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ int run(const Common::String &target, const MetaEngine *metaEngine);
+ virtual const Common::String &getResultString() const = 0;
+
+protected:
+ virtual int runIntern() = 0;
+
+ const bool _saveMode;
+ const MetaEngine *_metaEngine;
+ bool _delSupport;
+ bool _metaInfoSupport;
+ bool _thumbnailSupport;
+ bool _saveDateSupport;
+ bool _playTimeSupport;
+ Common::String _target;
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ ButtonWidget *_listButton;
+ ButtonWidget *_gridButton;
+
+ void addChooserButtons();
+ ButtonWidget *createSwitchButton(const Common::String &name, const char *desc, const char *tooltip, const char *image, uint32 cmd = 0);
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+};
+
+class SaveLoadChooserSimple : public SaveLoadChooserDialog {
+ typedef Common::String String;
+ typedef Common::Array<Common::String> StringArray;
+public:
+ SaveLoadChooserSimple(const String &title, const String &buttonLabel, bool saveMode);
+
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+ virtual const Common::String &getResultString() const;
+
+ virtual void reflowLayout();
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ virtual SaveLoadChooserType getType() const { return kSaveLoadDialogList; }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ virtual void close();
+private:
+ virtual int runIntern();
+
+ ListWidget *_list;
+ ButtonWidget *_chooseButton;
+ ButtonWidget *_deleteButton;
+ GraphicsWidget *_gfxWidget;
+ ContainerWidget *_container;
+ StaticTextWidget *_date;
+ StaticTextWidget *_time;
+ StaticTextWidget *_playtime;
+
+ SaveStateList _saveList;
+ String _resultString;
+
+ uint8 _fillR, _fillG, _fillB;
+
+ void updateSaveList();
+ void updateSelection(bool redraw);
+};
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+
+class EditTextWidget;
+
+class SavenameDialog : public Dialog {
+public:
+ SavenameDialog();
+
+ void setDescription(const Common::String &desc);
+ const Common::String &getDescription();
+
+ void setTargetSlot(int slot) { _targetSlot = slot; }
+
+ virtual void open();
+protected:
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+private:
+ int _targetSlot;
+ StaticTextWidget *_title;
+ EditTextWidget *_description;
+};
+
+class SaveLoadChooserGrid : public SaveLoadChooserDialog {
+public:
+ SaveLoadChooserGrid(const Common::String &title, bool saveMode);
+ ~SaveLoadChooserGrid();
+
+ virtual const Common::String &getResultString() const;
+
+ virtual void open();
+
+ virtual void reflowLayout();
+
+ virtual SaveLoadChooserType getType() const { return kSaveLoadDialogGrid; }
+
+ virtual void close();
+protected:
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void handleMouseWheel(int x, int y, int direction);
+private:
+ virtual int runIntern();
+
+ uint _columns, _lines;
+ uint _entriesPerPage;
+ uint _curPage;
+ SaveStateList _saveList;
+
+ ButtonWidget *_nextButton;
+ ButtonWidget *_prevButton;
+
+ StaticTextWidget *_pageDisplay;
+
+ ContainerWidget *_newSaveContainer;
+ int _nextFreeSaveSlot;
+ Common::String _resultString;
+
+ SavenameDialog _savenameDialog;
+ bool selectDescription();
+
+ struct SlotButton {
+ SlotButton() : container(0), button(0), description(0) {}
+ SlotButton(ContainerWidget *c, PicButtonWidget *b, StaticTextWidget *d) : container(c), button(b), description(d) {}
+
+ ContainerWidget *container;
+ PicButtonWidget *button;
+ StaticTextWidget *description;
+
+ void setVisible(bool state) {
+ container->setVisible(state);
+ }
+ };
+ typedef Common::Array<SlotButton> ButtonArray;
+ ButtonArray _buttons;
+ void destroyButtons();
+ void hideButtons();
+ void updateSaves();
+};
+
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/saveload.cpp b/gui/saveload.cpp
index ac315cb6f6..c2bbcd9bec 100644
--- a/gui/saveload.cpp
+++ b/gui/saveload.cpp
@@ -20,112 +20,45 @@
*/
#include "common/config-manager.h"
-#include "common/translation.h"
#include "common/system.h"
-#include "gui/widgets/list.h"
-#include "gui/message.h"
#include "gui/saveload.h"
-#include "gui/ThemeEval.h"
+#include "gui/saveload-dialog.h"
#include "gui/gui-manager.h"
-#include "graphics/scaler.h"
-
#include "engines/metaengine.h"
namespace GUI {
-enum {
- kChooseCmd = 'CHOS',
- kDelCmd = 'DEL '
-
-};
-
SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode)
- : Dialog("SaveLoadChooser"), _delSupport(0), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) {
- _delSupport = _metaInfoSupport = _thumbnailSupport = _saveDateSupport = _playTimeSupport = false;
- _fillR = _fillG = _fillB = 0;
-
- _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
-
- new StaticTextWidget(this, "SaveLoadChooser.Title", title);
-
- // Add choice list
- _list = new GUI::ListWidget(this, "SaveLoadChooser.List");
- _list->setNumberingMode(GUI::kListNumberingZero);
- _list->setEditable(saveMode);
-
- _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
-
- _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
- _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
- _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
-
- // Buttons
- new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
- _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
- _chooseButton->setEnabled(false);
-
- _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
- _deleteButton->setEnabled(false);
-
- _delSupport = _metaInfoSupport = _thumbnailSupport = false;
-
- _container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
-// _container->setHints(GUI::THEME_HINT_USE_SHADOW);
+ : _impl(0), _title(title), _buttonLabel(buttonLabel), _saveMode(saveMode) {
}
SaveLoadChooser::~SaveLoadChooser() {
+ delete _impl;
+ _impl = 0;
}
-int SaveLoadChooser::runModalWithCurrentTarget() {
- const Common::String gameId = ConfMan.get("gameid");
-
- const EnginePlugin *plugin = 0;
- EngineMan.findGame(gameId, &plugin);
-
- return runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
-}
-
-int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target) {
- if (_gfxWidget)
- _gfxWidget->setGfx(0);
-
- // Set up the game domain as newly active domain, so
- // target specific savepath will be checked
- String oldDomain = ConfMan.getActiveDomainName();
- ConfMan.setActiveDomain(target);
-
- _plugin = plugin;
- _target = target;
- _delSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
- _metaInfoSupport = (*_plugin)->hasFeature(MetaEngine::kSavesSupportMetaInfo);
- _thumbnailSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportThumbnail);
- _saveDateSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportCreationDate);
- _playTimeSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportPlayTime);
- _resultString.clear();
- reflowLayout();
- updateSaveList();
-
- int ret = Dialog::runModal();
-
- // Revert to the old active domain
- ConfMan.setActiveDomain(oldDomain);
-
- return ret;
-}
-
-void SaveLoadChooser::open() {
- Dialog::open();
-
- // So that quitting ScummVM will not cause the dialog result to say a
- // savegame was selected.
- setResult(-1);
-}
-
-const Common::String &SaveLoadChooser::getResultString() const {
- int selItem = _list->getSelected();
- return (selItem >= 0) ? _list->getSelectedString() : _resultString;
+void SaveLoadChooser::selectChooser(const MetaEngine &engine) {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(engine);
+ if (!_impl || _impl->getType() != requestedType) {
+ delete _impl;
+ _impl = 0;
+
+ switch (requestedType) {
+ case kSaveLoadDialogGrid:
+ _impl = new SaveLoadChooserGrid(_title, _saveMode);
+ break;
+
+ case kSaveLoadDialogList:
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ _impl = new SaveLoadChooserSimple(_title, _buttonLabel, _saveMode);
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ break;
+ }
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
}
Common::String SaveLoadChooser::createDefaultSaveDescription(const int slot) const {
@@ -140,267 +73,44 @@ Common::String SaveLoadChooser::createDefaultSaveDescription(const int slot) con
#endif
}
-void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
- int selItem = _list->getSelected();
-
- switch (cmd) {
- case GUI::kListItemActivatedCmd:
- case GUI::kListItemDoubleClickedCmd:
- if (selItem >= 0 && _chooseButton->isEnabled()) {
- if (_list->isEditable() || !_list->getSelectedString().empty()) {
- _list->endEditMode();
- if (!_saveList.empty()) {
- setResult(_saveList[selItem].getSaveSlot());
- _resultString = _list->getSelectedString();
- }
- close();
- }
- }
- break;
- case kChooseCmd:
- _list->endEditMode();
- if (!_saveList.empty()) {
- setResult(_saveList[selItem].getSaveSlot());
- _resultString = _list->getSelectedString();
- }
- close();
- break;
- case GUI::kListSelectionChangedCmd:
- updateSelection(true);
- break;
- case kDelCmd:
- if (selItem >= 0 && _delSupport) {
- MessageDialog alert(_("Do you really want to delete this savegame?"),
- _("Delete"), _("Cancel"));
- if (alert.runModal() == GUI::kMessageOK) {
- (*_plugin)->removeSaveState(_target.c_str(), _saveList[selItem].getSaveSlot());
-
- setResult(-1);
- _list->setSelected(-1);
-
- updateSaveList();
- updateSelection(true);
- }
- }
- break;
- case kCloseCmd:
- setResult(-1);
- default:
- Dialog::handleCommand(sender, cmd, data);
- }
-}
-
-void SaveLoadChooser::reflowLayout() {
- if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && _thumbnailSupport) {
- int16 x, y;
- uint16 w, h;
-
- if (!g_gui.xmlEval()->getWidgetData("SaveLoadChooser.Thumbnail", x, y, w, h))
- error("Error when loading position data for Save/Load Thumbnails");
-
- int thumbW = kThumbnailWidth;
- int thumbH = kThumbnailHeight2;
- int thumbX = x + (w >> 1) - (thumbW >> 1);
- int thumbY = y + kLineHeight;
-
- int textLines = 0;
- if (!_saveDateSupport)
- textLines++;
- if (!_playTimeSupport)
- textLines++;
-
- _container->resize(x, y, w, h - (kLineHeight * textLines));
- _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
-
- int height = thumbY + thumbH + kLineHeight;
-
- if (_saveDateSupport) {
- _date->resize(thumbX, height, kThumbnailWidth, kLineHeight);
- height += kLineHeight;
- _time->resize(thumbX, height, kThumbnailWidth, kLineHeight);
- height += kLineHeight;
- }
-
- if (_playTimeSupport)
- _playtime->resize(thumbX, height, kThumbnailWidth, kLineHeight);
-
- _container->setVisible(true);
- _gfxWidget->setVisible(true);
-
- _date->setVisible(_saveDateSupport);
- _time->setVisible(_saveDateSupport);
-
- _playtime->setVisible(_playTimeSupport);
+int SaveLoadChooser::runModalWithCurrentTarget() {
+ const Common::String gameId = ConfMan.get("gameid");
- _fillR = 0;
- _fillG = 0;
- _fillB = 0;
- updateSelection(false);
- } else {
- _container->setVisible(false);
- _gfxWidget->setVisible(false);
- _date->setVisible(false);
- _time->setVisible(false);
- _playtime->setVisible(false);
- }
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
- Dialog::reflowLayout();
+ return runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
}
-void SaveLoadChooser::updateSelection(bool redraw) {
- int selItem = _list->getSelected();
-
- bool isDeletable = _delSupport;
- bool isWriteProtected = false;
- bool startEditMode = _list->isEditable();
-
- _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
- _date->setLabel(_("No date saved"));
- _time->setLabel(_("No time saved"));
- _playtime->setLabel(_("No playtime saved"));
-
- if (selItem >= 0 && _metaInfoSupport) {
- SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot());
-
- isDeletable = desc.getDeletableFlag() && _delSupport;
- isWriteProtected = desc.getWriteProtectedFlag();
-
- // Don't allow the user to change the description of write protected games
- if (isWriteProtected)
- startEditMode = false;
-
- if (_thumbnailSupport) {
- const Graphics::Surface *thumb = desc.getThumbnail();
- if (thumb) {
- _gfxWidget->setGfx(thumb);
- _gfxWidget->useAlpha(256);
- }
- }
-
- if (_saveDateSupport) {
- const Common::String &saveDate = desc.getSaveDate();
- if (!saveDate.empty())
- _date->setLabel(_("Date: ") + saveDate);
-
- const Common::String &saveTime = desc.getSaveTime();
- if (!saveTime.empty())
- _time->setLabel(_("Time: ") + saveTime);
- }
-
- if (_playTimeSupport) {
- const Common::String &playTime = desc.getPlayTime();
- if (!playTime.empty())
- _playtime->setLabel(_("Playtime: ") + playTime);
- }
- }
-
-
- if (_list->isEditable()) {
- // Disable the save button if nothing is selected, or if the selected
- // game is write protected
- _chooseButton->setEnabled(selItem >= 0 && !isWriteProtected);
+int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target) {
+ selectChooser(**plugin);
+ if (!_impl)
+ return -1;
- if (startEditMode) {
- _list->startEditMode();
+ // Set up the game domain as newly active domain, so
+ // target specific savepath will be checked
+ String oldDomain = ConfMan.getActiveDomainName();
+ ConfMan.setActiveDomain(target);
- if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") &&
- _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
- _list->setEditString("");
- _list->setEditColor(ThemeEngine::kFontColorNormal);
- }
+ int ret;
+ do {
+ ret = _impl->run(target, &(**plugin));
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ if (ret == kSwitchSaveLoadDialog) {
+ selectChooser(**plugin);
}
- } else {
- // Disable the load button if nothing is selected, or if an empty
- // list item is selected.
- _chooseButton->setEnabled(selItem >= 0 && !_list->getSelectedString().empty());
- }
-
- // Delete will always be disabled if the engine doesn't support it.
- _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
-
- if (redraw) {
- _gfxWidget->draw();
- _date->draw();
- _time->draw();
- _playtime->draw();
- _chooseButton->draw();
- _deleteButton->draw();
-
- draw();
- }
-}
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ } while (ret < -1);
-void SaveLoadChooser::close() {
- _plugin = 0;
- _target.clear();
- _saveList.clear();
- _list->setList(StringArray());
+ // Revert to the old active domain
+ ConfMan.setActiveDomain(oldDomain);
- Dialog::close();
+ return ret;
}
-void SaveLoadChooser::updateSaveList() {
- _saveList = (*_plugin)->listSaves(_target.c_str());
-
- int curSlot = 0;
- int saveSlot = 0;
- StringArray saveNames;
- ListWidget::ColorList colors;
- for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
- // Handle gaps in the list of save games
- saveSlot = x->getSaveSlot();
- if (curSlot < saveSlot) {
- while (curSlot < saveSlot) {
- SaveStateDescriptor dummySave(curSlot, "");
- _saveList.insert_at(curSlot, dummySave);
- saveNames.push_back(dummySave.getDescription());
- colors.push_back(ThemeEngine::kFontColorNormal);
- curSlot++;
- }
-
- // Sync the save list iterator
- for (x = _saveList.begin(); x != _saveList.end(); ++x) {
- if (x->getSaveSlot() == saveSlot)
- break;
- }
- }
-
- // Show "Untitled savestate" for empty/whitespace savegame descriptions
- Common::String description = x->getDescription();
- Common::String trimmedDescription = description;
- trimmedDescription.trim();
- if (trimmedDescription.empty()) {
- description = _("Untitled savestate");
- colors.push_back(ThemeEngine::kFontColorAlternate);
- } else {
- colors.push_back(ThemeEngine::kFontColorNormal);
- }
-
- saveNames.push_back(description);
- curSlot++;
- }
-
- // Fill the rest of the save slots with empty saves
-
- int maximumSaveSlots = (*_plugin)->getMaximumSaveSlot();
-
-#ifdef __DS__
- // Low memory on the DS means too many save slots are impractical, so limit
- // the maximum here.
- if (maximumSaveSlots > 99) {
- maximumSaveSlots = 99;
- }
-#endif
-
- Common::String emptyDesc;
- for (int i = curSlot; i <= maximumSaveSlots; i++) {
- saveNames.push_back(emptyDesc);
- SaveStateDescriptor dummySave(i, "");
- _saveList.push_back(dummySave);
- colors.push_back(ThemeEngine::kFontColorNormal);
- }
-
- _list->setList(saveNames, &colors);
+const Common::String &SaveLoadChooser::getResultString() const {
+ assert(_impl);
+ return _impl->getResultString();
}
} // End of namespace GUI
diff --git a/gui/saveload.h b/gui/saveload.h
index a19f5ab083..17fd99a31d 100644
--- a/gui/saveload.h
+++ b/gui/saveload.h
@@ -19,54 +19,30 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef GUI_SAVELOAD_DIALOG_H
-#define GUI_SAVELOAD_DIALOG_H
+#ifndef GUI_SAVELOAD_H
+#define GUI_SAVELOAD_H
#include "gui/dialog.h"
#include "engines/metaengine.h"
namespace GUI {
-class ListWidget;
-class GraphicsWidget;
-class ButtonWidget;
-class CommandSender;
-class ContainerWidget;
-class StaticTextWidget;
+class SaveLoadChooserDialog;
-class SaveLoadChooser : GUI::Dialog {
+class SaveLoadChooser {
typedef Common::String String;
- typedef Common::Array<Common::String> StringArray;
protected:
- GUI::ListWidget *_list;
- GUI::ButtonWidget *_chooseButton;
- GUI::ButtonWidget *_deleteButton;
- GUI::GraphicsWidget *_gfxWidget;
- GUI::ContainerWidget *_container;
- GUI::StaticTextWidget *_date;
- GUI::StaticTextWidget *_time;
- GUI::StaticTextWidget *_playtime;
+ SaveLoadChooserDialog *_impl;
- const EnginePlugin *_plugin;
- bool _delSupport;
- bool _metaInfoSupport;
- bool _thumbnailSupport;
- bool _saveDateSupport;
- bool _playTimeSupport;
- String _target;
- SaveStateList _saveList;
- String _resultString;
+ const String _title;
+ const String _buttonLabel;
+ const bool _saveMode;
- uint8 _fillR, _fillG, _fillB;
-
- void updateSaveList();
- void updateSelection(bool redraw);
+ void selectChooser(const MetaEngine &engine);
public:
SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode);
~SaveLoadChooser();
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
-
/**
* Runs the save/load chooser with the currently active config manager
* domain as target.
@@ -75,7 +51,6 @@ public:
*/
int runModalWithCurrentTarget();
int runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target);
- void open();
const Common::String &getResultString() const;
@@ -93,10 +68,6 @@ public:
* @return The slot description.
*/
Common::String createDefaultSaveDescription(const int slot) const;
-
- virtual void reflowLayout();
-
- virtual void close();
};
} // End of namespace GUI
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 86d0061e1b..bfd78db3ae 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -619,6 +619,8 @@
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
+"<def var='ShowChooserPics' value='0'/> "
+"<def var='ShowChooserPageDisplay' value='0'/> "
"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
"<def var='KeyMapper.Spacing' value='5'/> "
"<def var='KeyMapper.LabelWidth' value='80'/> "
@@ -1362,6 +1364,14 @@
"<widget name='Title' height='Globals.Line.Height'/> "
"<widget name='List' /> "
"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='ListSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
+"<widget name='GridSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
@@ -1376,6 +1386,26 @@
"</layout> "
"</layout> "
"</dialog> "
+"<dialog name='SavenameDialog' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='DescriptionText' "
+"width='180' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Description' "
+"height='19' "
+"/> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<space/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
"<dialog name='ScummHelp' overlays='screen'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Title' "
@@ -1564,6 +1594,8 @@
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
+"<def var='ShowChooserPics' value='0'/> "
+"<def var='ShowChooserPageDisplay' value='1'/> "
"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
"<def var='KeyMapper.Spacing' value='10'/> "
"<def var='KeyMapper.LabelWidth' value='100'/> "
@@ -2294,9 +2326,16 @@
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='Title' "
"height='Globals.Line.Height' "
"/> "
+"<space/> "
+"<widget name='PageDisplay' "
+"width='200' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
"<widget name='List' /> "
"<widget name='Thumbnail' "
@@ -2305,6 +2344,14 @@
"/> "
"</layout> "
"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='ListSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
+"<widget name='GridSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
@@ -2319,6 +2366,26 @@
"</layout> "
"</layout> "
"</dialog> "
+"<dialog name='SavenameDialog' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='DescriptionText' "
+"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Description' "
+"height='19' "
+"/> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<space/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
"<dialog name='ScummHelp' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Title' "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index d126ed0774..468f4b1594 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index d4bed29cf8..b8937adcb2 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.13:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.16:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 8717892995..4a6aae00bc 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -32,6 +32,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '1'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
@@ -793,9 +796,16 @@
<dialog name = 'SaveLoadChooser' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
- <widget name = 'Title'
- height = 'Globals.Line.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <space/>
+ <widget name = 'PageDisplay'
+ width = '200'
+ height = 'Globals.Line.Height'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
<widget name = 'List' />
<widget name = 'Thumbnail'
@@ -804,6 +814,14 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -819,6 +837,27 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 8f5db9d364..57e149b570 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -33,6 +33,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '0'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '5'/>
@@ -807,6 +810,14 @@
<widget name = 'Title' height = 'Globals.Line.Height'/>
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -822,6 +833,26 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '180'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index db116325e2..34a1db9c06 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index 60744d386f..52eb683ebd 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.13:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.16:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/grid.bmp b/gui/themes/scummmodern/grid.bmp
new file mode 100644
index 0000000000..adeb209380
--- /dev/null
+++ b/gui/themes/scummmodern/grid.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/list.bmp b/gui/themes/scummmodern/list.bmp
new file mode 100644
index 0000000000..2f54a40bcd
--- /dev/null
+++ b/gui/themes/scummmodern/list.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 037c327235..4703683bc3 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -101,6 +101,8 @@
<bitmap filename = 'search.bmp'/>
<bitmap filename = 'eraser.bmp'/>
<bitmap filename = 'delbtn.bmp'/>
+ <bitmap filename = 'list.bmp'/>
+ <bitmap filename = 'grid.bmp'/>
</bitmaps>
<fonts>
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 087a844a1b..d99d7416c2 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -39,6 +39,9 @@
<def var = 'ShowGlobalMenuLogo' value = '1'/>
<def var = 'ShowSearchPic' value = '1'/>
+ <def var = 'ShowChooserPics' value = '1'/>
+ <def var = 'ShowChooserPageDisplay' value = '1'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
@@ -807,9 +810,16 @@
<dialog name = 'SaveLoadChooser' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
- <widget name = 'Title'
- height = 'Globals.Line.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <space/>
+ <widget name = 'PageDisplay'
+ width = '200'
+ height = 'Globals.Line.Height'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
<widget name = 'List' />
<widget name = 'Thumbnail'
@@ -818,6 +828,14 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'ListSwitch'
+ height = '20'
+ width = '20'
+ />
+ <widget name = 'GridSwitch'
+ height = '20'
+ width = '20'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -833,6 +851,27 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 987fee800a..4fd5bdcf40 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -31,6 +31,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '0'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'Predictive.Button.Width' value = '45' />
@@ -806,6 +809,14 @@
<widget name = 'Title' height = 'Globals.Line.Height'/>
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -821,6 +832,26 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '180'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen' inset = '8'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 1b68e36ea8..9046bcc9c1 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -296,8 +296,8 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co
void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) {
- sendCommand(_cmd, 0);
startAnimatePressedState();
+ sendCommand(_cmd, 0);
}
}
@@ -414,6 +414,19 @@ void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
_gfx->copyFrom(*gfx);
}
+void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
+ if (w == -1)
+ w = _w;
+ if (h == -1)
+ h = _h;
+
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
+
+ _gfx->free();
+ _gfx->create(w, h, requiredFormat);
+ _gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
+}
+
void PicButtonWidget::drawWidget() {
g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
@@ -698,6 +711,26 @@ ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) :
_type = kContainerWidget;
}
+ContainerWidget::~ContainerWidget() {
+ // We also remove the widget from the boss to avoid segfaults, when the
+ // deleted widget is an active widget in the boss.
+ for (Widget *w = _firstWidget; w; w = w->next()) {
+ _boss->removeWidget(w);
+ }
+}
+
+Widget *ContainerWidget::findWidget(int x, int y) {
+ return findWidgetInChain(_firstWidget, x, y);
+}
+
+void ContainerWidget::removeWidget(Widget *widget) {
+ // We also remove the widget from the boss to avoid a reference to a
+ // widget not in the widget chain anymore.
+ _boss->removeWidget(widget);
+
+ Widget::removeWidget(widget);
+}
+
void ContainerWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
}
diff --git a/gui/widget.h b/gui/widget.h
index 6de56862c3..6f710f302f 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -88,7 +88,7 @@ protected:
uint16 _id;
bool _hasFocus;
ThemeEngine::WidgetStateInfo _state;
- const char *_tooltip;
+ Common::String _tooltip;
private:
uint16 _flags;
@@ -142,7 +142,9 @@ public:
uint8 parseHotkey(const Common::String &label);
Common::String cleanupHotkey(const Common::String &label);
- const char *getTooltip() const { return _tooltip; }
+ bool hasTooltip() const { return !_tooltip.empty(); }
+ const Common::String &getTooltip() const { return _tooltip; }
+ void setTooltip(const Common::String &tooltip) { _tooltip = tooltip; }
protected:
void updateState(int oldFlags, int newFlags);
@@ -220,6 +222,7 @@ public:
~PicButtonWidget();
void setGfx(const Graphics::Surface *gfx);
+ void setGfx(int w, int h, int r, int g, int b);
void useAlpha(int alpha) { _alpha = alpha; }
void useThemeTransparency(bool enable) { _transparency = enable; }
@@ -365,7 +368,10 @@ class ContainerWidget : public Widget {
public:
ContainerWidget(GuiObject *boss, int x, int y, int w, int h);
ContainerWidget(GuiObject *boss, const Common::String &name);
+ ~ContainerWidget();
+ virtual Widget *findWidget(int x, int y);
+ virtual void removeWidget(Widget *widget);
protected:
void drawWidget();
};