refactored common code into a new class OptionsDialog; various fixes and cleanup to the launcher/option dialogs

svn-id: r11152
This commit is contained in:
Max Horn 2003-11-05 12:25:42 +00:00
parent 0dfd0e4414
commit 297ddb370b
4 changed files with 533 additions and 470 deletions

View File

@ -41,6 +41,9 @@
#include "gui/TabWidget.h"
#include "gui/PopUpWidget.h"
#include "sound/mididrv.h"
using Common::ConfigManager;
enum {
@ -73,40 +76,32 @@ enum {
* - Maybe SFX/Master/Music volumes?
*/
enum {
kOKCmd = 'OK '
};
class EditGameDialog : public Dialog {
class EditGameDialog : public OptionsDialog {
typedef Common::String String;
typedef Common::StringList StringList;
public:
EditGameDialog(const String &domain, GameSettings target);
void open();
void close();
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
protected:
const String &_domain;
EditTextWidget *_descriptionWidget;
EditTextWidget *_domainWidget;
PopUpWidget *_langPopUp;
PopUpWidget *_platformPopUp;
PopUpWidget *_gfxPopUp;
CheckboxWidget *_fullscreenCheckbox;
CheckboxWidget *_aspectCheckbox;
CheckboxWidget *_multiMidiCheckbox;
CheckboxWidget *_mt32Checkbox;
};
EditGameDialog::EditGameDialog(const String &domain, GameSettings target)
: Dialog(8, 50, 320 - 2 * 8, 140),
_domain(domain) {
: OptionsDialog(domain, 10, 50, 320 - 2 * 10, 140) {
const int x = 5;
const int w = _w - 15;
const int labelWidth = 65;
const int vBorder = 5; // Tab border
int yoffset;
int sel;
// GAME: Path to game data (r/o)
String path(ConfMan.get("path", _domain));
@ -127,37 +122,32 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target)
yoffset = vBorder;
// GUI: Label & edit widget for the game ID
new StaticTextWidget(tab, 10, yoffset+2, 40, kLineHeight, "ID: ", kTextAlignRight);
_domainWidget = new EditTextWidget(tab, 50, yoffset, _w - 50 - 10, kLineHeight, _domain);
new StaticTextWidget(tab, x, yoffset+2, labelWidth, kLineHeight, "ID: ", kTextAlignRight);
_domainWidget = new EditTextWidget(tab, x+labelWidth, yoffset, _w - labelWidth - 10, kLineHeight, _domain);
yoffset += 16;
// GUI: Label & edit widget for the description
new StaticTextWidget(tab, 10, yoffset+2, 40, kLineHeight, "Name: ", kTextAlignRight);
_descriptionWidget = new EditTextWidget(tab, 50, yoffset, _w - 50 - 10, kLineHeight, description);
new StaticTextWidget(tab, x, yoffset+2, labelWidth, kLineHeight, "Name: ", kTextAlignRight);
_descriptionWidget = new EditTextWidget(tab, x+labelWidth, yoffset, _w - labelWidth - 10, kLineHeight, description);
yoffset += 16;
// GUI: Label for the game path
new StaticTextWidget(tab, 10, yoffset, 40, kLineHeight, "Path: ", kTextAlignRight);
new StaticTextWidget(tab, 50, yoffset, _w - 50 - 10, kLineHeight, path, kTextAlignLeft);
new StaticTextWidget(tab, x, yoffset, labelWidth, kLineHeight, "Path: ", kTextAlignRight);
new StaticTextWidget(tab, x+labelWidth, yoffset, _w - labelWidth - 10, kLineHeight, path, kTextAlignLeft);
yoffset += 16;
// Languag popup
_langPopUp = new PopUpWidget(tab, 5, yoffset, 280, kLineHeight, "Language: ", 100);
_langPopUp = new PopUpWidget(tab, x, yoffset, w, kLineHeight, "Language: ", labelWidth);
yoffset += 16;
_langPopUp->appendEntry("<default>");
_langPopUp->appendEntry("");
const Common::LanguageDescription *l = Common::g_languages;
int lang = Common::parseLanguage(ConfMan.get("language", _domain));
sel = 0;
for (int i = 0; l->name; ++l, ++i) {
for (; l->name; ++l) {
_langPopUp->appendEntry(l->description, l->id);
if (lang == l->id)
sel = i + 2;
}
_langPopUp->setSelected(sel);
// Platform popup
_platformPopUp = new PopUpWidget(tab, 5, yoffset, 280, kLineHeight, "Platform: ", 100);
_platformPopUp = new PopUpWidget(tab, x, yoffset, w, kLineHeight, "Platform: ", labelWidth);
yoffset += 16;
_platformPopUp->appendEntry("<default>");
_platformPopUp->appendEntry("");
@ -165,6 +155,53 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target)
_platformPopUp->appendEntry("Atari ST", Common::kPlatformAtariST);
_platformPopUp->appendEntry("Macintosh", Common::kPlatformMacintosh);
_platformPopUp->appendEntry("PC", Common::kPlatformPC);
//
// 2) The graphics tab
//
tab->addTab("Graphics");
yoffset = vBorder;
yoffset = addGraphicControls(tab, yoffset);
//
// 3) The audio tab
//
tab->addTab("Audio");
yoffset = vBorder;
yoffset = addMIDIControls(tab, yoffset);
//
// 3) The volume tab
//
tab->addTab("Volume");
yoffset = vBorder;
yoffset = addVolumeControls(tab, yoffset);
// Activate the first tab
tab->setActiveTab(0);
// Add OK & Cancel buttons
addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
addButton(_w - (kButtonWidth + 10), _h - 24, "OK", kOKCmd, 0);
}
void EditGameDialog::open() {
OptionsDialog::open();
int sel = 0;
// TODO: game path
const Common::LanguageDescription *l = Common::g_languages;
int lang = Common::parseLanguage(ConfMan.get("language", _domain));
for (int i = 0; l->name; ++l, ++i) {
if (lang == l->id)
sel = i + 2;
}
_langPopUp->setSelected(sel);
switch (Common::parsePlatform(ConfMan.get("platform", _domain))) {
case Common::kPlatformPC: sel = 5; break;
case Common::kPlatformAmiga: sel = 2; break;
@ -173,72 +210,26 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target)
default: sel = 0; break;
}
_platformPopUp->setSelected(sel);
//
// 2) The graphics tab
//
tab->addTab("Graphics");
yoffset = vBorder;
// The GFX mode popup & a label
// TODO - add an API to query the list of available GFX modes, and to get/set the mode
_gfxPopUp = new PopUpWidget(tab, 5, yoffset, 280, kLineHeight, "Graphics mode: ", 100);
yoffset += 16;
_gfxPopUp->appendEntry("<global default>");
_gfxPopUp->appendEntry("");
_gfxPopUp->appendEntry("Normal (no scaling)");
_gfxPopUp->appendEntry("2x");
_gfxPopUp->appendEntry("3x");
_gfxPopUp->appendEntry("2xSAI");
_gfxPopUp->appendEntry("Super2xSAI");
_gfxPopUp->appendEntry("SuperEagle");
_gfxPopUp->appendEntry("AdvMAME2x");
_gfxPopUp->appendEntry("AdvMAME3x");
_gfxPopUp->appendEntry("hq2x");
_gfxPopUp->appendEntry("hq3x");
_gfxPopUp->appendEntry("TV2x");
_gfxPopUp->appendEntry("DotMatrix");
_gfxPopUp->setSelected(0);
// FIXME - disable GFX popup for now
_gfxPopUp->setEnabled(false);
// GUI: Full screen checkbox
_fullscreenCheckbox = new CheckboxWidget(tab, 15, yoffset, 200, 16, "Fullscreen mode", 0, 'F');
_fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain));
yoffset += 16;
_aspectCheckbox = new CheckboxWidget(tab, 15, yoffset, 200, 16, "Aspect ratio correction");
_aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain));
yoffset += 16;
//
// 3) The audio tab
//
tab->addTab("Audio");
yoffset = vBorder;
// Multi midi setting
_multiMidiCheckbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "Mixed Adlib/MIDI mode");
_multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain));
yoffset += 16;
// Native mt32 setting
_mt32Checkbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "True Roland MT-32 (disable GM emulation)");
_mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
yoffset += 16;
// TODO: Volume/driver/midi/... settings
}
void EditGameDialog::close() {
if (getResult()) {
ConfMan.set("description", _descriptionWidget->getLabel(), _domain);
// Activate the first tab
tab->setActiveTab(0);
Common::Language lang = (Common::Language)_langPopUp->getSelectedTag();
if (lang < 0)
ConfMan.removeKey("language", _domain);
else
ConfMan.set("language", Common::getLanguageString(lang), _domain);
// GUI: Add OK & Cancel buttons
addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
addButton(_w - (kButtonWidth + 10), _h - 24, "OK", kOKCmd, 0);
Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag();
if (platform < 0)
ConfMan.removeKey("platform", _domain);
else
ConfMan.set("platform", Common::getPlatformString(platform), _domain);
}
OptionsDialog::close();
}
void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
@ -252,32 +243,16 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
return;
}
ConfMan.renameGameDomain(_domain, newDomain);
_domain = newDomain;
}
ConfMan.set("description", _descriptionWidget->getLabel(), newDomain);
ConfMan.set("fullscreen", _fullscreenCheckbox->getState(), newDomain);
ConfMan.set("aspect_ratio", _aspectCheckbox->getState(), newDomain);
ConfMan.set("multi_midi", _multiMidiCheckbox->getState(), newDomain);
ConfMan.set("native_mt32", _mt32Checkbox->getState(), newDomain);
Common::Language lang = (Common::Language)_langPopUp->getSelectedTag();
if (lang < 0)
ConfMan.removeKey("language", newDomain);
else
ConfMan.set("language", Common::getLanguageString(lang), newDomain);
Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag();
if (platform < 0)
ConfMan.removeKey("platform", newDomain);
else
ConfMan.set("platform", Common::getPlatformString(platform), newDomain);
setResult(1);
close();
} else {
Dialog::handleCommand(sender, cmd, data);
}
OptionsDialog::handleCommand(sender, cmd, data);
}
#pragma mark -
LauncherDialog::LauncherDialog(GameDetector &detector)
: Dialog(0, 0, 320, 200), _detector(detector) {
// Show game name
@ -323,21 +298,6 @@ LauncherDialog::~LauncherDialog() {
delete _browser;
}
void LauncherDialog::open() {
Dialog::open();
/* FIXME / TODO: config rewrite
g_config->set_writing(true);
*/
}
void LauncherDialog::close() {
ConfMan.flushToDisk();
/* FIXME / TODO: config rewrite
g_config->set_writing(false);
*/
Dialog::close();
}
void LauncherDialog::updateListing() {
Common::StringList l;
@ -372,144 +332,148 @@ void LauncherDialog::updateListing() {
updateButtons();
}
void LauncherDialog::addGame() {
// 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 preent 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.
if (_browser->runModal()) {
// User made his choice...
FilesystemNode *dir = _browser->getResult();
FSList *files = dir->listDir(FilesystemNode::kListFilesOnly);
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
GameList candidates;
// Iterate over all known games and for each check if it might be
// the game in the presented directory.
const PluginList &plugins = PluginManager::instance().getPlugins();
PluginList::ConstIterator iter = plugins.begin();
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
candidates.push_back((*iter)->detectGames(*files));
}
int idx;
if (candidates.isEmpty()) {
// No game was found in the specified directory
MessageDialog alert("ScummVM could not find any game in the specified directory!");
alert.runModal();
idx = -1;
} else if (candidates.size() == 1) {
// Exact match
idx = 0;
} else {
// Display the candidates to the user and let her/him pick one
StringList list;
for (idx = 0; idx < candidates.size(); idx++)
list.push_back(candidates[idx].description);
ChooserDialog dialog("Pick the game:", list);
idx = dialog.runModal();
}
if (0 <= idx && idx < candidates.size()) {
GameSettings result = candidates[idx];
// The auto detector or the user made a choice.
// Pick a domain name which does not yet exist (after all, we
// are *adding* a game to the config, not replacing).
String domain(result.gameName);
if (ConfMan.hasGameDomain(domain)) {
char suffix = 'a';
domain += suffix;
while (ConfMan.hasGameDomain(domain)) {
assert(suffix < 'z');
domain.deleteLastChar();
suffix++;
domain += suffix;
}
ConfMan.set("gameid", result.gameName, domain);
ConfMan.set("description", result.description, domain);
}
ConfMan.set("path", dir->path(), domain);
// Display edit dialog for the new entry
EditGameDialog editDialog(domain, result);
if (editDialog.runModal()) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget and force a redraw
updateListing();
draw();
} else {
// User aborted, remove the the new domain again
ConfMan.removeGameDomain(domain);
}
}
}
}
void LauncherDialog::removeGame(int item) {
MessageDialog alert("Do you really want to remove this game configuration?", "Yes", "No");
if (alert.runModal() == 1) {
// 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();
draw();
}
}
void LauncherDialog::editGame(int item) {
// Set game specifc 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.isEmpty())
gameId = _domains[item];
EditGameDialog editDialog(_domains[item], GameDetector::findGame(gameId));
if (editDialog.runModal()) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget and force a redraw
updateListing();
draw();
}
}
void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
int item = _list->getSelected();
switch (cmd) {
case kAddGameCmd:
// 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 preent 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.
if (_browser->runModal()) {
// User made his choice...
FilesystemNode *dir = _browser->getResult();
FSList *files = dir->listDir(FilesystemNode::kListFilesOnly);
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
GameList candidates;
// Iterate over all known games and for each check if it might be
// the game in the presented directory.
const PluginList &plugins = PluginManager::instance().getPlugins();
PluginList::ConstIterator iter = plugins.begin();
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
candidates.push_back((*iter)->detectGames(*files));
}
int idx;
if (candidates.isEmpty()) {
// No game was found in the specified directory
MessageDialog alert("ScummVM could not find any game in the specified directory!");
alert.runModal();
idx = -1;
} else if (candidates.size() == 1) {
// Exact match
idx = 0;
} else {
// Display the candidates to the user and let her/him pick one
StringList list;
for (idx = 0; idx < candidates.size(); idx++)
list.push_back(candidates[idx].description);
ChooserDialog dialog("Pick the game:", list);
idx = dialog.runModal();
}
if (0 <= idx && idx < candidates.size()) {
GameSettings result = candidates[idx];
// The auto detector or the user made a choice.
// Pick a domain name which does not yet exist (after all, we
// are *adding* a game to the config, not replacing).
String domain(result.gameName);
if (ConfMan.hasGameDomain(domain)) {
char suffix = 'a';
domain += suffix;
while (ConfMan.hasGameDomain(domain)) {
assert(suffix < 'z');
domain.deleteLastChar();
suffix++;
domain += suffix;
}
ConfMan.set("gameid", result.gameName, domain);
ConfMan.set("description", result.description, domain);
}
ConfMan.set("path", dir->path(), domain);
// Display edit dialog for the new entry
EditGameDialog editDialog(domain, result);
if (editDialog.runModal()) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget and force a redraw
updateListing();
draw();
} else {
// User aborted, remove the the new domain again
ConfMan.removeGameDomain(domain);
}
}
}
addGame();
break;
case kRemoveGameCmd: {
MessageDialog alert("Do you really want to remove this game configuration?", "Yes", "No");
if (alert.runModal() == 1) {
// 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();
draw();
}
}
case kRemoveGameCmd:
removeGame(item);
break;
case kEditGameCmd: {
// Set game specifc 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.isEmpty())
gameId = _domains[item];
EditGameDialog editDialog(_domains[item], GameDetector::findGame(gameId));
if (editDialog.runModal()) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
// Update the ListWidget and force a redraw
updateListing();
draw();
}
}
case kEditGameCmd:
editGame(item);
break;
case kOptionsCmd: {
// TODO - show up a generic options dialog with global options, including:
// - the save path (use _browser!)
// - music & graphics driver (but see also the comments on EditGameDialog
// for some techincal difficulties with this)
// - default volumes (sfx/master/music)
GlobalOptionsDialog options(_detector);
options.runModal();
}

View File

@ -36,8 +36,6 @@ public:
LauncherDialog(GameDetector &detector);
~LauncherDialog();
virtual void open();
virtual void close();
virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
protected:
@ -51,6 +49,10 @@ protected:
void updateListing();
void updateButtons();
void addGame();
void removeGame(int item);
void editGame(int item);
};
#endif

View File

@ -29,24 +29,13 @@
#include "backends/fs/fs.h"
#include "base/gameDetector.h"
#include "common/config-manager.h"
#include "common/scaler.h"
#include "sound/mididrv.h"
#if (!( defined(__DC__) || defined(__GP32__)) && !defined(_MSC_VER))
#include <unistd.h>
#endif
/*
_____ _ _ _ _ _
|_ _| |__ (_)___ (_)___ __ _ __| |_ _ _ __ ___ _ __ ___ _ _| |
| | | '_ \| / __| | / __| / _` | / _` | | | | '_ ` _ \| '_ ` _ \| | | | |
| | | | | | \__ \ | \__ \ | (_| | | (_| | |_| | | | | | | | | | | | |_| |_|
|_| |_| |_|_|___/ |_|___/ \__,_| \__,_|\__,_|_| |_| |_|_| |_| |_|\__, (_)
|___/
This just looks like an option dialog, but it doesn't change any actual settings currently!
*/
// TODO - allow changing options for:
// - the save path (use _browser!)
// - music & graphics driver (but see also the comments on EditGameDialog
@ -55,192 +44,105 @@ This just looks like an option dialog, but it doesn't change any actual settings
// - aspect ratio, language, platform, subtitles, debug mode/level, cd drive, joystick, multi midi, native mt32
enum {
kMasterVolumeChanged = 'mavc',
kMasterVolumeChanged = 'mavc',
kMusicVolumeChanged = 'muvc',
kSfxVolumeChanged = 'sfvc',
kChooseSaveDirCmd = 'chos',
kOKCmd = 'ok '
kChooseSaveDirCmd = 'chos'
};
GlobalOptionsDialog::GlobalOptionsDialog(GameDetector &detector)
: Dialog(10, 20, 320 - 2 * 10, 200 - 2 * 20) {
OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h)
: Dialog(x, y, w, h),
_domain(domain),
_gfxPopUp(0), _fullscreenCheckbox(0), _aspectCheckbox(0),
_multiMidiCheckbox(0), _mt32Checkbox(0),
_masterVolumeSlider(0), _masterVolumeLabel(0),
_musicVolumeSlider(0), _musicVolumeLabel(0),
_sfxVolumeSlider(0), _sfxVolumeLabel(0) {
const int vBorder = 5;
int yoffset;
}
// The tab widget
TabWidget *tab = new TabWidget(this, 0, vBorder, _w, _h - 24 - 2*vBorder);
//
// 1) The graphics tab
//
tab->addTab("Graphics");
yoffset = vBorder;
// The GFX mode popup & a label
// TODO - add an API to query the list of available GFX modes, and to get/set the mode
_gfxPopUp = new PopUpWidget(tab, 5, yoffset, 280, kLineHeight, "Graphics mode: ", 100);
yoffset += 16;
// Ender: We don't really want a <default> here at all, we want to setSelected to the current global
_gfxPopUp->appendEntry("<default>");
_gfxPopUp->appendEntry("");
_gfxPopUp->appendEntry("Normal (no scaling)");
_gfxPopUp->appendEntry("2x");
_gfxPopUp->appendEntry("3x");
_gfxPopUp->appendEntry("2xSAI");
_gfxPopUp->appendEntry("Super2xSAI");
_gfxPopUp->appendEntry("SuperEagle");
_gfxPopUp->appendEntry("AdvMAME2x");
_gfxPopUp->appendEntry("AdvMAME3x");
_gfxPopUp->appendEntry("hq2x");
_gfxPopUp->appendEntry("hq3x");
_gfxPopUp->appendEntry("TV2x");
_gfxPopUp->appendEntry("DotMatrix");
_gfxPopUp->setSelected(0);
void OptionsDialog::open() {
Dialog::open();
// Reset result value
setResult(0);
// FIXME - disable GFX popup for now
_gfxPopUp->setSelected(0);
_gfxPopUp->setEnabled(false);
#if 1
// TODO: Aspect ratio setting
// TODO: Fullscreen setting
_fullscreenCheckbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "Fullscreen mode");
_fullscreenCheckbox->setState(ConfMan.getBool("fullscreen"));
yoffset += 16;
_aspectCheckbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "Aspect ratio correction");
_aspectCheckbox->setState(ConfMan.getBool("aspect_ratio"));
yoffset += 16;
#endif
// Fullscreen setting
_fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain));
// Aspect ratio setting
_aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain));
//
// 2) The audio tab
//
tab->addTab("Audio");
yoffset = vBorder;
// The MIDI mode popup & a label
_midiPopUp = new PopUpWidget(tab, 5, yoffset, 280, kLineHeight, "Music driver: ", 100);
yoffset += 16;
// Populate it
// Music driver
const MidiDriverDescription *md = getAvailableMidiDrivers();
const int midiDriver = parseMusicDriver(ConfMan.get("music_driver"));
int midiSelected = 0, i = 0;
while (md->name) {
_midiPopUp->appendEntry(md->description, md->id);
if (md->id == midiDriver)
midiSelected = i;
const int midiDriver = parseMusicDriver(ConfMan.get("music_driver", _domain));
int i = 0;
while (md->name && md->id != midiDriver) {
i++;
md++;
}
_midiPopUp->setSelected(midiSelected);
// Volume controllers
_masterVolumeSlider = new SliderWidget(tab, 5, yoffset, 185, 12, "Master volume: ", 100, kMasterVolumeChanged);
_masterVolumeLabel = new StaticTextWidget(tab, 200, yoffset+2, 24, 16, "100%", kTextAlignLeft);
_masterVolumeSlider->setMinValue(0); _masterVolumeSlider->setMaxValue(255);
_masterVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
_midiPopUp->setSelected(md->name ? i : 0);
_musicVolumeSlider = new SliderWidget(tab, 5, yoffset, 185, 12, "Music volume: ", 100, kMusicVolumeChanged);
_musicVolumeLabel = new StaticTextWidget(tab, 200, yoffset+2, 24, 16, "100%", kTextAlignLeft);
_musicVolumeSlider->setMinValue(0); _musicVolumeSlider->setMaxValue(255);
_musicVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
_sfxVolumeSlider = new SliderWidget(tab, 5, yoffset, 185, 12, "SFX volume: ", 100, kSfxVolumeChanged);
_sfxVolumeLabel = new StaticTextWidget(tab, 200, yoffset+2, 24, 16, "100%", kTextAlignLeft);
_sfxVolumeSlider->setMinValue(0); _sfxVolumeSlider->setMaxValue(255);
_sfxVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
// Multi midi setting
_multiMidiCheckbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "Mixed Adlib/MIDI mode");
_multiMidiCheckbox->setState(ConfMan.getBool("multi_midi"));
yoffset += 16;
_multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain));
// Native mt32 setting
_mt32Checkbox = new CheckboxWidget(tab, 10, yoffset, 280, 16, "True Roland MT-32 (disable GM emulation)");
_mt32Checkbox->setState(ConfMan.getBool("native_mt32"));
yoffset += 16;
_mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
// TODO: cd drive setting
//
// 3) The miscellaneous tab
//
tab->addTab("Misc");
yoffset = vBorder;
#if !( defined(__DC__) || defined(__GP32__) )
// Save game path
new StaticTextWidget(tab, 5, yoffset+2, 100, kLineHeight, "Savegame path: ", kTextAlignRight);
_savePath = new StaticTextWidget(tab, 105, yoffset+2, 180, kLineHeight, "/foo/bar", kTextAlignLeft);
new ButtonWidget(tab, 105, yoffset+14, 64, 16, "Choose...", kChooseSaveDirCmd, 0);
// TODO: set _savePath to the current save path
Common::String dir(ConfMan.get("savepath"));
if (!dir.isEmpty()) {
_savePath->setLabel(dir);
} else {
// Default to the current directory...
char buf[256];
getcwd(buf, sizeof(buf));
_savePath->setLabel(buf);
}
#endif
// TODO: joystick setting
//
// Add OK & Cancel buttons
//
addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
addButton(_w - (kButtonWidth + 10), _h - 24, "OK", kOKCmd, 0);
// Create file browser dialog
_browser = new BrowserDialog("Select directory for savegames");
// Activate the first tab
tab->setActiveTab(0);
}
GlobalOptionsDialog::~GlobalOptionsDialog() {
delete _browser;
}
void GlobalOptionsDialog::open() {
Dialog::open();
int vol;
vol = ConfMan.getInt("master_volume");
vol = ConfMan.getInt("master_volume", _domain);
_masterVolumeSlider->setValue(vol);
_masterVolumeLabel->setValue(vol);
vol = ConfMan.getInt("music_volume");
vol = ConfMan.getInt("music_volume", _domain);
_musicVolumeSlider->setValue(vol);
_musicVolumeLabel->setValue(vol);
vol = ConfMan.getInt("sfx_volume");
vol = ConfMan.getInt("sfx_volume", _domain);
_sfxVolumeSlider->setValue(vol);
_sfxVolumeLabel->setValue(vol);
}
void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kChooseSaveDirCmd:
if (_browser->runModal()) {
// User made his choice...
FilesystemNode *dir = _browser->getResult();
_savePath->setLabel(dir->path());
// TODO - we should check if the directory is writeable before accepting it
void OptionsDialog::close() {
if (getResult()) {
if (_fullscreenCheckbox) {
ConfMan.set("fullscreen", _fullscreenCheckbox->getState(), _domain);
ConfMan.set("aspect_ratio", _aspectCheckbox->getState(), _domain);
}
break;
if (_masterVolumeSlider) {
ConfMan.set("master_volume", _masterVolumeSlider->getValue(), _domain);
ConfMan.set("music_volume", _musicVolumeSlider->getValue(), _domain);
ConfMan.set("sfx_volume", _sfxVolumeSlider->getValue(), _domain);
}
if (_multiMidiCheckbox) {
ConfMan.set("multi_midi", _multiMidiCheckbox->getState(), _domain);
ConfMan.set("native_mt32", _mt32Checkbox->getState(), _domain);
const MidiDriverDescription *md = getAvailableMidiDrivers();
while (md->name && md->id != (int)_midiPopUp->getSelectedTag())
md++;
if (md->name)
ConfMan.set("music_driver", md->name, _domain);
else
ConfMan.removeKey("music_driver", _domain);
}
// Save config file
ConfMan.flushToDisk();
}
Dialog::close();
}
void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kMasterVolumeChanged:
_masterVolumeLabel->setValue(_masterVolumeSlider->getValue());
_masterVolumeLabel->draw();
@ -253,35 +155,196 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
_sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue());
_sfxVolumeLabel->draw();
break;
case kOKCmd: {
case kOKCmd:
setResult(1);
// TODO: All these settings should take effect immediately.
// There are two ways to ensure that:
// 1) Add code here which pushes the changes on to the mixer/backend
// 2) Implement the ConfigManager callback API; then, let the mixer/backend
// and any other interested parties register for notifications sent
// whenever these config values change.
ConfMan.set("master_volume", _masterVolumeSlider->getValue());
ConfMan.set("music_volume", _musicVolumeSlider->getValue());
ConfMan.set("sfx_volume", _sfxVolumeSlider->getValue());
ConfMan.set("fullscreen", _fullscreenCheckbox->getState());
ConfMan.set("aspect_ratio", _aspectCheckbox->getState());
ConfMan.set("multi_midi", _multiMidiCheckbox->getState());
ConfMan.set("native_mt32", _mt32Checkbox->getState());
const MidiDriverDescription *md = getAvailableMidiDrivers();
for (; md->name; md++) {
if (md->id == (int)_midiPopUp->getSelectedTag()) {
ConfMan.set("music_driver", md->name);
break;
}
}
if (!md->name)
ConfMan.removeKey("music_driver", Common::ConfigManager::kApplicationDomain);
close();
break; }
break;
default:
Dialog::handleCommand(sender, cmd, data);
}
}
int OptionsDialog::addGraphicControls(GuiObject *boss, int yoffset) {
const int x = 10;
const int w = _w - 2 * 10;
// The GFX mode popup
// TODO - add an API to query the list of available GFX modes, and to get/set the mode
_gfxPopUp = new PopUpWidget(boss, x-5, yoffset, w+5, kLineHeight, "Graphics mode: ", 100);
yoffset += 16;
// FIXME: For the GlobalOptionsDialog, we don't want a <default> here;
// rather, we want to setSelected to the current global
_gfxPopUp->appendEntry("<default>");
_gfxPopUp->appendEntry("");
_gfxPopUp->appendEntry("Normal (no scaling)", GFX_NORMAL);
_gfxPopUp->appendEntry("2x", GFX_DOUBLESIZE);
_gfxPopUp->appendEntry("3x", GFX_TRIPLESIZE);
_gfxPopUp->appendEntry("2xSAI", GFX_2XSAI);
_gfxPopUp->appendEntry("Super2xSAI", GFX_SUPER2XSAI);
_gfxPopUp->appendEntry("SuperEagle", GFX_SUPEREAGLE);
_gfxPopUp->appendEntry("AdvMAME2x", GFX_ADVMAME2X);
_gfxPopUp->appendEntry("AdvMAME3x", GFX_ADVMAME3X);
_gfxPopUp->appendEntry("hq2x", GFX_HQ2X);
_gfxPopUp->appendEntry("hq3x", GFX_HQ3X);
_gfxPopUp->appendEntry("TV2x", GFX_TV2X);
_gfxPopUp->appendEntry("DotMatrix", GFX_DOTMATRIX);
// Fullscreen checkbox
_fullscreenCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Fullscreen mode");
yoffset += 16;
// Aspect ratio checkbox
_aspectCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Aspect ratio correction");
yoffset += 16;
return yoffset;
}
int OptionsDialog::addMIDIControls(GuiObject *boss, int yoffset) {
const int x = 10;
const int w = _w - 20;
// The MIDI mode popup & a label
_midiPopUp = new PopUpWidget(boss, x-5, yoffset, w+5, kLineHeight, "Music driver: ", 100);
yoffset += 16;
// Populate it
const MidiDriverDescription *md = getAvailableMidiDrivers();
while (md->name) {
_midiPopUp->appendEntry(md->description, md->id);
md++;
}
// Multi midi setting
_multiMidiCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Mixed Adlib/MIDI mode");
yoffset += 16;
// Native mt32 setting
_mt32Checkbox = new CheckboxWidget(boss, x, yoffset, w, 16, "True Roland MT-32 (disable GM emulation)");
yoffset += 16;
return yoffset;
}
int OptionsDialog::addVolumeControls(GuiObject *boss, int yoffset) {
// Volume controllers
_masterVolumeSlider = new SliderWidget(boss, 5, yoffset, 185, 12, "Master volume: ", 100, kMasterVolumeChanged);
_masterVolumeLabel = new StaticTextWidget(boss, 200, yoffset+2, 24, kLineHeight, "100%", kTextAlignLeft);
_masterVolumeSlider->setMinValue(0); _masterVolumeSlider->setMaxValue(255);
_masterVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
_musicVolumeSlider = new SliderWidget(boss, 5, yoffset, 185, 12, "Music volume: ", 100, kMusicVolumeChanged);
_musicVolumeLabel = new StaticTextWidget(boss, 200, yoffset+2, 24, kLineHeight, "100%", kTextAlignLeft);
_musicVolumeSlider->setMinValue(0); _musicVolumeSlider->setMaxValue(255);
_musicVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
_sfxVolumeSlider = new SliderWidget(boss, 5, yoffset, 185, 12, "SFX volume: ", 100, kSfxVolumeChanged);
_sfxVolumeLabel = new StaticTextWidget(boss, 200, yoffset+2, 24, kLineHeight, "100%", kTextAlignLeft);
_sfxVolumeSlider->setMinValue(0); _sfxVolumeSlider->setMaxValue(255);
_sfxVolumeLabel->setFlags(WIDGET_CLEARBG);
yoffset += 16;
return yoffset;
}
#pragma mark -
GlobalOptionsDialog::GlobalOptionsDialog(GameDetector &detector)
: OptionsDialog(Common::ConfigManager::kApplicationDomain, 10, 20, 320 - 2 * 10, 200 - 2 * 20) {
const int vBorder = 5;
int yoffset;
// The tab widget
TabWidget *tab = new TabWidget(this, 0, vBorder, _w, _h - 24 - 2*vBorder);
//
// 1) The graphics tab
//
tab->addTab("Graphics");
yoffset = vBorder;
yoffset = addGraphicControls(tab, yoffset);
//
// 2) The audio tab
//
tab->addTab("Audio");
yoffset = vBorder;
yoffset = addMIDIControls(tab, yoffset);
yoffset = addVolumeControls(tab, yoffset);
// TODO: cd drive setting
//
// 3) The miscellaneous tab
//
tab->addTab("Misc");
yoffset = vBorder;
#if !( defined(__DC__) || defined(__GP32__) )
// Save game path
new StaticTextWidget(tab, 5, yoffset+2, 100, kLineHeight, "Savegame path: ", kTextAlignRight);
_savePath = new StaticTextWidget(tab, 105, yoffset+2, 180, kLineHeight, "/foo/bar", kTextAlignLeft);
new ButtonWidget(tab, 105, yoffset+14, 64, 16, "Choose...", kChooseSaveDirCmd, 0);
#endif
// TODO: joystick setting
// Activate the first tab
tab->setActiveTab(0);
// Add OK & Cancel buttons
addButton(_w - 2 * (kButtonWidth + 10), _h - 24, "Cancel", kCloseCmd, 0);
addButton(_w - (kButtonWidth + 10), _h - 24, "OK", kOKCmd, 0);
// Create file browser dialog
_browser = new BrowserDialog("Select directory for savegames");
}
GlobalOptionsDialog::~GlobalOptionsDialog() {
delete _browser;
}
void GlobalOptionsDialog::open() {
OptionsDialog::open();
#if !( defined(__DC__) || defined(__GP32__) )
// Set _savePath to the current save path
Common::String dir(ConfMan.get("savepath", _domain));
if (!dir.isEmpty()) {
_savePath->setLabel(dir);
} else {
// Default to the current directory...
char buf[256];
getcwd(buf, sizeof(buf));
_savePath->setLabel(buf);
}
#endif
}
void GlobalOptionsDialog::close() {
if (getResult()) {
// TODO: Savepath
}
OptionsDialog::close();
}
void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kChooseSaveDirCmd:
if (_browser->runModal()) {
// User made his choice...
FilesystemNode *dir = _browser->getResult();
_savePath->setLabel(dir->path());
// TODO - we should check if the directory is writeable before accepting it
}
break;
default:
OptionsDialog::handleCommand(sender, cmd, data);
}
}

View File

@ -21,7 +21,7 @@
#ifndef OPTIONS_DIALOG_H
#define OPTIONS_DIALOG_H
#include "dialog.h"
#include "gui/dialog.h"
#include "common/str.h"
#include "common/list.h"
@ -32,36 +32,70 @@ class PopUpWidget;
class SliderWidget;
class StaticTextWidget;
class GlobalOptionsDialog : public Dialog {
class OptionsDialog : public Dialog {
typedef Common::String String;
public:
OptionsDialog(const String &domain, int x, int y, int w, int h);
void open();
void close();
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
enum {
kOKCmd = 'ok '
};
protected:
/** Config domain this dialog is used to edit. */
String _domain;
int addGraphicControls(GuiObject *boss, int yoffset);
int addMIDIControls(GuiObject *boss, int yoffset);
int addVolumeControls(GuiObject *boss, int yoffset);
private:
//
// Graphics controls
//
PopUpWidget *_gfxPopUp;
CheckboxWidget *_fullscreenCheckbox;
CheckboxWidget *_aspectCheckbox;
//
// MIDI controls
//
PopUpWidget *_midiPopUp;
CheckboxWidget *_multiMidiCheckbox;
CheckboxWidget *_mt32Checkbox;
//
// Volume controls
//
SliderWidget *_masterVolumeSlider;
StaticTextWidget *_masterVolumeLabel;
SliderWidget *_musicVolumeSlider;
StaticTextWidget *_musicVolumeLabel;
SliderWidget *_sfxVolumeSlider;
StaticTextWidget *_sfxVolumeLabel;
};
class GlobalOptionsDialog : public OptionsDialog {
typedef Common::String String;
public:
GlobalOptionsDialog(GameDetector &detector);
~GlobalOptionsDialog();
void open();
// void close();
void close();
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
protected:
BrowserDialog *_browser;
StaticTextWidget *_savePath;
PopUpWidget *_gfxPopUp;
CheckboxWidget *_fullscreenCheckbox;
CheckboxWidget *_aspectCheckbox;
PopUpWidget *_midiPopUp;
SliderWidget *_masterVolumeSlider;
SliderWidget *_musicVolumeSlider;
SliderWidget *_sfxVolumeSlider;
StaticTextWidget *_masterVolumeLabel;
StaticTextWidget *_musicVolumeLabel;
StaticTextWidget *_sfxVolumeLabel;
CheckboxWidget *_multiMidiCheckbox;
CheckboxWidget *_mt32Checkbox;
};
#endif