From c0d8b6d9fc73abc8de4575686e0776e3468d37b2 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 28 Dec 2019 10:43:58 +0100 Subject: GUI: Introduce dynamic layouts Prior to this change, a GUI layout was only affected by the screen size. Now, a layout can additionally be influenced by the GUI dialog and widgets that uses it. This capability is leveraged to implement the following features: * Layout elements that are not bound to a GUI widget do not take space. This means that dialogs where the widgets shown depend on for example a feature being enabled at configure time no longer have blank spaces. * Widgets can define a minimal required size for their contents not to be cut. For now this is only used for buttons so their width is always sufficient for their caption not to be cut. This mechanism could be applied to other widget types in the future. --- gui/EventRecorder.cpp | 1 + gui/ThemeEngine.cpp | 3 + gui/ThemeEval.cpp | 35 ++++---- gui/ThemeEval.h | 3 +- gui/ThemeLayout.cpp | 100 +++++++++++++++++++-- gui/ThemeLayout.h | 86 +++++++++++------- gui/ThemeParser.cpp | 6 +- gui/dialog.cpp | 5 ++ gui/editgamedialog.cpp | 22 ++--- gui/fluidsynth-dialog.cpp | 6 +- gui/launcher.cpp | 8 +- gui/object.cpp | 1 - gui/onscreendialog.cpp | 6 +- gui/options.cpp | 42 ++++----- gui/recorderdialog.cpp | 7 +- gui/saveload-dialog.cpp | 11 ++- gui/themes/default.inc | 20 ++--- gui/themes/scummclassic.zip | Bin 157690 -> 157670 bytes gui/themes/scummclassic/classic_layout.stx | 10 +-- gui/themes/scummclassic/classic_layout_lowres.stx | 10 +-- gui/themes/scummmodern.zip | Bin 287846 -> 287826 bytes gui/themes/scummmodern/scummmodern_layout.stx | 10 +-- .../scummmodern/scummmodern_layout_lowres.stx | 10 +-- gui/themes/scummremastered.zip | Bin 285890 -> 285870 bytes gui/themes/scummremastered/remastered_layout.stx | 10 +-- .../scummremastered/remastered_layout_lowres.stx | 10 +-- gui/widget.cpp | 31 ++++++- gui/widget.h | 11 +++ gui/widgets/list.cpp | 10 +-- gui/widgets/scrollcontainer.cpp | 8 +- gui/widgets/scrollcontainer.h | 3 +- gui/widgets/tab.cpp | 7 +- gui/widgets/tab.h | 3 +- 33 files changed, 320 insertions(+), 175 deletions(-) (limited to 'gui') diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp index 92fbf65d35..f66738efee 100644 --- a/gui/EventRecorder.cpp +++ b/gui/EventRecorder.cpp @@ -290,6 +290,7 @@ void EventRecorder::init(Common::String recordFileName, RecordMode mode) { } if (_recordMode != kPassthrough) { _controlPanel = new GUI::OnScreenDialog(_recordMode == kRecorderRecord); + _controlPanel->reflowLayout(); } if (_recordMode == kRecorderPlayback) { applyPlaybackSettings(); diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 2c089708a4..946864bf47 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -1165,6 +1165,9 @@ void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, Widg return; switch (background) { + case kWidgetBackgroundNo: + break; + case kWidgetBackgroundBorderSmall: drawDD(kDDWidgetBackgroundSmall, r); break; diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp index 5255587089..66b5db5fb7 100644 --- a/gui/ThemeEval.cpp +++ b/gui/ThemeEval.cpp @@ -105,30 +105,18 @@ void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign); _curLayout.top()->addChild(widget); - setVar(_curDialog + "." + name + ".Enabled", enabled ? 1 : 0); + setVar("Dialog." + _curDialog + "." + name + ".Enabled", enabled ? 1 : 0); } void ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, bool enabled, int inset) { - int16 x, y; - uint16 w, h; + Common::String var = "Dialog." + name; - ThemeLayout *layout = 0; - - if (overlays == "screen") { - layout = new ThemeLayoutMain(inset, inset, g_system->getOverlayWidth() - 2 * inset, g_system->getOverlayHeight() - 2 * inset); - } else if (overlays == "screen_center") { - layout = new ThemeLayoutMain(-1, -1, -1, -1); - } else if (getWidgetData(overlays, x, y, w, h)) { - layout = new ThemeLayoutMain(x + inset, y + inset, w - 2 * inset, h - 2 * inset); - } - - if (!layout) - error("Error when loading dialog position for '%s'", overlays.c_str()); + ThemeLayout *layout = new ThemeLayoutMain(name, overlays, enabled, inset); - if (_layouts.contains(name)) - delete _layouts[name]; + if (_layouts.contains(var)) + delete _layouts[var]; - _layouts[name] = layout; + _layouts[var] = layout; layout->setPadding( getVar("Globals.Padding.Left", 0), @@ -139,7 +127,7 @@ void ThemeEval::addDialog(const Common::String &name, const Common::String &over _curLayout.push(layout); _curDialog = name; - setVar(name + ".Enabled", enabled ? 1 : 0); + setVar(var + ".Enabled", enabled ? 1 : 0); } void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool center) { @@ -168,6 +156,15 @@ void ThemeEval::addSpace(int size) { _curLayout.top()->addChild(space); } +void ThemeEval::reflowDialogLayout(const Common::String &name, Widget *widgetChain) { + if (!_layouts.contains("Dialog." + name)) { + warning("No layout found for dialog '%s'", name.c_str()); + return; + } + + _layouts["Dialog." + name]->reflowLayout(widgetChain); +} + bool ThemeEval::addImportedLayout(const Common::String &name) { if (!_layouts.contains(name)) return false; diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h index f76a613bc4..520c280427 100644 --- a/gui/ThemeEval.h +++ b/gui/ThemeEval.h @@ -83,8 +83,9 @@ public: void addPadding(int16 l, int16 r, int16 t, int16 b) { _curLayout.top()->setPadding(l, r, t, b); } void closeLayout() { _curLayout.pop(); } - void closeDialog() { _curLayout.pop()->reflowLayout(); _curDialog.clear(); } + void closeDialog() { _curLayout.pop(); _curDialog.clear(); } + void reflowDialogLayout(const Common::String &name, Widget *widgetChain); bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h); Graphics::TextAlign getWidgetTextHAlign(const Common::String &widget); diff --git a/gui/ThemeLayout.cpp b/gui/ThemeLayout.cpp index a05ac8797e..eeaaf1e465 100644 --- a/gui/ThemeLayout.cpp +++ b/gui/ThemeLayout.cpp @@ -23,6 +23,9 @@ #include "common/util.h" #include "common/system.h" +#include "gui/gui-manager.h" +#include "gui/widget.h" +#include "gui/ThemeEval.h" #include "gui/ThemeLayout.h" #include "graphics/font.h" @@ -49,6 +52,16 @@ void ThemeLayout::importLayout(ThemeLayout *layout) { } } +void ThemeLayout::resetLayout() { + _x = 0; + _y = 0; + _w = _defaultW; + _h = _defaultH; + + for (uint i = 0; i < _children.size(); ++i) + _children[i]->resetLayout(); +} + bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { if (name.empty()) { assert(getLayoutType() == kLayoutMain); @@ -154,14 +167,73 @@ Graphics::TextAlign ThemeLayoutWidget::getWidgetTextHAlign(const Common::String return Graphics::kTextAlignInvalid; } -void ThemeLayoutMain::reflowLayout() { +void ThemeLayoutWidget::reflowLayout(Widget *widgetChain) { + Widget *guiWidget = getWidget(widgetChain); + if (!guiWidget) { + return; + } + + int minWidth = -1; + int minHeight = -1; + guiWidget->getMinSize(minWidth, minHeight); + + if (_w != -1 && minWidth != -1 && minWidth > _w) { + _w = minWidth; + } + + if (_h != -1 && minHeight != -1 && minHeight > _h) { + _h = minHeight; + } +} + +bool ThemeLayoutWidget::isBound(Widget *widgetChain) const { + Widget *guiWidget = getWidget(widgetChain); + return guiWidget != nullptr; +} + +Widget *ThemeLayoutWidget::getWidget(Widget *widgetChain) const { + const ThemeLayout *topLevelLayout = this; + while (topLevelLayout->_parent) { + topLevelLayout = topLevelLayout->_parent; + } + + assert(topLevelLayout && topLevelLayout->getLayoutType() == kLayoutMain); + const ThemeLayoutMain *dialogLayout = static_cast(topLevelLayout); + + Common::String widgetName = Common::String::format("%s.%s", dialogLayout->getName(), _name.c_str()); + return Widget::findWidgetInChain(widgetChain, widgetName.c_str()); +} + +void ThemeLayoutMain::reflowLayout(Widget *widgetChain) { assert(_children.size() <= 1); + resetLayout(); + + if (_overlays == "screen") { + _x = 0; + _y = 0; + _w = g_system->getOverlayWidth(); + _h = g_system->getOverlayHeight(); + } else if (_overlays == "screen_center") { + _x = -1; + _y = -1; + _w = -1; + _h = -1; + } else { + if (!g_gui.xmlEval()->getWidgetData(_overlays, _x, _y, (uint16 &) _w, (uint16 &) _h)) { + warning("Unable to retrieve overlayed dialog position %s", _overlays.c_str()); + } + } + + if (_x >= 0) _x += _inset; + if (_y >= 0) _y += _inset; + if (_w >= 0) _w -= 2 * _inset; + if (_h >= 0) _h -= 2 * _inset; + if (_children.size()) { - _children[0]->resetLayout(); _children[0]->setWidth(_w); _children[0]->setHeight(_h); - _children[0]->reflowLayout(); + _children[0]->reflowLayout(widgetChain); if (_w == -1) _w = _children[0]->getWidth(); @@ -177,7 +249,7 @@ void ThemeLayoutMain::reflowLayout() { } } -void ThemeLayoutStacked::reflowLayoutVertical() { +void ThemeLayoutStacked::reflowLayoutVertical(Widget *widgetChain) { int curX, curY; int resize[8]; int rescount = 0; @@ -188,9 +260,9 @@ void ThemeLayoutStacked::reflowLayoutVertical() { _h = _padding.top + _padding.bottom; for (uint i = 0; i < _children.size(); ++i) { + if (!_children[i]->isBound(widgetChain)) continue; - _children[i]->resetLayout(); - _children[i]->reflowLayout(); + _children[i]->reflowLayout(widgetChain); if (_children[i]->getWidth() == -1) _children[i]->setWidth((_w == -1 ? getParentWidth() : _w) - _padding.left - _padding.right); @@ -225,6 +297,11 @@ void ThemeLayoutStacked::reflowLayoutVertical() { if (!_children.empty()) _h -= _spacing; + // If the width is not set at this point, then we have no bound widgets. + if (!fixedWidth && _w == -1) { + _w = 0; + } + // If there were any items with undetermined height, then compute and set // their height now. We do so by determining how much space is left, and // then distributing this equally over all items which need auto-resizing. @@ -243,7 +320,7 @@ void ThemeLayoutStacked::reflowLayoutVertical() { } } -void ThemeLayoutStacked::reflowLayoutHorizontal() { +void ThemeLayoutStacked::reflowLayoutHorizontal(Widget *widgetChain) { int curX, curY; int resize[8]; int rescount = 0; @@ -254,9 +331,9 @@ void ThemeLayoutStacked::reflowLayoutHorizontal() { _w = _padding.left + _padding.right; for (uint i = 0; i < _children.size(); ++i) { + if (!_children[i]->isBound(widgetChain)) continue; - _children[i]->resetLayout(); - _children[i]->reflowLayout(); + _children[i]->reflowLayout(widgetChain); if (_children[i]->getHeight() == -1) _children[i]->setHeight((_h == -1 ? getParentHeight() : _h) - _padding.top - _padding.bottom); @@ -291,6 +368,11 @@ void ThemeLayoutStacked::reflowLayoutHorizontal() { if (!_children.empty()) _w -= _spacing; + // If the height is not set at this point, then we have no bound widgets. + if (!fixedHeight && _h == -1) { + _h = 0; + } + // If there were any items with undetermined width, then compute and set // their width now. We do so by determining how much space is left, and // then distributing this equally over all items which need auto-resizing. diff --git a/gui/ThemeLayout.h b/gui/ThemeLayout.h index e738002aa6..a99de5a99c 100644 --- a/gui/ThemeLayout.h +++ b/gui/ThemeLayout.h @@ -35,6 +35,8 @@ struct Surface; namespace GUI { +class Widget; + class ThemeLayout { friend class ThemeLayoutMain; friend class ThemeLayoutStacked; @@ -46,12 +48,13 @@ public: kLayoutVertical, kLayoutHorizontal, kLayoutWidget, - kLayoutTabWidget + kLayoutTabWidget, + kLayoutSpace }; ThemeLayout(ThemeLayout *p) : _parent(p), _x(0), _y(0), _w(-1), _h(-1), - _centered(false), _defaultW(-1), _defaultH(-1), + _defaultW(-1), _defaultH(-1), _textHAlign(Graphics::kTextAlignInvalid) {} virtual ~ThemeLayout() { @@ -59,9 +62,8 @@ public: delete _children[i]; } - virtual void reflowLayout() = 0; - - virtual void resetLayout() { _x = 0; _y = 0; _w = _defaultW; _h = _defaultH; } + virtual void reflowLayout(Widget *widgetChain) = 0; + virtual void resetLayout(); void addChild(ThemeLayout *child) { _children.push_back(child); } @@ -92,7 +94,14 @@ protected: void setHeight(int16 height) { _h = height; } void setTextHAlign(Graphics::TextAlign align) { _textHAlign = align; } - virtual LayoutType getLayoutType() = 0; + /** + * Checks if the layout element is attached to a GUI widget + * + * Layout elements that are not bound do not take space. + */ + virtual bool isBound(Widget *widgetChain) const { return true; } + + virtual LayoutType getLayoutType() const = 0; virtual ThemeLayout *makeClone(ThemeLayout *newParent) = 0; @@ -116,20 +125,24 @@ protected: int16 _x, _y, _w, _h; Common::Rect _padding; Common::Array _children; - bool _centered; int16 _defaultW, _defaultH; Graphics::TextAlign _textHAlign; }; class ThemeLayoutMain : public ThemeLayout { public: - ThemeLayoutMain(int16 x, int16 y, int16 w, int16 h) : ThemeLayout(0) { - _w = _defaultW = w; - _h = _defaultH = h; - _x = _defaultX = x; - _y = _defaultY = y; + ThemeLayoutMain(const Common::String &name, const Common::String &overlays, bool enabled, int inset) : + ThemeLayout(nullptr), + _name(name), + _overlays(overlays), + _enabled(enabled), + _inset(inset) { + _w = _defaultW = -1; + _h = _defaultH = -1; + _x = _defaultX = -1; + _y = _defaultY = -1; } - void reflowLayout(); + void reflowLayout(Widget *widgetChain) override; void resetLayout() { ThemeLayout::resetLayout(); @@ -137,35 +150,39 @@ public: _y = _defaultY; } -#ifdef LAYOUT_DEBUG_DIALOG - const char *getName() const { return "Global Layout"; } -#endif + const char *getName() const { return _name.c_str(); } protected: - LayoutType getLayoutType() { return kLayoutMain; } + LayoutType getLayoutType() const override { return kLayoutMain; } ThemeLayout *makeClone(ThemeLayout *newParent) { assert(!"Do not copy Main Layouts!"); return 0; } int16 _defaultX; int16 _defaultY; + + Common::String _name; + Common::String _overlays; + bool _enabled; + int _inset; }; class ThemeLayoutStacked : public ThemeLayout { public: ThemeLayoutStacked(ThemeLayout *p, LayoutType type, int spacing, bool center) : - ThemeLayout(p), _type(type) { + ThemeLayout(p), _type(type), _centered(center) { assert((type == kLayoutVertical) || (type == kLayoutHorizontal)); _spacing = spacing; _centered = center; } - void reflowLayout() { + void reflowLayout(Widget *widgetChain) override { if (_type == kLayoutVertical) - reflowLayoutVertical(); + reflowLayoutVertical(widgetChain); else - reflowLayoutHorizontal(); + reflowLayoutHorizontal(widgetChain); } - void reflowLayoutHorizontal(); - void reflowLayoutVertical(); + + void reflowLayoutHorizontal(Widget *widgetChain); + void reflowLayoutVertical(Widget *widgetChain); #ifdef LAYOUT_DEBUG_DIALOG const char *getName() const { @@ -178,7 +195,7 @@ protected: int16 getParentWidth(); int16 getParentHeight(); - LayoutType getLayoutType() { return _type; } + LayoutType getLayoutType() const override { return _type; } ThemeLayout *makeClone(ThemeLayout *newParent) { ThemeLayoutStacked *n = new ThemeLayoutStacked(*this); @@ -191,6 +208,7 @@ protected: } const LayoutType _type; + bool _centered; int8 _spacing; }; @@ -206,14 +224,15 @@ public: bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); Graphics::TextAlign getWidgetTextHAlign(const Common::String &name); - void reflowLayout() {} + void reflowLayout(Widget *widgetChain) override; -#ifdef LAYOUT_DEBUG_DIALOG virtual const char *getName() const { return _name.c_str(); } -#endif protected: - LayoutType getLayoutType() { return kLayoutWidget; } + LayoutType getLayoutType() const override { return kLayoutWidget; } + + bool isBound(Widget *widgetChain) const override; + Widget *getWidget(Widget *widgetChain) const; ThemeLayout *makeClone(ThemeLayout *newParent) { ThemeLayout *n = new ThemeLayoutWidget(*this); @@ -233,10 +252,9 @@ public: _tabHeight = tabHeight; } - void reflowLayout() { + void reflowLayout(Widget *widgetChain) override { for (uint i = 0; i < _children.size(); ++i) { - _children[i]->resetLayout(); - _children[i]->reflowLayout(); + _children[i]->reflowLayout(widgetChain); } } @@ -250,7 +268,7 @@ public: } protected: - LayoutType getLayoutType() { return kLayoutTabWidget; } + LayoutType getLayoutType() const override { return kLayoutTabWidget; } ThemeLayout *makeClone(ThemeLayout *newParent) { ThemeLayoutTabWidget *n = new ThemeLayoutTabWidget(*this); @@ -272,13 +290,13 @@ public: } bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { return false; } - void reflowLayout() {} + void reflowLayout(Widget *widgetChain) override {} #ifdef LAYOUT_DEBUG_DIALOG const char *getName() const { return "SPACE"; } #endif protected: - LayoutType getLayoutType() { return kLayoutWidget; } + LayoutType getLayoutType() const override { return kLayoutSpace; } ThemeLayout *makeClone(ThemeLayout *newParent) { ThemeLayout *n = new ThemeLayoutSpacing(*this); diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index f92676a383..b92dd334f3 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -721,7 +721,7 @@ bool ThemeParser::parserCallback_widget(ParserNode *node) { } bool ThemeParser::parserCallback_dialog(ParserNode *node) { - Common::String var = "Dialog." + node->values["name"]; + Common::String name = node->values["name"]; bool enabled = true; int inset = 0; @@ -740,7 +740,7 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { return false; } - _theme->getEvaluator()->addDialog(var, node->values["overlays"], enabled, inset); + _theme->getEvaluator()->addDialog(name, node->values["overlays"], enabled, inset); if (node->values.contains("shading")) { int shading = 0; @@ -750,7 +750,7 @@ bool ThemeParser::parserCallback_dialog(ParserNode *node) { shading = 2; else return parserError("Invalid value for Dialog background shading."); - _theme->getEvaluator()->setVar(var + ".Shading", shading); + _theme->getEvaluator()->setVar("Dialog." + name + ".Shading", shading); } return true; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index aeb2e1ad90..ed6958b568 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -25,6 +25,7 @@ #include "gui/gui-manager.h" #include "gui/dialog.h" +#include "gui/ThemeEval.h" #include "gui/widget.h" namespace GUI { @@ -104,6 +105,10 @@ void Dialog::reflowLayout() { // changed, so any cached image may be invalid. The subsequent redraw // should be treated as the very first draw. + if (!_name.empty()) { + g_gui.xmlEval()->reflowDialogLayout(_name, _firstWidget); + } + GuiObject::reflowLayout(); Widget *w = _firstWidget; diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp index 6c553f8783..a1e368580f 100644 --- a/gui/editgamedialog.cpp +++ b/gui/editgamedialog.cpp @@ -131,7 +131,7 @@ EditGameDialog::EditGameDialog(const String &domain) // // 1) The game tab // - tab->addTab(_("Game")); + tab->addTab(_("Game"), "GameOptions_Game"); // GUI: Label & edit widget for the game ID if (g_system->getOverlayWidth() > 320) @@ -175,7 +175,7 @@ EditGameDialog::EditGameDialog(const String &domain) // 2) The engine tab (shown only if there are custom engine options) // if (_engineOptions.size() > 0) { - tab->addTab(_("Engine")); + tab->addTab(_("Engine"), "GameOptions_Engine"); addEngineControls(tab, "GameOptions_Engine.", _engineOptions); } @@ -183,8 +183,8 @@ EditGameDialog::EditGameDialog(const String &domain) // // 3) The graphics tab // - _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); - ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GameOptions_Graphics.Container", kGraphicsTabContainerReflowCmd); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"), "GameOptions_Graphics"); + ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GameOptions_Graphics.Container", "GameOptions_Graphics_Container", kGraphicsTabContainerReflowCmd); graphicsContainer->setBackgroundType(ThemeEngine::kDialogBackgroundNone); graphicsContainer->setTarget(this); @@ -198,7 +198,7 @@ EditGameDialog::EditGameDialog(const String &domain) // // 4) The audio tab // - tab->addTab(_("Audio")); + tab->addTab(_("Audio"), "GameOptions_Audio"); if (g_system->getOverlayWidth() > 320) _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), 0, kCmdGlobalAudioOverride); @@ -212,9 +212,9 @@ EditGameDialog::EditGameDialog(const String &domain) // 5) The volume tab // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Volume")); + tab->addTab(_("Volume"), "GameOptions_Volume"); else - tab->addTab(_c("Volume", "lowres")); + tab->addTab(_c("Volume", "lowres"), "GameOptions_Volume"); if (g_system->getOverlayWidth() > 320) _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), 0, kCmdGlobalVolumeOverride); @@ -230,7 +230,7 @@ EditGameDialog::EditGameDialog(const String &domain) // _globalMIDIOverride = NULL; if (showMidi) { - tab->addTab(_("MIDI")); + tab->addTab(_("MIDI"), "GameOptions_MIDI"); if (g_system->getOverlayWidth() > 320) _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), 0, kCmdGlobalMIDIOverride); @@ -245,7 +245,7 @@ EditGameDialog::EditGameDialog(const String &domain) // _globalMT32Override = NULL; if (showMidi) { - tab->addTab(_("MT-32")); + tab->addTab(_("MT-32"), "GameOptions_MT32"); if (g_system->getOverlayWidth() > 320) _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _("Override global MT-32 settings"), 0, kCmdGlobalMT32Override); @@ -259,9 +259,9 @@ EditGameDialog::EditGameDialog(const String &domain) // 8) The Paths tab // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Paths")); + tab->addTab(_("Paths"), "GameOptions_Paths"); else - tab->addTab(_c("Paths", "lowres")); + tab->addTab(_c("Paths", "lowres"), "GameOptions_Paths"); // These buttons have to be extra wide, or the text will be truncated // in the small version of the GUI. diff --git a/gui/fluidsynth-dialog.cpp b/gui/fluidsynth-dialog.cpp index 921449eee8..34fbbf9585 100644 --- a/gui/fluidsynth-dialog.cpp +++ b/gui/fluidsynth-dialog.cpp @@ -66,7 +66,7 @@ FluidSynthSettingsDialog::FluidSynthSettingsDialog() _tabWidget = new TabWidget(this, "FluidSynthSettings.TabWidget"); - _tabWidget->addTab(_("Reverb")); + _tabWidget->addTab(_("Reverb"), "FluidSynthSettings_Reverb"); _reverbActivate = new CheckboxWidget(_tabWidget, "FluidSynthSettings_Reverb.EnableTabCheckbox", _("Active"), 0, kActivateReverbCmd); @@ -98,7 +98,7 @@ FluidSynthSettingsDialog::FluidSynthSettingsDialog() _reverbLevelSlider->setMaxValue(100); _reverbLevelLabel = new StaticTextWidget(_tabWidget, "FluidSynthSettings_Reverb.LevelLabel", "90"); - _tabWidget->addTab(_("Chorus")); + _tabWidget->addTab(_("Chorus"), "FluidSynthSettings_Chorus"); _chorusActivate = new CheckboxWidget(_tabWidget, "FluidSynthSettings_Chorus.EnableTabCheckbox", _("Active"), 0, kActivateChorusCmd); @@ -136,7 +136,7 @@ FluidSynthSettingsDialog::FluidSynthSettingsDialog() _chorusWaveFormTypePopUp->appendEntry(_("Sine"), kWaveFormTypeSine); _chorusWaveFormTypePopUp->appendEntry(_("Triangle"), kWaveFormTypeTriangle); - _tabWidget->addTab(_("Misc")); + _tabWidget->addTab(_("Misc"), "FluidSynthSettings_Misc"); _miscInterpolationPopUpDesc = new StaticTextWidget(_tabWidget, "FluidSynthSettings_Misc.InterpolationText", _("Interpolation:")); _miscInterpolationPopUp = new PopUpWidget(_tabWidget, "FluidSynthSettings_Misc.Interpolation"); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 21937494c4..0a6f00cee8 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -94,13 +94,9 @@ enum { #pragma mark - LauncherDialog::LauncherDialog() - : Dialog(0, 0, 320, 200) { - _backgroundType = GUI::ThemeEngine::kDialogBackgroundMain; - const int screenW = g_system->getOverlayWidth(); - const int screenH = g_system->getOverlayHeight(); + : Dialog("Launcher") { - _w = screenW; - _h = screenH; + _backgroundType = GUI::ThemeEngine::kDialogBackgroundMain; build(); diff --git a/gui/object.cpp b/gui/object.cpp index d2a6701443..036465a85c 100644 --- a/gui/object.cpp +++ b/gui/object.cpp @@ -31,7 +31,6 @@ namespace GUI { GuiObject::GuiObject(const Common::String &name) : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(nullptr) { - reflowLayout(); } GuiObject::~GuiObject() { diff --git a/gui/onscreendialog.cpp b/gui/onscreendialog.cpp index 7d348d720d..6b6fa2c66b 100644 --- a/gui/onscreendialog.cpp +++ b/gui/onscreendialog.cpp @@ -51,15 +51,15 @@ enum { }; void OnScreenDialog::reflowLayout() { - GuiObject::reflowLayout(); + Dialog::reflowLayout(); + + _x = _y = 0; } void OnScreenDialog::releaseFocus() { } OnScreenDialog::OnScreenDialog(bool isRecord) : Dialog("OnScreenDialog") { - _x = _y = 0; - #ifndef DISABLE_FANCY_THEMES if (g_gui.xmlEval()->getVar("Globals.OnScreenDialog.ShowPics") == 1 && g_gui.theme()->supportsImages()) { GUI::PicButtonWidget *button; diff --git a/gui/options.cpp b/gui/options.cpp index 161742d9bc..599d865ffb 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -1548,8 +1548,8 @@ void GlobalOptionsDialog::build() { // // 1) The graphics tab // - _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); - ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GlobalOptions_Graphics.Container", kGraphicsTabContainerReflowCmd); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"), "GlobalOptions_Graphics"); + ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GlobalOptions_Graphics.Container", "GlobalOptions_Graphics_Container", kGraphicsTabContainerReflowCmd); graphicsContainer->setTarget(this); graphicsContainer->setBackgroundType(ThemeEngine::kDialogBackgroundNone); addGraphicControls(graphicsContainer, "GlobalOptions_Graphics_Container."); @@ -1559,7 +1559,7 @@ void GlobalOptionsDialog::build() { // if (g_system->hasFeature(OSystem::kFeatureShader)) { - tab->addTab(_("Shader")); + tab->addTab(_("Shader"), "GlobalOptions_Shader"); addShaderControls(tab, "GlobalOptions_Shader."); } @@ -1571,21 +1571,21 @@ void GlobalOptionsDialog::build() { g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons) || g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed) || g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) { - tab->addTab(_("Control")); + tab->addTab(_("Control"), "GlobalOptions_Control"); addControlControls(tab, "GlobalOptions_Control."); } // // 2) The audio tab // - tab->addTab(_("Audio")); + tab->addTab(_("Audio"), "GlobalOptions_Audio"); addAudioControls(tab, "GlobalOptions_Audio."); addSubtitleControls(tab, "GlobalOptions_Audio."); if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Volume")); + tab->addTab(_("Volume"), "GlobalOptions_Volume"); else - tab->addTab(_c("Volume", "lowres")); + tab->addTab(_c("Volume", "lowres"), "GlobalOptions_Volume"); addVolumeControls(tab, "GlobalOptions_Volume."); // TODO: cd drive setting @@ -1593,7 +1593,7 @@ void GlobalOptionsDialog::build() { // // 3) The MIDI tab // - _midiTabId = tab->addTab(_("MIDI")); + _midiTabId = tab->addTab(_("MIDI"), "GlobalOptions_MIDI"); addMIDIControls(tab, "GlobalOptions_MIDI."); #ifdef USE_FLUIDSYNTH @@ -1603,16 +1603,16 @@ void GlobalOptionsDialog::build() { // // 4) The MT-32 tab // - tab->addTab(_("MT-32")); + tab->addTab(_("MT-32"), "GlobalOptions_MT32"); addMT32Controls(tab, "GlobalOptions_MT32."); // // 5) The Paths tab // if (g_system->getOverlayWidth() > 320) - _pathsTabId = tab->addTab(_("Paths")); + _pathsTabId = tab->addTab(_("Paths"), "GlobalOptions_Paths"); else - _pathsTabId = tab->addTab(_c("Paths", "lowres")); + _pathsTabId = tab->addTab(_c("Paths", "lowres"), "GlobalOptions_Paths"); #if !defined(__DC__) // These two buttons have to be extra wide, or the text will be @@ -1656,9 +1656,9 @@ void GlobalOptionsDialog::build() { // 6) The miscellaneous tab // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Misc")); + tab->addTab(_("Misc"), "GlobalOptions_Misc"); else - tab->addTab(_c("Misc", "lowres")); + tab->addTab(_c("Misc", "lowres"), "GlobalOptions_Misc"); new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", _("Theme:"), 0, kChooseThemeCmd); _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); @@ -1762,11 +1762,11 @@ void GlobalOptionsDialog::build() { // 7) The Cloud tab (remote storages) // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Cloud")); + tab->addTab(_("Cloud"), "GlobalOptions_Cloud"); else - tab->addTab(_c("Cloud", "lowres")); + tab->addTab(_c("Cloud", "lowres"), "GlobalOptions_Cloud"); - ScrollContainerWidget *container = new ScrollContainerWidget(tab, "GlobalOptions_Cloud.Container", kCloudTabContainerReflowCmd); + ScrollContainerWidget *container = new ScrollContainerWidget(tab, "GlobalOptions_Cloud.Container", "GlobalOptions_Cloud_Container", kCloudTabContainerReflowCmd); container->setTarget(this); container->setBackgroundType(ThemeEngine::kDialogBackgroundNone); setTarget(container); @@ -1778,9 +1778,9 @@ void GlobalOptionsDialog::build() { // 8) The LAN tab (local "cloud" webserver) // if (g_system->getOverlayWidth() > 320) - tab->addTab(_("LAN")); + tab->addTab(_("LAN"), "GlobalOptions_Network"); else - tab->addTab(_c("LAN", "lowres")); + tab->addTab(_c("LAN", "lowres"), "GlobalOptions_Network"); addNetworkControls(tab, "GlobalOptions_Network.", g_system->getOverlayWidth() <= 320); #endif // USE_SDL_NET #endif // USE_CLOUD @@ -1788,9 +1788,9 @@ void GlobalOptionsDialog::build() { //Accessibility #ifdef USE_TTS if (g_system->getOverlayWidth() > 320) - tab->addTab(_("Accessibility")); + tab->addTab(_("Accessibility"), "GlobalOptions_Accessibility"); else - tab->addTab(_c("Accessibility", "lowres")); + tab->addTab(_c("Accessibility", "lowres"), "GlobalOptions_Accessibility"); _ttsCheckbox = new CheckboxWidget(tab, "GlobalOptions_Accessibility.TTSCheckbox", _("Use Text to speech"), _("Will read text in gui on mouse over.")); if (ConfMan.hasKey("tts_enabled")) @@ -2175,9 +2175,9 @@ void GlobalOptionsDialog::apply() { #endif if (isRebuildNeeded) { - rebuild(); if (_launcher != 0) _launcher->rebuild(); + rebuild(); } _newTheme.clear(); diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp index cbe90c93b8..b9ac1e2484 100644 --- a/gui/recorderdialog.cpp +++ b/gui/recorderdialog.cpp @@ -60,7 +60,7 @@ RecorderDialog::RecorderDialog() : Dialog("RecorderDialog"), _list(0), _currentS _backgroundType = ThemeEngine::kDialogBackgroundSpecial; - new StaticTextWidget(this, "SaveLoadChooser.Title", _("Recorder or Playback Gameplay")); + new StaticTextWidget(this, "RecorderDialog.Title", _("Recorder or Playback Gameplay")); _list = new GUI::ListWidget(this, "RecorderDialog.List"); _list->setNumberingMode(GUI::kListNumberingOff); @@ -77,7 +77,7 @@ RecorderDialog::RecorderDialog() : Dialog("RecorderDialog"), _list(0), _currentS _playbackButton->setEnabled(false); _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10); - _container = new GUI::ContainerWidget(this, 0, 0, 10, 10); + _container = new GUI::ContainerWidget(this, "RecorderDialog.Thumbnail"); if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) { new GUI::ButtonWidget(this,"RecorderDialog.NextScreenShotButton", "<", 0, kPrevScreenshotCmd); new GUI::ButtonWidget(this, "RecorderDialog.PreviousScreenShotButton", ">", 0, kNextScreenshotCmd); @@ -91,6 +91,8 @@ RecorderDialog::RecorderDialog() : Dialog("RecorderDialog"), _list(0), _currentS void RecorderDialog::reflowLayout() { + Dialog::reflowLayout(); + if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) { int16 x, y; uint16 w, h; @@ -114,7 +116,6 @@ void RecorderDialog::reflowLayout() { _container->setVisible(false); _gfxWidget->setVisible(false); } - Dialog::reflowLayout(); } diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp index 61fd392976..cca3a4d5b8 100644 --- a/gui/saveload-dialog.cpp +++ b/gui/saveload-dialog.cpp @@ -398,8 +398,7 @@ SaveLoadChooserSimple::SaveLoadChooserSimple(const String &title, const String & _delSupport = _metaInfoSupport = _thumbnailSupport = false; - _container = new ContainerWidget(this, 0, 0, 10, 10); -// _container->setHints(THEME_HINT_USE_SHADOW); + _container = new ContainerWidget(this, "SaveLoadChooser.Thumbnail"); } int SaveLoadChooserSimple::runIntern() { @@ -472,6 +471,8 @@ void SaveLoadChooserSimple::handleCommand(CommandSender *sender, uint32 cmd, uin } void SaveLoadChooserSimple::reflowLayout() { + SaveLoadChooserDialog::reflowLayout(); + if (g_gui.xmlEval()->getVar("Globals.SaveLoadChooser.ExtInfo.Visible") == 1 && (_thumbnailSupport || _saveDateSupport || _playTimeSupport)) { int16 x, y; uint16 w, h; @@ -536,8 +537,6 @@ void SaveLoadChooserSimple::reflowLayout() { _time->setVisible(false); _playtime->setVisible(false); } - - SaveLoadChooserDialog::reflowLayout(); } void SaveLoadChooserSimple::updateSelection(bool redraw) { @@ -745,6 +744,10 @@ SaveLoadChooserGrid::SaveLoadChooserGrid(const Common::String &title, bool saveM new StaticTextWidget(this, "SaveLoadChooser.Title", title); + // The list widget needs to be bound so it takes space in the layout + ContainerWidget *list = new ContainerWidget(this, "SaveLoadChooser.List"); + list->setBackgroundType(ThemeEngine::kWidgetBackgroundNo); + // Buttons new ButtonWidget(this, "SaveLoadChooser.Delete", _("Cancel"), 0, kCloseCmd); _nextButton = new ButtonWidget(this, "SaveLoadChooser.Choose", _("Next"), 0, kNextCmd); diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 9b6b102c23..90730e49db 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1825,7 +1825,7 @@ const char *defaultXML1 = "" "" "" "" -"" +"" "" "" "" @@ -1838,7 +1838,7 @@ const char *defaultXML1 = "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" @@ -3569,7 +3569,7 @@ const char *defaultXML1 = "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" "" "" "" -"" +"" "" " - + @@ -983,7 +983,7 @@ - + - + - + - + - + @@ -984,7 +984,7 @@ - + - + - + - + - + @@ -999,7 +999,7 @@ - + - + - + - + - + @@ -983,7 +983,7 @@ - + - + - + - + - + @@ -999,7 +999,7 @@ - + - + - + - + - + @@ -983,7 +983,7 @@ - + - + - + - + = 0 && x < _w && y >= 0 && y < _h) { setUnpressedState(); @@ -476,6 +484,14 @@ void DropdownButtonWidget::reflowLayout() { reset(); } +void DropdownButtonWidget::getMinSize(int &minWidth, int &minHeight) { + ButtonWidget::getMinSize(minWidth, minHeight); + + if (minWidth >= 0) { + minWidth += _dropdownWidth * 2; + } +} + void DropdownButtonWidget::appendEntry(const Common::String &label, uint32 cmd) { Entry e; e.label = label; @@ -838,12 +854,16 @@ void GraphicsWidget::drawWidget() { #pragma mark - -ContainerWidget::ContainerWidget(GuiObject *boss, int x, int y, int w, int h) : Widget(boss, x, y, w, h) { +ContainerWidget::ContainerWidget(GuiObject *boss, int x, int y, int w, int h) : + Widget(boss, x, y, w, h), + _backgroundType(ThemeEngine::kWidgetBackgroundBorder) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kContainerWidget; } -ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) : Widget(boss, name) { +ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) : + Widget(boss, name), + _backgroundType(ThemeEngine::kWidgetBackgroundBorder) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kContainerWidget; } @@ -875,9 +895,12 @@ void ContainerWidget::removeWidget(Widget *widget) { Widget::removeWidget(widget); } +void ContainerWidget::setBackgroundType(ThemeEngine::WidgetBackground backgroundType) { + _backgroundType = backgroundType; +} + void ContainerWidget::drawWidget() { - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, - ThemeEngine::kWidgetBackgroundBorder); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, _backgroundType); } } // End of namespace GUI diff --git a/gui/widget.h b/gui/widget.h index 2339012074..87099f5c7f 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -130,6 +130,9 @@ public: virtual void setPos(int x, int y) { _x = x; _y = y; } virtual void setSize(int w, int h) { _w = w; _h = h; } + /** Returns the minimal size the widget needs to have for its contents to fit */ + virtual void getMinSize(int &minWidth, int &minHeight) { minHeight = -1; minWidth = -1; } + virtual void handleMouseDown(int x, int y, int button, int clickCount) {} virtual void handleMouseUp(int x, int y, int button, int clickCount) {} virtual void handleMouseEntered(int button) {} @@ -218,6 +221,8 @@ public: ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); + void getMinSize(int &minWidth, int &minHeight) override; + void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } @@ -245,6 +250,8 @@ public: void handleMouseMoved(int x, int y, int button) override; void handleMouseUp(int x, int y, int button, int clickCount) override; void reflowLayout() override; + void getMinSize(int &minWidth, int &minHeight) override; + void appendEntry(const Common::String &label, uint32 cmd); void clearEntries(); @@ -430,8 +437,12 @@ public: virtual bool containsWidget(Widget *) const; virtual Widget *findWidget(int x, int y); virtual void removeWidget(Widget *widget); + + void setBackgroundType(ThemeEngine::WidgetBackground backgroundType); protected: void drawWidget(); + + ThemeEngine::WidgetBackground _backgroundType; }; ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32 cmd, int x=0, int y=0, int w=0, int h=0); diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp index 3ef365ba5c..9144282e65 100644 --- a/gui/widgets/list.cpp +++ b/gui/widgets/list.cpp @@ -36,10 +36,7 @@ namespace GUI { ListWidget::ListWidget(Dialog *boss, const String &name, const char *tooltip, uint32 cmd) : EditableWidget(boss, name, tooltip), _cmd(cmd) { - _scrollBar = NULL; - - // This ensures that _entriesPerPage is properly initialized. - reflowLayout(); + _entriesPerPage = 0; _scrollBar = new ScrollBarWidget(this, _w - _scrollBarWidth, 0, _scrollBarWidth, _h); _scrollBar->setTarget(this); @@ -69,10 +66,7 @@ ListWidget::ListWidget(Dialog *boss, const String &name, const char *tooltip, ui ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd) : EditableWidget(boss, x, y, w, h, tooltip), _cmd(cmd) { - _scrollBar = NULL; - - // This ensures that _entriesPerPage is properly initialized. - reflowLayout(); + _entriesPerPage = 0; _scrollBar = new ScrollBarWidget(this, _w - _scrollBarWidth, 0, _scrollBarWidth, _h); _scrollBar->setTarget(this); diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp index c136c57a81..e0680e123b 100644 --- a/gui/widgets/scrollcontainer.cpp +++ b/gui/widgets/scrollcontainer.cpp @@ -33,8 +33,8 @@ ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, int x, int y, int init(); } -ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::String &name, uint32 reflowCmd) - : Widget(boss, name), CommandSender(nullptr), _reflowCmd(reflowCmd) { +ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::String &name, const Common::String &dialogName, uint32 reflowCmd) + : Widget(boss, name), CommandSender(nullptr), _reflowCmd(reflowCmd), _dialogName(dialogName) { init(); } @@ -119,6 +119,10 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin void ScrollContainerWidget::reflowLayout() { Widget::reflowLayout(); + if (!_dialogName.empty()) { + g_gui.xmlEval()->reflowDialogLayout(_dialogName, _firstWidget); + } + //reflow layout of inner widgets Widget *ptr = _firstWidget; while (ptr) { diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h index c034cab4fd..fd8db765a3 100644 --- a/gui/widgets/scrollcontainer.h +++ b/gui/widgets/scrollcontainer.h @@ -35,12 +35,13 @@ class ScrollContainerWidget: public Widget, public CommandSender { uint16 _limitH; uint32 _reflowCmd; ThemeEngine::DialogBackground _backgroundType; + Common::String _dialogName; void recalc(); public: ScrollContainerWidget(GuiObject *boss, int x, int y, int w, int h, uint32 reflowCmd = 0); - ScrollContainerWidget(GuiObject *boss, const Common::String &name, uint32 reflowCmd = 0); + ScrollContainerWidget(GuiObject *boss, const Common::String &name, const Common::String &dialogName, uint32 reflowCmd = 0); ~ScrollContainerWidget() override; void init(); diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp index d373bc9222..1ca61565aa 100644 --- a/gui/widgets/tab.cpp +++ b/gui/widgets/tab.cpp @@ -104,10 +104,11 @@ uint16 TabWidget::getHeight() const { return _h + _tabHeight; } -int TabWidget::addTab(const String &title) { +int TabWidget::addTab(const String &title, const String &dialogName) { // Add a new tab page Tab newTab; newTab.title = title; + newTab.dialogName = dialogName; newTab.firstWidget = 0; // Determine the new tab width @@ -300,6 +301,10 @@ void TabWidget::reflowLayout() { _tabs[_activeTab].firstWidget = _firstWidget; for (uint i = 0; i < _tabs.size(); ++i) { + if (!_tabs[i].dialogName.empty()) { + g_gui.xmlEval()->reflowDialogLayout(_tabs[i].dialogName, _tabs[i].firstWidget); + } + Widget *w = _tabs[i].firstWidget; while (w) { w->reflowLayout(); diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h index 8411509bd0..1aa9ded031 100644 --- a/gui/widgets/tab.h +++ b/gui/widgets/tab.h @@ -38,6 +38,7 @@ class TabWidget : public Widget { typedef Common::String String; struct Tab { String title; + String dialogName; Widget *firstWidget; int _tabWidth; }; @@ -73,7 +74,7 @@ public: * Add a new tab with the given title. Returns a unique ID which can be used * to identify the tab (to remove it / activate it etc.). */ - int addTab(const String &title); + int addTab(const String &title, const String &dialogName); /** * Remove the tab with the given tab ID. Disposes all child widgets of that tab. -- cgit v1.2.3