diff options
author | Johannes Schickel | 2012-08-12 14:49:28 +0200 |
---|---|---|
committer | Johannes Schickel | 2012-08-12 14:49:28 +0200 |
commit | 4f7c65af0e4c5fb3c6c03b44e3b4405314b6ab24 (patch) | |
tree | efa33c489905333cd56c8988c3a03e27f47f1fcf /gui | |
parent | 61af435d8a870a0630b5dea2ecf69cd58fc95946 (diff) | |
parent | 71daae7bbc03c1d9327f5353b1450f9d0d9774da (diff) | |
download | scummvm-rg350-4f7c65af0e4c5fb3c6c03b44e3b4405314b6ab24.tar.gz scummvm-rg350-4f7c65af0e4c5fb3c6c03b44e3b4405314b6ab24.tar.bz2 scummvm-rg350-4f7c65af0e4c5fb3c6c03b44e3b4405314b6ab24.zip |
Merge pull request #260 from lordhoto/new-chooser.
New save/load chooser
Conflicts:
gui/saveload.cpp
Diffstat (limited to 'gui')
-rw-r--r-- | gui/ThemeEngine.cpp | 2 | ||||
-rw-r--r-- | gui/ThemeEngine.h | 4 | ||||
-rw-r--r-- | gui/Tooltip.cpp | 2 | ||||
-rw-r--r-- | gui/gui-manager.cpp | 2 | ||||
-rw-r--r-- | gui/module.mk | 1 | ||||
-rw-r--r-- | gui/saveload-dialog.cpp | 881 | ||||
-rw-r--r-- | gui/saveload-dialog.h | 210 | ||||
-rw-r--r-- | gui/saveload.cpp | 392 | ||||
-rw-r--r-- | gui/saveload.h | 47 | ||||
-rw-r--r-- | gui/themes/default.inc | 67 | ||||
-rw-r--r-- | gui/themes/scummclassic.zip | bin | 93390 -> 95181 bytes | |||
-rw-r--r-- | gui/themes/scummclassic/THEMERC | 2 | ||||
-rw-r--r-- | gui/themes/scummclassic/classic_layout.stx | 45 | ||||
-rw-r--r-- | gui/themes/scummclassic/classic_layout_lowres.stx | 31 | ||||
-rw-r--r-- | gui/themes/scummmodern.zip | bin | 1449870 -> 1453476 bytes | |||
-rw-r--r-- | gui/themes/scummmodern/THEMERC | 2 | ||||
-rw-r--r-- | gui/themes/scummmodern/grid.bmp | bin | 0 -> 822 bytes | |||
-rw-r--r-- | gui/themes/scummmodern/list.bmp | bin | 0 -> 822 bytes | |||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_gfx.stx | 2 | ||||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_layout.stx | 45 | ||||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_layout_lowres.stx | 31 | ||||
-rw-r--r-- | gui/widget.cpp | 35 | ||||
-rw-r--r-- | gui/widget.h | 10 |
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 Binary files differindex d126ed0774..468f4b1594 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip 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 Binary files differindex db116325e2..34a1db9c06 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip 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 Binary files differnew file mode 100644 index 0000000000..adeb209380 --- /dev/null +++ b/gui/themes/scummmodern/grid.bmp diff --git a/gui/themes/scummmodern/list.bmp b/gui/themes/scummmodern/list.bmp Binary files differnew file mode 100644 index 0000000000..2f54a40bcd --- /dev/null +++ b/gui/themes/scummmodern/list.bmp 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(); }; |