ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

saveload-dialog.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "gui/saveload-dialog.h"
00024 
00025 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00026 #include "backends/cloud/cloudmanager.h"
00027 #include "backends/cloud/savessyncrequest.h"
00028 #include "backends/networking/curl/connectionmanager.h"
00029 #endif
00030 
00031 #include "common/translation.h"
00032 #include "common/config-manager.h"
00033 
00034 #include "gui/message.h"
00035 #include "gui/gui-manager.h"
00036 #include "gui/ThemeEval.h"
00037 #include "gui/widgets/edittext.h"
00038 
00039 #include "graphics/scaler.h"
00040 #include <common/savefile.h>
00041 
00042 namespace GUI {
00043 
00044 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00045 
00046 enum {
00047     kCancelSyncCmd = 'PDCS',
00048     kBackgroundSyncCmd = 'PDBS'
00049 };
00050 
00051 SaveLoadCloudSyncProgressDialog::SaveLoadCloudSyncProgressDialog(bool canRunInBackground): Dialog("SaveLoadCloudSyncProgress"), _close(false) {
00052     _label = new StaticTextWidget(this, "SaveLoadCloudSyncProgress.TitleText", "Downloading saves...");
00053     uint32 progress = (uint32)(100 * CloudMan.getSyncDownloadingProgress());
00054     _progressBar = new SliderWidget(this, "SaveLoadCloudSyncProgress.ProgressBar");
00055     _progressBar->setMinValue(0);
00056     _progressBar->setMaxValue(100);
00057     _progressBar->setValue(progress);
00058     _progressBar->setEnabled(false);
00059     _percentLabel = new StaticTextWidget(this, "SaveLoadCloudSyncProgress.PercentText", Common::String::format("%u %%", progress));
00060     new ButtonWidget(this, "SaveLoadCloudSyncProgress.Cancel", "Cancel", 0, kCancelSyncCmd, Common::ASCII_ESCAPE);  // Cancel dialog
00061     ButtonWidget *backgroundButton = new ButtonWidget(this, "SaveLoadCloudSyncProgress.Background", "Run in background", 0, kBackgroundSyncCmd, Common::ASCII_RETURN);  // Confirm dialog
00062     backgroundButton->setEnabled(canRunInBackground);
00063     g_gui.scheduleTopDialogRedraw();
00064 }
00065 
00066 SaveLoadCloudSyncProgressDialog::~SaveLoadCloudSyncProgressDialog() {
00067     CloudMan.setSyncTarget(nullptr); //not that dialog, at least
00068 }
00069 
00070 void SaveLoadCloudSyncProgressDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00071     switch(cmd) {
00072     case kSavesSyncProgressCmd:
00073         _percentLabel->setLabel(Common::String::format("%u%%", data));
00074         _progressBar->setValue(data);
00075         _progressBar->markAsDirty();
00076         break;
00077 
00078     case kCancelSyncCmd:
00079         setResult(kCancelSyncCmd);
00080         close();
00081         break;
00082 
00083     case kSavesSyncEndedCmd:
00084     case kBackgroundSyncCmd:
00085         _close = true;
00086         break;
00087     }
00088 
00089     Dialog::handleCommand(sender, cmd, data);
00090 }
00091 
00092 void SaveLoadCloudSyncProgressDialog::handleTickle() {
00093     if (_close) {
00094         setResult(kBackgroundSyncCmd);
00095         close();
00096     }
00097 
00098     Dialog::handleTickle();
00099 }
00100 #endif
00101 
00102 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00103 SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) {
00104     const Common::String &userConfig = ConfMan.get("gui_saveload_chooser", Common::ConfigManager::kApplicationDomain);
00105 
00106     // Check (and update if necessary) the theme config here. This catches
00107     // resolution changes, which happened after the GUI was closed. This
00108     // should assure that the correct GUI width/height are returned below and
00109     // prevent the logic from picking the grid dialog, even though it is not
00110     // possible to use it.
00111     g_gui.checkScreenChange();
00112 
00113     if (g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400
00114         && metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo)
00115         && metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail)
00116         && userConfig.equalsIgnoreCase("grid")) {
00117         // In case we are 640x400 or higher, this dialog is not in save mode,
00118         // the user requested the grid dialog and the engines supports it we
00119         // try to set it up.
00120         return kSaveLoadDialogGrid;
00121     } else {
00122         // In all other cases we want to use the list dialog.
00123         return kSaveLoadDialogList;
00124     }
00125 }
00126 
00127 enum {
00128     kListSwitchCmd = 'LIST',
00129     kGridSwitchCmd = 'GRID'
00130 };
00131 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00132 
00133 SaveLoadChooserDialog::SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode)
00134     : Dialog(dialogName), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
00135     _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode),
00136     _dialogWasShown(false)
00137 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00138     , _listButton(0), _gridButton(0)
00139 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00140     {
00141 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00142     addChooserButtons();
00143 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00144 }
00145 
00146 SaveLoadChooserDialog::SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode)
00147     : Dialog(x, y, w, h), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
00148     _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode),
00149     _dialogWasShown(false)
00150 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00151     , _listButton(0), _gridButton(0)
00152 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00153     {
00154 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00155     addChooserButtons();
00156 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00157 }
00158 
00159 SaveLoadChooserDialog::~SaveLoadChooserDialog() {
00160 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00161     CloudMan.setSyncTarget(nullptr); //not that dialog, at least
00162 #endif
00163 }
00164 
00165 void SaveLoadChooserDialog::open() {
00166     Dialog::open();
00167 
00168     // So that quitting ScummVM will not cause the dialog result to say a
00169     // saved game was selected.
00170     setResult(-1);
00171 
00172     _dialogWasShown = false;
00173 }
00174 
00175 void SaveLoadChooserDialog::close() {
00176 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00177     CloudMan.setSyncTarget(nullptr); //not that dialog, at least
00178 #endif
00179     Dialog::close();
00180 }
00181 
00182 int SaveLoadChooserDialog::run(const Common::String &target, const MetaEngine *metaEngine) {
00183     _metaEngine = metaEngine;
00184     _target = target;
00185     _delSupport = _metaEngine->hasFeature(MetaEngine::kSupportsDeleteSave);
00186     _metaInfoSupport = _metaEngine->hasFeature(MetaEngine::kSavesSupportMetaInfo);
00187     _thumbnailSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportThumbnail);
00188     _saveDateSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportCreationDate);
00189     _playTimeSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportPlayTime);
00190 
00191     return runIntern();
00192 }
00193 
00194 void SaveLoadChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00195 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00196     switch (cmd) {
00197     case kListSwitchCmd:
00198         setResult(kSwitchSaveLoadDialog);
00199         // We save the requested dialog type here to avoid the setting to be
00200         // overwritten when our reflowLayout logic selects a different dialog
00201         // type.
00202         ConfMan.set("gui_saveload_chooser", "list", Common::ConfigManager::kApplicationDomain);
00203         close();
00204         break;
00205 
00206     case kGridSwitchCmd:
00207         setResult(kSwitchSaveLoadDialog);
00208         // See above.
00209         ConfMan.set("gui_saveload_chooser", "grid", Common::ConfigManager::kApplicationDomain);
00210         close();
00211         break;
00212 
00213     default:
00214         break;
00215     }
00216 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00217 
00218 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00219     if (cmd == kSavesSyncProgressCmd || cmd == kSavesSyncEndedCmd) {
00220         //this dialog only gets these commands if the progress dialog was shown and user clicked "run in background"
00221         return updateSaveList();
00222     }
00223 #endif
00224 
00225     return Dialog::handleCommand(sender, cmd, data);
00226 }
00227 
00228 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00229 void SaveLoadChooserDialog::runSaveSync(bool hasSavepathOverride) {
00230     if (!CloudMan.isSyncing()) {
00231         if (hasSavepathOverride) {
00232             CloudMan.showCloudDisabledIcon();
00233         } else {
00234             Cloud::SavesSyncRequest *request = CloudMan.syncSaves();
00235             if (request)
00236                 request->setTarget(this);
00237         }
00238     }
00239 }
00240 #endif
00241 
00242 void SaveLoadChooserDialog::handleTickle() {
00243 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00244     if (!_dialogWasShown && CloudMan.isSyncing()) {
00245         Common::Array<Common::String> files = CloudMan.getSyncingFiles();
00246         if (!files.empty()) {
00247             {
00248                 SaveLoadCloudSyncProgressDialog dialog(_metaEngine ? _metaEngine->hasFeature(MetaEngine::kSimpleSavesNames) : false);
00249                 CloudMan.setSyncTarget(&dialog);
00250                 int result = dialog.runModal();
00251                 if (result == kCancelSyncCmd) {
00252                     CloudMan.cancelSync();
00253                 }
00254             }
00255             //dialog changes syncTarget to nullptr after that }
00256             CloudMan.setSyncTarget(this);
00257             _dialogWasShown = true;
00258             updateSaveList();
00259         }
00260     }
00261 #endif
00262     Dialog::handleTickle();
00263 }
00264 
00265 void SaveLoadChooserDialog::reflowLayout() {
00266 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00267     const SaveLoadChooserType currentType = getType();
00268     const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
00269 
00270     addChooserButtons();
00271     if (currentType == kSaveLoadDialogList) {
00272         _listButton->setEnabled(false);
00273     }
00274     if (currentType == kSaveLoadDialogGrid) {
00275         _gridButton->setEnabled(false);
00276     }
00277 
00278     // Change the dialog type if there is any need for it.
00279     if (requestedType != currentType) {
00280         setResult(kSwitchSaveLoadDialog);
00281         close();
00282     }
00283 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00284 
00285     Dialog::reflowLayout();
00286 }
00287 
00288 void SaveLoadChooserDialog::updateSaveList() {
00289 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00290     Common::Array<Common::String> files = CloudMan.getSyncingFiles(); //returns empty array if not syncing
00291     g_system->getSavefileManager()->updateSavefilesList(files);
00292 #endif
00293     listSaves();
00294 }
00295 
00296 void SaveLoadChooserDialog::listSaves() {
00297     if (!_metaEngine) return; //very strange
00298     _saveList = _metaEngine->listSaves(_target.c_str());
00299 
00300 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00301     //if there is Cloud support, add currently synced files as "locked" saves in the list
00302     if (_metaEngine->hasFeature(MetaEngine::kSimpleSavesNames)) {
00303         Common::String pattern = _target + ".###";
00304         Common::Array<Common::String> files = CloudMan.getSyncingFiles(); //returns empty array if not syncing
00305         for (uint32 i = 0; i < files.size(); ++i) {
00306             if (!files[i].matchString(pattern, true))
00307                 continue;
00308 
00309             //make up some slot number
00310             int slotNum = 0;
00311             for (uint32 j = (files[i].size() > 3 ? files[i].size() - 3 : 0); j < files[i].size(); ++j) { //3 last chars
00312                 char c = files[i][j];
00313                 if (c < '0' || c > '9')
00314                     continue;
00315                 slotNum = slotNum * 10 + (c - '0');
00316             }
00317 
00318             SaveStateDescriptor slot(slotNum, files[i]);
00319             slot.setLocked(true);
00320             _saveList.push_back(slot);
00321         }
00322 
00323         Common::sort(_saveList.begin(), _saveList.end(), SaveStateDescriptorSlotComparator());
00324     }
00325 #endif
00326 }
00327 
00328 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00329 void SaveLoadChooserDialog::addChooserButtons() {
00330     if (_listButton) {
00331         removeWidget(_listButton);
00332         delete _listButton;
00333     }
00334 
00335     if (_gridButton) {
00336         removeWidget(_gridButton);
00337         delete _gridButton;
00338     }
00339 
00340     _listButton = createSwitchButton("SaveLoadChooser.ListSwitch", "L", _("List view"), ThemeEngine::kImageList, kListSwitchCmd);
00341     _gridButton = createSwitchButton("SaveLoadChooser.GridSwitch", "G", _("Grid view"), ThemeEngine::kImageGrid, kGridSwitchCmd);
00342     if (!_metaInfoSupport || !_thumbnailSupport || !(g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400)) {
00343         _gridButton->setEnabled(false);
00344         _listButton->setEnabled(false);
00345     }
00346 }
00347 
00348 ButtonWidget *SaveLoadChooserDialog::createSwitchButton(const Common::String &name, const char *desc, const char *tooltip, const char *image, uint32 cmd) {
00349     ButtonWidget *button;
00350 
00351 #ifndef DISABLE_FANCY_THEMES
00352     if (g_gui.xmlEval()->getVar("Globals.ShowChooserPics") == 1 && g_gui.theme()->supportsImages()) {
00353         button = new PicButtonWidget(this, name, tooltip, cmd);
00354         ((PicButtonWidget *)button)->useThemeTransparency(true);
00355         ((PicButtonWidget *)button)->setGfx(g_gui.theme()->getImageSurface(image));
00356     } else
00357 #endif
00358         button = new ButtonWidget(this, name, desc, tooltip, cmd);
00359 
00360     return button;
00361 }
00362 #endif // !DISABLE_SAVELOADCHOOSER_GRID
00363 
00364 // SaveLoadChooserSimple implementation
00365 
00366 enum {
00367     kChooseCmd = 'CHOS',
00368     kDelCmd = 'DEL '
00369 };
00370 
00371 SaveLoadChooserSimple::SaveLoadChooserSimple(const String &title, const String &buttonLabel, bool saveMode)
00372     : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0)  {
00373     _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
00374 
00375     new StaticTextWidget(this, "SaveLoadChooser.Title", title);
00376 
00377     // Add choice list
00378     _list = new ListWidget(this, "SaveLoadChooser.List");
00379     _list->setNumberingMode(kListNumberingZero);
00380     _list->setEditable(saveMode);
00381 
00382     _gfxWidget = new GraphicsWidget(this, 0, 0, 10, 10);
00383 
00384     _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
00385     _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
00386     _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
00387 
00388     // Buttons
00389     new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
00390     _chooseButton = new ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
00391     _chooseButton->setEnabled(false);
00392 
00393     _deleteButton = new ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
00394     _deleteButton->setEnabled(false);
00395 
00396     _delSupport = _metaInfoSupport = _thumbnailSupport = false;
00397 
00398     _container = new ContainerWidget(this, 0, 0, 10, 10);
00399 //  _container->setHints(THEME_HINT_USE_SHADOW);
00400 }
00401 
00402 int SaveLoadChooserSimple::runIntern() {
00403     if (_gfxWidget)
00404         _gfxWidget->setGfx(0);
00405 
00406     _resultString.clear();
00407     reflowLayout();
00408     updateSaveList();
00409 
00410     return Dialog::runModal();
00411 }
00412 
00413 const Common::String &SaveLoadChooserSimple::getResultString() const {
00414     int selItem = _list->getSelected();
00415     return (selItem >= 0) ? _list->getSelectedString() : _resultString;
00416 }
00417 
00418 void SaveLoadChooserSimple::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00419     int selItem = _list->getSelected();
00420 
00421     switch (cmd) {
00422     case kListItemActivatedCmd:
00423     case kListItemDoubleClickedCmd:
00424         if (selItem >= 0 && _chooseButton->isEnabled()) {
00425             if (_list->isEditable() || !_list->getSelectedString().empty()) {
00426                 _list->endEditMode();
00427                 if (!_saveList.empty()) {
00428                     setResult(_saveList[selItem].getSaveSlot());
00429                     _resultString = _list->getSelectedString();
00430                 }
00431                 close();
00432             }
00433         }
00434         break;
00435     case kChooseCmd:
00436         _list->endEditMode();
00437         if (selItem >= 0) {
00438             if (!_saveList.empty()) {
00439                 setResult(_saveList[selItem].getSaveSlot());
00440                 _resultString = _list->getSelectedString();
00441             }
00442             close();
00443         }
00444         break;
00445     case kListSelectionChangedCmd:
00446         updateSelection(true);
00447         break;
00448     case kDelCmd:
00449         if (selItem >= 0 && _delSupport) {
00450             MessageDialog alert(_("Do you really want to delete this saved game?"),
00451                                 _("Delete"), _("Cancel"));
00452             if (alert.runModal() == kMessageOK) {
00453                 _metaEngine->removeSaveState(_target.c_str(), _saveList[selItem].getSaveSlot());
00454 
00455                 setResult(-1);
00456                 _list->setSelected(-1);
00457 
00458                 updateSaveList();
00459                 updateSelection(true);
00460             }
00461         }
00462         break;
00463     case kCloseCmd:
00464         setResult(-1);
00465         // Fall through
00466     default:
00467         SaveLoadChooserDialog::handleCommand(sender, cmd, data);
00468     }
00469 }
00470 
00471 void SaveLoadChooserSimple::reflowLayout() {
00472     if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && (_thumbnailSupport || _saveDateSupport || _playTimeSupport)) {
00473         int16 x, y;
00474         uint16 w, h;
00475 
00476         if (!g_gui.xmlEval()->getWidgetData("SaveLoadChooser.Thumbnail", x, y, w, h))
00477             error("Error when loading position data for Save/Load Thumbnails");
00478 
00479         // Even if there is no thumbnail support, getWidgetData() will provide default thumbnail values
00480         int thumbW = kThumbnailWidth;
00481         int thumbH = kThumbnailHeight2;
00482         int thumbX = x + (w >> 1) - (thumbW >> 1);
00483         int thumbY = y + kLineHeight;
00484 
00485         int textLines = 0;
00486         if (_saveDateSupport)
00487             textLines += 2;
00488         if (_playTimeSupport)
00489             textLines++;
00490         if (textLines > 0)
00491             textLines++; // add a line of padding at the bottom
00492 
00493         if (_thumbnailSupport) {
00494             _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH); 
00495             _gfxWidget->setVisible(true);
00496         } else { 
00497             // choose sensible values for displaying playtime and date/time when a thumbnail is not being used
00498             thumbH = 0;
00499             thumbY = y;
00500             h = kLineHeight;
00501             _gfxWidget->setVisible(false);
00502         }
00503 
00504         int height = thumbY + thumbH + kLineHeight;
00505 
00506         if (_saveDateSupport) {
00507             _date->resize(thumbX, height, thumbW, kLineHeight);
00508             height += kLineHeight;
00509             _time->resize(thumbX, height, thumbW, kLineHeight);
00510             height += kLineHeight;
00511             _date->setVisible(_saveDateSupport);
00512             _time->setVisible(_saveDateSupport);
00513         } else {
00514             _date->setVisible(false);
00515             _time->setVisible(false);
00516         }
00517 
00518         if (_playTimeSupport) {
00519             _playtime->resize(thumbX, height, thumbW, kLineHeight);
00520             _playtime->setVisible(_playTimeSupport);
00521         } else {
00522             _playtime->setVisible(false);
00523         }
00524 
00525         _container->resize(x, y, w, h + (kLineHeight * textLines));
00526         _container->setVisible(true);
00527 
00528         updateSelection(false);
00529     } else {
00530         _container->setVisible(false);
00531         _gfxWidget->setVisible(false);
00532         _date->setVisible(false);
00533         _time->setVisible(false);
00534         _playtime->setVisible(false);
00535     }
00536 
00537     SaveLoadChooserDialog::reflowLayout();
00538 }
00539 
00540 void SaveLoadChooserSimple::updateSelection(bool redraw) {
00541     int selItem = _list->getSelected();
00542 
00543     bool isDeletable = _delSupport;
00544     bool isWriteProtected = false;
00545     bool startEditMode = _list->isEditable();
00546     bool isLocked = false;
00547 
00548     // We used to support letting the themes specify the fill color with our
00549     // initial theme based GUI. But this support was dropped.
00550     _gfxWidget->setGfx(-1, -1, 0, 0, 0);
00551     _date->setLabel(_("No date saved"));
00552     _time->setLabel(_("No time saved"));
00553     _playtime->setLabel(_("No playtime saved"));
00554 
00555     if (selItem >= 0 && _metaInfoSupport) {
00556         SaveStateDescriptor desc = (_saveList[selItem].getLocked() ? _saveList[selItem] : _metaEngine->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot()));
00557 
00558         isDeletable = desc.getDeletableFlag() && _delSupport;
00559         isWriteProtected = desc.getWriteProtectedFlag();
00560         isLocked = desc.getLocked();
00561 
00562         // Don't allow the user to change the description of write protected games
00563         if (isWriteProtected)
00564             startEditMode = false;
00565 
00566         if (_thumbnailSupport) {
00567             const Graphics::Surface *thumb = desc.getThumbnail();
00568             if (thumb) {
00569                 _gfxWidget->setGfx(thumb);
00570                 _gfxWidget->useAlpha(256);
00571             }
00572         }
00573 
00574         if (_saveDateSupport) {
00575             const Common::String &saveDate = desc.getSaveDate();
00576             if (!saveDate.empty())
00577                 _date->setLabel(_("Date: ") + saveDate);
00578 
00579             const Common::String &saveTime = desc.getSaveTime();
00580             if (!saveTime.empty())
00581                 _time->setLabel(_("Time: ") + saveTime);
00582         }
00583 
00584         if (_playTimeSupport) {
00585             const Common::String &playTime = desc.getPlayTime();
00586             if (!playTime.empty())
00587                 _playtime->setLabel(_("Playtime: ") + playTime);
00588         }
00589     }
00590 
00591 
00592     if (_list->isEditable()) {
00593         // Disable the save button if slot is locked, nothing is selected,
00594         // or if the selected game is write protected
00595         _chooseButton->setEnabled(!isLocked && selItem >= 0 && !isWriteProtected);
00596 
00597         if (startEditMode) {
00598             _list->startEditMode();
00599 
00600             if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled saved game") &&
00601                     _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
00602                 _list->setEditString("");
00603                 _list->setEditColor(ThemeEngine::kFontColorNormal);
00604             }
00605         }
00606     } else {
00607         // Disable the load button if slot is locked, nothing is selected,
00608         // or if an empty list item is selected.
00609         _chooseButton->setEnabled(!isLocked && selItem >= 0 && !_list->getSelectedString().empty());
00610     }
00611 
00612     // Delete will always be disabled if the engine doesn't support it.
00613     _deleteButton->setEnabled(isDeletable && !isLocked && (selItem >= 0) && (!_list->getSelectedString().empty()));
00614 
00615     if (redraw) {
00616         _gfxWidget->markAsDirty();
00617         _date->markAsDirty();
00618         _time->markAsDirty();
00619         _playtime->markAsDirty();
00620         _chooseButton->markAsDirty();
00621         _deleteButton->markAsDirty();
00622 
00623         g_gui.scheduleTopDialogRedraw();
00624     }
00625 }
00626 
00627 void SaveLoadChooserSimple::open() {
00628     SaveLoadChooserDialog::open();
00629 
00630     // Scroll the list to the last used entry.
00631     _list->scrollTo(ConfMan.getInt("gui_saveload_last_pos"));
00632 }
00633 
00634 void SaveLoadChooserSimple::close() {
00635     // Save the current scroll position/used entry.
00636     const int result = getResult();
00637     if (result >= 0) {
00638         ConfMan.setInt("gui_saveload_last_pos", result);
00639     } else {
00640         // Use the current scroll position here.
00641         // TODO: This means we canceled the dialog (or switch to the grid). Do
00642         // we want to save this position here? Does the user want that?
00643         // TODO: Do we want to save the current scroll position or the
00644         // currently selected item here? The scroll position is what the user
00645         // currently sees and seems to make more sense.
00646         ConfMan.setInt("gui_saveload_last_pos", _list->getCurrentScrollPos());
00647     }
00648 
00649     _metaEngine = 0;
00650     _target.clear();
00651     _saveList.clear();
00652     _list->setList(StringArray());
00653 
00654     SaveLoadChooserDialog::close();
00655 }
00656 
00657 void SaveLoadChooserSimple::updateSaveList() {
00658     SaveLoadChooserDialog::updateSaveList();
00659 
00660     int curSlot = 0;
00661     int saveSlot = 0;
00662     StringArray saveNames;
00663     ListWidget::ColorList colors;
00664     for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
00665         // Handle gaps in the list of save games
00666         saveSlot = x->getSaveSlot();
00667         if (curSlot < saveSlot) {
00668             while (curSlot < saveSlot) {
00669                 SaveStateDescriptor dummySave(curSlot, "");
00670                 _saveList.insert_at(curSlot, dummySave);
00671                 saveNames.push_back(dummySave.getDescription());
00672                 colors.push_back(ThemeEngine::kFontColorNormal);
00673                 curSlot++;
00674             }
00675 
00676             // Sync the save list iterator
00677             for (x = _saveList.begin(); x != _saveList.end(); ++x) {
00678                 if (x->getSaveSlot() == saveSlot)
00679                     break;
00680             }
00681         }
00682 
00683         // Show "Untitled saved game" for empty/whitespace saved game descriptions
00684         Common::String description = x->getDescription();
00685         Common::String trimmedDescription = description;
00686         trimmedDescription.trim();
00687         if (trimmedDescription.empty()) {
00688             description = _("Untitled saved game");
00689             colors.push_back(ThemeEngine::kFontColorAlternate);
00690         } else {
00691             colors.push_back((x->getLocked() ? ThemeEngine::kFontColorAlternate : ThemeEngine::kFontColorNormal));
00692         }
00693 
00694         saveNames.push_back(description);
00695         curSlot++;
00696     }
00697 
00698     // Fill the rest of the save slots with empty saves
00699 
00700     int maximumSaveSlots = _metaEngine->getMaximumSaveSlot();
00701 
00702 #ifdef __DS__
00703     // Low memory on the DS means too many save slots are impractical, so limit
00704     // the maximum here.
00705     if (maximumSaveSlots > 99) {
00706         maximumSaveSlots = 99;
00707     }
00708 #endif
00709 
00710     Common::String emptyDesc;
00711     for (int i = curSlot; i <= maximumSaveSlots; i++) {
00712         saveNames.push_back(emptyDesc);
00713         SaveStateDescriptor dummySave(i, "");
00714         _saveList.push_back(dummySave);
00715         colors.push_back(ThemeEngine::kFontColorNormal);
00716     }
00717 
00718     int selected = _list->getSelected();
00719     _list->setList(saveNames, &colors);
00720     if (selected >= 0 && selected < (int)saveNames.size())
00721         _list->setSelected(selected);
00722     else
00723         _chooseButton->setEnabled(false);
00724 
00725     g_gui.scheduleTopDialogRedraw();
00726 }
00727 
00728 // SaveLoadChooserGrid implementation
00729 
00730 #ifndef DISABLE_SAVELOADCHOOSER_GRID
00731 
00732 enum {
00733     kNextCmd = 'NEXT',
00734     kPrevCmd = 'PREV',
00735     kNewSaveCmd = 'SAVE'
00736 };
00737 
00738 SaveLoadChooserGrid::SaveLoadChooserGrid(const Common::String &title, bool saveMode)
00739     : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _lines(0), _columns(0), _entriesPerPage(0),
00740     _curPage(0), _newSaveContainer(0), _nextFreeSaveSlot(0), _buttons() {
00741     _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
00742 
00743     new StaticTextWidget(this, "SaveLoadChooser.Title", title);
00744 
00745     // Buttons
00746     new ButtonWidget(this, "SaveLoadChooser.Delete", _("Cancel"), 0, kCloseCmd);
00747     _nextButton = new ButtonWidget(this, "SaveLoadChooser.Choose", _("Next"), 0, kNextCmd);
00748     _nextButton->setEnabled(false);
00749 
00750     _prevButton = new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Prev"), 0, kPrevCmd);
00751     _prevButton->setEnabled(false);
00752 
00753     // Page display
00754     _pageDisplay = new StaticTextWidget(this, "SaveLoadChooser.PageDisplay", Common::String());
00755     _pageDisplay->setAlign(Graphics::kTextAlignRight);
00756 }
00757 
00758 SaveLoadChooserGrid::~SaveLoadChooserGrid() {
00759     removeWidget(_pageDisplay);
00760     delete _pageDisplay;
00761 }
00762 
00763 const Common::String &SaveLoadChooserGrid::getResultString() const {
00764     return _resultString;
00765 }
00766 
00767 void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00768     if (cmd <= _entriesPerPage && cmd + _curPage * _entriesPerPage <= _saveList.size()) {
00769         const SaveStateDescriptor &desc = _saveList[cmd - 1 + _curPage * _entriesPerPage];
00770 
00771         if (_saveMode) {
00772             _resultString = desc.getDescription();
00773         }
00774 
00775         setResult(desc.getSaveSlot());
00776         close();
00777     }
00778 
00779     switch (cmd) {
00780     case kNextCmd:
00781         ++_curPage;
00782         updateSaves();
00783         g_gui.scheduleTopDialogRedraw();
00784         break;
00785 
00786     case kPrevCmd:
00787         --_curPage;
00788         updateSaves();
00789         g_gui.scheduleTopDialogRedraw();
00790         break;
00791 
00792     case kNewSaveCmd:
00793         setResult(_nextFreeSaveSlot);
00794         close();
00795         break;
00796 
00797     case kCloseCmd:
00798         setResult(-1);
00799         // Fall through
00800     default:
00801         SaveLoadChooserDialog::handleCommand(sender, cmd, data);
00802     }
00803 }
00804 
00805 void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
00806     if (direction > 0) {
00807         if (_nextButton->isEnabled()) {
00808             ++_curPage;
00809             updateSaves();
00810             g_gui.scheduleTopDialogRedraw();
00811         }
00812     } else {
00813         if (_prevButton->isEnabled()) {
00814             --_curPage;
00815             updateSaves();
00816             g_gui.scheduleTopDialogRedraw();
00817         }
00818     }
00819 }
00820 
00821 void SaveLoadChooserGrid::updateSaveList() {
00822     SaveLoadChooserDialog::updateSaveList();
00823     updateSaves();
00824     g_gui.scheduleTopDialogRedraw();
00825 }
00826 
00827 void SaveLoadChooserGrid::open() {
00828     SaveLoadChooserDialog::open();
00829 
00830     listSaves();
00831     _resultString.clear();
00832 
00833     // Load information to restore the last page the user had open.
00834     assert(_entriesPerPage != 0);
00835     const uint lastPos = ConfMan.getInt("gui_saveload_last_pos");
00836     const uint listSize = _saveList.size();
00837     uint bestMatch = 0;
00838     uint diff = 0xFFFFFFFF;
00839 
00840     // We look for the nearest available slot, since a slot might be missing
00841     // due to the user deleting it via the list based chooser, by deleting
00842     // it by hand, etc.
00843     for (uint i = 0; i < listSize; ++i) {
00844         uint curDiff = ABS(_saveList[i].getSaveSlot() - (int)lastPos);
00845         if (curDiff < diff) {
00846             diff = curDiff;
00847             bestMatch = i;
00848         }
00849     }
00850 
00851     _curPage = bestMatch / _entriesPerPage;
00852 
00853     // Determine the next free save slot for save mode
00854     if (_saveMode) {
00855         int lastSlot = -1;
00856         _nextFreeSaveSlot = -1;
00857         for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
00858             const int curSlot = x->getSaveSlot();
00859 
00860             // In case there was a gap found use the slot.
00861             if (lastSlot + 1 < curSlot) {
00862                 // Check that the save slot can be used for user saves.
00863                 SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), lastSlot + 1);
00864                 if (!desc.getWriteProtectedFlag()) {
00865                     _nextFreeSaveSlot = lastSlot + 1;
00866                     break;
00867                 }
00868             }
00869 
00870             lastSlot = curSlot;
00871         }
00872 
00873         // Use the next available slot otherwise.
00874         const int maxSlot = _metaEngine->getMaximumSaveSlot();
00875         for (int i = lastSlot; _nextFreeSaveSlot == -1 && i < maxSlot; ++i) {
00876             // Check that the save slot can be used for user saves.
00877             SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), i + 1);
00878             if (!desc.getWriteProtectedFlag()) {
00879                 _nextFreeSaveSlot = i + 1;
00880             }
00881         }
00882     }
00883 
00884     updateSaves();
00885 }
00886 
00887 void SaveLoadChooserGrid::reflowLayout() {
00888     // HACK: The page display is not available in low resolution layout. We
00889     // remove and readd the widget here to avoid our GUI from erroring out.
00890     removeWidget(_pageDisplay);
00891     if (g_gui.xmlEval()->getVar("Globals.ShowChooserPageDisplay") == 1) {
00892         _pageDisplay->init();
00893     }
00894 
00895     SaveLoadChooserDialog::reflowLayout();
00896     destroyButtons();
00897 
00898     // HACK: The whole code below really works around the fact, that we have
00899     // no easy way to dynamically layout widgets.
00900     const uint16 availableWidth = getWidth() - 20;
00901     uint16 availableHeight;
00902 
00903     int16 x, y;
00904     uint16 w;
00905     g_gui.xmlEval()->getWidgetData("SaveLoadChooser.List", x, y, w, availableHeight);
00906 
00907     const int16 buttonWidth = kThumbnailWidth + 6;
00908     const int16 buttonHeight = kThumbnailHeight2 + 6;
00909 
00910     const int16 containerFrameWidthAdd = 10;
00911     const int16 containerFrameHeightAdd = 0;
00912     const int16 containerWidth = buttonWidth + containerFrameWidthAdd;
00913     const int16 containerHeight = buttonHeight + kLineHeight + containerFrameHeightAdd;
00914 
00915     const int16 defaultSpacingHorizontal = 4;
00916     const int16 defaultSpacingVertical = 8;
00917     const int16 slotAreaWidth = containerWidth + defaultSpacingHorizontal;
00918     const int16 slotAreaHeight = containerHeight + defaultSpacingVertical;
00919 
00920     const uint oldEntriesPerPage = _entriesPerPage;
00921     _columns = MAX<uint>(1, availableWidth / slotAreaWidth);
00922     _lines = MAX<uint>(1, availableHeight / slotAreaHeight);
00923     _entriesPerPage = _columns * _lines;
00924 
00925     // In save mode the first button is always "New Save", thus we need to
00926     // adjust the entries per page here.
00927     if (_saveMode) {
00928         --_entriesPerPage;
00929     }
00930 
00931     // Recalculate the page number
00932     if (!_saveList.empty() && oldEntriesPerPage != 0) {
00933         if (_entriesPerPage != 0) {
00934             _curPage = (_curPage * oldEntriesPerPage) / _entriesPerPage;
00935         } else {
00936             _curPage = 0;
00937         }
00938     }
00939 
00940     const uint addX = _columns > 1 ? (availableWidth % slotAreaWidth) / (_columns - 1) : 0;
00941     //const uint addY = _lines > 1 ? (availableHeight % slotAreaHeight) / (_lines - 1) : 0;
00942 
00943     _buttons.reserve(_lines * _columns);
00944     y += defaultSpacingVertical / 2;
00945     for (uint curLine = 0; curLine < _lines; ++curLine, y += slotAreaHeight/* + addY*/) {
00946         for (uint curColumn = 0, curX = x + defaultSpacingHorizontal / 2; curColumn < _columns; ++curColumn, curX += slotAreaWidth + addX) {
00947             int dstY = containerFrameHeightAdd / 2;
00948             int dstX = containerFrameWidthAdd / 2;
00949 
00950             // In the save mode we will always create a new save button as the first button.
00951             if (_saveMode && curLine == 0 && curColumn == 0) {
00952                 _newSaveContainer = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
00953                 ButtonWidget *newSave = new ButtonWidget(_newSaveContainer, dstX, dstY, buttonWidth, buttonHeight, _("New Save"), _("Create a new saved game"), kNewSaveCmd);
00954                 // In case no more slots are free, we will disable the new save button
00955                 if (_nextFreeSaveSlot == -1) {
00956                     newSave->setEnabled(false);
00957                 }
00958                 continue;
00959             }
00960 
00961             ContainerWidget *container = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
00962             container->setVisible(false);
00963 
00964             // Command 0 cannot be used, since it won't be send. Thus we will adjust
00965             // command number here, if required. This is only the case for load mode
00966             // since for save mode, the first button used is index 1 anyway.
00967             uint buttonCmd = curLine * _columns + curColumn;
00968             if (!_saveMode) {
00969                 buttonCmd += 1;
00970             }
00971 
00972             PicButtonWidget *button = new PicButtonWidget(container, dstX, dstY, buttonWidth, buttonHeight, 0, buttonCmd);
00973             dstY += buttonHeight;
00974 
00975             StaticTextWidget *description = new StaticTextWidget(container, dstX, dstY, buttonWidth, kLineHeight, Common::String(), Graphics::kTextAlignLeft);
00976 
00977             _buttons.push_back(SlotButton(container, button, description));
00978         }
00979     }
00980 
00981     if (!_target.empty())
00982         updateSaves();
00983 }
00984 
00985 void SaveLoadChooserGrid::close() {
00986     // Save the current page.
00987     const int result = getResult();
00988     if (result >= 0 && result != _nextFreeSaveSlot) {
00989         // If the user selected a slot we use that one. We ignore new slots
00990         // here, since otherwise the dialog would reset to page 0 when the
00991         // user cancels the savename dialog.
00992         ConfMan.setInt("gui_saveload_last_pos", result);
00993     } else {
00994         // Otherwise save the first entry on the current page.
00995         // This is less precise than the solution above, since the number of
00996         // entries shown differs between save and load version of the dialog,
00997         // thus it might wrap to a different page than expected.
00998         // Similar things happen on resolution changes.
00999         // TODO: Should we ignore this here? Is the user likely to be
01000         // interested in having this page restored when he canceled?
01001         ConfMan.setInt("gui_saveload_last_pos", !_saveList.empty() ? _saveList[_curPage * _entriesPerPage].getSaveSlot() : 0);
01002     }
01003 
01004     SaveLoadChooserDialog::close();
01005     hideButtons();
01006 }
01007 
01008 int SaveLoadChooserGrid::runIntern() {
01009     int slot;
01010     do {
01011         const SaveLoadChooserType currentType = getType();
01012         const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
01013 
01014         // Catch resolution changes when the save name dialog was open.
01015         if (currentType != requestedType) {
01016             setResult(kSwitchSaveLoadDialog);
01017             return kSwitchSaveLoadDialog;
01018         }
01019 
01020         slot = runModal();
01021     } while (_saveMode && slot >= 0 && !selectDescription());
01022 
01023     // Special case for new save games. We need to handle this here, since
01024     // we cannot handle it in close() without problems.
01025     if (slot == _nextFreeSaveSlot) {
01026         ConfMan.setInt("gui_saveload_last_pos", slot);
01027     }
01028 
01029     return slot;
01030 }
01031 
01032 bool SaveLoadChooserGrid::selectDescription() {
01033     _savenameDialog.setDescription(_resultString);
01034     _savenameDialog.setTargetSlot(getResult());
01035     if (_savenameDialog.runModal() == 0) {
01036         _resultString = _savenameDialog.getDescription();
01037         return true;
01038     } else {
01039         return false;
01040     }
01041 }
01042 
01043 void SaveLoadChooserGrid::destroyButtons() {
01044     if (_newSaveContainer) {
01045         removeWidget(_newSaveContainer);
01046         delete _newSaveContainer;
01047         _newSaveContainer = 0;
01048     }
01049 
01050     for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
01051         removeWidget(i->container);
01052         delete i->container;
01053     }
01054 
01055     _buttons.clear();
01056 }
01057 
01058 void SaveLoadChooserGrid::hideButtons() {
01059     for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
01060         i->button->setGfx(0);
01061         i->setVisible(false);
01062     }
01063 }
01064 
01065 void SaveLoadChooserGrid::updateSaves() {
01066     hideButtons();
01067 
01068     for (uint i = _curPage * _entriesPerPage, curNum = 0; i < _saveList.size() && curNum < _entriesPerPage; ++i, ++curNum) {
01069         const uint saveSlot = _saveList[i].getSaveSlot();
01070 
01071         SaveStateDescriptor desc =  (_saveList[i].getLocked() ? _saveList[i] : _metaEngine->querySaveMetaInfos(_target.c_str(), saveSlot));
01072         SlotButton &curButton = _buttons[curNum];
01073         curButton.setVisible(true);
01074         const Graphics::Surface *thumbnail = desc.getThumbnail();
01075         if (thumbnail) {
01076             curButton.button->setGfx(desc.getThumbnail());
01077         } else {
01078             curButton.button->setGfx(kThumbnailWidth, kThumbnailHeight2, 0, 0, 0);
01079         }
01080         curButton.description->setLabel(Common::String::format("%d. %s", saveSlot, desc.getDescription().c_str()));
01081 
01082         Common::String tooltip(_("Name: "));
01083         tooltip += desc.getDescription();
01084 
01085         if (_saveDateSupport) {
01086             const Common::String &saveDate = desc.getSaveDate();
01087             if (!saveDate.empty()) {
01088                 tooltip += "\n";
01089                 tooltip +=  _("Date: ") + saveDate;
01090             }
01091 
01092             const Common::String &saveTime = desc.getSaveTime();
01093             if (!saveTime.empty()) {
01094                 tooltip += "\n";
01095                 tooltip += _("Time: ") + saveTime;
01096             }
01097         }
01098 
01099         if (_playTimeSupport) {
01100             const Common::String &playTime = desc.getPlayTime();
01101             if (!playTime.empty()) {
01102                 tooltip += "\n";
01103                 tooltip += _("Playtime: ") + playTime;
01104             }
01105         }
01106 
01107         curButton.button->setTooltip(tooltip);
01108 
01109         // In save mode we disable the button, when it's write protected.
01110         // TODO: Maybe we should not display it at all then?
01111         if (_saveMode && desc.getWriteProtectedFlag()) {
01112             curButton.button->setEnabled(false);
01113         } else {
01114             curButton.button->setEnabled(true);
01115         }
01116 
01117         //that would make it look "disabled" if slot is locked
01118         curButton.button->setEnabled(!desc.getLocked());
01119         curButton.description->setEnabled(!desc.getLocked());
01120     }
01121 
01122     const uint numPages = (_entriesPerPage != 0 && !_saveList.empty()) ? ((_saveList.size() + _entriesPerPage - 1) / _entriesPerPage) : 1;
01123     _pageDisplay->setLabel(Common::String::format("%u/%u", _curPage + 1, numPages));
01124 
01125     if (_curPage > 0)
01126         _prevButton->setEnabled(true);
01127     else
01128         _prevButton->setEnabled(false);
01129 
01130     if ((_curPage + 1) * _entriesPerPage < _saveList.size())
01131         _nextButton->setEnabled(true);
01132     else
01133         _nextButton->setEnabled(false);
01134 }
01135 
01136 SavenameDialog::SavenameDialog()
01137     : Dialog("SavenameDialog") {
01138     _title = new StaticTextWidget(this, "SavenameDialog.DescriptionText", Common::String());
01139 
01140     new ButtonWidget(this, "SavenameDialog.Cancel", _("Cancel"), 0, kCloseCmd);
01141     new ButtonWidget(this, "SavenameDialog.Ok", _("OK"), 0, kOKCmd);
01142 
01143     _description = new EditTextWidget(this, "SavenameDialog.Description", Common::String(), 0, 0, kOKCmd);
01144 
01145     _targetSlot = 0;
01146 }
01147 
01148 void SavenameDialog::setDescription(const Common::String &desc) {
01149     _description->setEditString(desc);
01150 }
01151 
01152 const Common::String &SavenameDialog::getDescription() {
01153     return _description->getEditString();
01154 }
01155 
01156 void SavenameDialog::open() {
01157     Dialog::open();
01158     setResult(-1);
01159 
01160     _title->setLabel(Common::String::format(_("Enter a description for slot %d:"), _targetSlot));
01161 }
01162 
01163 void SavenameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
01164     switch (cmd) {
01165     case kOKCmd:
01166         setResult(0);
01167         close();
01168         break;
01169 
01170     default:
01171         Dialog::handleCommand(sender, cmd, data);
01172     }
01173 }
01174 
01175 #endif // !DISABLE_SAVELOADCHOOSER_GRID
01176 
01177 } // End of namespace GUI


Generated on Sat Feb 16 2019 05:01:03 for ResidualVM by doxygen 1.7.1
curved edge   curved edge