scummvm/gui/launcher.cpp
Bastien Bouclet c5b92bcb2e GUI: Better integration for the unknown game dialog when adding games
* The list of candidates now includes unknown variants. When an unknown
variant is selected, the unknown game dialog is shown.
* On the unknown game dialog, users are given the choice to add the game
when that is possible, or to cancel.

The goal of those changes is to make the unknown game dialog less
confusing for users, especially when both known and unknown games
variants are found.
2019-05-12 11:44:51 +03:00

813 lines
24 KiB
C++

/* 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 "base/version.h"
#include "common/config-manager.h"
#include "common/events.h"
#include "common/fs.h"
#include "common/gui_options.h"
#include "common/util.h"
#include "common/system.h"
#include "common/translation.h"
#include "gui/about.h"
#include "gui/browser.h"
#include "gui/chooser.h"
#include "gui/editgamedialog.h"
#include "gui/launcher.h"
#include "gui/massadd.h"
#include "gui/message.h"
#include "gui/gui-manager.h"
#include "gui/options.h"
#ifdef ENABLE_EVENTRECORDER
#include "gui/onscreendialog.h"
#include "gui/recorderdialog.h"
#include "gui/EventRecorder.h"
#endif
#include "gui/saveload.h"
#include "gui/unknown-game-dialog.h"
#include "gui/widgets/edittext.h"
#include "gui/widgets/list.h"
#include "gui/widgets/tab.h"
#include "gui/widgets/popup.h"
#include "gui/ThemeEval.h"
#include "graphics/cursorman.h"
#if defined(USE_CLOUD) && defined(USE_LIBCURL)
#include "backends/cloud/cloudmanager.h"
#endif
using Common::ConfigManager;
namespace GUI {
enum {
kStartCmd = 'STRT',
kAboutCmd = 'ABOU',
kOptionsCmd = 'OPTN',
kAddGameCmd = 'ADDG',
kEditGameCmd = 'EDTG',
kRemoveGameCmd = 'REMG',
kLoadGameCmd = 'LOAD',
kQuitCmd = 'QUIT',
kSearchCmd = 'SRCH',
kListSearchCmd = 'LSSR',
kSearchClearCmd = 'SRCL',
kCmdGlobalGraphicsOverride = 'OGFX',
kCmdGlobalAudioOverride = 'OSFX',
kCmdGlobalMIDIOverride = 'OMID',
kCmdGlobalMT32Override = 'OM32',
kCmdGlobalVolumeOverride = 'OVOL',
kCmdChooseSoundFontCmd = 'chsf',
kCmdExtraBrowser = 'PEXT',
kCmdExtraPathClear = 'PEXC',
kCmdGameBrowser = 'PGME',
kCmdSaveBrowser = 'PSAV',
kCmdSavePathClear = 'PSAC'
};
#pragma mark -
LauncherDialog::LauncherDialog()
: Dialog(0, 0, 320, 200) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundMain;
const int screenW = g_system->getOverlayWidth();
const int screenH = g_system->getOverlayHeight();
_w = screenW;
_h = screenH;
build();
GUI::GuiManager::instance()._launched = true;
}
void LauncherDialog::selectTarget(const String &target) {
if (!target.empty()) {
int itemToSelect = 0;
StringArray::const_iterator iter;
for (iter = _domains.begin(); iter != _domains.end(); ++iter, ++itemToSelect) {
if (target == *iter) {
_list->setSelected(itemToSelect);
break;
}
}
}
}
LauncherDialog::~LauncherDialog() {
delete _browser;
delete _loadDialog;
}
void LauncherDialog::build() {
#ifndef DISABLE_FANCY_THEMES
_logo = 0;
if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
_logo = new GraphicsWidget(this, "Launcher.Logo");
_logo->useThemeTransparency(true);
_logo->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageLogo));
new StaticTextWidget(this, "Launcher.Version", gScummVMVersionDate);
} else
new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion);
#else
// Show ScummVM version
new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion);
#endif
new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), _("Quit ScummVM"), kQuitCmd);
new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), _("About ScummVM"), kAboutCmd);
new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), _("Change global ScummVM options"), kOptionsCmd);
_startButton =
new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), _("Start selected game"), kStartCmd);
_loadButton =
new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load saved game for selected game"), kLoadGameCmd);
// Above the lowest button rows: two more buttons (directly below the list box)
if (g_system->getOverlayWidth() > 320) {
_addButton =
new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd);
_editButton =
new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), _("Change game options"), kEditGameCmd);
_removeButton =
new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
} else {
_addButton =
new ButtonWidget(this, "Launcher.AddGameButton", _c("~A~dd Game...", "lowres"), _("Hold Shift for Mass Add"), kAddGameCmd);
_editButton =
new ButtonWidget(this, "Launcher.EditGameButton", _c("~E~dit Game...", "lowres"), _("Change game options"), kEditGameCmd);
_removeButton =
new ButtonWidget(this, "Launcher.RemoveGameButton", _c("~R~emove Game", "lowres"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd);
}
// Search box
_searchDesc = 0;
#ifndef DISABLE_FANCY_THEMES
_searchPic = 0;
if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
_searchPic = new GraphicsWidget(this, "Launcher.SearchPic", _("Search in game list"));
_searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch));
} else
#endif
_searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
_searchWidget = new EditTextWidget(this, "Launcher.Search", _search, 0, kSearchCmd);
_searchClearButton = addClearButton(this, "Launcher.SearchClearButton", kSearchClearCmd);
// Add list with game titles
_list = new ListWidget(this, "Launcher.GameList", 0, kListSearchCmd);
_list->setEditable(false);
_list->setNumberingMode(kListNumberingOff);
// Populate the list
updateListing();
// Restore last selection
String last(ConfMan.get("lastselectedgame", ConfigManager::kApplicationDomain));
selectTarget(last);
// En-/disable the buttons depending on the list selection
updateButtons();
// Create file browser dialog
_browser = new BrowserDialog(_("Select directory with game data"), true);
// Create Load dialog
_loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"), false);
}
void LauncherDialog::clean() {
while (_firstWidget) {
Widget* w = _firstWidget;
removeWidget(w);
// This is called from rebuild() which may result from handleCommand being called by
// a child widget sendCommand call. In such a case sendCommand is still being executed
// so we should not delete yet the child widget. Thus delay the deletion.
g_gui.addToTrash(w, this);
}
delete _browser;
delete _loadDialog;
}
void LauncherDialog::rebuild() {
clean();
build();
reflowLayout();
setDefaultFocusedWidget();
}
void LauncherDialog::open() {
// Clear the active domain, in case we return to the dialog from a
// failure to launch a game. Otherwise, pressing ESC will attempt to
// re-launch the same game again.
ConfMan.setActiveDomain("");
CursorMan.popAllCursors();
Dialog::open();
updateButtons();
}
void LauncherDialog::close() {
// Save last selection
const int sel = _list->getSelected();
if (sel >= 0)
ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplicationDomain);
else
ConfMan.removeKey("lastselectedgame", ConfigManager::kApplicationDomain);
ConfMan.flushToDisk();
Dialog::close();
}
void LauncherDialog::updateListing() {
StringArray l;
ListWidget::ColorList colors;
ThemeEngine::FontColor color;
// Retrieve a list of all games defined in the config file
_domains.clear();
const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
ConfigManager::DomainMap::const_iterator iter;
for (iter = domains.begin(); iter != domains.end(); ++iter) {
#ifdef __DS__
// DS port uses an extra section called 'ds'. This prevents the section from being
// detected as a game.
if (iter->_key == "ds") {
continue;
}
#endif
String gameid(iter->_value.getVal("gameid"));
String description(iter->_value.getVal("description"));
Common::FSNode path(iter->_value.getVal("path"));
if (gameid.empty())
gameid = iter->_key;
if (description.empty()) {
PlainGameDescriptor g = EngineMan.findGame(gameid);
if (g.description)
description = g.description;
}
if (description.empty()) {
description = Common::String::format("Unknown (target %s, gameid %s)", iter->_key.c_str(), gameid.c_str());
}
if (!gameid.empty() && !description.empty()) {
// Insert the game into the launcher list
int pos = 0, size = l.size();
while (pos < size && (scumm_stricmp(description.c_str(), l[pos].c_str()) > 0))
pos++;
color = ThemeEngine::kFontColorNormal;
if (!path.isDirectory()) {
color = ThemeEngine::kFontColorAlternate;
// If more conditions which grey out entries are added we should consider
// enabling this so that it is easy to spot why a certain game entry cannot
// be started.
// description += Common::String::format(" (%s)", _("Not found"));
}
l.insert_at(pos, description);
colors.insert_at(pos, color);
_domains.insert_at(pos, iter->_key);
}
}
const int oldSel = _list->getSelected();
_list->setList(l, &colors);
if (oldSel < (int)l.size())
_list->setSelected(oldSel); // Restore the old selection
else if (oldSel != -1)
// Select the last entry if the list has been reduced
_list->setSelected(_list->getList().size() - 1);
updateButtons();
// Update the filter settings, those are lost when "setList"
// is called.
_list->setFilter(_searchWidget->getEditString());
}
void LauncherDialog::addGame() {
#ifndef DISABLE_MASS_ADD
const bool massAdd = checkModifier(Common::KBD_SHIFT);
if (massAdd) {
MessageDialog alert(_("Do you really want to run the mass game detector? "
"This could potentially add a huge number of games."), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
MassAddDialog massAddDlg(_browser->getResult());
massAddDlg.runModal();
// Update the ListWidget and force a redraw
// If new target(s) were added, update the ListWidget and move
// the selection to to first newly detected game.
Common::String newTarget = massAddDlg.getFirstAddedTarget();
if (!newTarget.empty()) {
updateListing();
selectTarget(newTarget);
}
g_gui.scheduleTopDialogRedraw();
}
// We need to update the buttons here, so "Mass add" will revert to "Add game"
// without any additional event.
updateButtons();
return;
}
#endif
// Allow user to add a new game to the list.
// 1) show a dir selection dialog which lets the user pick the directory
// the game data resides in.
// 2) try to auto detect which game is in the directory, if we cannot
// determine it uniquely present a list of candidates to the user
// to pick from
// 3) Display the 'Edit' dialog for that item, letting the user specify
// an alternate description (to distinguish multiple versions of the
// game, e.g. 'Monkey German' and 'Monkey English') and set default
// options for that game
// 4) If no game is found in the specified directory, return to the
// dialog.
bool looping;
do {
looping = false;
if (_browser->runModal() > 0) {
// User made his choice...
#if defined(USE_CLOUD) && defined(USE_LIBCURL)
String selectedDirectory = _browser->getResult().getPath();
String bannedDirectory = CloudMan.getDownloadLocalDirectory();
if (selectedDirectory.size() && selectedDirectory.lastChar() != '/' && selectedDirectory.lastChar() != '\\')
selectedDirectory += '/';
if (bannedDirectory.size() && bannedDirectory.lastChar() != '/' && bannedDirectory.lastChar() != '\\') {
if (selectedDirectory.size()) {
bannedDirectory += selectedDirectory.lastChar();
} else {
bannedDirectory += '/';
}
}
if (selectedDirectory.equalsIgnoreCase(bannedDirectory)) {
MessageDialog alert(_("This directory cannot be used yet, it is being downloaded into!"));
alert.runModal();
return;
}
#endif
looping = !doGameDetection(_browser->getResult().getPath());
}
} while (looping);
}
void LauncherDialog::removeGame(int item) {
MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK) {
// Remove the currently selected game from the list
assert(item >= 0);
ConfMan.removeGameDomain(_domains[item]);
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget and force a redraw
updateListing();
g_gui.scheduleTopDialogRedraw();
}
}
void LauncherDialog::editGame(int item) {
// Set game specific options. Most of these should be "optional", i.e. by
// default set nothing and use the global ScummVM settings. E.g. the user
// can set here an optional alternate music volume, or for specific games
// a different music driver etc.
// This is useful because e.g. MonkeyVGA needs AdLib music to have decent
// music support etc.
assert(item >= 0);
String gameId(ConfMan.get("gameid", _domains[item]));
if (gameId.empty())
gameId = _domains[item];
EditGameDialog editDialog(_domains[item]);
if (editDialog.runModal() > 0) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget, reselect the edited game and force a redraw
updateListing();
selectTarget(editDialog.getDomain());
g_gui.scheduleTopDialogRedraw();
}
}
void LauncherDialog::loadGameButtonPressed(int item) {
#ifdef ENABLE_EVENTRECORDER
const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
if (shiftPressed) {
recordGame(item);
} else {
loadGame(item);
}
updateButtons();
#else
loadGame(item);
#endif
}
#ifdef ENABLE_EVENTRECORDER
void LauncherDialog::recordGame(int item) {
RecorderDialog recorderDialog;
MessageDialog alert(_("Do you want to load saved game?"),
_("Yes"), _("No"));
switch(recorderDialog.runModal(_domains[item])) {
case RecorderDialog::kRecordDialogClose:
break;
case RecorderDialog::kRecordDialogPlayback:
ConfMan.setActiveDomain(_domains[item]);
close();
ConfMan.set("record_mode", "playback", ConfigManager::kTransientDomain);
ConfMan.set("record_file_name", recorderDialog.getFileName(), ConfigManager::kTransientDomain);
break;
case RecorderDialog::kRecordDialogRecord:
ConfMan.setActiveDomain(_domains[item]);
if (alert.runModal() == GUI::kMessageOK) {
loadGame(item);
}
close();
g_eventRec.setAuthor(recorderDialog._author);
g_eventRec.setName(recorderDialog._name);
g_eventRec.setNotes(recorderDialog._notes);
ConfMan.set("record_mode", "record", ConfigManager::kTransientDomain);
break;
}
}
#endif
void LauncherDialog::loadGame(int item) {
String gameId = ConfMan.get("gameid", _domains[item]);
if (gameId.empty())
gameId = _domains[item];
const Plugin *plugin = nullptr;
EngineMan.findGame(gameId, &plugin);
String target = _domains[item];
target.toLowercase();
if (plugin) {
const MetaEngine &metaEngine = plugin->get<MetaEngine>();
if (metaEngine.hasFeature(MetaEngine::kSupportsListSaves) &&
metaEngine.hasFeature(MetaEngine::kSupportsLoadingDuringStartup)) {
int slot = _loadDialog->runModalWithPluginAndTarget(plugin, target);
if (slot >= 0) {
ConfMan.setActiveDomain(_domains[item]);
ConfMan.setInt("save_slot", slot, Common::ConfigManager::kTransientDomain);
close();
}
} else {
MessageDialog dialog
(_("This game does not support loading games from the launcher."), _("OK"));
dialog.runModal();
}
} else {
MessageDialog dialog(_("ScummVM could not find any engine capable of running the selected game!"), _("OK"));
dialog.runModal();
}
}
void LauncherDialog::handleKeyDown(Common::KeyState state) {
if (state.keycode == Common::KEYCODE_TAB) {
// Toggle between the game list and the quick search field.
if (getFocusWidget() == _searchWidget) {
setFocusWidget(_list);
} else if (getFocusWidget() == _list) {
setFocusWidget(_searchWidget);
}
}
Dialog::handleKeyDown(state);
updateButtons();
}
void LauncherDialog::handleKeyUp(Common::KeyState state) {
Dialog::handleKeyUp(state);
updateButtons();
}
void LauncherDialog::handleOtherEvent(Common::Event evt) {
Dialog::handleOtherEvent(evt);
if (evt.type == Common::EVENT_DROP_FILE) {
doGameDetection(evt.path);
}
}
bool LauncherDialog::doGameDetection(const Common::String &path) {
// Allow user to add a new game to the list.
// 2) try to auto detect which game is in the directory, if we cannot
// determine it uniquely present a list of candidates to the user
// to pick from
// 3) Display the 'Edit' dialog for that item, letting the user specify
// an alternate description (to distinguish multiple versions of the
// game, e.g. 'Monkey German' and 'Monkey English') and set default
// options for that game
// 4) If no game is found in the specified directory, return to the
// dialog.
// User made his choice...
Common::FSNode dir(path);
Common::FSList files;
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
alert.runModal();
return true;
}
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
DetectionResults detectionResults = EngineMan.detectGames(files);
if (detectionResults.foundUnknownGames()) {
Common::String report = detectionResults.generateUnknownGameReport(false, 80);
g_system->logMessage(LogMessageType::kInfo, report.c_str());
}
Common::Array<DetectedGame> candidates = detectionResults.listDetectedGames();
int idx;
if (candidates.empty()) {
// No game was found in the specified directory
MessageDialog alert(_("ScummVM could not find any game in the specified directory!"));
alert.runModal();
idx = -1;
return false;
} else if (candidates.size() == 1) {
// Exact match
idx = 0;
} else {
// Display the candidates to the user and let her/him pick one
StringArray list;
for (idx = 0; idx < (int)candidates.size(); idx++) {
Common::String description = candidates[idx].description;
if (candidates[idx].hasUnknownFiles) {
description += " - ";
description += _("Unknown variant");
}
list.push_back(description);
}
ChooserDialog dialog(_("Pick the game:"));
dialog.setList(list);
idx = dialog.runModal();
}
if (0 <= idx && idx < (int)candidates.size()) {
const DetectedGame &result = candidates[idx];
if (result.hasUnknownFiles) {
UnknownGameDialog dialog(result);
bool cancel = dialog.runModal() == -1;
if (cancel) {
idx = -1;
}
}
}
if (0 <= idx && idx < (int)candidates.size()) {
const DetectedGame &result = candidates[idx];
Common::String domain = EngineMan.createTargetForGame(result);
// Display edit dialog for the new entry
EditGameDialog editDialog(domain);
if (editDialog.runModal() > 0) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget, select the new item, and force a redraw
updateListing();
selectTarget(editDialog.getDomain());
g_gui.scheduleTopDialogRedraw();
} else {
// User aborted, remove the the new domain again
ConfMan.removeGameDomain(domain);
}
}
return true;
}
void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
int item = _list->getSelected();
switch (cmd) {
case kAddGameCmd:
addGame();
break;
case kRemoveGameCmd:
removeGame(item);
break;
case kEditGameCmd:
editGame(item);
break;
case kLoadGameCmd:
loadGameButtonPressed(item);
break;
case kOptionsCmd: {
GlobalOptionsDialog options(this);
options.runModal();
}
break;
case kAboutCmd: {
AboutDialog about;
about.runModal();
}
break;
case kStartCmd:
case kListItemActivatedCmd:
case kListItemDoubleClickedCmd:
// Start the selected game.
assert(item >= 0);
ConfMan.setActiveDomain(_domains[item]);
close();
break;
case kListItemRemovalRequestCmd:
removeGame(item);
break;
case kListSelectionChangedCmd:
updateButtons();
break;
case kQuitCmd:
ConfMan.setActiveDomain("");
setResult(-1);
close();
break;
case kSearchCmd:
// Update the active search filter.
_list->setFilter(_searchWidget->getEditString());
break;
case kSearchClearCmd:
// Reset the active search filter, thus showing all games again
_searchWidget->setEditString("");
_list->setFilter("");
break;
default:
Dialog::handleCommand(sender, cmd, data);
}
}
void LauncherDialog::updateButtons() {
bool enable = (_list->getSelected() >= 0);
if (enable != _startButton->isEnabled()) {
_startButton->setEnabled(enable);
_startButton->markAsDirty();
}
if (enable != _editButton->isEnabled()) {
_editButton->setEnabled(enable);
_editButton->markAsDirty();
}
if (enable != _removeButton->isEnabled()) {
_removeButton->setEnabled(enable);
_removeButton->markAsDirty();
}
int item = _list->getSelected();
bool en = enable;
if (item >= 0)
en = !(Common::checkGameGUIOption(GUIO_NOLAUNCHLOAD, ConfMan.get("guioptions", _domains[item])));
if (en != _loadButton->isEnabled()) {
_loadButton->setEnabled(en);
_loadButton->markAsDirty();
}
switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add..."));
#ifdef ENABLE_EVENTRECORDER
switchButtonsText(_loadButton, "~L~oad...", _s("Record..."));
#endif
}
// Update the label of the button depending on whether shift is pressed or not
void LauncherDialog::switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText) {
const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
const bool lowRes = g_system->getOverlayWidth() <= 320;
const char *newAddButtonLabel = shiftPressed
? (lowRes ? _c(shiftedText, "lowres") : _(shiftedText))
: (lowRes ? _c(normalText, "lowres") : _(normalText));
if (button->getLabel() != newAddButtonLabel)
button->setLabel(newAddButtonLabel);
}
void LauncherDialog::reflowLayout() {
#ifndef DISABLE_FANCY_THEMES
if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
StaticTextWidget *ver = (StaticTextWidget *)findWidget("Launcher.Version");
if (ver) {
ver->setAlign(g_gui.xmlEval()->getWidgetTextHAlign("Launcher.Version"));
ver->setLabel(gScummVMVersionDate);
}
if (!_logo)
_logo = new GraphicsWidget(this, "Launcher.Logo");
_logo->useThemeTransparency(true);
_logo->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageLogo));
} else {
StaticTextWidget *ver = (StaticTextWidget *)findWidget("Launcher.Version");
if (ver) {
ver->setAlign(g_gui.xmlEval()->getWidgetTextHAlign("Launcher.Version"));
ver->setLabel(gScummVMFullVersion);
}
if (_logo) {
removeWidget(_logo);
_logo->setNext(0);
delete _logo;
_logo = 0;
}
}
if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
if (!_searchPic)
_searchPic = new GraphicsWidget(this, "Launcher.SearchPic");
_searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch));
if (_searchDesc) {
removeWidget(_searchDesc);
_searchDesc->setNext(0);
delete _searchDesc;
_searchDesc = 0;
}
} else {
if (!_searchDesc)
_searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:"));
if (_searchPic) {
removeWidget(_searchPic);
_searchPic->setNext(0);
delete _searchPic;
_searchPic = 0;
}
}
removeWidget(_searchClearButton);
_searchClearButton->setNext(0);
delete _searchClearButton;
_searchClearButton = addClearButton(this, "Launcher.SearchClearButton", kSearchClearCmd);
#endif
_w = g_system->getOverlayWidth();
_h = g_system->getOverlayHeight();
Dialog::reflowLayout();
}
bool LauncherDialog::checkModifier(int checkedModifier) {
int modifiers = g_system->getEventManager()->getModifierState();
return (modifiers & checkedModifier) != 0;
}
} // End of namespace GUI