aboutsummaryrefslogtreecommitdiff
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/ThemeEngine.cpp18
-rw-r--r--gui/ThemeEngine.h17
-rw-r--r--gui/ThemeParser.cpp7
-rw-r--r--gui/ThemeParser.h1
-rw-r--r--gui/Tooltip.cpp2
-rw-r--r--gui/credits.h13
-rw-r--r--gui/dialog.cpp13
-rw-r--r--gui/dialog.h7
-rw-r--r--gui/gui-manager.cpp13
-rw-r--r--gui/launcher.cpp3
-rw-r--r--gui/module.mk1
-rw-r--r--gui/predictivedialog.cpp288
-rw-r--r--gui/predictivedialog.h9
-rw-r--r--gui/saveload-dialog.cpp882
-rw-r--r--gui/saveload-dialog.h208
-rw-r--r--gui/saveload.cpp391
-rw-r--r--gui/saveload.h70
-rw-r--r--gui/themes/default.inc855
-rw-r--r--gui/themes/scummclassic.zipbin93076 -> 95180 bytes
-rw-r--r--gui/themes/scummclassic/THEMERC2
-rw-r--r--gui/themes/scummclassic/classic_gfx.stx13
-rw-r--r--gui/themes/scummclassic/classic_layout.stx45
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx31
-rw-r--r--gui/themes/scummmodern.zipbin1449403 -> 1453485 bytes
-rw-r--r--gui/themes/scummmodern/THEMERC2
-rw-r--r--gui/themes/scummmodern/grid.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/list.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx29
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx45
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx31
-rw-r--r--gui/themes/translations.datbin311215 -> 370908 bytes
-rw-r--r--gui/widget.cpp173
-rw-r--r--gui/widget.h32
33 files changed, 2252 insertions, 949 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index fdd7750af9..e2fa2580f5 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -48,6 +48,8 @@ const char * const ThemeEngine::kImageLogoSmall = "logo_small.bmp";
const char * const ThemeEngine::kImageSearch = "search.bmp";
const char * const ThemeEngine::kImageEraser = "eraser.bmp";
const char * const ThemeEngine::kImageDelbtn = "delbtn.bmp";
+const char * const ThemeEngine::kImageList = "list.bmp";
+const char * const ThemeEngine::kImageGrid = "grid.bmp";
struct TextDrawData {
const Graphics::Font *_fontPtr;
@@ -175,6 +177,7 @@ static const DrawDataInfo kDrawDataDefaults[] = {
{kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider},
{kDDButtonHover, "button_hover", false, kDDButtonIdle},
{kDDButtonDisabled, "button_disabled", true, kDDNone},
+ {kDDButtonPressed, "button_pressed", false, kDDButtonIdle},
{kDDSliderFull, "slider_full", false, kDDNone},
{kDDSliderHover, "slider_hover", false, kDDNone},
@@ -428,7 +431,7 @@ bool ThemeEngine::init() {
void ThemeEngine::clearAll() {
if (_initOk) {
_system->clearOverlay();
- _system->grabOverlay((OverlayColor *)_screen.pixels, _screen.w);
+ _system->grabOverlay(_screen.pixels, _screen.pitch);
}
}
@@ -453,7 +456,7 @@ void ThemeEngine::refresh() {
if (_useCursor) {
CursorMan.replaceCursorPalette(_cursorPal, 0, _cursorPalSize);
- CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale);
+ CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
}
}
}
@@ -464,7 +467,7 @@ void ThemeEngine::enable() {
if (_useCursor) {
CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize);
- CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale);
+ CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
CursorMan.showMouse(true);
}
@@ -877,6 +880,8 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
dd = kDDButtonHover;
else if (state == kStateDisabled)
dd = kDDButtonDisabled;
+ else if (state == kStatePressed)
+ dd = kDDButtonPressed;
queueDD(dd, r, 0, hints & WIDGET_CLEARBG);
queueDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
@@ -1125,6 +1130,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
break;
case kStateEnabled:
+ case kStatePressed:
colorId = kTextColorNormal;
break;
}
@@ -1145,6 +1151,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
break;
case kStateEnabled:
+ case kStatePressed:
colorId = kTextColorAlternative;
break;
}
@@ -1282,7 +1289,7 @@ void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) {
_vectorRenderer->setSurface(&_screen);
}
-bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) {
+bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY) {
if (!_system->hasFeature(OSystem::kFeatureCursorPalette))
return true;
@@ -1300,7 +1307,6 @@ bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int
// Set up the cursor parameters
_cursorHotspotX = hotspotX;
_cursorHotspotY = hotspotY;
- _cursorTargetScale = scale;
_cursorWidth = cursor->w;
_cursorHeight = cursor->h;
@@ -1418,7 +1424,7 @@ const Graphics::Font *ThemeEngine::loadScalableFont(const Common::String &filena
for (Common::ArchiveMemberList::const_iterator i = members.begin(), end = members.end(); i != end; ++i) {
Common::SeekableReadStream *stream = (*i)->createReadStream();
if (stream) {
- font = Graphics::loadTTFFont(*stream, pointsize, false,
+ font = Graphics::loadTTFFont(*stream, pointsize, 0, false,
#ifdef USE_TRANSLATION
TransMan.getCharsetMapping()
#else
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 0495a85c88..6fb93d3b46 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -35,7 +35,7 @@
#include "graphics/pixelformat.h"
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.11"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.16"
class OSystem;
@@ -81,6 +81,7 @@ enum DrawData {
kDDButtonIdle,
kDDButtonHover,
kDDButtonDisabled,
+ kDDButtonPressed,
kDDSliderFull,
kDDSliderHover,
@@ -178,7 +179,8 @@ public:
enum State {
kStateDisabled, ///< Indicates that the widget is disabled, that does NOT include that it is invisible
kStateEnabled, ///< Indicates that the widget is enabled
- kStateHighlight ///< Indicates that the widget is highlighted by the user
+ kStateHighlight, ///< Indicates that the widget is highlighted by the user
+ kStatePressed ///< Indicates that the widget is pressed, currently works for buttons
};
typedef State WidgetStateInfo;
@@ -230,6 +232,8 @@ public:
static const char *const kImageSearch; ///< Search tool image used in the launcher
static const char *const kImageEraser; ///< Clear input image used in the launcher
static const char *const kImageDelbtn; ///< Delete characters in the predictive dialog
+ static const char *const kImageList; ///< List image used in save/load chooser selection
+ static const char *const kImageGrid; ///< Grid image used in save/load chooser selection
/**
* Graphics mode enumeration.
@@ -274,6 +278,11 @@ public:
void disable();
/**
+ * Query the set up pixel format.
+ */
+ const Graphics::PixelFormat getPixelFormat() const { return _overlayFormat; }
+
+ /**
* Implementation of the GUI::Theme API. Called when a
* new dialog is opened. Note that the boolean parameter
* meaning has been changed.
@@ -493,9 +502,8 @@ public:
* @param filename File name of the bitmap to load.
* @param hotspotX X Coordinate of the bitmap which does the cursor click.
* @param hotspotY Y Coordinate of the bitmap which does the cursor click.
- * @param scale Scale at which the bitmap is supposed to be used.
*/
- bool createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale);
+ bool createCursor(const Common::String &filename, int hotspotX, int hotspotY);
/**
* Wrapper for restoring data from the Back Buffer to the screen.
@@ -667,7 +675,6 @@ protected:
bool _useCursor;
int _cursorHotspotX, _cursorHotspotY;
- int _cursorTargetScale;
enum {
MAX_CURS_COLORS = 255
};
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index 9ccdedd564..9a85399ed1 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -218,15 +218,12 @@ bool ThemeParser::parserCallback_cursor(ParserNode *node) {
return true;
}
- int spotx, spoty, scale;
+ int spotx, spoty;
if (!parseIntegerKey(node->values["hotspot"], 2, &spotx, &spoty))
return parserError("Error parsing cursor Hot Spot coordinates.");
- if (!parseIntegerKey(node->values["scale"], 1, &scale))
- return parserError("Error parsing cursor scale.");
-
- if (!_theme->createCursor(node->values["file"], spotx, spoty, scale))
+ if (!_theme->createCursor(node->values["file"], spotx, spoty))
return parserError("Error creating Bitmap Cursor.");
return true;
diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h
index 4b7e88cbf3..82f774b803 100644
--- a/gui/ThemeParser.h
+++ b/gui/ThemeParser.h
@@ -85,7 +85,6 @@ protected:
XML_KEY(cursor)
XML_PROP(file, true)
XML_PROP(hotspot, true)
- XML_PROP(scale, true)
XML_PROP(resolution, false)
KEY_END()
diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp
index 85e5856cff..88124e782b 100644
--- a/gui/Tooltip.cpp
+++ b/gui/Tooltip.cpp
@@ -37,7 +37,7 @@ Tooltip::Tooltip() :
}
void Tooltip::setup(Dialog *parent, Widget *widget, int x, int y) {
- assert(widget->getTooltip());
+ assert(widget->hasTooltip());
_maxWidth = g_gui.xmlEval()->getVar("Globals.Tooltip.MaxWidth", 100);
_xdelta = g_gui.xmlEval()->getVar("Globals.Tooltip.XDelta", 0);
diff --git a/gui/credits.h b/gui/credits.h
index ecfe280d20..fdde2da821 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -106,8 +106,10 @@ static const char *credits[] = {
"C1""DreamWeb",
"C0""Torbj\366rn Andersson",
"C0""Bertrand Augereau",
+"C0""Filippos Karapetis",
"C0""Vladimir Menshakov",
"C2""(retired)",
+"C0""Willem Jan Palenstijn",
"",
"C1""Gob",
"C0""Torbj\366rn Andersson",
@@ -474,6 +476,9 @@ static const char *credits[] = {
"C1""French",
"C0""Thierry Crozat",
"",
+"C1""Galician",
+"C0""Santiago G. Sanz",
+"",
"C1""German",
"C0""Simon Sawatzki",
"C0""Lothar Serra Mari",
@@ -486,10 +491,10 @@ static const char *credits[] = {
"C0""Matteo Angelino",
"",
"C1""Norwegian (Bokm\345l)",
-"C0""Einar Johan T. S\370m\345en",
+"C0""Einar Johan S\370m\345en",
"",
"C1""Norwegian (Nynorsk)",
-"C0""Einar Johan T. S\370m\345en",
+"C0""Einar Johan S\370m\345en",
"",
"C1""Polish",
"C0""GrajPoPolsku.pl Team",
@@ -710,5 +715,9 @@ static const char *credits[] = {
"C0""",
"C0""Broken Sword 2.5 team for providing sources of their engine and their great support.",
"C0""",
+"C0""Neil Dodwell and David Dew from Creative Reality for providing the source of Dreamweb and for their tremendous support.",
+"C0""",
+"C0""Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon for providing full source code for Soltys and letting us to redistribute the game.",
+"C0""",
"",
};
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 2201e83ca5..ffca15bbc8 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -42,7 +42,7 @@ namespace GUI {
Dialog::Dialog(int x, int y, int w, int h)
: GuiObject(x, y, w, h),
- _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false),
+ _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _tickleWidget(0), _visible(false),
_backgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) {
// Some dialogs like LauncherDialog use internally a fixed size, even though
// their widgets rely on the layout to be initialized correctly by the theme.
@@ -54,7 +54,7 @@ Dialog::Dialog(int x, int y, int w, int h)
Dialog::Dialog(const Common::String &name)
: GuiObject(name),
- _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false),
+ _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _tickleWidget(0), _visible(false),
_backgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) {
// It may happen that we have 3x scaler in launcher (960xY) and then 640x480
@@ -117,6 +117,12 @@ void Dialog::reflowLayout() {
GuiObject::reflowLayout();
}
+void Dialog::lostFocus() {
+ if (_tickleWidget) {
+ _tickleWidget->lostFocus();
+ }
+}
+
void Dialog::setFocusWidget(Widget *widget) {
// The focus will change. Tell the old focused widget (if any)
// that it lost the focus.
@@ -308,6 +314,9 @@ void Dialog::handleTickle() {
// Focused widget receives tickle notifications
if (_focusedWidget && _focusedWidget->getFlags() & WIDGET_WANT_TICKLE)
_focusedWidget->handleTickle();
+
+ if (_tickleWidget && _tickleWidget->getFlags() & WIDGET_WANT_TICKLE)
+ _tickleWidget->handleTickle();
}
void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/gui/dialog.h b/gui/dialog.h
index f5a5f94a68..1773c6633e 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -52,6 +52,7 @@ protected:
Widget *_mouseWidget;
Widget *_focusedWidget;
Widget *_dragWidget;
+ Widget *_tickleWidget;
bool _visible;
ThemeEngine::DialogBackground _backgroundType;
@@ -71,7 +72,13 @@ public:
void setFocusWidget(Widget *widget);
Widget *getFocusWidget() { return _focusedWidget; }
+ void setTickleWidget(Widget *widget) { _tickleWidget = widget; }
+ void unSetTickleWidget() { _tickleWidget = NULL; }
+ Widget *getTickleWidget() { return _tickleWidget; }
+
virtual void reflowLayout();
+ virtual void lostFocus();
+ virtual void receivedFocus() {}
protected:
virtual void open();
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index ffecd928bc..a0ef4216aa 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -381,7 +381,7 @@ void GuiManager::runLoop() {
if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
- if (wdg && wdg->getTooltip()) {
+ if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
Tooltip *tooltip = new Tooltip();
tooltip->setup(activeDialog, wdg, _lastMousePosition.x, _lastMousePosition.y);
tooltip->runModal();
@@ -441,6 +441,11 @@ void GuiManager::restoreState() {
}
void GuiManager::openDialog(Dialog *dialog) {
+ dialog->receivedFocus();
+
+ if (!_dialogStack.empty())
+ getTopDialog()->lostFocus();
+
_dialogStack.push(dialog);
if (_redrawStatus != kRedrawFull)
_redrawStatus = kRedrawOpenDialog;
@@ -458,7 +463,11 @@ void GuiManager::closeTopDialog() {
return;
// Remove the dialog from the stack
- _dialogStack.pop();
+ _dialogStack.pop()->lostFocus();
+
+ if (!_dialogStack.empty())
+ getTopDialog()->receivedFocus();
+
if (_redrawStatus != kRedrawFull)
_redrawStatus = kRedrawCloseDialog;
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index a86a98f819..26fafa5279 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -663,7 +663,6 @@ LauncherDialog::LauncherDialog()
_list->setEditable(false);
_list->setNumberingMode(kListNumberingOff);
-
// Populate the list
updateListing();
@@ -678,7 +677,7 @@ LauncherDialog::LauncherDialog()
_browser = new BrowserDialog(_("Select directory with game data"), true);
// Create Load dialog
- _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"));
+ _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load"), false);
}
void LauncherDialog::selectTarget(const String &target) {
diff --git a/gui/module.mk b/gui/module.mk
index d272bb0313..a435d8cca7 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -15,6 +15,7 @@ MODULE_OBJS := \
options.o \
predictivedialog.o \
saveload.o \
+ saveload-dialog.o \
themebrowser.o \
ThemeEngine.o \
ThemeEval.o \
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index 9cd18b81ba..b827d49416 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -69,31 +69,33 @@ enum {
PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
new StaticTextWidget(this, "Predictive.Headline", "Enter Text");
- new ButtonWidget(this, "Predictive.Cancel" , _("Cancel"), 0, kCancelCmd);
- new ButtonWidget(this, "Predictive.OK" , _("Ok") , 0, kOkCmd);
- new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd);
- new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd);
- new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd);
- new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd);
- new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd);
- new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd);
- new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd);
- new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd);
- new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd);
- new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd);
- // I18N: You must leave "#" as is, only word 'next' is translatable
- new ButtonWidget(this, "Predictive.Next" , _("# next"), 0, kNextCmd);
- _addBtn = new ButtonWidget(this, "Predictive.Add", _("add"), 0, kAddCmd);
- _addBtn->setEnabled(false);
-
-#ifndef DISABLE_FANCY_THEMES
- _delbtn = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd);
- ((PicButtonWidget *)_delbtn)->useThemeTransparency(true);
- ((PicButtonWidget *)_delbtn)->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelbtn));
-#endif
- _delbtn = new ButtonWidget(this, "Predictive.Delete" , _("<"), 0, kDelCmd);
- // I18N: Pre means 'Predictive', leave '*' as is
- _modebutton = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd);
+ _btns = (ButtonWidget **)calloc(1, sizeof(ButtonWidget *) * 16);
+
+ _btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd);
+ _btns[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd);
+ _btns[kBtn1Act] = new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd);
+ _btns[kBtn2Act] = new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd);
+ _btns[kBtn3Act] = new ButtonWidget(this, "Predictive.Button3", "3 def" , 0, kBut3Cmd);
+ _btns[kBtn4Act] = new ButtonWidget(this, "Predictive.Button4", "4 ghi" , 0, kBut4Cmd);
+ _btns[kBtn5Act] = new ButtonWidget(this, "Predictive.Button5", "5 jkl" , 0, kBut5Cmd);
+ _btns[kBtn6Act] = new ButtonWidget(this, "Predictive.Button6", "6 mno" , 0, kBut6Cmd);
+ _btns[kBtn7Act] = new ButtonWidget(this, "Predictive.Button7", "7 pqrs" , 0, kBut7Cmd);
+ _btns[kBtn8Act] = new ButtonWidget(this, "Predictive.Button8", "8 tuv" , 0, kBut8Cmd);
+ _btns[kBtn9Act] = new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd);
+ _btns[kBtn0Act] = new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd);
+ // I18N: You must leave "#" as is, only word 'next' is translatable
+ _btns[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd);
+ _btns[kAddAct] = new ButtonWidget(this, "Predictive.Add", _("add") , 0, kAddCmd);
+ _btns[kAddAct]->setEnabled(false);
+
+ #ifndef DISABLE_FANCY_THEMES
+ _btns[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd);
+ ((PicButtonWidget *)_btns[kDelAct])->useThemeTransparency(true);
+ ((PicButtonWidget *)_btns[kDelAct])->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDelbtn));
+ #endif
+ _btns[kDelAct] = new ButtonWidget(this, "Predictive.Delete" , _("<") , 0, kDelCmd);
+ // I18N: Pre means 'Predictive', leave '*' as is
+ _btns[kModeAct] = new ButtonWidget(this, "Predictive.Pre", _("* Pre"), 0, kModeCmd);
_edittext = new EditTextWidget(this, "Predictive.Word", _search, 0, 0, 0);
_userDictHasChanged = false;
@@ -164,6 +166,8 @@ PredictiveDialog::~PredictiveDialog() {
free(_userDict.dictLine);
free(_predictiveDict.dictLine);
free(_unitedDict.dictLine);
+
+ free(_btns);
}
void PredictiveDialog::saveUserDictToFile() {
@@ -182,11 +186,23 @@ void PredictiveDialog::saveUserDictToFile() {
}
}
+void PredictiveDialog::handleKeyUp(Common::KeyState state) {
+ if (_currBtn != kNoAct && !_needRefresh) {
+ _btns[_currBtn]->startAnimatePressedState();
+ processBtnActive(_currBtn);
+ }
+}
+
void PredictiveDialog::handleKeyDown(Common::KeyState state) {
- ButtonId act = kNoAct;
+ _currBtn = kNoAct;
+ _needRefresh = false;
if (getFocusWidget() == _edittext) {
- setFocusWidget(_addBtn);
+ setFocusWidget(_btns[kAddAct]);
+ }
+
+ if (_lastbutton == kNoAct) {
+ _lastbutton = kBtn5Act;
}
switch (state.keycode) {
@@ -197,96 +213,126 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_LEFT:
_navigationwithkeys = true;
if (_lastbutton == kBtn1Act || _lastbutton == kBtn4Act || _lastbutton == kBtn7Act)
- act = ButtonId(_lastbutton + 2);
+ _currBtn = ButtonId(_lastbutton + 2);
+ else if (_lastbutton == kDelAct)
+ _currBtn = kBtn1Act;
+ else if (_lastbutton == kModeAct)
+ _currBtn = kNextAct;
else if (_lastbutton == kNextAct)
- act = kBtn0Act;
- else if (_lastbutton == kDelAct)
- act = kDelAct;
+ _currBtn = kBtn0Act;
+ else if (_lastbutton == kAddAct)
+ _currBtn = kOkAct;
else if (_lastbutton == kCancelAct)
- act = kOkAct;
- else if (_lastbutton == kModeAct)
- act = kAddAct;
+ _currBtn = kAddAct;
else
- act = ButtonId(_lastbutton - 1);
- _lastbutton = act;
- //needRefresh = true;
+ _currBtn = ButtonId(_lastbutton - 1);
+
+
+ if (_mode != kModeAbc && _lastbutton == kCancelAct)
+ _currBtn = kOkAct;
+
+ _needRefresh = true;
break;
case Common::KEYCODE_RIGHT:
_navigationwithkeys = true;
- if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act)
- act = ButtonId(_lastbutton - 2);
+ if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act || _lastbutton == kOkAct)
+ _currBtn = ButtonId(_lastbutton - 2);
+ else if (_lastbutton == kDelAct)
+ _currBtn = kBtn3Act;
+ else if (_lastbutton == kBtn0Act)
+ _currBtn = kNextAct;
+ else if (_lastbutton == kNextAct)
+ _currBtn = kModeAct;
else if (_lastbutton == kAddAct)
- act = kModeAct;
- else if (_lastbutton == kDelAct)
- act = kDelAct;
+ _currBtn = kCancelAct;
else if (_lastbutton == kOkAct)
- act = kCancelAct;
- else if (_lastbutton == kBtn0Act)
- act = kNextAct;
+ _currBtn = kAddAct;
else
- act = ButtonId(_lastbutton + 1);
- _lastbutton = act;
- //needRefresh = true;
+ _currBtn = ButtonId(_lastbutton + 1);
+
+ if (_mode != kModeAbc && _lastbutton == kOkAct)
+ _currBtn = kCancelAct;
+ _needRefresh = true;
break;
case Common::KEYCODE_UP:
_navigationwithkeys = true;
if (_lastbutton <= kBtn3Act)
- act = kDelAct;
- else if (_lastbutton == kNextAct || _lastbutton == kAddAct)
- act = ButtonId(_lastbutton - 2);
+ _currBtn = kDelAct;
else if (_lastbutton == kDelAct)
- act = kOkAct;
- else if (_lastbutton == kModeAct)
- act = kBtn9Act;
+ _currBtn = kOkAct;
+ else if (_lastbutton == kModeAct)
+ _currBtn = kBtn7Act;
else if (_lastbutton == kBtn0Act)
- act = kBtn7Act;
+ _currBtn = kBtn8Act;
+ else if (_lastbutton == kNextAct)
+ _currBtn = kBtn9Act;
+ else if (_lastbutton == kAddAct)
+ _currBtn = kModeAct;
+ else if (_lastbutton == kCancelAct)
+ _currBtn = kBtn0Act;
+ else if (_lastbutton == kOkAct)
+ _currBtn = kNextAct;
else
- act = ButtonId(_lastbutton - 3);
- _lastbutton = act;
- //needRefresh = true;
+ _currBtn = ButtonId(_lastbutton - 3);
+ _needRefresh = true;
break;
case Common::KEYCODE_DOWN:
_navigationwithkeys = true;
- if (_lastbutton == kBtn7Act)
- act = kBtn0Act;
- else if (_lastbutton == kBtn8Act || _lastbutton == kBtn9Act)
- act = ButtonId(_lastbutton + 2);
- else if (_lastbutton == kDelAct)
- act = kBtn1Act;
- else if (_lastbutton == kCancelAct || _lastbutton == kOkAct)
- act = kDelAct;
- else if (_lastbutton == kModeAct || _lastbutton == kBtn0Act)
- act = ButtonId(_lastbutton - 2);
+ if (_lastbutton == kDelAct)
+ _currBtn = kBtn3Act;
+ else if (_lastbutton == kBtn7Act)
+ _currBtn = kModeAct;
+ else if (_lastbutton == kBtn8Act)
+ _currBtn = kBtn0Act;
+ else if (_lastbutton == kBtn9Act)
+ _currBtn = kNextAct;
+ else if (_lastbutton == kModeAct)
+ _currBtn = kAddAct;
+ else if (_lastbutton == kBtn0Act)
+ _currBtn = kCancelAct;
+ else if (_lastbutton == kNextAct)
+ _currBtn = kOkAct;
+ else if (_lastbutton == kAddAct || _lastbutton == kCancelAct || _lastbutton == kOkAct)
+ _currBtn = kDelAct;
else
- act = ButtonId(_lastbutton + 3);
- _lastbutton = act;
- //needRefresh = true;
+ _currBtn = ButtonId(_lastbutton + 3);
+
+ if (_mode != kModeAbc && _lastbutton == kModeAct)
+ _currBtn = kCancelAct;
+
+ _needRefresh = true;
break;
case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_RETURN:
+ if (state.flags & Common::KBD_CTRL) {
+ _currBtn = kOkAct;
+ break;
+ }
if (_navigationwithkeys) {
// when the user has utilized arrow key navigation,
- // interpret enter as 'click' on the act button
- act = _lastbutton;
+ // interpret enter as 'click' on the _currBtn button
+ _currBtn = _lastbutton;
+ _needRefresh = false;
} else {
// else it is a shortcut for 'Ok'
- act = kOkAct;
+ _currBtn = kOkAct;
}
break;
case Common::KEYCODE_KP_PLUS:
- act = kAddAct;
+ _currBtn = kAddAct;
break;
case Common::KEYCODE_BACKSPACE:
case Common::KEYCODE_KP_MINUS:
- act = kDelAct;
+ _currBtn = kDelAct;
break;
case Common::KEYCODE_KP_DIVIDE:
- act = kNextAct;
+ _currBtn = kNextAct;
break;
case Common::KEYCODE_KP_MULTIPLY:
- act = kModeAct;
+ _currBtn = kModeAct;
break;
case Common::KEYCODE_KP0:
- act = kBtn0Act;
+ _currBtn = kBtn0Act;
break;
case Common::KEYCODE_KP1:
case Common::KEYCODE_KP2:
@@ -297,78 +343,93 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
case Common::KEYCODE_KP7:
case Common::KEYCODE_KP8:
case Common::KEYCODE_KP9:
- act = ButtonId(state.keycode - Common::KEYCODE_KP1);
+ _currBtn = ButtonId(state.keycode - Common::KEYCODE_KP1);
break;
default:
Dialog::handleKeyDown(state);
}
- if (act != kNoAct) {
- processBtnActive(act);
+ if (_lastbutton != _currBtn)
+ _btns[_lastbutton]->stopAnimatePressedState();
+
+ if (_currBtn != kNoAct && !_needRefresh)
+ _btns[_currBtn]->setPressedState();
+ else
+ updateHighLightedButton(_currBtn);
+}
+
+void PredictiveDialog::updateHighLightedButton(ButtonId act) {
+ if (_currBtn != kNoAct) {
+ _btns[_lastbutton]->setHighLighted(false);
+ _lastbutton = act;
+ _btns[_lastbutton]->setHighLighted(true);
}
}
void PredictiveDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
- ButtonId act = kNoAct;
+ _currBtn = kNoAct;
_navigationwithkeys = false;
+ if (_lastbutton != kNoAct)
+ _btns[_lastbutton]->setHighLighted(false);
+
switch (cmd) {
case kDelCmd:
- act = kDelAct;
+ _currBtn = kDelAct;
break;
case kNextCmd:
- act = kNextAct;
+ _currBtn = kNextAct;
break;
case kAddCmd:
- act = kAddAct;
+ _currBtn = kAddAct;
break;
case kModeCmd:
- act = kModeAct;
+ _currBtn = kModeAct;
break;
case kBut1Cmd:
- act = kBtn1Act;
+ _currBtn = kBtn1Act;
break;
case kBut2Cmd:
- act = kBtn2Act;
+ _currBtn = kBtn2Act;
break;
case kBut3Cmd:
- act = kBtn3Act;
+ _currBtn = kBtn3Act;
break;
case kBut4Cmd:
- act = kBtn4Act;
+ _currBtn = kBtn4Act;
break;
case kBut5Cmd:
- act = kBtn5Act;
+ _currBtn = kBtn5Act;
break;
case kBut6Cmd:
- act = kBtn6Act;
+ _currBtn = kBtn6Act;
break;
case kBut7Cmd:
- act = kBtn7Act;
+ _currBtn = kBtn7Act;
break;
case kBut8Cmd:
- act = kBtn8Act;
+ _currBtn = kBtn8Act;
break;
case kBut9Cmd:
- act = kBtn9Act;
+ _currBtn = kBtn9Act;
break;
case kBut0Cmd:
- act = kBtn0Act;
+ _currBtn = kBtn0Act;
break;
case kCancelCmd:
saveUserDictToFile();
close();
return;
case kOkCmd:
- act = kOkAct;
+ _currBtn = kOkAct;
break;
default:
Dialog::handleCommand(sender, cmd, data);
}
- if (act != kNoAct) {
- processBtnActive(act);
+ if (_currBtn != kNoAct) {
+ processBtnActive(_currBtn);
}
}
@@ -500,18 +561,18 @@ void PredictiveDialog::processBtnActive(ButtonId button) {
bringWordtoTop(_unitedDict.dictActLine, _wordNumber);
} else if (button == kModeAct) { // Mode
_mode++;
- _addBtn->setEnabled(false);
+ _btns[kAddAct]->setEnabled(false);
if (_mode > kModeAbc) {
_mode = kModePre;
// I18N: Pre means 'Predictive', leave '*' as is
- _modebutton->setLabel("* Pre");
+ _btns[kModeAct]->setLabel("* Pre");
} else if (_mode == kModeNum) {
// I18N: 'Num' means Numbers
- _modebutton->setLabel("* Num");
+ _btns[kModeAct]->setLabel("* Num");
} else {
// I18N: 'Abc' means Latin alphabet input
- _modebutton->setLabel("* Abc");
- _addBtn->setEnabled(true);
+ _btns[kModeAct]->setLabel("* Abc");
+ _btns[kAddAct]->setEnabled(true);
}
// truncate current input at mode change
@@ -532,18 +593,23 @@ void PredictiveDialog::processBtnActive(ButtonId button) {
if (button == kOkAct)
close();
+
+ if (button == kCancelAct) {
+ saveUserDictToFile();
+ close();
+ }
}
void PredictiveDialog::handleTickle() {
- // TODO/FIXME: This code does not seem to make any sense. It is only
- // triggered when _lastTime is zero and sets _lastTime to zero again
- // under some condition. This should really be a nop. Probably this
- // code intends to check "_lastTime" instead of "!_lastTime".
- if (!_lastTime) {
+ if (_lastTime) {
if ((_curTime - _lastTime) > kRepeatDelay) {
_lastTime = 0;
}
}
+
+ if (getTickleWidget()) {
+ getTickleWidget()->handleTickle();
+ }
}
void PredictiveDialog::mergeDicts() {
@@ -664,7 +730,7 @@ bool PredictiveDialog::matchWord() {
// The entries in the dictionary consist of a code, a space, and then
// a space-separated list of words matching this code.
- // To exactly match a code, we therefore match the code plus the trailing
+ // To ex_currBtnly match a code, we therefore match the code plus the trailing
// space in the dictionary.
Common::String code = _currentCode + " ";
diff --git a/gui/predictivedialog.h b/gui/predictivedialog.h
index 32de36d5f2..0e3d2967c0 100644
--- a/gui/predictivedialog.h
+++ b/gui/predictivedialog.h
@@ -68,6 +68,7 @@ public:
~PredictiveDialog();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void handleKeyUp(Common::KeyState state);
virtual void handleKeyDown(Common::KeyState state);
virtual void handleTickle();
@@ -98,6 +99,8 @@ private:
void saveUserDictToFile();
void mergeDicts();
+
+ void updateHighLightedButton(ButtonId active);
private:
Dict _unitedDict;
Dict _predictiveDict;
@@ -118,6 +121,7 @@ private:
uint32 _curTime, _lastTime;
ButtonId _lastPressBtn;
+ ButtonId _currBtn;
char _temp[kMaxWordLen + 1];
int _repeatcount[kMaxWordLen];
@@ -128,11 +132,10 @@ private:
Common::String _search;
bool _navigationwithkeys;
+ bool _needRefresh;
private:
EditTextWidget *_edittext;
- ButtonWidget *_modebutton;
- ButtonWidget *_delbtn;
- ButtonWidget *_addBtn;
+ ButtonWidget **_btns;
};
} // namespace GUI
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp
new file mode 100644
index 0000000000..850dfcc78f
--- /dev/null
+++ b/gui/saveload-dialog.cpp
@@ -0,0 +1,882 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "gui/saveload-dialog.h"
+#include "common/translation.h"
+#include "common/config-manager.h"
+
+#include "gui/message.h"
+#include "gui/gui-manager.h"
+#include "gui/ThemeEval.h"
+#include "gui/widgets/edittext.h"
+
+#include "graphics/scaler.h"
+
+namespace GUI {
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) {
+ const Common::String &userConfig = ConfMan.get("gui_saveload_chooser", Common::ConfigManager::kApplicationDomain);
+ if (g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400
+ && metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo)
+ && metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail)
+ && userConfig.equalsIgnoreCase("grid")) {
+ // In case we are 640x400 or higher, this dialog is not in save mode,
+ // the user requested the grid dialog and the engines supports it we
+ // try to set it up.
+ return kSaveLoadDialogGrid;
+ } else {
+ // In all other cases we want to use the list dialog.
+ return kSaveLoadDialogList;
+ }
+}
+
+enum {
+ kListSwitchCmd = 'LIST',
+ kGridSwitchCmd = 'GRID'
+};
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+SaveLoadChooserDialog::SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode)
+ : Dialog(dialogName), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
+ _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode)
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ , _listButton(0), _gridButton(0)
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+}
+
+SaveLoadChooserDialog::SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode)
+ : Dialog(x, y, w, h), _metaEngine(0), _delSupport(false), _metaInfoSupport(false),
+ _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode)
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ , _listButton(0), _gridButton(0)
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+}
+
+void SaveLoadChooserDialog::open() {
+ Dialog::open();
+
+ // So that quitting ScummVM will not cause the dialog result to say a
+ // savegame was selected.
+ setResult(-1);
+}
+
+int SaveLoadChooserDialog::run(const Common::String &target, const MetaEngine *metaEngine) {
+ _metaEngine = metaEngine;
+ _target = target;
+ _delSupport = _metaEngine->hasFeature(MetaEngine::kSupportsDeleteSave);
+ _metaInfoSupport = _metaEngine->hasFeature(MetaEngine::kSavesSupportMetaInfo);
+ _thumbnailSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportThumbnail);
+ _saveDateSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportCreationDate);
+ _playTimeSupport = _metaInfoSupport && _metaEngine->hasFeature(MetaEngine::kSavesSupportPlayTime);
+
+ return runIntern();
+}
+
+void SaveLoadChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ switch (cmd) {
+ case kListSwitchCmd:
+ setResult(kSwitchSaveLoadDialog);
+ // We save the requested dialog type here to avoid the setting to be
+ // overwritten when our reflowLayout logic selects a different dialog
+ // type.
+ ConfMan.set("gui_saveload_chooser", "list", Common::ConfigManager::kApplicationDomain);
+ close();
+ break;
+
+ case kGridSwitchCmd:
+ setResult(kSwitchSaveLoadDialog);
+ // See above.
+ ConfMan.set("gui_saveload_chooser", "grid", Common::ConfigManager::kApplicationDomain);
+ close();
+ break;
+
+ default:
+ break;
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ return Dialog::handleCommand(sender, cmd, data);
+}
+
+void SaveLoadChooserDialog::reflowLayout() {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ addChooserButtons();
+
+ const SaveLoadChooserType currentType = getType();
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
+
+ // Change the dialog type if there is any need for it.
+ if (requestedType != currentType) {
+ setResult(kSwitchSaveLoadDialog);
+ close();
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ Dialog::reflowLayout();
+}
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+void SaveLoadChooserDialog::addChooserButtons() {
+ if (_listButton) {
+ removeWidget(_listButton);
+ delete _listButton;
+ }
+
+ if (_gridButton) {
+ removeWidget(_gridButton);
+ delete _gridButton;
+ }
+
+ _listButton = createSwitchButton("SaveLoadChooser.ListSwitch", "L", _("List view"), ThemeEngine::kImageList, kListSwitchCmd);
+ _gridButton = createSwitchButton("SaveLoadChooser.GridSwitch", "G", _("Grid view"), ThemeEngine::kImageGrid, kGridSwitchCmd);
+ if (!_metaInfoSupport || !_thumbnailSupport || !(g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400)) {
+ _gridButton->setEnabled(false);
+ _listButton->setEnabled(false);
+ }
+}
+
+ButtonWidget *SaveLoadChooserDialog::createSwitchButton(const Common::String &name, const char *desc, const char *tooltip, const char *image, uint32 cmd) {
+ ButtonWidget *button;
+
+#ifndef DISABLE_FANCY_THEMES
+ if (g_gui.xmlEval()->getVar("Globals.ShowChooserPics") == 1 && g_gui.theme()->supportsImages()) {
+ button = new PicButtonWidget(this, name, tooltip, cmd);
+ ((PicButtonWidget *)button)->useThemeTransparency(true);
+ ((PicButtonWidget *)button)->setGfx(g_gui.theme()->getImageSurface(image));
+ } else
+#endif
+ button = new ButtonWidget(this, name, desc, tooltip, cmd);
+
+ return button;
+}
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+// SaveLoadChooserSimple implementation
+
+enum {
+ kChooseCmd = 'CHOS',
+ kDelCmd = 'DEL '
+};
+
+SaveLoadChooserSimple::SaveLoadChooserSimple(const String &title, const String &buttonLabel, bool saveMode)
+ : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) {
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", title);
+
+ // Add choice list
+ _list = new ListWidget(this, "SaveLoadChooser.List");
+ _list->setNumberingMode(kListNumberingZero);
+ _list->setEditable(saveMode);
+
+ _gfxWidget = new GraphicsWidget(this, 0, 0, 10, 10);
+
+ _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
+ _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
+ _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
+
+ // Buttons
+ new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
+ _chooseButton = new ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
+ _chooseButton->setEnabled(false);
+
+ _deleteButton = new ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
+ _deleteButton->setEnabled(false);
+
+ _delSupport = _metaInfoSupport = _thumbnailSupport = false;
+
+ _container = new ContainerWidget(this, 0, 0, 10, 10);
+// _container->setHints(THEME_HINT_USE_SHADOW);
+}
+
+int SaveLoadChooserSimple::runIntern() {
+ if (_gfxWidget)
+ _gfxWidget->setGfx(0);
+
+ _resultString.clear();
+ reflowLayout();
+ updateSaveList();
+
+ return Dialog::runModal();
+}
+
+const Common::String &SaveLoadChooserSimple::getResultString() const {
+ int selItem = _list->getSelected();
+ return (selItem >= 0) ? _list->getSelectedString() : _resultString;
+}
+
+void SaveLoadChooserSimple::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ int selItem = _list->getSelected();
+
+ switch (cmd) {
+ case kListItemActivatedCmd:
+ case kListItemDoubleClickedCmd:
+ if (selItem >= 0 && _chooseButton->isEnabled()) {
+ if (_list->isEditable() || !_list->getSelectedString().empty()) {
+ _list->endEditMode();
+ if (!_saveList.empty()) {
+ setResult(_saveList[selItem].getSaveSlot());
+ _resultString = _list->getSelectedString();
+ }
+ close();
+ }
+ }
+ break;
+ case kChooseCmd:
+ _list->endEditMode();
+ if (!_saveList.empty()) {
+ setResult(_saveList[selItem].getSaveSlot());
+ _resultString = _list->getSelectedString();
+ }
+ close();
+ break;
+ case kListSelectionChangedCmd:
+ updateSelection(true);
+ break;
+ case kDelCmd:
+ if (selItem >= 0 && _delSupport) {
+ MessageDialog alert(_("Do you really want to delete this savegame?"),
+ _("Delete"), _("Cancel"));
+ if (alert.runModal() == kMessageOK) {
+ _metaEngine->removeSaveState(_target.c_str(), _saveList[selItem].getSaveSlot());
+
+ setResult(-1);
+ _list->setSelected(-1);
+
+ updateSaveList();
+ updateSelection(true);
+ }
+ }
+ break;
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ SaveLoadChooserDialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void SaveLoadChooserSimple::reflowLayout() {
+ if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && _thumbnailSupport) {
+ int16 x, y;
+ uint16 w, h;
+
+ if (!g_gui.xmlEval()->getWidgetData("SaveLoadChooser.Thumbnail", x, y, w, h))
+ error("Error when loading position data for Save/Load Thumbnails");
+
+ int thumbW = kThumbnailWidth;
+ int thumbH = kThumbnailHeight2;
+ int thumbX = x + (w >> 1) - (thumbW >> 1);
+ int thumbY = y + kLineHeight;
+
+ int textLines = 0;
+ if (!_saveDateSupport)
+ textLines++;
+ if (!_playTimeSupport)
+ textLines++;
+
+ _container->resize(x, y, w, h - (kLineHeight * textLines));
+ _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
+
+ int height = thumbY + thumbH + kLineHeight;
+
+ if (_saveDateSupport) {
+ _date->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ _time->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+ height += kLineHeight;
+ }
+
+ if (_playTimeSupport)
+ _playtime->resize(thumbX, height, kThumbnailWidth, kLineHeight);
+
+ _container->setVisible(true);
+ _gfxWidget->setVisible(true);
+
+ _date->setVisible(_saveDateSupport);
+ _time->setVisible(_saveDateSupport);
+
+ _playtime->setVisible(_playTimeSupport);
+
+ updateSelection(false);
+ } else {
+ _container->setVisible(false);
+ _gfxWidget->setVisible(false);
+ _date->setVisible(false);
+ _time->setVisible(false);
+ _playtime->setVisible(false);
+ }
+
+ SaveLoadChooserDialog::reflowLayout();
+}
+
+void SaveLoadChooserSimple::updateSelection(bool redraw) {
+ int selItem = _list->getSelected();
+
+ bool isDeletable = _delSupport;
+ bool isWriteProtected = false;
+ bool startEditMode = _list->isEditable();
+
+ // We used to support letting the themes specify the fill color with our
+ // initial theme based GUI. But this support was dropped.
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ _date->setLabel(_("No date saved"));
+ _time->setLabel(_("No time saved"));
+ _playtime->setLabel(_("No playtime saved"));
+
+ if (selItem >= 0 && _metaInfoSupport) {
+ SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot());
+
+ isDeletable = desc.getDeletableFlag() && _delSupport;
+ isWriteProtected = desc.getWriteProtectedFlag();
+
+ // Don't allow the user to change the description of write protected games
+ if (isWriteProtected)
+ startEditMode = false;
+
+ if (_thumbnailSupport) {
+ const Graphics::Surface *thumb = desc.getThumbnail();
+ if (thumb) {
+ _gfxWidget->setGfx(thumb);
+ _gfxWidget->useAlpha(256);
+ }
+ }
+
+ if (_saveDateSupport) {
+ const Common::String &saveDate = desc.getSaveDate();
+ if (!saveDate.empty())
+ _date->setLabel(_("Date: ") + saveDate);
+
+ const Common::String &saveTime = desc.getSaveTime();
+ if (!saveTime.empty())
+ _time->setLabel(_("Time: ") + saveTime);
+ }
+
+ if (_playTimeSupport) {
+ const Common::String &playTime = desc.getPlayTime();
+ if (!playTime.empty())
+ _playtime->setLabel(_("Playtime: ") + playTime);
+ }
+ }
+
+
+ if (_list->isEditable()) {
+ // Disable the save button if nothing is selected, or if the selected
+ // game is write protected
+ _chooseButton->setEnabled(selItem >= 0 && !isWriteProtected);
+
+ if (startEditMode) {
+ _list->startEditMode();
+
+ if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") &&
+ _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
+ _list->setEditString("");
+ _list->setEditColor(ThemeEngine::kFontColorNormal);
+ }
+ }
+ } else {
+ // Disable the load button if nothing is selected, or if an empty
+ // list item is selected.
+ _chooseButton->setEnabled(selItem >= 0 && !_list->getSelectedString().empty());
+ }
+
+ // Delete will always be disabled if the engine doesn't support it.
+ _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
+
+ if (redraw) {
+ _gfxWidget->draw();
+ _date->draw();
+ _time->draw();
+ _playtime->draw();
+ _chooseButton->draw();
+ _deleteButton->draw();
+
+ draw();
+ }
+}
+
+void SaveLoadChooserSimple::close() {
+ _metaEngine = 0;
+ _target.clear();
+ _saveList.clear();
+ _list->setList(StringArray());
+
+ SaveLoadChooserDialog::close();
+}
+
+void SaveLoadChooserSimple::updateSaveList() {
+ _saveList = _metaEngine->listSaves(_target.c_str());
+
+ int curSlot = 0;
+ int saveSlot = 0;
+ StringArray saveNames;
+ ListWidget::ColorList colors;
+ for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
+ // Handle gaps in the list of save games
+ saveSlot = x->getSaveSlot();
+ if (curSlot < saveSlot) {
+ while (curSlot < saveSlot) {
+ SaveStateDescriptor dummySave(curSlot, "");
+ _saveList.insert_at(curSlot, dummySave);
+ saveNames.push_back(dummySave.getDescription());
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ curSlot++;
+ }
+
+ // Sync the save list iterator
+ for (x = _saveList.begin(); x != _saveList.end(); ++x) {
+ if (x->getSaveSlot() == saveSlot)
+ break;
+ }
+ }
+
+ // Show "Untitled savestate" for empty/whitespace savegame descriptions
+ Common::String description = x->getDescription();
+ Common::String trimmedDescription = description;
+ trimmedDescription.trim();
+ if (trimmedDescription.empty()) {
+ description = _("Untitled savestate");
+ colors.push_back(ThemeEngine::kFontColorAlternate);
+ } else {
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ }
+
+ saveNames.push_back(description);
+ curSlot++;
+ }
+
+ // Fill the rest of the save slots with empty saves
+
+ int maximumSaveSlots = _metaEngine->getMaximumSaveSlot();
+
+#ifdef __DS__
+ // Low memory on the DS means too many save slots are impractical, so limit
+ // the maximum here.
+ if (maximumSaveSlots > 99) {
+ maximumSaveSlots = 99;
+ }
+#endif
+
+ Common::String emptyDesc;
+ for (int i = curSlot; i <= maximumSaveSlots; i++) {
+ saveNames.push_back(emptyDesc);
+ SaveStateDescriptor dummySave(i, "");
+ _saveList.push_back(dummySave);
+ colors.push_back(ThemeEngine::kFontColorNormal);
+ }
+
+ _list->setList(saveNames, &colors);
+}
+
+// SaveLoadChooserGrid implementation
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+
+enum {
+ kNextCmd = 'NEXT',
+ kPrevCmd = 'PREV',
+ kNewSaveCmd = 'SAVE'
+};
+
+SaveLoadChooserGrid::SaveLoadChooserGrid(const Common::String &title, bool saveMode)
+ : SaveLoadChooserDialog("SaveLoadChooser", saveMode), _lines(0), _columns(0), _entriesPerPage(0),
+ _curPage(0), _newSaveContainer(0), _nextFreeSaveSlot(0), _buttons() {
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", title);
+
+ // Buttons
+ new ButtonWidget(this, "SaveLoadChooser.Delete", _("Cancel"), 0, kCloseCmd);
+ _nextButton = new ButtonWidget(this, "SaveLoadChooser.Choose", _("Next"), 0, kNextCmd);
+ _nextButton->setEnabled(false);
+
+ _prevButton = new ButtonWidget(this, "SaveLoadChooser.Cancel", _("Prev"), 0, kPrevCmd);
+ _prevButton->setEnabled(false);
+
+ // Page display
+ _pageDisplay = new StaticTextWidget(this, "SaveLoadChooser.PageDisplay", Common::String());
+ _pageDisplay->setAlign(Graphics::kTextAlignRight);
+}
+
+SaveLoadChooserGrid::~SaveLoadChooserGrid() {
+ removeWidget(_pageDisplay);
+ delete _pageDisplay;
+}
+
+const Common::String &SaveLoadChooserGrid::getResultString() const {
+ return _resultString;
+}
+
+void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ if (cmd <= _entriesPerPage && cmd + _curPage * _entriesPerPage <= _saveList.size()) {
+ const SaveStateDescriptor &desc = _saveList[cmd - 1 + _curPage * _entriesPerPage];
+
+ if (_saveMode) {
+ _resultString = desc.getDescription();
+ }
+
+ setResult(desc.getSaveSlot());
+ close();
+ }
+
+ switch (cmd) {
+ case kNextCmd:
+ ++_curPage;
+ updateSaves();
+ draw();
+ break;
+
+ case kPrevCmd:
+ --_curPage;
+ updateSaves();
+ draw();
+ break;
+
+ case kNewSaveCmd:
+ setResult(_nextFreeSaveSlot);
+ close();
+ break;
+
+ case kCloseCmd:
+ setResult(-1);
+ default:
+ SaveLoadChooserDialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
+ if (direction > 0) {
+ if (_nextButton->isEnabled()) {
+ ++_curPage;
+ updateSaves();
+ draw();
+ }
+ } else {
+ if (_prevButton->isEnabled()) {
+ --_curPage;
+ updateSaves();
+ draw();
+ }
+ }
+}
+
+void SaveLoadChooserGrid::open() {
+ SaveLoadChooserDialog::open();
+
+ _curPage = 0;
+ _saveList = _metaEngine->listSaves(_target.c_str());
+ _resultString.clear();
+
+ // Determine the next free save slot for save mode
+ if (_saveMode) {
+ int lastSlot = -1;
+ _nextFreeSaveSlot = -1;
+ for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
+ const int curSlot = x->getSaveSlot();
+
+ // In case there was a gap found use the slot.
+ if (lastSlot + 1 < curSlot) {
+ _nextFreeSaveSlot = lastSlot + 1;
+ break;
+ }
+
+ lastSlot = curSlot;
+ }
+
+ // Use the next available slot otherwise.
+ if (_nextFreeSaveSlot == -1 && lastSlot + 1 < _metaEngine->getMaximumSaveSlot()) {
+ _nextFreeSaveSlot = lastSlot + 1;
+ }
+ }
+
+ updateSaves();
+}
+
+void SaveLoadChooserGrid::reflowLayout() {
+ // HACK: The page display is not available in low resolution layout. We
+ // remove and readd the widget here to avoid our GUI from erroring out.
+ removeWidget(_pageDisplay);
+ if (g_gui.xmlEval()->getVar("Globals.ShowChooserPageDisplay") == 1) {
+ _pageDisplay->init();
+ }
+
+ SaveLoadChooserDialog::reflowLayout();
+ destroyButtons();
+
+ // HACK: The whole code below really works around the fact, that we have
+ // no easy way to dynamically layout widgets.
+ const uint16 availableWidth = getWidth() - 20;
+ uint16 availableHeight;
+
+ int16 x, y;
+ uint16 w;
+ g_gui.xmlEval()->getWidgetData("SaveLoadChooser.List", x, y, w, availableHeight);
+
+ const int16 buttonWidth = kThumbnailWidth + 6;
+ const int16 buttonHeight = kThumbnailHeight2 + 6;
+
+ const int16 containerFrameWidthAdd = 10;
+ const int16 containerFrameHeightAdd = 0;
+ const int16 containerWidth = buttonWidth + containerFrameWidthAdd;
+ const int16 containerHeight = buttonHeight + kLineHeight + containerFrameHeightAdd;
+
+ const int16 defaultSpacingHorizontal = 4;
+ const int16 defaultSpacingVertical = 8;
+ const int16 slotAreaWidth = containerWidth + defaultSpacingHorizontal;
+ const int16 slotAreaHeight = containerHeight + defaultSpacingVertical;
+
+ const uint oldEntriesPerPage = _entriesPerPage;
+ _columns = MAX<uint>(1, availableWidth / slotAreaWidth);
+ _lines = MAX<uint>(1, availableHeight / slotAreaHeight);
+ _entriesPerPage = _columns * _lines;
+
+ // In save mode the first button is always "New Save", thus we need to
+ // adjust the entries per page here.
+ if (_saveMode) {
+ --_entriesPerPage;
+ }
+
+ // Recalculate the page number
+ if (!_saveList.empty() && oldEntriesPerPage != 0) {
+ if (_entriesPerPage != 0) {
+ _curPage = (_curPage * oldEntriesPerPage) / _entriesPerPage;
+ } else {
+ _curPage = 0;
+ }
+ }
+
+ const uint addX = _columns > 1 ? (availableWidth % slotAreaWidth) / (_columns - 1) : 0;
+ //const uint addY = _lines > 1 ? (availableHeight % slotAreaHeight) / (_lines - 1) : 0;
+
+ _buttons.reserve(_lines * _columns);
+ y += defaultSpacingVertical / 2;
+ for (uint curLine = 0; curLine < _lines; ++curLine, y += slotAreaHeight/* + addY*/) {
+ for (uint curColumn = 0, curX = x + defaultSpacingHorizontal / 2; curColumn < _columns; ++curColumn, curX += slotAreaWidth + addX) {
+ int dstY = containerFrameHeightAdd / 2;
+ int dstX = containerFrameWidthAdd / 2;
+
+ // In the save mode we will always create a new save button as the first button.
+ if (_saveMode && curLine == 0 && curColumn == 0) {
+ _newSaveContainer = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
+ ButtonWidget *newSave = new ButtonWidget(_newSaveContainer, dstX, dstY, buttonWidth, buttonHeight, _("New Save"), _("Create a new save game"), kNewSaveCmd);
+ // In case no more slots are free, we will disable the new save button
+ if (_nextFreeSaveSlot == -1) {
+ newSave->setEnabled(false);
+ }
+ continue;
+ }
+
+ ContainerWidget *container = new ContainerWidget(this, curX, y, containerWidth, containerHeight);
+ container->setVisible(false);
+
+ // Command 0 cannot be used, since it won't be send. Thus we will adjust
+ // command number here, if required. This is only the case for load mode
+ // since for save mode, the first button used is index 1 anyway.
+ uint buttonCmd = curLine * _columns + curColumn;
+ if (!_saveMode) {
+ buttonCmd += 1;
+ }
+
+ PicButtonWidget *button = new PicButtonWidget(container, dstX, dstY, buttonWidth, buttonHeight, 0, buttonCmd);
+ dstY += buttonHeight;
+
+ StaticTextWidget *description = new StaticTextWidget(container, dstX, dstY, buttonWidth, kLineHeight, Common::String(), Graphics::kTextAlignLeft);
+
+ _buttons.push_back(SlotButton(container, button, description));
+ }
+ }
+
+ if (!_target.empty())
+ updateSaves();
+}
+
+void SaveLoadChooserGrid::close() {
+ SaveLoadChooserDialog::close();
+ hideButtons();
+}
+
+int SaveLoadChooserGrid::runIntern() {
+ int slot;
+ do {
+ const SaveLoadChooserType currentType = getType();
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(*_metaEngine);
+
+ // Catch resolution changes when the save name dialog was open.
+ if (currentType != requestedType) {
+ setResult(kSwitchSaveLoadDialog);
+ return kSwitchSaveLoadDialog;
+ }
+
+ slot = runModal();
+ } while (_saveMode && slot >= 0 && !selectDescription());
+
+ return slot;
+}
+
+bool SaveLoadChooserGrid::selectDescription() {
+ _savenameDialog.setDescription(_resultString);
+ _savenameDialog.setTargetSlot(getResult());
+ if (_savenameDialog.runModal() == 0) {
+ _resultString = _savenameDialog.getDescription();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SaveLoadChooserGrid::destroyButtons() {
+ if (_newSaveContainer) {
+ removeWidget(_newSaveContainer);
+ delete _newSaveContainer;
+ _newSaveContainer = 0;
+ }
+
+ for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
+ removeWidget(i->container);
+ delete i->container;
+ }
+
+ _buttons.clear();
+}
+
+void SaveLoadChooserGrid::hideButtons() {
+ for (ButtonArray::iterator i = _buttons.begin(), end = _buttons.end(); i != end; ++i) {
+ i->button->setGfx(0);
+ i->setVisible(false);
+ }
+}
+
+void SaveLoadChooserGrid::updateSaves() {
+ hideButtons();
+
+ for (uint i = _curPage * _entriesPerPage, curNum = 0; i < _saveList.size() && curNum < _entriesPerPage; ++i, ++curNum) {
+ const uint saveSlot = _saveList[i].getSaveSlot();
+
+ SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), saveSlot);
+ SlotButton &curButton = _buttons[curNum];
+ curButton.setVisible(true);
+ const Graphics::Surface *thumbnail = desc.getThumbnail();
+ if (thumbnail) {
+ curButton.button->setGfx(desc.getThumbnail());
+ } else {
+ curButton.button->setGfx(kThumbnailWidth, kThumbnailHeight2, 0, 0, 0);
+ }
+ curButton.description->setLabel(Common::String::format("%d. %s", saveSlot, desc.getDescription().c_str()));
+
+ Common::String tooltip(_("Name: "));
+ tooltip += desc.getDescription();
+
+ if (_saveDateSupport) {
+ const Common::String &saveDate = desc.getSaveDate();
+ if (!saveDate.empty()) {
+ tooltip += "\n";
+ tooltip += _("Date: ") + saveDate;
+ }
+
+ const Common::String &saveTime = desc.getSaveTime();
+ if (!saveTime.empty()) {
+ tooltip += "\n";
+ tooltip += _("Time: ") + saveTime;
+ }
+ }
+
+ if (_playTimeSupport) {
+ const Common::String &playTime = desc.getPlayTime();
+ if (!playTime.empty()) {
+ tooltip += "\n";
+ tooltip += _("Playtime: ") + playTime;
+ }
+ }
+
+ curButton.button->setTooltip(tooltip);
+
+ // In save mode we disable the button, when it's write protected.
+ // TODO: Maybe we should not display it at all then?
+ if (_saveMode && desc.getWriteProtectedFlag()) {
+ curButton.button->setEnabled(false);
+ } else {
+ curButton.button->setEnabled(true);
+ }
+ }
+
+ const uint numPages = (_entriesPerPage != 0) ? (_saveList.size() / _entriesPerPage + 1) : 1;
+ _pageDisplay->setLabel(Common::String::format("%u/%u", _curPage + 1, numPages));
+
+ if (_curPage > 0)
+ _prevButton->setEnabled(true);
+ else
+ _prevButton->setEnabled(false);
+
+ if ((_curPage + 1) * _entriesPerPage < _saveList.size())
+ _nextButton->setEnabled(true);
+ else
+ _nextButton->setEnabled(false);
+}
+
+SavenameDialog::SavenameDialog()
+ : Dialog("SavenameDialog") {
+ _title = new StaticTextWidget(this, "SavenameDialog.DescriptionText", Common::String());
+
+ new ButtonWidget(this, "SavenameDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new ButtonWidget(this, "SavenameDialog.Ok", _("OK"), 0, kOKCmd);
+
+ _description = new EditTextWidget(this, "SavenameDialog.Description", Common::String(), 0, 0, kOKCmd);
+}
+
+void SavenameDialog::setDescription(const Common::String &desc) {
+ _description->setEditString(desc);
+}
+
+const Common::String &SavenameDialog::getDescription() {
+ return _description->getEditString();
+}
+
+void SavenameDialog::open() {
+ Dialog::open();
+ setResult(-1);
+
+ _title->setLabel(Common::String::format(_("Enter a description for slot %d:"), _targetSlot));
+}
+
+void SavenameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch (cmd) {
+ case kOKCmd:
+ setResult(0);
+ close();
+ break;
+
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+} // End of namespace GUI
diff --git a/gui/saveload-dialog.h b/gui/saveload-dialog.h
new file mode 100644
index 0000000000..9d0350d69d
--- /dev/null
+++ b/gui/saveload-dialog.h
@@ -0,0 +1,208 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GUI_SAVELOAD_DIALOG_H
+#define GUI_SAVELOAD_DIALOG_H
+
+#include "gui/dialog.h"
+#include "gui/widgets/list.h"
+
+#include "engines/metaengine.h"
+
+namespace GUI {
+
+#define kSwitchSaveLoadDialog -2
+
+// TODO: We might want to disable the grid based save/load chooser for more
+// platforms, than those which define DISABLE_FANCY_THEMES. But those are
+// probably not able to handle the grid chooser anyway, so disabling it
+// for them is a good start.
+#ifdef DISABLE_FANCY_THEMES
+#define DISABLE_SAVELOADCHOOSER_GRID
+#endif // DISABLE_FANCY_THEMES
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+enum SaveLoadChooserType {
+ kSaveLoadDialogList = 0,
+ kSaveLoadDialogGrid = 1
+};
+
+SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine);
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+class SaveLoadChooserDialog : protected Dialog {
+public:
+ SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode);
+ SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode);
+
+ virtual void open();
+
+ virtual void reflowLayout();
+
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ virtual SaveLoadChooserType getType() const = 0;
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ int run(const Common::String &target, const MetaEngine *metaEngine);
+ virtual const Common::String &getResultString() const = 0;
+
+protected:
+ virtual int runIntern() = 0;
+
+ const bool _saveMode;
+ const MetaEngine *_metaEngine;
+ bool _delSupport;
+ bool _metaInfoSupport;
+ bool _thumbnailSupport;
+ bool _saveDateSupport;
+ bool _playTimeSupport;
+ Common::String _target;
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ ButtonWidget *_listButton;
+ ButtonWidget *_gridButton;
+
+ void addChooserButtons();
+ ButtonWidget *createSwitchButton(const Common::String &name, const char *desc, const char *tooltip, const char *image, uint32 cmd = 0);
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+};
+
+class SaveLoadChooserSimple : public SaveLoadChooserDialog {
+ typedef Common::String String;
+ typedef Common::Array<Common::String> StringArray;
+public:
+ SaveLoadChooserSimple(const String &title, const String &buttonLabel, bool saveMode);
+
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+ virtual const Common::String &getResultString() const;
+
+ virtual void reflowLayout();
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ virtual SaveLoadChooserType getType() const { return kSaveLoadDialogList; }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+ virtual void close();
+private:
+ virtual int runIntern();
+
+ ListWidget *_list;
+ ButtonWidget *_chooseButton;
+ ButtonWidget *_deleteButton;
+ GraphicsWidget *_gfxWidget;
+ ContainerWidget *_container;
+ StaticTextWidget *_date;
+ StaticTextWidget *_time;
+ StaticTextWidget *_playtime;
+
+ SaveStateList _saveList;
+ String _resultString;
+
+ void updateSaveList();
+ void updateSelection(bool redraw);
+};
+
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+
+class EditTextWidget;
+
+class SavenameDialog : public Dialog {
+public:
+ SavenameDialog();
+
+ void setDescription(const Common::String &desc);
+ const Common::String &getDescription();
+
+ void setTargetSlot(int slot) { _targetSlot = slot; }
+
+ virtual void open();
+protected:
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+private:
+ int _targetSlot;
+ StaticTextWidget *_title;
+ EditTextWidget *_description;
+};
+
+class SaveLoadChooserGrid : public SaveLoadChooserDialog {
+public:
+ SaveLoadChooserGrid(const Common::String &title, bool saveMode);
+ ~SaveLoadChooserGrid();
+
+ virtual const Common::String &getResultString() const;
+
+ virtual void open();
+
+ virtual void reflowLayout();
+
+ virtual SaveLoadChooserType getType() const { return kSaveLoadDialogGrid; }
+
+ virtual void close();
+protected:
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void handleMouseWheel(int x, int y, int direction);
+private:
+ virtual int runIntern();
+
+ uint _columns, _lines;
+ uint _entriesPerPage;
+ uint _curPage;
+ SaveStateList _saveList;
+
+ ButtonWidget *_nextButton;
+ ButtonWidget *_prevButton;
+
+ StaticTextWidget *_pageDisplay;
+
+ ContainerWidget *_newSaveContainer;
+ int _nextFreeSaveSlot;
+ Common::String _resultString;
+
+ SavenameDialog _savenameDialog;
+ bool selectDescription();
+
+ struct SlotButton {
+ SlotButton() : container(0), button(0), description(0) {}
+ SlotButton(ContainerWidget *c, PicButtonWidget *b, StaticTextWidget *d) : container(c), button(b), description(d) {}
+
+ ContainerWidget *container;
+ PicButtonWidget *button;
+ StaticTextWidget *description;
+
+ void setVisible(bool state) {
+ container->setVisible(state);
+ }
+ };
+ typedef Common::Array<SlotButton> ButtonArray;
+ ButtonArray _buttons;
+ void destroyButtons();
+ void hideButtons();
+ void updateSaves();
+};
+
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/saveload.cpp b/gui/saveload.cpp
index 3dc9961906..c2bbcd9bec 100644
--- a/gui/saveload.cpp
+++ b/gui/saveload.cpp
@@ -20,83 +20,87 @@
*/
#include "common/config-manager.h"
-#include "common/translation.h"
+#include "common/system.h"
-#include "gui/widgets/list.h"
-#include "gui/message.h"
#include "gui/saveload.h"
-#include "gui/ThemeEval.h"
+#include "gui/saveload-dialog.h"
#include "gui/gui-manager.h"
-#include "graphics/scaler.h"
-
#include "engines/metaengine.h"
namespace GUI {
-enum {
- kChooseCmd = 'CHOS',
- kDelCmd = 'DEL '
-
-};
-
-SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel)
- : Dialog("SaveLoadChooser"), _delSupport(0), _list(0), _chooseButton(0), _deleteButton(0), _gfxWidget(0) {
- _delSupport = _metaInfoSupport = _thumbnailSupport = _saveDateSupport = _playTimeSupport = false;
-
- _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
-
- new StaticTextWidget(this, "SaveLoadChooser.Title", title);
-
- // Add choice list
- _list = new GUI::ListWidget(this, "SaveLoadChooser.List");
- _list->setNumberingMode(GUI::kListNumberingZero);
- setSaveMode(false);
-
- _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
+SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode)
+ : _impl(0), _title(title), _buttonLabel(buttonLabel), _saveMode(saveMode) {
+}
- _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter);
- _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter);
- _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter);
+SaveLoadChooser::~SaveLoadChooser() {
+ delete _impl;
+ _impl = 0;
+}
- // Buttons
- new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd);
- _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd);
- _chooseButton->setEnabled(false);
+void SaveLoadChooser::selectChooser(const MetaEngine &engine) {
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog(engine);
+ if (!_impl || _impl->getType() != requestedType) {
+ delete _impl;
+ _impl = 0;
+
+ switch (requestedType) {
+ case kSaveLoadDialogGrid:
+ _impl = new SaveLoadChooserGrid(_title, _saveMode);
+ break;
+
+ case kSaveLoadDialogList:
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ _impl = new SaveLoadChooserSimple(_title, _buttonLabel, _saveMode);
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ break;
+ }
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+}
- _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd);
- _deleteButton->setEnabled(false);
+Common::String SaveLoadChooser::createDefaultSaveDescription(const int slot) const {
+#if defined(USE_SAVEGAME_TIMESTAMP)
+ TimeDate curTime;
+ g_system->getTimeAndDate(curTime);
+ curTime.tm_year += 1900; // fixup year
+ curTime.tm_mon++; // fixup month
+ return Common::String::format("%04d.%02d.%02d / %02d:%02d:%02d", curTime.tm_year, curTime.tm_mon, curTime.tm_mday, curTime.tm_hour, curTime.tm_min, curTime.tm_sec);
+#else
+ return Common::String::format("Save %d", slot + 1);
+#endif
+}
- _delSupport = _metaInfoSupport = _thumbnailSupport = false;
+int SaveLoadChooser::runModalWithCurrentTarget() {
+ const Common::String gameId = ConfMan.get("gameid");
- _container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
-// _container->setHints(GUI::THEME_HINT_USE_SHADOW);
-}
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
-SaveLoadChooser::~SaveLoadChooser() {
+ return runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
}
int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target) {
- if (_gfxWidget)
- _gfxWidget->setGfx(0);
+ selectChooser(**plugin);
+ if (!_impl)
+ return -1;
// Set up the game domain as newly active domain, so
// target specific savepath will be checked
String oldDomain = ConfMan.getActiveDomainName();
ConfMan.setActiveDomain(target);
- _plugin = plugin;
- _target = target;
- _delSupport = (*_plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
- _metaInfoSupport = (*_plugin)->hasFeature(MetaEngine::kSavesSupportMetaInfo);
- _thumbnailSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportThumbnail);
- _saveDateSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportCreationDate);
- _playTimeSupport = _metaInfoSupport && (*_plugin)->hasFeature(MetaEngine::kSavesSupportPlayTime);
- _resultString.clear();
- reflowLayout();
- updateSaveList();
-
- int ret = Dialog::runModal();
+ int ret;
+ do {
+ ret = _impl->run(target, &(**plugin));
+#ifndef DISABLE_SAVELOADCHOOSER_GRID
+ if (ret == kSwitchSaveLoadDialog) {
+ selectChooser(**plugin);
+ }
+#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ } while (ret < -1);
// Revert to the old active domain
ConfMan.setActiveDomain(oldDomain);
@@ -104,284 +108,9 @@ int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, con
return ret;
}
-void SaveLoadChooser::open() {
- Dialog::open();
-
- // So that quitting ScummVM will not cause the dialog result to say a
- // savegame was selected.
- setResult(-1);
-}
-
const Common::String &SaveLoadChooser::getResultString() const {
- int selItem = _list->getSelected();
- return (selItem >= 0) ? _list->getSelectedString() : _resultString;
-}
-
-void SaveLoadChooser::setSaveMode(bool saveMode) {
- _list->setEditable(saveMode);
-}
-
-void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
- int selItem = _list->getSelected();
-
- switch (cmd) {
- case GUI::kListItemActivatedCmd:
- case GUI::kListItemDoubleClickedCmd:
- if (selItem >= 0 && _chooseButton->isEnabled()) {
- if (_list->isEditable() || !_list->getSelectedString().empty()) {
- _list->endEditMode();
- if (!_saveList.empty()) {
- setResult(_saveList[selItem].getSaveSlot());
- _resultString = _list->getSelectedString();
- }
- close();
- }
- }
- break;
- case kChooseCmd:
- _list->endEditMode();
- if (!_saveList.empty()) {
- setResult(_saveList[selItem].getSaveSlot());
- _resultString = _list->getSelectedString();
- }
- close();
- break;
- case GUI::kListSelectionChangedCmd:
- updateSelection(true);
- break;
- case kDelCmd:
- if (selItem >= 0 && _delSupport) {
- MessageDialog alert(_("Do you really want to delete this savegame?"),
- _("Delete"), _("Cancel"));
- if (alert.runModal() == GUI::kMessageOK) {
- (*_plugin)->removeSaveState(_target.c_str(), _saveList[selItem].getSaveSlot());
-
- setResult(-1);
- _list->setSelected(-1);
-
- updateSaveList();
- updateSelection(true);
- }
- }
- break;
- case kCloseCmd:
- setResult(-1);
- default:
- Dialog::handleCommand(sender, cmd, data);
- }
-}
-
-void SaveLoadChooser::reflowLayout() {
- if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && _thumbnailSupport) {
- int16 x, y;
- uint16 w, h;
-
- if (!g_gui.xmlEval()->getWidgetData("SaveLoadChooser.Thumbnail", x, y, w, h))
- error("Error when loading position data for Save/Load Thumbnails");
-
- int thumbW = kThumbnailWidth;
- int thumbH = kThumbnailHeight2;
- int thumbX = x + (w >> 1) - (thumbW >> 1);
- int thumbY = y + kLineHeight;
-
- int textLines = 0;
- if (!_saveDateSupport)
- textLines++;
- if (!_playTimeSupport)
- textLines++;
-
- _container->resize(x, y, w, h - (kLineHeight * textLines));
- _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
-
- int height = thumbY + thumbH + kLineHeight;
-
- if (_saveDateSupport) {
- _date->resize(thumbX, height, kThumbnailWidth, kLineHeight);
- height += kLineHeight;
- _time->resize(thumbX, height, kThumbnailWidth, kLineHeight);
- height += kLineHeight;
- }
-
- if (_playTimeSupport)
- _playtime->resize(thumbX, height, kThumbnailWidth, kLineHeight);
-
- _container->setVisible(true);
- _gfxWidget->setVisible(true);
-
- _date->setVisible(_saveDateSupport);
- _time->setVisible(_saveDateSupport);
-
- _playtime->setVisible(_playTimeSupport);
-
- _fillR = 0;
- _fillG = 0;
- _fillB = 0;
- updateSelection(false);
- } else {
- _container->setVisible(false);
- _gfxWidget->setVisible(false);
- _date->setVisible(false);
- _time->setVisible(false);
- _playtime->setVisible(false);
- }
-
- Dialog::reflowLayout();
-}
-
-void SaveLoadChooser::updateSelection(bool redraw) {
- int selItem = _list->getSelected();
-
- bool isDeletable = _delSupport;
- bool isWriteProtected = false;
- bool startEditMode = _list->isEditable();
-
- _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB);
- _date->setLabel(_("No date saved"));
- _time->setLabel(_("No time saved"));
- _playtime->setLabel(_("No playtime saved"));
-
- if (selItem >= 0 && _metaInfoSupport) {
- SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot());
-
- isDeletable = desc.getDeletableFlag() && _delSupport;
- isWriteProtected = desc.getWriteProtectedFlag();
-
- // Don't allow the user to change the description of write protected games
- if (isWriteProtected)
- startEditMode = false;
-
- if (_thumbnailSupport) {
- const Graphics::Surface *thumb = desc.getThumbnail();
- if (thumb) {
- _gfxWidget->setGfx(thumb);
- _gfxWidget->useAlpha(256);
- }
- }
-
- if (_saveDateSupport) {
- const Common::String &saveDate = desc.getSaveDate();
- if (!saveDate.empty())
- _date->setLabel(_("Date: ") + saveDate);
-
- const Common::String &saveTime = desc.getSaveTime();
- if (!saveTime.empty())
- _time->setLabel(_("Time: ") + saveTime);
- }
-
- if (_playTimeSupport) {
- const Common::String &playTime = desc.getPlayTime();
- if (!playTime.empty())
- _playtime->setLabel(_("Playtime: ") + playTime);
- }
- }
-
-
- if (_list->isEditable()) {
- // Disable the save button if nothing is selected, or if the selected
- // game is write protected
- _chooseButton->setEnabled(selItem >= 0 && !isWriteProtected);
-
- if (startEditMode) {
- _list->startEditMode();
-
- if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") &&
- _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) {
- _list->setEditString("");
- _list->setEditColor(ThemeEngine::kFontColorNormal);
- }
- }
- } else {
- // Disable the load button if nothing is selected, or if an empty
- // list item is selected.
- _chooseButton->setEnabled(selItem >= 0 && !_list->getSelectedString().empty());
- }
-
- // Delete will always be disabled if the engine doesn't support it.
- _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty()));
-
- if (redraw) {
- _gfxWidget->draw();
- _date->draw();
- _time->draw();
- _playtime->draw();
- _chooseButton->draw();
- _deleteButton->draw();
-
- draw();
- }
-}
-
-void SaveLoadChooser::close() {
- _plugin = 0;
- _target.clear();
- _saveList.clear();
- _list->setList(StringArray());
-
- Dialog::close();
-}
-
-void SaveLoadChooser::updateSaveList() {
- _saveList = (*_plugin)->listSaves(_target.c_str());
-
- int curSlot = 0;
- int saveSlot = 0;
- StringArray saveNames;
- ListWidget::ColorList colors;
- for (SaveStateList::const_iterator x = _saveList.begin(); x != _saveList.end(); ++x) {
- // Handle gaps in the list of save games
- saveSlot = x->getSaveSlot();
- if (curSlot < saveSlot) {
- while (curSlot < saveSlot) {
- SaveStateDescriptor dummySave(curSlot, "");
- _saveList.insert_at(curSlot, dummySave);
- saveNames.push_back(dummySave.getDescription());
- colors.push_back(ThemeEngine::kFontColorNormal);
- curSlot++;
- }
-
- // Sync the save list iterator
- for (x = _saveList.begin(); x != _saveList.end(); ++x) {
- if (x->getSaveSlot() == saveSlot)
- break;
- }
- }
-
- // Show "Untitled savestate" for empty/whitespace savegame descriptions
- Common::String description = x->getDescription();
- Common::String trimmedDescription = description;
- trimmedDescription.trim();
- if (trimmedDescription.empty()) {
- description = _("Untitled savestate");
- colors.push_back(ThemeEngine::kFontColorAlternate);
- } else {
- colors.push_back(ThemeEngine::kFontColorNormal);
- }
-
- saveNames.push_back(description);
- curSlot++;
- }
-
- // Fill the rest of the save slots with empty saves
-
- int maximumSaveSlots = (*_plugin)->getMaximumSaveSlot();
-
-#ifdef __DS__
- // Low memory on the DS means too many save slots are impractical, so limit
- // the maximum here.
- if (maximumSaveSlots > 99) {
- maximumSaveSlots = 99;
- }
-#endif
-
- Common::String emptyDesc;
- for (int i = curSlot; i <= maximumSaveSlots; i++) {
- saveNames.push_back(emptyDesc);
- SaveStateDescriptor dummySave(i, "");
- _saveList.push_back(dummySave);
- colors.push_back(ThemeEngine::kFontColorNormal);
- }
-
- _list->setList(saveNames, &colors);
+ assert(_impl);
+ return _impl->getResultString();
}
} // End of namespace GUI
diff --git a/gui/saveload.h b/gui/saveload.h
index adaf311fd2..17fd99a31d 100644
--- a/gui/saveload.h
+++ b/gui/saveload.h
@@ -19,63 +19,55 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef GUI_SAVELOAD_DIALOG_H
-#define GUI_SAVELOAD_DIALOG_H
+#ifndef GUI_SAVELOAD_H
+#define GUI_SAVELOAD_H
#include "gui/dialog.h"
#include "engines/metaengine.h"
namespace GUI {
-class ListWidget;
-class GraphicsWidget;
-class ButtonWidget;
-class CommandSender;
-class ContainerWidget;
-class StaticTextWidget;
+class SaveLoadChooserDialog;
-class SaveLoadChooser : GUI::Dialog {
+class SaveLoadChooser {
typedef Common::String String;
- typedef Common::Array<Common::String> StringArray;
protected:
- GUI::ListWidget *_list;
- GUI::ButtonWidget *_chooseButton;
- GUI::ButtonWidget *_deleteButton;
- GUI::GraphicsWidget *_gfxWidget;
- GUI::ContainerWidget *_container;
- GUI::StaticTextWidget *_date;
- GUI::StaticTextWidget *_time;
- GUI::StaticTextWidget *_playtime;
+ SaveLoadChooserDialog *_impl;
- const EnginePlugin *_plugin;
- bool _delSupport;
- bool _metaInfoSupport;
- bool _thumbnailSupport;
- bool _saveDateSupport;
- bool _playTimeSupport;
- String _target;
- SaveStateList _saveList;
- String _resultString;
+ const String _title;
+ const String _buttonLabel;
+ const bool _saveMode;
- uint8 _fillR, _fillG, _fillB;
-
- void updateSaveList();
- void updateSelection(bool redraw);
+ void selectChooser(const MetaEngine &engine);
public:
- SaveLoadChooser(const String &title, const String &buttonLabel);
+ SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode);
~SaveLoadChooser();
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
- void setList(const StringArray& list);
+ /**
+ * Runs the save/load chooser with the currently active config manager
+ * domain as target.
+ *
+ * @return The selcted save slot. -1 in case none is selected.
+ */
+ int runModalWithCurrentTarget();
int runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target);
- void open();
const Common::String &getResultString() const;
- void setSaveMode(bool saveMode);
-
- virtual void reflowLayout();
- virtual void close();
+ /**
+ * Creates a default save description for the specified slot. Depending
+ * on the ScummVM configuration this might be a simple "Slot #" description
+ * or the current date and time.
+ *
+ * TODO: This might not be the best place to put this, since engines not
+ * using this class might want to mimic the same behavior. Check whether
+ * moving this to a better place makes sense and find what this place would
+ * be.
+ *
+ * @param slot The slot number (must be >= 0).
+ * @return The slot description.
+ */
+ Common::String createDefaultSaveDescription(const int slot) const;
};
} // End of namespace GUI
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 542f776dbd..7f565eb05d 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -460,6 +460,17 @@
"bevel='2' "
"/> "
"</drawdata> "
+"<drawdata id='button_pressed' cache='false'> "
+"<text font='text_button' "
+"text_color='color_alternative_inverted' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"/> "
+"</drawdata> "
"<drawdata id='button_idle' cache='false'> "
"<text font='text_button' "
"text_color='color_button' "
@@ -599,50 +610,50 @@
"/> "
"</drawdata> "
"</render_info> "
-"<layout_info resolution='y>399'> "
+"<layout_info resolution='y<400'> "
"<globals> "
-"<def var='Line.Height' value='16' /> "
-"<def var='Font.Height' value='16' /> "
-"<def var='About.OuterBorder' value='80'/> "
-"<def var='Layout.Spacing' value='8' /> "
+"<def var='Line.Height' value='12' /> "
+"<def var='Font.Height' value='10' /> "
+"<def var='About.OuterBorder' value='10'/> "
+"<def var='Layout.Spacing' value='8'/> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
-"<def var='KeyMapper.Spacing' value='10'/> "
-"<def var='KeyMapper.LabelWidth' value='100'/> "
-"<def var='KeyMapper.ButtonWidth' value='80'/> "
-"<def var='Tooltip.MaxWidth' value='200'/> "
-"<def var='Tooltip.XDelta' value='16'/> "
-"<def var='Tooltip.YDelta' value='16'/> "
-"<def var='Predictive.Button.Width' value='60' /> "
+"<def var='ShowChooserPics' value='0'/> "
+"<def var='ShowChooserPageDisplay' value='0'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
+"<def var='KeyMapper.Spacing' value='5'/> "
+"<def var='KeyMapper.LabelWidth' value='80'/> "
+"<def var='KeyMapper.ButtonWidth' value='60'/> "
+"<def var='Tooltip.MaxWidth' value='70'/> "
+"<def var='Tooltip.XDelta' value='8'/> "
+"<def var='Tooltip.YDelta' value='8'/> "
+"<def var='Predictive.Button.Width' value='45' /> "
+"<def var='Predictive.Button.Height' value='15' /> "
+"<widget name='Button' "
+"size='72,16' "
+"/> "
+"<widget name='Slider' "
+"size='85,12' "
+"/> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='24,Globals.Line.Height' "
-"/> "
-"<widget name='ShortOptionsLabel' "
-"size='60,Globals.Line.Height' "
-"/> "
-"<widget name='Button' "
-"size='108,24' "
-"/> "
-"<widget name='Slider' "
-"size='128,18' "
+"size='18,Globals.Line.Height' "
"/> "
"<widget name='PopUp' "
-"size='-1,19' "
+"size='-1,15' "
"/> "
"<widget name='Checkbox' "
-"size='-1,14' "
+"size='-1,Globals.Line.Height' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,8,0' "
+"padding='5,0,0,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -654,28 +665,28 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='15,0' "
+"size='9,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='75,27' "
-"padding='0,0,8,0' "
+"size='45,16' "
+"padding='0,0,2,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,0' "
+"padding='0,0,0,-8' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='15,18' "
-"padding='0,3,4,0' "
+"size='32,18' "
+"padding='0,0,1,0' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"<layout type='vertical' center='true' padding='6,6,2,2'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"/> "
-"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
"<widget name='SearchDesc' "
-"width='60' "
+"width='50' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -690,39 +701,38 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='LoadGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AddGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='EditGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='RemoveGameButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='QuitButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AboutButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='OptionsButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='StartButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,0,4'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -730,7 +740,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,8,0'> "
"<widget name='Up' "
"type='Button' "
"/> "
@@ -744,10 +754,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -760,7 +770,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -768,7 +778,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -786,7 +796,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -794,7 +804,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -802,7 +812,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -810,7 +820,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -824,7 +834,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -838,9 +848,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -851,7 +860,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -862,7 +871,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -873,8 +882,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -883,7 +892,7 @@
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -891,7 +900,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -906,7 +915,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -922,7 +931,7 @@
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -940,7 +949,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -952,7 +961,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -964,7 +973,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -988,7 +997,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -996,25 +1005,31 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='RendererPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -1049,10 +1064,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1064,7 +1079,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1072,7 +1087,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1080,7 +1095,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1088,7 +1103,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1096,7 +1111,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1104,34 +1119,43 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Id' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Name' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<space size='8'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='LangPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='PlatformPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -1140,8 +1164,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -1153,7 +1177,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -1165,7 +1189,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -1176,7 +1200,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -1201,57 +1225,55 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
"<widget name='Title' "
-"width='210' "
-"height='Globals.Line.Height' "
+"width='160' "
+"height='4' "
"/> "
"<widget name='Version' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Resume' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='160' "
+"height='4' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Load' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Save' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Options' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Help' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='About' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
+"/> "
+"<space size='1'/> "
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Quit' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<layout type='vertical' padding='0,0,0,0' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1262,7 +1284,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1273,7 +1295,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1284,33 +1306,34 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"</layout> "
+"<space size='2' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1321,8 +1344,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<space size='16'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -1337,23 +1360,23 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,32' center='true'> "
-"<widget name='Title' "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' height='Globals.Line.Height'/> "
+"<widget name='List' /> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
"/> "
-"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
-"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
+"<widget name='GridSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='32'/> "
+"<space size='16'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -1363,16 +1386,35 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<dialog name='SavenameDialog' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='DescriptionText' "
+"width='180' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Description' "
+"height='19' "
+"/> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Title' "
-"width='320' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='200' "
+"height='140' "
"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -1389,7 +1431,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='320' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -1407,20 +1449,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"<layout type='vertical' padding='4,4,16,4' center='true'> "
"<widget name='DirProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='480' "
-"height='250' "
+"width='280' "
+"height='100' "
"/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='4,4,4,4'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -1431,20 +1473,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='400' "
+"width='150' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
+"width='300' "
+"height='120' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -1452,140 +1494,142 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='5,5,5,5' center='true'> "
+"<layout type='vertical' padding='1,1,1,1' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='210' "
+"width='150' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='5,5,5,5'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Word' "
-"width='190' "
+"width='120' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='3,3,3,0'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<space size='3' /> "
+"<layout type='horizontal' padding='3,3,0,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
-"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='y<400'> "
+"<layout_info resolution='y>399'> "
"<globals> "
-"<def var='Line.Height' value='12' /> "
-"<def var='Font.Height' value='10' /> "
-"<def var='About.OuterBorder' value='10'/> "
-"<def var='Layout.Spacing' value='8'/> "
+"<def var='Line.Height' value='16' /> "
+"<def var='Font.Height' value='16' /> "
+"<def var='About.OuterBorder' value='80'/> "
+"<def var='Layout.Spacing' value='8' /> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
-"<def var='KeyMapper.Spacing' value='5'/> "
-"<def var='KeyMapper.LabelWidth' value='80'/> "
-"<def var='KeyMapper.ButtonWidth' value='60'/> "
-"<def var='Tooltip.MaxWidth' value='70'/> "
-"<def var='Tooltip.XDelta' value='8'/> "
-"<def var='Tooltip.YDelta' value='8'/> "
-"<def var='Predictive.Button.Width' value='45' /> "
-"<def var='Predictive.Button.Height' value='15' /> "
-"<widget name='Button' "
-"size='72,16' "
-"/> "
-"<widget name='Slider' "
-"size='85,12' "
-"/> "
+"<def var='ShowChooserPics' value='0'/> "
+"<def var='ShowChooserPageDisplay' value='1'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
+"<def var='KeyMapper.Spacing' value='10'/> "
+"<def var='KeyMapper.LabelWidth' value='100'/> "
+"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='Tooltip.MaxWidth' value='200'/> "
+"<def var='Tooltip.XDelta' value='16'/> "
+"<def var='Tooltip.YDelta' value='16'/> "
+"<def var='Predictive.Button.Width' value='60' /> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='18,Globals.Line.Height' "
+"size='24,Globals.Line.Height' "
+"/> "
+"<widget name='ShortOptionsLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='Button' "
+"size='108,24' "
+"/> "
+"<widget name='Slider' "
+"size='128,18' "
"/> "
"<widget name='PopUp' "
-"size='-1,15' "
+"size='-1,19' "
"/> "
"<widget name='Checkbox' "
-"size='-1,Globals.Line.Height' "
+"size='-1,14' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,0,0' "
+"padding='5,0,8,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -1597,28 +1641,28 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='9,0' "
+"size='15,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='45,16' "
-"padding='0,0,2,0' "
+"size='75,27' "
+"padding='0,0,8,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,-8' "
+"padding='0,0,0,0' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='32,18' "
-"padding='0,0,1,0' "
+"size='15,18' "
+"padding='0,3,4,0' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='6,6,2,2'> "
+"<layout type='vertical' center='true' padding='16,16,8,8'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"/> "
-"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
"<widget name='SearchDesc' "
-"width='50' "
+"width='60' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -1633,38 +1677,39 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='LoadGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AddGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='EditGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='RemoveGameButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<space size='4'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='QuitButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AboutButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='OptionsButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='StartButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -1672,7 +1717,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,8,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Up' "
"type='Button' "
"/> "
@@ -1686,10 +1731,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1702,7 +1747,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1710,7 +1755,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1728,7 +1773,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1736,7 +1781,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1744,7 +1789,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1752,7 +1797,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -1766,7 +1811,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1780,8 +1825,9 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1792,7 +1838,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1803,7 +1849,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1814,8 +1860,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,0,24,0' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -1824,7 +1870,7 @@
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1832,7 +1878,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -1847,7 +1893,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -1863,7 +1909,7 @@
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1881,7 +1927,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -1893,7 +1939,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1905,7 +1951,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -1929,7 +1975,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1937,31 +1983,25 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='RendererPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -1996,10 +2036,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,4'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -2011,7 +2051,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2019,7 +2059,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2027,7 +2067,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2035,7 +2075,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2043,7 +2083,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2051,43 +2091,34 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Id' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Name' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<space size='8'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='LangPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PlatformPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -2096,8 +2127,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -2109,7 +2140,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -2121,7 +2152,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -2132,7 +2163,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='vertical' padding='16,16,16,16'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -2157,55 +2188,57 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' center='true'> "
"<widget name='Title' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
"<widget name='Version' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
-"<space size='1'/> "
+"<widget name='Resume' "
+"width='150' "
+"height='Globals.Button.Height' "
+"/> "
+"<space size='10'/> "
"<widget name='Load' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Save' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
-"<space size='1'/> "
+"<space size='10'/> "
"<widget name='Options' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Help' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='About' "
-"width='120' "
-"height='12' "
-"/> "
-"<space size='1'/> "
-"<widget name='Resume' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='10'/> "
"<widget name='RTL' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Quit' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='0,0,0,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -2216,7 +2249,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -2227,7 +2260,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -2238,34 +2271,33 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,24,24,24' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"</layout> "
+"<space size='8' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"</layout> "
-"</layout> "
-"<space size='2' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -2276,8 +2308,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='16'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"<space size='60'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -2292,15 +2324,38 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' height='Globals.Line.Height'/> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<space/> "
+"<widget name='PageDisplay' "
+"width='200' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Thumbnail' "
+"width='180' "
+"height='200' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='ListSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
+"<widget name='GridSwitch' "
+"height='Globals.Line.Height' "
+"width='Globals.Line.Height' "
+"/> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='16'/> "
+"<space size='32'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -2310,16 +2365,36 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen'> "
+"<dialog name='SavenameDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='DescriptionText' "
+"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='Description' "
+"height='19' "
+"/> "
+"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<space size='96'/> "
+"<widget name='Ok' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Title' "
-"width='180' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='140' "
+"height='200' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -2336,7 +2411,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='280' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -2354,20 +2429,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' center='true'> "
"<widget name='DirProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='280' "
-"height='100' "
+"width='480' "
+"height='250' "
"/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -2378,20 +2453,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='150' "
+"width='400' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
+"width='600' "
+"height='280' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -2399,91 +2474,93 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='1,1,1,1' center='true'> "
+"<layout type='vertical' padding='5,5,5,5' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='150' "
+"width='210' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='5,5,5,5'> "
"<widget name='Word' "
-"width='120' "
+"width='190' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
+"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,0'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<space size='3' /> "
-"<layout type='horizontal' padding='3,3,0,3'> "
+"<space size='5' /> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</layout> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index eb5ac2d9f7..62eae0cd43 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index b808aee32f..b8937adcb2 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.11:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.16:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index f07499ce79..49ecea2e11 100644
--- a/gui/themes/scummclassic/classic_gfx.stx
+++ b/gui/themes/scummclassic/classic_gfx.stx
@@ -541,6 +541,19 @@
/>
</drawdata>
+ <!-- Pressed button -->
+ <drawdata id = 'button_pressed' cache = 'false'>
+ <text font = 'text_button'
+ text_color = 'color_alternative_inverted'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'square'
+ fill = 'foreground'
+ fg_color = 'green'
+ />
+ </drawdata>
+
<drawdata id = 'button_idle' cache = 'false'>
<text font = 'text_button'
text_color = 'color_button'
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 8717892995..4a6aae00bc 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -32,6 +32,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '1'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
@@ -793,9 +796,16 @@
<dialog name = 'SaveLoadChooser' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
- <widget name = 'Title'
- height = 'Globals.Line.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <space/>
+ <widget name = 'PageDisplay'
+ width = '200'
+ height = 'Globals.Line.Height'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
<widget name = 'List' />
<widget name = 'Thumbnail'
@@ -804,6 +814,14 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -819,6 +837,27 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 8f5db9d364..57e149b570 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -33,6 +33,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '0'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '5'/>
@@ -807,6 +810,14 @@
<widget name = 'Title' height = 'Globals.Line.Height'/>
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -822,6 +833,26 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '180'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 94f7cd8f6e..38352bcc2f 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index e6c441d543..52eb683ebd 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.11:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.16:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/grid.bmp b/gui/themes/scummmodern/grid.bmp
new file mode 100644
index 0000000000..adeb209380
--- /dev/null
+++ b/gui/themes/scummmodern/grid.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/list.bmp b/gui/themes/scummmodern/list.bmp
new file mode 100644
index 0000000000..2f54a40bcd
--- /dev/null
+++ b/gui/themes/scummmodern/list.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 403f636fd0..4d449f50ec 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -101,6 +101,8 @@
<bitmap filename = 'search.bmp'/>
<bitmap filename = 'eraser.bmp'/>
<bitmap filename = 'delbtn.bmp'/>
+ <bitmap filename = 'list.bmp'/>
+ <bitmap filename = 'grid.bmp'/>
</bitmaps>
<fonts>
@@ -153,7 +155,7 @@
/>
<text_color id = 'color_normal_disabled'
- color = '192, 192, 192'
+ color = '96, 96, 96'
/>
<text_color id = 'color_alternative'
@@ -187,8 +189,8 @@
<!-- <defaults fill = 'gradient' fg_color = 'white'/> -->
- <cursor file = 'cursor.bmp' hotspot = '0, 0' scale = '3'/>
- <cursor resolution = 'y<400' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/>
+ <cursor file = 'cursor.bmp' hotspot = '0, 0'/>
+ <cursor resolution = 'y<400' file = 'cursor_small.bmp' hotspot = '0, 0'/>
<!-- Selection (text or list items) -->
<drawdata id = 'text_selection' cache = 'false'>
@@ -740,6 +742,27 @@
/>
</drawdata>
+ <!-- Pressed button -->
+ <drawdata id = 'button_pressed' cache = 'false'>
+ <text font = 'text_button'
+ text_color = 'color_button'
+ vertical_align = 'center'
+ horizontal_align = 'center'
+ />
+ <drawstep func = 'roundedsq'
+ radius = '5'
+ stroke = '1'
+ fill = 'foreground'
+ shadow = '0'
+ factor = '0'
+ fg_color = '120, 40, 16'
+ gradient_start = '255, 0, 0'
+ gradient_end = '255, 0, 0'
+ bevel = '1'
+ bevel_color = 'black'
+ />
+ </drawdata>
+
<!-- Idle button -->
<drawdata id = 'button_idle' cache = 'false'>
<text font = 'text_button'
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 087a844a1b..d99d7416c2 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -39,6 +39,9 @@
<def var = 'ShowGlobalMenuLogo' value = '1'/>
<def var = 'ShowSearchPic' value = '1'/>
+ <def var = 'ShowChooserPics' value = '1'/>
+ <def var = 'ShowChooserPageDisplay' value = '1'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
@@ -807,9 +810,16 @@
<dialog name = 'SaveLoadChooser' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
- <widget name = 'Title'
- height = 'Globals.Line.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <space/>
+ <widget name = 'PageDisplay'
+ width = '200'
+ height = 'Globals.Line.Height'
+ />
+ </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
<widget name = 'List' />
<widget name = 'Thumbnail'
@@ -818,6 +828,14 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'ListSwitch'
+ height = '20'
+ width = '20'
+ />
+ <widget name = 'GridSwitch'
+ height = '20'
+ width = '20'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -833,6 +851,27 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 987fee800a..4fd5bdcf40 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -31,6 +31,9 @@
<def var = 'ShowGlobalMenuLogo' value = '0'/>
<def var = 'ShowSearchPic' value = '0'/>
+ <def var = 'ShowChooserPics' value = '0'/>
+ <def var = 'ShowChooserPageDisplay' value = '0'/>
+
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
<def var = 'Predictive.Button.Width' value = '45' />
@@ -806,6 +809,14 @@
<widget name = 'Title' height = 'Globals.Line.Height'/>
<widget name = 'List' />
<layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'ListSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
+ <widget name = 'GridSwitch'
+ height = 'Globals.Line.Height'
+ width = 'Globals.Line.Height'
+ />
<space/>
<widget name = 'Delete'
type = 'Button'
@@ -821,6 +832,26 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '180'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen' inset = '8'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index a9645f226a..1c3abf84a8 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 0e2fd248b1..9046bcc9c1 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -30,6 +30,8 @@
#include "gui/ThemeEval.h"
+#include "gui/dialog.h"
+
namespace GUI {
Widget::Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
@@ -77,6 +79,8 @@ void Widget::updateState(int oldFlags, int newFlags) {
_state = ThemeEngine::kStateEnabled;
if (newFlags & WIDGET_HILITED)
_state = ThemeEngine::kStateHighlight;
+ if (newFlags & WIDGET_PRESSED)
+ _state = ThemeEngine::kStatePressed;
} else {
_state = ThemeEngine::kStateDisabled;
}
@@ -272,7 +276,7 @@ void StaticTextWidget::drawWidget() {
ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
: StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss),
- _cmd(cmd), _hotkey(hotkey) {
+ _cmd(cmd), _hotkey(hotkey), _lastTime(0) {
if (hotkey == 0)
_hotkey = parseHotkey(label);
@@ -283,7 +287,7 @@ ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Co
ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
: StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss),
- _cmd(cmd) {
+ _cmd(cmd), _lastTime(0) {
if (hotkey == 0)
_hotkey = parseHotkey(label);
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
@@ -291,8 +295,14 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co
}
void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
- if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h)
+ if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) {
+ startAnimatePressedState();
sendCommand(_cmd, 0);
+ }
+}
+
+void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+ setPressedState();
}
void ButtonWidget::drawWidget() {
@@ -324,11 +334,49 @@ ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32
return button;
}
+void ButtonWidget::setHighLighted(bool enable) {
+ (enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED);
+ draw();
+}
+
+void ButtonWidget::handleTickle() {
+ if (_lastTime) {
+ uint32 curTime = g_system->getMillis();
+ if (curTime - _lastTime > kPressedButtonTime) {
+ stopAnimatePressedState();
+ }
+ }
+}
+
+void ButtonWidget::setPressedState() {
+ wantTickle(true);
+ setFlags(WIDGET_PRESSED);
+ draw();
+}
+
+void ButtonWidget::stopAnimatePressedState() {
+ wantTickle(false);
+ _lastTime = 0;
+ clearFlags(WIDGET_PRESSED);
+ draw();
+}
+
+void ButtonWidget::startAnimatePressedState() {
+ _lastTime = g_system->getMillis();
+}
+
+void ButtonWidget::wantTickle(bool tickled) {
+ if (tickled)
+ ((GUI::Dialog *)_boss)->setTickleWidget(this);
+ else
+ ((GUI::Dialog *)_boss)->unSetTickleWidget();
+}
+
#pragma mark -
PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
- _gfx(), _alpha(256), _transparency(false) {
+ _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
@@ -336,38 +384,67 @@ PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, co
PicButtonWidget::PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, name, "", tooltip, cmd, hotkey),
- _alpha(256), _transparency(false) {
+ _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
}
PicButtonWidget::~PicButtonWidget() {
- _gfx.free();
+ _gfx->free();
+ delete _gfx;
}
void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
- _gfx.free();
+ _gfx->free();
if (!gfx || !gfx->pixels)
return;
+ if (gfx->format.bytesPerPixel == 1) {
+ warning("PicButtonWidget::setGfx got paletted surface passed");
+ return;
+ }
+
+
if (gfx->w > _w || gfx->h > _h) {
warning("PicButtonWidget has size %dx%d, but a surface with %dx%d is to be set", _w, _h, gfx->w, gfx->h);
return;
}
- // TODO: add conversion to OverlayColor
- _gfx.copyFrom(*gfx);
+ _gfx->copyFrom(*gfx);
+}
+
+void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
+ if (w == -1)
+ w = _w;
+ if (h == -1)
+ h = _h;
+
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
+
+ _gfx->free();
+ _gfx->create(w, h, requiredFormat);
+ _gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
}
void PicButtonWidget::drawWidget() {
g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
- if (sizeof(OverlayColor) == _gfx.format.bytesPerPixel && _gfx.pixels) {
- const int x = _x + (_w - _gfx.w) / 2;
- const int y = _y + (_h - _gfx.h) / 2;
+ if (_gfx->pixels) {
+ // Check whether the set up surface needs to be converted to the GUI
+ // color format.
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
+ if (_gfx->format != requiredFormat) {
+ Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
+ _gfx->free();
+ delete _gfx;
+ _gfx = converted;
+ }
+
+ const int x = _x + (_w - _gfx->w) / 2;
+ const int y = _y + (_h - _gfx->h) / 2;
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w, y + _gfx->h), *_gfx, _state, _alpha, _transparency);
}
}
@@ -555,34 +632,39 @@ int SliderWidget::posToValue(int pos) {
#pragma mark -
GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
- : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) {
+ : Widget(boss, x, y, w, h, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip)
- : Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) {
+ : Widget(boss, name, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
GraphicsWidget::~GraphicsWidget() {
- _gfx.free();
+ _gfx->free();
+ delete _gfx;
}
void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
- _gfx.free();
+ _gfx->free();
if (!gfx || !gfx->pixels)
return;
+ if (gfx->format.bytesPerPixel == 1) {
+ warning("GraphicsWidget::setGfx got paletted surface passed");
+ return;
+ }
+
if (gfx->w > _w || gfx->h > _h) {
warning("GraphicsWidget has size %dx%d, but a surface with %dx%d is to be set", _w, _h, gfx->w, gfx->h);
return;
}
- // TODO: add conversion to OverlayColor
- _gfx.copyFrom(*gfx);
+ _gfx->copyFrom(*gfx);
}
void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
@@ -591,26 +673,29 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
if (h == -1)
h = _h;
- Graphics::PixelFormat overlayFormat = g_system->getOverlayFormat();
-
- _gfx.free();
- _gfx.create(w, h, overlayFormat);
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- OverlayColor *dst = (OverlayColor *)_gfx.pixels;
- OverlayColor fillCol = overlayFormat.RGBToColor(r, g, b);
- while (h--) {
- for (int i = 0; i < w; ++i) {
- *dst++ = fillCol;
- }
- }
+ _gfx->free();
+ _gfx->create(w, h, requiredFormat);
+ _gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
}
void GraphicsWidget::drawWidget() {
- if (sizeof(OverlayColor) == _gfx.format.bytesPerPixel && _gfx.pixels) {
- const int x = _x + (_w - _gfx.w) / 2;
- const int y = _y + (_h - _gfx.h) / 2;
+ if (_gfx->pixels) {
+ // Check whether the set up surface needs to be converted to the GUI
+ // color format.
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
+ if (_gfx->format != requiredFormat) {
+ Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
+ _gfx->free();
+ delete _gfx;
+ _gfx = converted;
+ }
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
+ const int x = _x + (_w - _gfx->w) / 2;
+ const int y = _y + (_h - _gfx->h) / 2;
+
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w, y + _gfx->h), *_gfx, _state, _alpha, _transparency);
}
}
@@ -626,6 +711,26 @@ ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) :
_type = kContainerWidget;
}
+ContainerWidget::~ContainerWidget() {
+ // We also remove the widget from the boss to avoid segfaults, when the
+ // deleted widget is an active widget in the boss.
+ for (Widget *w = _firstWidget; w; w = w->next()) {
+ _boss->removeWidget(w);
+ }
+}
+
+Widget *ContainerWidget::findWidget(int x, int y) {
+ return findWidgetInChain(_firstWidget, x, y);
+}
+
+void ContainerWidget::removeWidget(Widget *widget) {
+ // We also remove the widget from the boss to avoid a reference to a
+ // widget not in the widget chain anymore.
+ _boss->removeWidget(widget);
+
+ Widget::removeWidget(widget);
+}
+
void ContainerWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorder);
}
diff --git a/gui/widget.h b/gui/widget.h
index 789fc09231..6f710f302f 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -38,6 +38,7 @@ enum {
WIDGET_INVISIBLE = 1 << 1,
WIDGET_HILITED = 1 << 2,
WIDGET_BORDER = 1 << 3,
+ WIDGET_PRESSED = 1 << 4,
//WIDGET_INV_BORDER = 1 << 4,
WIDGET_CLEARBG = 1 << 5,
WIDGET_WANT_TICKLE = 1 << 7,
@@ -73,6 +74,10 @@ enum {
kCaretBlinkTime = 300
};
+enum {
+ kPressedButtonTime = 200
+};
+
/* Widget */
class Widget : public GuiObject {
friend class Dialog;
@@ -83,7 +88,7 @@ protected:
uint16 _id;
bool _hasFocus;
ThemeEngine::WidgetStateInfo _state;
- const char *_tooltip;
+ Common::String _tooltip;
private:
uint16 _flags;
@@ -137,7 +142,9 @@ public:
uint8 parseHotkey(const Common::String &label);
Common::String cleanupHotkey(const Common::String &label);
- const char *getTooltip() const { return _tooltip; }
+ bool hasTooltip() const { return !_tooltip.empty(); }
+ const Common::String &getTooltip() const { return _tooltip; }
+ void setTooltip(const Common::String &tooltip) { _tooltip = tooltip; }
protected:
void updateState(int oldFlags, int newFlags);
@@ -189,11 +196,22 @@ public:
void setLabel(const Common::String &label);
void handleMouseUp(int x, int y, int button, int clickCount);
+ void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); }
- void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); }
+ void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); }
+ void handleTickle();
+
+ void setHighLighted(bool enable);
+ void setPressedState();
+ void startAnimatePressedState();
+ void stopAnimatePressedState();
+ void lostFocusWidget() { stopAnimatePressedState(); }
protected:
void drawWidget();
+ void wantTickle(bool tickled);
+private:
+ uint32 _lastTime;
};
/* PicButtonWidget */
@@ -204,6 +222,7 @@ public:
~PicButtonWidget();
void setGfx(const Graphics::Surface *gfx);
+ void setGfx(int w, int h, int r, int g, int b);
void useAlpha(int alpha) { _alpha = alpha; }
void useThemeTransparency(bool enable) { _transparency = enable; }
@@ -211,7 +230,7 @@ public:
protected:
void drawWidget();
- Graphics::Surface _gfx;
+ Graphics::Surface *_gfx;
int _alpha;
bool _transparency;
};
@@ -339,7 +358,7 @@ public:
protected:
void drawWidget();
- Graphics::Surface _gfx;
+ Graphics::Surface *_gfx;
int _alpha;
bool _transparency;
};
@@ -349,7 +368,10 @@ class ContainerWidget : public Widget {
public:
ContainerWidget(GuiObject *boss, int x, int y, int w, int h);
ContainerWidget(GuiObject *boss, const Common::String &name);
+ ~ContainerWidget();
+ virtual Widget *findWidget(int x, int y);
+ virtual void removeWidget(Widget *widget);
protected:
void drawWidget();
};