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

launcher.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 "base/version.h"
00024 
00025 #include "common/config-manager.h"
00026 #include "common/events.h"
00027 #include "common/fs.h"
00028 #include "common/gui_options.h"
00029 #include "common/util.h"
00030 #include "common/system.h"
00031 #include "common/translation.h"
00032 
00033 #include "gui/about.h"
00034 #include "gui/browser.h"
00035 #include "gui/chooser.h"
00036 #include "gui/editgamedialog.h"
00037 #include "gui/launcher.h"
00038 #include "gui/massadd.h"
00039 #include "gui/message.h"
00040 #include "gui/gui-manager.h"
00041 #include "gui/options.h"
00042 #ifdef ENABLE_EVENTRECORDER
00043 #include "gui/onscreendialog.h"
00044 #include "gui/recorderdialog.h"
00045 #include "gui/EventRecorder.h"
00046 #endif
00047 #include "gui/saveload.h"
00048 #include "gui/unknown-game-dialog.h"
00049 #include "gui/widgets/edittext.h"
00050 #include "gui/widgets/list.h"
00051 #include "gui/widgets/tab.h"
00052 #include "gui/widgets/popup.h"
00053 #include "gui/ThemeEval.h"
00054 
00055 #include "graphics/cursorman.h"
00056 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00057 #include "backends/cloud/cloudmanager.h"
00058 #endif
00059 
00060 using Common::ConfigManager;
00061 
00062 namespace GUI {
00063 
00064 enum {
00065     kStartCmd = 'STRT',
00066     kAboutCmd = 'ABOU',
00067     kOptionsCmd = 'OPTN',
00068     kAddGameCmd = 'ADDG',
00069     kEditGameCmd = 'EDTG',
00070     kRemoveGameCmd = 'REMG',
00071     kLoadGameCmd = 'LOAD',
00072     kQuitCmd = 'QUIT',
00073     kSearchCmd = 'SRCH',
00074     kListSearchCmd = 'LSSR',
00075     kSearchClearCmd = 'SRCL',
00076 
00077     kCmdGlobalGraphicsOverride = 'OGFX',
00078     kCmdGlobalAudioOverride = 'OSFX',
00079     kCmdGlobalMIDIOverride = 'OMID',
00080     kCmdGlobalMT32Override = 'OM32',
00081     kCmdGlobalVolumeOverride = 'OVOL',
00082 
00083     kCmdChooseSoundFontCmd = 'chsf',
00084 
00085     kCmdExtraBrowser = 'PEXT',
00086     kCmdExtraPathClear = 'PEXC',
00087     kCmdGameBrowser = 'PGME',
00088     kCmdSaveBrowser = 'PSAV',
00089     kCmdSavePathClear = 'PSAC'
00090 };
00091 
00092 #pragma mark -
00093 
00094 LauncherDialog::LauncherDialog()
00095     : Dialog(0, 0, 640, 480) { // ResidualVM specific
00096     _backgroundType = GUI::ThemeEngine::kDialogBackgroundMain;
00097     const int screenW = g_system->getOverlayWidth();
00098     const int screenH = g_system->getOverlayHeight();
00099 
00100     _w = screenW;
00101     _h = screenH;
00102 
00103     build();
00104 
00105     GUI::GuiManager::instance()._launched = true;
00106 }
00107 
00108 void LauncherDialog::selectTarget(const String &target) {
00109     if (!target.empty()) {
00110         int itemToSelect = 0;
00111         StringArray::const_iterator iter;
00112         for (iter = _domains.begin(); iter != _domains.end(); ++iter, ++itemToSelect) {
00113             if (target == *iter) {
00114                 _list->setSelected(itemToSelect);
00115                 break;
00116             }
00117         }
00118     }
00119 }
00120 
00121 LauncherDialog::~LauncherDialog() {
00122     delete _browser;
00123     delete _loadDialog;
00124 }
00125 
00126 void LauncherDialog::build() {
00127 #ifndef DISABLE_FANCY_THEMES
00128     _logo = 0;
00129     if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
00130         _logo = new GraphicsWidget(this, "Launcher.Logo");
00131         _logo->useThemeTransparency(true);
00132         _logo->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageLogo));
00133 
00134         new StaticTextWidget(this, "Launcher.Version", gScummVMVersionDate);
00135     } else
00136         new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion);
00137 #else
00138     // Show ScummVM version
00139     new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion);
00140 #endif
00141 
00142     new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), _("Quit ResidualVM"), kQuitCmd);
00143     new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), _("About ResidualVM"), kAboutCmd);
00144     new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), _("Change global ResidualVM options"), kOptionsCmd);
00145     _startButton =
00146         new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), _("Start selected game"), kStartCmd);
00147 
00148     _loadButton =
00149         new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load saved game for selected game"), kLoadGameCmd);
00150 
00151     // Above the lowest button rows: two more buttons (directly below the list box)
00152     if (g_system->getOverlayWidth() > 320) {
00153         _addButton =
00154             new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd);
00155         _editButton =
00156             new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), _("Change game options"), kEditGameCmd);
00157         _removeButton =
00158             new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
00159     } else {
00160         _addButton =
00161         new ButtonWidget(this, "Launcher.AddGameButton", _c("~A~dd Game...", "lowres"), _("Hold Shift for Mass Add"), kAddGameCmd);
00162         _editButton =
00163         new ButtonWidget(this, "Launcher.EditGameButton", _c("~E~dit Game...", "lowres"), _("Change game options"), kEditGameCmd);
00164         _removeButton =
00165         new ButtonWidget(this, "Launcher.RemoveGameButton", _c("~R~emove Game", "lowres"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
00166     }
00167 
00168     // Search box
00169     _searchDesc = 0;
00170 #ifndef DISABLE_FANCY_THEMES
00171     _searchPic = 0;
00172     if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
00173         _searchPic = new GraphicsWidget(this, "Launcher.SearchPic", _("Search in game list"));
00174         _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch));
00175     } else
00176 #endif
00177         _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
00178 
00179     _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, 0, kSearchCmd);
00180     _searchClearButton = addClearButton(this, "Launcher.SearchClearButton", kSearchClearCmd);
00181 
00182     // Add list with game titles
00183     _list = new ListWidget(this, "Launcher.GameList", 0, kListSearchCmd);
00184     _list->setEditable(false);
00185     _list->setNumberingMode(kListNumberingOff);
00186 
00187     // Populate the list
00188     updateListing();
00189 
00190     // Restore last selection
00191     String last(ConfMan.get("lastselectedgame", ConfigManager::kApplicationDomain));
00192     selectTarget(last);
00193 
00194     // En-/disable the buttons depending on the list selection
00195     updateButtons();
00196 
00197     // Create file browser dialog
00198     _browser = new BrowserDialog(_("Select directory with game data"), true);
00199 
00200     // Create Load dialog
00201     _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"), false);
00202 }
00203 
00204 void LauncherDialog::clean() {
00205     while (_firstWidget) {
00206         Widget* w = _firstWidget;
00207         removeWidget(w);
00208         // This is called from rebuild() which may result from handleCommand being called by
00209         // a child widget sendCommand call. In such a case sendCommand is still being executed
00210         // so we should not delete yet the child widget. Thus delay the deletion.
00211         g_gui.addToTrash(w, this);
00212     }
00213     delete _browser;
00214     delete _loadDialog;
00215 }
00216 
00217 void LauncherDialog::rebuild() {
00218     clean();
00219     build();
00220     reflowLayout();
00221     setDefaultFocusedWidget();
00222 }
00223 
00224 void LauncherDialog::open() {
00225     // Clear the active domain, in case we return to the dialog from a
00226     // failure to launch a game. Otherwise, pressing ESC will attempt to
00227     // re-launch the same game again.
00228     ConfMan.setActiveDomain("");
00229 
00230     CursorMan.popAllCursors();
00231     Dialog::open();
00232 
00233     updateButtons();
00234 }
00235 
00236 void LauncherDialog::close() {
00237     // Save last selection
00238     const int sel = _list->getSelected();
00239     if (sel >= 0)
00240         ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplicationDomain);
00241     else
00242         ConfMan.removeKey("lastselectedgame", ConfigManager::kApplicationDomain);
00243 
00244     ConfMan.flushToDisk();
00245     Dialog::close();
00246 }
00247 
00248 void LauncherDialog::updateListing() {
00249     StringArray l;
00250     ListWidget::ColorList colors;
00251     ThemeEngine::FontColor color;
00252 
00253     // Retrieve a list of all games defined in the config file
00254     _domains.clear();
00255     const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
00256     ConfigManager::DomainMap::const_iterator iter;
00257     for (iter = domains.begin(); iter != domains.end(); ++iter) {
00258 #ifdef __DS__
00259         // DS port uses an extra section called 'ds'.  This prevents the section from being
00260         // detected as a game.
00261         if (iter->_key == "ds") {
00262             continue;
00263         }
00264 #endif
00265 
00266         String gameid(iter->_value.getVal("gameid"));
00267         String description(iter->_value.getVal("description"));
00268         Common::FSNode path(iter->_value.getVal("path"));
00269 
00270         if (gameid.empty())
00271             gameid = iter->_key;
00272         if (description.empty()) {
00273             PlainGameDescriptor g = EngineMan.findGame(gameid);
00274             if (g.description)
00275                 description = g.description;
00276         }
00277 
00278         if (description.empty()) {
00279             description = Common::String::format("Unknown (target %s, gameid %s)", iter->_key.c_str(), gameid.c_str());
00280         }
00281 
00282         if (!gameid.empty() && !description.empty()) {
00283             // Insert the game into the launcher list
00284             int pos = 0, size = l.size();
00285 
00286             while (pos < size && (scumm_stricmp(description.c_str(), l[pos].c_str()) > 0))
00287                 pos++;
00288 
00289             color = ThemeEngine::kFontColorNormal;
00290             if (!path.isDirectory()) {
00291                 color = ThemeEngine::kFontColorAlternate;
00292                 // If more conditions which grey out entries are added we should consider
00293                 // enabling this so that it is easy to spot why a certain game entry cannot
00294                 // be started.
00295 
00296                 // description += Common::String::format(" (%s)", _("Not found"));
00297             }
00298 
00299             l.insert_at(pos, description);
00300             colors.insert_at(pos, color);
00301             _domains.insert_at(pos, iter->_key);
00302         }
00303     }
00304 
00305     const int oldSel = _list->getSelected();
00306     _list->setList(l, &colors);
00307     if (oldSel < (int)l.size())
00308         _list->setSelected(oldSel); // Restore the old selection
00309     else if (oldSel != -1)
00310         // Select the last entry if the list has been reduced
00311         _list->setSelected(_list->getList().size() - 1);
00312     updateButtons();
00313 
00314     // Update the filter settings, those are lost when "setList"
00315     // is called.
00316     _list->setFilter(_searchWidget->getEditString());
00317 }
00318 
00319 void LauncherDialog::addGame() {
00320 
00321 #ifndef DISABLE_MASS_ADD
00322     const bool massAdd = checkModifier(Common::KBD_SHIFT);
00323 
00324     if (massAdd) {
00325         MessageDialog alert(_("Do you really want to run the mass game detector? "
00326                               "This could potentially add a huge number of games."), _("Yes"), _("No"));
00327         if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
00328             MassAddDialog massAddDlg(_browser->getResult());
00329 
00330             massAddDlg.runModal();
00331 
00332             // Update the ListWidget and force a redraw
00333 
00334             // If new target(s) were added, update the ListWidget and move
00335             // the selection to to first newly detected game.
00336             Common::String newTarget = massAddDlg.getFirstAddedTarget();
00337             if (!newTarget.empty()) {
00338                 updateListing();
00339                 selectTarget(newTarget);
00340             }
00341 
00342             g_gui.scheduleTopDialogRedraw();
00343         }
00344 
00345         // We need to update the buttons here, so "Mass add" will revert to "Add game"
00346         // without any additional event.
00347         updateButtons();
00348         return;
00349     }
00350 #endif
00351 
00352     // Allow user to add a new game to the list.
00353     // 1) show a dir selection dialog which lets the user pick the directory
00354     //    the game data resides in.
00355     // 2) try to auto detect which game is in the directory, if we cannot
00356     //    determine it uniquely present a list of candidates to the user
00357     //    to pick from
00358     // 3) Display the 'Edit' dialog for that item, letting the user specify
00359     //    an alternate description (to distinguish multiple versions of the
00360     //    game, e.g. 'Monkey German' and 'Monkey English') and set default
00361     //    options for that game
00362     // 4) If no game is found in the specified directory, return to the
00363     //    dialog.
00364 
00365     bool looping;
00366     do {
00367         looping = false;
00368 
00369         if (_browser->runModal() > 0) {
00370             // User made his choice...
00371 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
00372             String selectedDirectory = _browser->getResult().getPath();
00373             String bannedDirectory = CloudMan.getDownloadLocalDirectory();
00374             if (selectedDirectory.size() && selectedDirectory.lastChar() != '/' && selectedDirectory.lastChar() != '\\')
00375                 selectedDirectory += '/';
00376             if (bannedDirectory.size() && bannedDirectory.lastChar() != '/' && bannedDirectory.lastChar() != '\\') {
00377                 if (selectedDirectory.size()) {
00378                     bannedDirectory += selectedDirectory.lastChar();
00379                 } else {
00380                     bannedDirectory += '/';
00381                 }
00382             }
00383             if (selectedDirectory.equalsIgnoreCase(bannedDirectory)) {
00384                 MessageDialog alert(_("This directory cannot be used yet, it is being downloaded into!"));
00385                 alert.runModal();
00386                 return;
00387             }
00388 #endif
00389             looping = !doGameDetection(_browser->getResult().getPath());
00390         }
00391     } while (looping);
00392 }
00393 
00394 void LauncherDialog::removeGame(int item) {
00395     MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No"));
00396 
00397     if (alert.runModal() == GUI::kMessageOK) {
00398         // Remove the currently selected game from the list
00399         assert(item >= 0);
00400         ConfMan.removeGameDomain(_domains[item]);
00401 
00402         // Write config to disk
00403         ConfMan.flushToDisk();
00404 
00405         // Update the ListWidget and force a redraw
00406         updateListing();
00407         g_gui.scheduleTopDialogRedraw();
00408     }
00409 }
00410 
00411 void LauncherDialog::editGame(int item) {
00412     // Set game specific options. Most of these should be "optional", i.e. by
00413     // default set nothing and use the global ScummVM settings. E.g. the user
00414     // can set here an optional alternate music volume, or for specific games
00415     // a different music driver etc.
00416     // This is useful because e.g. MonkeyVGA needs AdLib music to have decent
00417     // music support etc.
00418     assert(item >= 0);
00419     String gameId(ConfMan.get("gameid", _domains[item]));
00420     if (gameId.empty())
00421         gameId = _domains[item];
00422 
00423     EditGameDialog editDialog(_domains[item]);
00424     if (editDialog.runModal() > 0) {
00425         // User pressed OK, so make changes permanent
00426 
00427         // Write config to disk
00428         ConfMan.flushToDisk();
00429 
00430         // Update the ListWidget, reselect the edited game and force a redraw
00431         updateListing();
00432         selectTarget(editDialog.getDomain());
00433         g_gui.scheduleTopDialogRedraw();
00434     }
00435 }
00436 
00437 void LauncherDialog::loadGameButtonPressed(int item) {
00438 #ifdef ENABLE_EVENTRECORDER
00439     const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
00440     if (shiftPressed) {
00441         recordGame(item);
00442     } else {
00443         loadGame(item);
00444     }
00445     updateButtons();
00446 #else
00447     loadGame(item);
00448 #endif
00449 }
00450 
00451 #ifdef ENABLE_EVENTRECORDER
00452 void LauncherDialog::recordGame(int item) {
00453     RecorderDialog recorderDialog;
00454     MessageDialog alert(_("Do you want to load saved game?"),
00455         _("Yes"), _("No"));
00456     switch(recorderDialog.runModal(_domains[item])) {
00457     case RecorderDialog::kRecordDialogClose:
00458         break;
00459     case RecorderDialog::kRecordDialogPlayback:
00460         ConfMan.setActiveDomain(_domains[item]);
00461         close();
00462         ConfMan.set("record_mode", "playback", ConfigManager::kTransientDomain);
00463         ConfMan.set("record_file_name", recorderDialog.getFileName(), ConfigManager::kTransientDomain);
00464         break;
00465     case RecorderDialog::kRecordDialogRecord:
00466         ConfMan.setActiveDomain(_domains[item]);
00467         if (alert.runModal() == GUI::kMessageOK) {
00468             loadGame(item);
00469         }
00470         close();
00471         g_eventRec.setAuthor(recorderDialog._author);
00472         g_eventRec.setName(recorderDialog._name);
00473         g_eventRec.setNotes(recorderDialog._notes);
00474         ConfMan.set("record_mode", "record", ConfigManager::kTransientDomain);
00475         break;
00476     }
00477 }
00478 #endif
00479 
00480 void LauncherDialog::loadGame(int item) {
00481     String gameId = ConfMan.get("gameid", _domains[item]);
00482     if (gameId.empty())
00483         gameId = _domains[item];
00484 
00485     const Plugin *plugin = nullptr;
00486 
00487     EngineMan.findGame(gameId, &plugin);
00488 
00489     String target = _domains[item];
00490     target.toLowercase();
00491 
00492     if (plugin) {
00493         const MetaEngine &metaEngine = plugin->get<MetaEngine>();
00494         if (metaEngine.hasFeature(MetaEngine::kSupportsListSaves) &&
00495             metaEngine.hasFeature(MetaEngine::kSupportsLoadingDuringStartup)) {
00496             int slot = _loadDialog->runModalWithPluginAndTarget(plugin, target);
00497             if (slot >= 0) {
00498                 ConfMan.setActiveDomain(_domains[item]);
00499                 ConfMan.setInt("save_slot", slot, Common::ConfigManager::kTransientDomain);
00500                 close();
00501             }
00502         } else {
00503             MessageDialog dialog
00504                 (_("This game does not support loading games from the launcher."), _("OK"));
00505             dialog.runModal();
00506         }
00507     } else {
00508         MessageDialog dialog(_("ResidualVM could not find any engine capable of running the selected game!"), _("OK"));
00509         dialog.runModal();
00510     }
00511 }
00512 
00513 void LauncherDialog::handleKeyDown(Common::KeyState state) {
00514     if (state.keycode == Common::KEYCODE_TAB) {
00515         // Toggle between the game list and the quick search field.
00516         if (getFocusWidget() == _searchWidget) {
00517             setFocusWidget(_list);
00518         } else if (getFocusWidget() == _list) {
00519             setFocusWidget(_searchWidget);
00520         }
00521     }
00522     Dialog::handleKeyDown(state);
00523     updateButtons();
00524 }
00525 
00526 void LauncherDialog::handleKeyUp(Common::KeyState state) {
00527     Dialog::handleKeyUp(state);
00528     updateButtons();
00529 }
00530 
00531 bool LauncherDialog::doGameDetection(const Common::String &path) {
00532     // Allow user to add a new game to the list.
00533     // 2) try to auto detect which game is in the directory, if we cannot
00534     //    determine it uniquely present a list of candidates to the user
00535     //    to pick from
00536     // 3) Display the 'Edit' dialog for that item, letting the user specify
00537     //    an alternate description (to distinguish multiple versions of the
00538     //    game, e.g. 'Monkey German' and 'Monkey English') and set default
00539     //    options for that game
00540     // 4) If no game is found in the specified directory, return to the
00541     //    dialog.
00542 
00543     // User made his choice...
00544     Common::FSNode dir(path);
00545     Common::FSList files;
00546     if (!dir.getChildren(files, Common::FSNode::kListAll)) {
00547         MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
00548         alert.runModal();
00549         return true;
00550     }
00551 
00552     // ...so let's determine a list of candidates, games that
00553     // could be contained in the specified directory.
00554     DetectionResults detectionResults = EngineMan.detectGames(files);
00555 
00556     if (detectionResults.foundUnknownGames()) {
00557         Common::String report = detectionResults.generateUnknownGameReport(false, 80);
00558         g_system->logMessage(LogMessageType::kInfo, report.c_str());
00559 
00560         UnknownGameDialog dialog(detectionResults);
00561         dialog.runModal();
00562     }
00563 
00564     Common::Array<DetectedGame> candidates = detectionResults.listRecognizedGames();
00565 
00566     int idx;
00567     if (candidates.empty()) {
00568         // No game was found in the specified directory
00569         MessageDialog alert(_("ScummVM could not find any game in the specified directory!"));
00570         alert.runModal();
00571         idx = -1;
00572         return false;
00573     } else if (candidates.size() == 1) {
00574         // Exact match
00575         idx = 0;
00576     } else {
00577         // Display the candidates to the user and let her/him pick one
00578         StringArray list;
00579         for (idx = 0; idx < (int)candidates.size(); idx++)
00580             list.push_back(candidates[idx].description);
00581 
00582         ChooserDialog dialog(_("Pick the game:"));
00583         dialog.setList(list);
00584         idx = dialog.runModal();
00585     }
00586     if (0 <= idx && idx < (int)candidates.size()) {
00587         const DetectedGame &result = candidates[idx];
00588 
00589         Common::String domain = EngineMan.createTargetForGame(result);
00590 
00591         // Display edit dialog for the new entry
00592         EditGameDialog editDialog(domain);
00593         if (editDialog.runModal() > 0) {
00594             // User pressed OK, so make changes permanent
00595 
00596             // Write config to disk
00597             ConfMan.flushToDisk();
00598 
00599             // Update the ListWidget, select the new item, and force a redraw
00600             updateListing();
00601             selectTarget(editDialog.getDomain());
00602             g_gui.scheduleTopDialogRedraw();
00603         } else {
00604             // User aborted, remove the the new domain again
00605             ConfMan.removeGameDomain(domain);
00606         }
00607 
00608     }
00609 
00610     return true;
00611 }
00612 
00613 void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00614     int item = _list->getSelected();
00615 
00616     switch (cmd) {
00617     case kAddGameCmd:
00618         addGame();
00619         break;
00620     case kRemoveGameCmd:
00621         removeGame(item);
00622         break;
00623     case kEditGameCmd:
00624         editGame(item);
00625         break;
00626     case kLoadGameCmd:
00627         loadGameButtonPressed(item);
00628         break;
00629     case kOptionsCmd: {
00630         GlobalOptionsDialog options(this);
00631         options.runModal();
00632         }
00633         break;
00634     case kAboutCmd: {
00635         AboutDialog about;
00636         about.runModal();
00637         }
00638         break;
00639     case kStartCmd:
00640     case kListItemActivatedCmd:
00641     case kListItemDoubleClickedCmd:
00642         // Start the selected game.
00643         assert(item >= 0);
00644         ConfMan.setActiveDomain(_domains[item]);
00645         close();
00646         break;
00647     case kListItemRemovalRequestCmd:
00648         removeGame(item);
00649         break;
00650     case kListSelectionChangedCmd:
00651         updateButtons();
00652         break;
00653     case kQuitCmd:
00654         ConfMan.setActiveDomain("");
00655         setResult(-1);
00656         close();
00657         break;
00658     case kSearchCmd:
00659         // Update the active search filter.
00660         _list->setFilter(_searchWidget->getEditString());
00661         break;
00662     case kSearchClearCmd:
00663         // Reset the active search filter, thus showing all games again
00664         _searchWidget->setEditString("");
00665         _list->setFilter("");
00666         break;
00667     default:
00668         Dialog::handleCommand(sender, cmd, data);
00669     }
00670 }
00671 
00672 void LauncherDialog::updateButtons() {
00673     bool enable = (_list->getSelected() >= 0);
00674     if (enable != _startButton->isEnabled()) {
00675         _startButton->setEnabled(enable);
00676         _startButton->markAsDirty();
00677     }
00678     if (enable != _editButton->isEnabled()) {
00679         _editButton->setEnabled(enable);
00680         _editButton->markAsDirty();
00681     }
00682     if (enable != _removeButton->isEnabled()) {
00683         _removeButton->setEnabled(enable);
00684         _removeButton->markAsDirty();
00685     }
00686 
00687     int item = _list->getSelected();
00688     bool en = enable;
00689 
00690     if (item >= 0)
00691         en = !(Common::checkGameGUIOption(GUIO_NOLAUNCHLOAD, ConfMan.get("guioptions", _domains[item])));
00692 
00693     if (en != _loadButton->isEnabled()) {
00694         _loadButton->setEnabled(en);
00695         _loadButton->markAsDirty();
00696     }
00697     switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add..."));
00698 #ifdef ENABLE_EVENTRECORDER
00699     switchButtonsText(_loadButton, "~L~oad...", _s("Record..."));
00700 #endif
00701 }
00702 
00703 // Update the label of the button depending on whether shift is pressed or not
00704 void LauncherDialog::switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText) {
00705     const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
00706     const bool lowRes = g_system->getOverlayWidth() <= 320;
00707 
00708     const char *newAddButtonLabel = shiftPressed
00709         ? (lowRes ? _c(shiftedText, "lowres") : _(shiftedText))
00710         : (lowRes ? _c(normalText, "lowres") : _(normalText));
00711 
00712     if (button->getLabel() != newAddButtonLabel)
00713         button->setLabel(newAddButtonLabel);
00714 }
00715 
00716 
00717 
00718 
00719 void LauncherDialog::reflowLayout() {
00720 #ifndef DISABLE_FANCY_THEMES
00721     if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
00722         StaticTextWidget *ver = (StaticTextWidget *)findWidget("Launcher.Version");
00723         if (ver) {
00724             ver->setAlign(g_gui.xmlEval()->getWidgetTextHAlign("Launcher.Version"));
00725             ver->setLabel(gScummVMVersionDate);
00726         }
00727 
00728         if (!_logo)
00729             _logo = new GraphicsWidget(this, "Launcher.Logo");
00730         _logo->useThemeTransparency(true);
00731         _logo->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageLogo));
00732     } else {
00733         StaticTextWidget *ver = (StaticTextWidget *)findWidget("Launcher.Version");
00734         if (ver) {
00735             ver->setAlign(g_gui.xmlEval()->getWidgetTextHAlign("Launcher.Version"));
00736             ver->setLabel(gScummVMFullVersion);
00737         }
00738 
00739         if (_logo) {
00740             removeWidget(_logo);
00741             _logo->setNext(0);
00742             delete _logo;
00743             _logo = 0;
00744         }
00745     }
00746 
00747     if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
00748         if (!_searchPic)
00749             _searchPic = new GraphicsWidget(this, "Launcher.SearchPic");
00750         _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch));
00751 
00752         if (_searchDesc) {
00753             removeWidget(_searchDesc);
00754             _searchDesc->setNext(0);
00755             delete _searchDesc;
00756             _searchDesc = 0;
00757         }
00758     } else {
00759         if (!_searchDesc)
00760             _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
00761 
00762         if (_searchPic) {
00763             removeWidget(_searchPic);
00764             _searchPic->setNext(0);
00765             delete _searchPic;
00766             _searchPic = 0;
00767         }
00768     }
00769 
00770     removeWidget(_searchClearButton);
00771     _searchClearButton->setNext(0);
00772     delete _searchClearButton;
00773     _searchClearButton = addClearButton(this, "Launcher.SearchClearButton", kSearchClearCmd);
00774 #endif
00775 
00776     _w = g_system->getOverlayWidth();
00777     _h = g_system->getOverlayHeight();
00778 
00779     Dialog::reflowLayout();
00780 }
00781 
00782 bool LauncherDialog::checkModifier(int checkedModifier) {
00783     int modifiers = g_system->getEventManager()->getModifierState();
00784     return (modifiers & checkedModifier) != 0;
00785 }
00786 
00787 } // End of namespace GUI


Generated on Sat Mar 16 2019 05:01:41 for ResidualVM by doxygen 1.7.1
curved edge   curved edge