diff options
Diffstat (limited to 'gui')
55 files changed, 8644 insertions, 5653 deletions
diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp index 3b5afab669..889310d958 100644 --- a/gui/EditTextWidget.cpp +++ b/gui/EditTextWidget.cpp @@ -24,9 +24,10 @@ #include "gui/EditTextWidget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text) @@ -41,7 +42,6 @@ EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String : EditableWidget(boss, name) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; - _hints |= THEME_HINT_USE_SHADOW; setEditString(text); } @@ -52,10 +52,10 @@ void EditTextWidget::setEditString(const String &str) { } void EditTextWidget::reflowLayout() { - _leftPadding = g_gui.evaluator()->getVar("EditTextWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("EditTextWidget.rightPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.EditTextWidget.Padding.Right", 0); - _font = (Theme::FontStyle)g_gui.evaluator()->getVar("EditTextWidget.font", Theme::kFontStyleNormal); + _font = (Theme::FontStyle)g_gui.xmlEval()->getVar("EditTextWidget.Font", Theme::kFontStyleNormal); EditableWidget::reflowLayout(); } @@ -82,7 +82,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) { void EditTextWidget::drawWidget() { - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _hints, Theme::kWidgetBackgroundEditText); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, Theme::kWidgetBackgroundEditText); // Draw the text adjustOffset(); diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 80898d06c8..c17963ea95 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -27,9 +27,10 @@ #include "gui/ListWidget.h" #include "gui/ScrollBarWidget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { ListWidget::ListWidget(GuiObject *boss, const String &name) @@ -45,7 +46,6 @@ ListWidget::ListWidget(GuiObject *boss, const String &name) _scrollBar->setTarget(this); setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); - setHints(THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); _type = kListWidget; _editMode = false; _numberingMode = kListNumberingOne; @@ -75,7 +75,6 @@ ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h) _scrollBar->setTarget(this); setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); - setHints(THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); _type = kListWidget; _editMode = false; _numberingMode = kListNumberingOne; @@ -361,7 +360,8 @@ void ListWidget::drawWidget() { Common::String buffer; // Draw a thin frame around the list. - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _hints, Theme::kWidgetBackgroundBorder); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, Theme::kWidgetBackgroundBorder); + const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0; // Draw the list items for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) { @@ -374,7 +374,8 @@ void ListWidget::drawWidget() { if (_hasFocus) inverted = true; else - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1), _hints, Theme::kWidgetBackgroundBorderSmall); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1), + 0, Theme::kWidgetBackgroundBorderSmall); } Common::Rect r(getEditRect()); @@ -385,7 +386,8 @@ void ListWidget::drawWidget() { char temp[10]; sprintf(temp, "%2d. ", (pos + _numberingMode)); buffer = temp; - g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), buffer, _state, Theme::kTextAlignLeft, inverted, _leftPadding); + g_gui.theme()->drawText(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), + buffer, _state, Theme::kTextAlignLeft, inverted, _leftPadding); pad = 0; } @@ -394,20 +396,22 @@ void ListWidget::drawWidget() { if (_selectedItem == pos && _editMode) { buffer = _editString; adjustOffset(); - width = _w - r.left - _hlRightPadding - _leftPadding; - g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); + width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW; + g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight-2), + buffer, _state, Theme::kTextAlignLeft, inverted, pad); } else { int maxWidth = _textWidth[i]; buffer = _list[pos]; if (_selectedItem != pos) { width = g_gui.getStringWidth(buffer) + pad; if (width > _w - r.left) - width = _w - r.left; + width = _w - r.left - _hlRightPadding - scrollbarW; } else - width = _w - r.left - _hlRightPadding; + width = _w - r.left - _hlRightPadding - scrollbarW; if (width > maxWidth) maxWidth = width; - g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), buffer, _state, Theme::kTextAlignLeft, inverted, pad); + g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + maxWidth, y + fontHeight-2), + buffer, _state, Theme::kTextAlignLeft, inverted, pad); } _textWidth[i] = width; @@ -480,12 +484,12 @@ void ListWidget::abortEditMode() { void ListWidget::reflowLayout() { Widget::reflowLayout(); - _leftPadding = g_gui.evaluator()->getVar("ListWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("ListWidget.rightPadding", 0); - _topPadding = g_gui.evaluator()->getVar("ListWidget.topPadding", 0); - _bottomPadding = g_gui.evaluator()->getVar("ListWidget.bottomPadding", 0); - _hlLeftPadding = g_gui.evaluator()->getVar("ListWidget.hlLeftPadding", 0); - _hlRightPadding = g_gui.evaluator()->getVar("ListWidget.hlRightPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Right", 0); + _topPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Top", 0); + _bottomPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Bottom", 0); + _hlLeftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlLeftPadding", 0); + _hlRightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlRightPadding", 0); if (g_gui.getWidgetSize() == kBigWidgetSize) { _scrollBarWidth = kBigScrollBarWidth; @@ -493,7 +497,19 @@ void ListWidget::reflowLayout() { _scrollBarWidth = kNormalScrollBarWidth; } - _entriesPerPage = (_h - _topPadding - _bottomPadding) / kLineHeight; + // HACK: Once we take padding into account, there are times where + // integer rounding leaves a big chunk of white space in the bottom + // of the list. + // We do a rough rounding on the decimal places of Entries Per Page, + // to add another entry even if it goes a tad over the padding. + _entriesPerPage = ((_h - _topPadding - _bottomPadding) << 16) / kLineHeight; + + if ((uint)(_entriesPerPage & 0xFFFF) >= 0xF000) + _entriesPerPage += (1 << 16); + + _entriesPerPage >>= 16; + + assert(_entriesPerPage > 0); delete[] _textWidth; _textWidth = new int[_entriesPerPage]; diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 91b7c40687..6c89e7113c 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -25,11 +25,12 @@ #include "common/system.h" #include "common/events.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/PopUpWidget.h" #include "engines/engine.h" +#include "gui/ThemeEval.h" + namespace GUI { // @@ -71,7 +72,7 @@ protected: }; PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) - : Dialog(0, 0, 16, 16, false), + : Dialog(0, 0, 16, 16), _popUpBoss(boss) { // Copy the selection index @@ -151,7 +152,7 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) void PopUpDialog::drawDialog() { // Draw the menu border - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND | THEME_HINT_USE_SHADOW); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0); /*if (_twoColumns) g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/ @@ -358,7 +359,6 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) { PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const String &label, uint labelWidth) : Widget(boss, name), CommandSender(boss), _label(label), _labelWidth(labelWidth) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS); - setHints(THEME_HINT_SAVE_BACKGROUND); _type = kPopUpWidget; _selectedItem = -1; @@ -380,9 +380,9 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { } void PopUpWidget::reflowLayout() { - _leftPadding = g_gui.evaluator()->getVar("PopUpWidget.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("PopUpWidget.rightPadding", 0); - _labelSpacing = g_gui.evaluator()->getVar("PopUpWidget.labelSpacing", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.PopUpWidget.Padding.Right", 0); + _labelSpacing = g_gui.xmlEval()->getVar("Globals.PopUpWidget.labelSpacing", 10); Widget::reflowLayout(); } diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp index 7ad4edbd88..402e9075c1 100644 --- a/gui/TabWidget.cpp +++ b/gui/TabWidget.cpp @@ -26,7 +26,8 @@ #include "gui/TabWidget.h" #include "gui/dialog.h" #include "gui/newgui.h" -#include "gui/eval.h" + +#include "gui/ThemeEval.h" namespace GUI { @@ -55,21 +56,19 @@ void TabWidget::init() { _activeTab = -1; _firstVisibleTab = 0; - _tabWidth = g_gui.evaluator()->getVar("TabWidget.tabWidth"); - _tabHeight = g_gui.evaluator()->getVar("TabWidget.tabHeight"); - _titleVPad = g_gui.evaluator()->getVar("TabWidget.titleVPad"); + _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width"); + _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height"); + _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); - _butRP = g_gui.evaluator()->getVar("TabWidget.navButtonRightPad", 0); - _butTP = g_gui.evaluator()->getVar("TabWidget.navButtonTopPad", 0); - _butW = g_gui.evaluator()->getVar("TabWidget.navButtonW", 10); - _butH = g_gui.evaluator()->getVar("TabWidget.navButtonH", 10); + _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.navButtonPadding.Right", 0); + _butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0); + _butW = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Width", 10); + _butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10); int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", kCmdLeft, 0); - _navLeft->setHints(THEME_HINT_NO_BACKGROUND_RESTORE); _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", kCmdRight, 0); - _navRight->setHints(THEME_HINT_NO_BACKGROUND_RESTORE); } TabWidget::~TabWidget() { @@ -96,7 +95,7 @@ int TabWidget::addTab(const String &title) { int numTabs = _tabs.size(); - if (g_gui.evaluator()->getVar("TabWidget.tabWidth") == 0) { + if (g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width") == 0) { if (_tabWidth == 0) _tabWidth = 40; // Determine the new tab width @@ -216,9 +215,9 @@ void TabWidget::reflowLayout() { } } - _tabHeight = g_gui.evaluator()->getVar("TabWidget.tabHeight"); - _tabWidth = g_gui.evaluator()->getVar("TabWidget.tabWidth"); - _titleVPad = g_gui.evaluator()->getVar("TabWidget.titleVPad"); + _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height"); + _tabWidth = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width"); + _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); if (_tabWidth == 0) { _tabWidth = 40; @@ -234,10 +233,10 @@ void TabWidget::reflowLayout() { } } - _butRP = g_gui.evaluator()->getVar("TabWidget.navButtonRightPad", 0); - _butTP = g_gui.evaluator()->getVar("TabWidget.navButtonTopPad", 0); - _butW = g_gui.evaluator()->getVar("TabWidget.navButtonW", 10); - _butH = g_gui.evaluator()->getVar("TabWidget.navButtonH", 10); + _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.PaddingRight", 0); + _butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0); + _butW = g_gui.xmlEval()->getVar("GlobalsTabWidget.NavButton.Width", 10); + _butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10); int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; @@ -254,7 +253,7 @@ void TabWidget::drawWidget() { for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) { tabs.push_back(_tabs[i].title); } - g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, _hints, _titleVPad); + g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad); } void TabWidget::draw() { diff --git a/gui/TabWidget.h b/gui/TabWidget.h index bf316a7ac3..3dffcd2afe 100644 --- a/gui/TabWidget.h +++ b/gui/TabWidget.h @@ -85,6 +85,11 @@ public: * Widgets are always added to the active tab. */ void setActiveTab(int tabID); + + void setTabTitle(int tabID, const String &title) { + assert(0 <= tabID && tabID < (int)_tabs.size()); + _tabs[tabID].title = title; + } virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual bool handleKeyDown(Common::KeyState state); diff --git a/gui/ThemeClassic.cpp b/gui/ThemeClassic.cpp deleted file mode 100644 index be17cf0d09..0000000000 --- a/gui/ThemeClassic.cpp +++ /dev/null @@ -1,710 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - */ - -#include "gui/ThemeClassic.h" -#include "gui/eval.h" - -namespace GUI { -ThemeClassic::ThemeClassic(OSystem *system, const Common::String &config, const Common::ConfigFile *cfg) : Theme() { - _enableBlending = true; - _stylefile = config; - _system = system; - _initOk = false; - _enabled = false; - _font = 0; - _fontName.clear(); - memset(&_screen, 0, sizeof(_screen)); -#ifndef CT_NO_TRANSPARENCY - memset(&_dialog, 0, sizeof(_dialog)); -#endif - _font = 0; - - // 'classic' is always the built in one, we force it and - // ignore all 'classic' named config files - if (config.compareToIgnoreCase("classic (builtin)") != 0) { - if (cfg) - _configFile = *cfg; - else - loadConfigFile(_stylefile); - } - - if (_configFile.hasKey("name", "theme")) - _configFile.getKey("name", "theme", _stylename); - else - _stylename = _stylefile; -} - -ThemeClassic::~ThemeClassic() { - deinit(); -} - -bool ThemeClassic::init() { - deinit(); - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - resetDrawArea(); - } - - if (isThemeLoadingRequired()) { - loadTheme(_defaultConfig); - loadTheme(_configFile, false, true); - - setupConfig(); - } - - _bgcolor = _system->RGBToColor(_colors[kBGColor][0], _colors[kBGColor][1], _colors[kBGColor][2]); - _color = _system->RGBToColor(_colors[kColor][0], _colors[kColor][1], _colors[kColor][2]); - _shadowcolor = _system->RGBToColor(_colors[kShadowColor][0], _colors[kShadowColor][1], _colors[kShadowColor][2]); - _textcolor = _system->RGBToColor(_colors[kTextColor][0], _colors[kTextColor][1], _colors[kTextColor][2]); - _textcolorhi = _system->RGBToColor(_colors[kTextColorHi][0], _colors[kTextColorHi][1], _colors[kTextColorHi][2]); - if (_fontName.empty()) { - if (_screen.w >= 400 && _screen.h >= 300) { - _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } else { - _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } - } - - return true; -} - -void ThemeClassic::deinit() { - if (_initOk) { - _system->hideOverlay(); - _screen.free(); - _initOk = false; - } -} - -void ThemeClassic::refresh() { - init(); - if (_enabled) - _system->showOverlay(); -} - -void ThemeClassic::enable() { - init(); - resetDrawArea(); - _system->showOverlay(); - clearAll(); - _enabled = true; -} - -void ThemeClassic::disable() { - _system->hideOverlay(); - _enabled = false; -} - -void ThemeClassic::openDialog(bool topDialog) { -#ifndef CT_NO_TRANSPARENCY - if (!_dialog) { - _dialog = new DialogState; - assert(_dialog); - // first dialog - _dialog->screen.create(_screen.w, _screen.h, sizeof(OverlayColor)); - } - memcpy(_dialog->screen.pixels, _screen.pixels, _screen.pitch*_screen.h); - if (!_enableBlending) - _dialog->screen.fillRect(Common::Rect(0, 0, _screen.w, _screen.h), _bgcolor); - else - blendScreenToDialog(); -#endif -} - -void ThemeClassic::closeAllDialogs() { -#ifndef CT_NO_TRANSPARENCY - if (_dialog) { - _dialog->screen.free(); - delete _dialog; - _dialog = 0; - } - _forceRedraw = true; -#endif -} - -void ThemeClassic::clearAll() { - if (!_initOk) - return; - _system->clearOverlay(); - // FIXME: problem with the 'pitch' - _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); -} - -void ThemeClassic::updateScreen() { - _forceRedraw = false; -} - -void ThemeClassic::resetDrawArea() { - if (_initOk) { - _drawArea = Common::Rect(0, 0, _screen.w, _screen.h); - } -} - -int ThemeClassic::getTabSpacing() const { - return 2; -} -int ThemeClassic::getTabPadding() const { - return 3; -} - -void ThemeClassic::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - -#ifndef CT_NO_TRANSPARENCY - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - addDirtyRect(r); - return; - } -#endif - - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - addDirtyRect(r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeClassic::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!_initOk) - return; - - if (!inverted) { - restoreBackground(r); - _font->drawString(&_screen, str, r.left, r.top, r.width(), getColor(state), convertAligment(align), deltax, useEllipsis); - } else { - _screen.fillRect(r, getColor(state)); - _font->drawString(&_screen, str, r.left, r.top, r.width(), _bgcolor, convertAligment(align), deltax, useEllipsis); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - font->drawChar(&_screen, ch, r.left, r.top, getColor(state)); - addDirtyRect(r); -} - -void ThemeClassic::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { - if (!_initOk || background == kWidgetBackgroundNo) - return; - - restoreBackground(r); - -#ifndef CT_NO_TRANSPARENCY - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - addDirtyRect(r); - return; - } -#endif - - switch (background) { - case kWidgetBackgroundBorder: - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - break; - - //case kWidgetBackgroundPlain: - //case kWidgetBackgroundBorderSmall: - default: - box(r.left, r.top, r.width(), r.height()); - break; - }; - - addDirtyRect(r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeClassic::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!_initOk) - return; - restoreBackground(r); - - drawWidgetBackground(r, 0, kWidgetBackgroundBorder, state); - - const int off = (r.height() - _font->getFontHeight()) / 2; - _font->drawString(&_screen, str, r.left, r.top+off, r.width(), getColor(state), Graphics::kTextAlignCenter, 0, false); - - addDirtyRect(r); -} - -void ThemeClassic::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { - if (!_initOk) - return; - - Common::Rect rect(r.left, r.top, r.left + surface.w, r.top + surface.h); - rect.clip(_screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - assert(surface.bytesPerPixel == sizeof(OverlayColor)); - - OverlayColor *src = (OverlayColor *)surface.pixels; - OverlayColor *dst = (OverlayColor *)_screen.getBasePtr(rect.left, rect.top); - - int w = rect.width(); - int h = rect.height(); - - while (h--) { - memcpy(dst, src, surface.pitch); - src += w; - // FIXME: this should be pitch - dst += _screen.w; - } - addDirtyRect(r); -} - -void ThemeClassic::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { - if (!_initOk) - return; - Common::Rect r2 = r; - - restoreBackground(r); - - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - r2.left = r.left + 2; - r2.top = r.top + 2; - r2.bottom = r.bottom - 2; - r2.right = r2.left + width; - if (r2.right > r.right - 2) { - r2.right = r.right - 2; - } - - _screen.fillRect(r2, getColor(state)); - - addDirtyRect(r); -} - -void ThemeClassic::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { - if (!_initOk) - return; - - restoreBackground(r); - - box(r.left, r.top, r.width(), r.height()); - - Common::Point p0, p1; - - p0 = Common::Point(r.right + 1 - r.height() / 2, r.top + 4); - p1 = Common::Point(r.right + 1 - r.height() / 2, r.bottom - 4); - - OverlayColor color = getColor(state); - - // Evil HACK to draw filled triangles - // FIXME: The "big" version is pretty ugly. - for (; p1.y - p0.y > 1; p0.y++, p0.x--, p1.y--, p1.x++) { - _screen.drawLine(p0.x, p0.y, p1.x, p0.y, color); - _screen.drawLine(p0.x, p1.y, p1.x, p1.y, color); - } - - if (!sel.empty()) { - Common::Rect text(r.left + 2, r.top + 3, r.right - 4, r.top + 3 + _font->getFontHeight()); - _font->drawString(&_screen, sel, text.left, text.top, text.width(), color, convertAligment(align), deltax, false); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2 = r; - int checkBoxSize = getFontHeight(); - if (checkBoxSize > r.height()) { - checkBoxSize = r.height(); - } - r2.bottom = r2.top + checkBoxSize; - - restoreBackground(r2); - - box(r.left, r.top, checkBoxSize, checkBoxSize, _color, _shadowcolor); - - if (checked) { - r2.top += 3; - r2.bottom = r.top + checkBoxSize - 4; - r2.left += 3; - r2.right = r.left + checkBoxSize - 4; - - OverlayColor c = getColor(state); - - // Draw a cross - _screen.drawLine(r2.left, r2.top, r2.right, r2.bottom, c); - _screen.drawLine(r2.left, r2.bottom, r2.right, r2.top, c); - - if (r2.height() > 5) { - // Thicken the lines - _screen.drawLine(r2.left, r2.top + 1, r2.right - 1, r2.bottom, c); - _screen.drawLine(r2.left + 1, r2.top, r2.right, r2.bottom - 1, c); - _screen.drawLine(r2.left, r2.bottom - 1, r2.right - 1, r2.top, c); - _screen.drawLine(r2.left + 1, r2.bottom, r2.right, r2.top + 1, c); - } - - r2 = r; - } - - r2.left += checkBoxSize + 10; - _font->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, true); - - addDirtyRect(r); -} - -void ThemeClassic::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - - for (int i = 0; i < (int)tabs.size(); ++i) { - if (i == active) - continue; - box(r.left + i * tabWidth, r.top+2, tabWidth, tabHeight-2, _color, _shadowcolor); - _font->drawString(&_screen, tabs[i], r.left + i * tabWidth, r.top+4, tabWidth, getColor(state), Graphics::kTextAlignCenter, 0, true); - } - - if (active >= 0) { - box(r.left + active * tabWidth, r.top, tabWidth, tabHeight, _color, _shadowcolor, true); - _font->drawString(&_screen, tabs[active], r.left + active * tabWidth, r.top+titleVPad, tabWidth, getColor(kStateHighlight), Graphics::kTextAlignCenter, 0, true); - - _screen.hLine(r.left, r.top + tabHeight, r.left + active * tabWidth + 1, _color); - _screen.hLine(r.left + active * tabWidth + tabWidth - 2, r.top + tabHeight, r.right, _color); - _screen.hLine(r.left, r.bottom - 1, r.right - 1, _shadowcolor); - _screen.vLine(r.left, r.top + tabHeight, r.bottom - 1, _color); - _screen.vLine(r.right - 1, r.top + tabHeight, r.bottom - 1, _shadowcolor); - } - - addDirtyRect(r); -} - -void ThemeClassic::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scroll, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - Common::Rect r2 = r; - box(r.left, r.top, r.width(), r.height(), _color, _shadowcolor); - - const int UP_DOWN_BOX_HEIGHT = r.width() + 1; - const int B = 3; - const int arrowSize = (r.width() / 2 - B + 1); - - OverlayColor color = 0; - if (scroll == kScrollbarStateSinglePage) { - color = _color; - } else if (scroll == kScrollbarStateUp && state == kStateHighlight) { - color = _textcolorhi; - } else { - color = _textcolor; - } - - // draws the 'up' button - box(r.left, r.top, r.width(), UP_DOWN_BOX_HEIGHT, _color, _shadowcolor); - Common::Point p0 = Common::Point(r.left + r.width() / 2, r.top + (UP_DOWN_BOX_HEIGHT - arrowSize - 1) / 2); - Common::Point p1 = Common::Point(p0.x - arrowSize, p0.y + arrowSize); - Common::Point p2 = Common::Point(p0.x + arrowSize, p0.y + arrowSize); - for (; p1.x <= p2.x; ++p1.x) - _screen.drawLine(p0.x, p0.y, p1.x, p1.y, color); - - if (scroll != kScrollbarStateSinglePage) { - r2.top += sliderY; - r2.left += 2; - r2.right -= 2; - r2.bottom = r2.top + sliderHeight; - _screen.fillRect(r2, (state == kStateHighlight && scroll == kScrollbarStateSlider) ? _textcolorhi : _textcolor); - box(r2.left, r2.top, r2.width(), r2.height()); - int y = r2.top + sliderHeight / 2; - color = (state == kStateHighlight && scroll == kScrollbarStateSlider) ? _color : _bgcolor; - _screen.hLine(r2.left + 1, y - 2, r2.right - 2, color); - _screen.hLine(r2.left + 1, y, r2.right - 2, color); - _screen.hLine(r2.left + 1, y + 2, r2.right - 2, color); - r2 = r; - } - - r2.top = r2.bottom - UP_DOWN_BOX_HEIGHT; - if (scroll == kScrollbarStateSinglePage) { - color = _color; - } else if (scroll == kScrollbarStateDown && state == kStateHighlight) { - color = _textcolorhi; - } else { - color = _textcolor; - } - - // draws the 'down' button - box(r2.left, r2.top, r2.width(), UP_DOWN_BOX_HEIGHT, _color, _shadowcolor); - p0 = Common::Point(r2.left + r2.width() / 2, r2.top + (UP_DOWN_BOX_HEIGHT + arrowSize + 1) / 2); - p1 = Common::Point(p0.x - arrowSize, p0.y - arrowSize); - p2 = Common::Point(p0.x + arrowSize, p0.y - arrowSize); - for (; p1.x <= p2.x; ++p1.x) - _screen.drawLine(p0.x, p0.y, p1.x, p1.y, color); - - addDirtyRect(r); -} - -void ThemeClassic::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { - if (!_initOk) - return; - - OverlayColor color = 0; - if (erase) { - color = _bgcolor; - } else { - color = getColor(state); - } - - _screen.vLine(r.left, r.top, r.bottom - 2, color); - addDirtyRect(r); -} - -void ThemeClassic::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!_initOk) - return; - _screen.hLine(r.left - 1, r.top + r.height() / 2, r.right, _shadowcolor); - _screen.hLine(r.left, r.top + 1 + r.height() / 2, r.right, _color); - addDirtyRect(r); -} - -// intern drawing - -void ThemeClassic::restoreBackground(Common::Rect r, bool special) { - r.clip(_screen.w, _screen.h); - r.clip(_drawArea); -#ifdef CT_NO_TRANSPARENCY - _screen.fillRect(r, _bgcolor); -#else - if (_dialog) { - if (!_dialog->screen.pixels) { - _screen.fillRect(r, _bgcolor); - return; - } - const OverlayColor *src = (const OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - - int h = r.height(); - int w = r.width(); - while (h--) { - memcpy(dst, src, w*sizeof(OverlayColor)); - src += _dialog->screen.w; - dst += _screen.w; - } - } else { - _screen.fillRect(r, _bgcolor); - } -#endif -} - -bool ThemeClassic::addDirtyRect(Common::Rect r, bool save, bool special) { - // TODO: implement proper dirty rect handling - // FIXME: problem with the 'pitch' - r.clip(_screen.w, _screen.h); - r.clip(_drawArea); - _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(r.left, r.top), _screen.w, r.left, r.top, r.width(), r.height()); -#ifndef CT_NO_TRANSPARENCY - if (_dialog && save) { - if (_dialog->screen.pixels) { - OverlayColor *dst = (OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left, r.top); - int h = r.height(); - while (h--) { - memcpy(dst, src, r.width()*sizeof(OverlayColor)); - dst += _dialog->screen.w; - src += _screen.w; - } - } - } -#endif - return true; -} - -void ThemeClassic::box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB, bool skipLastRow) { - if (y >= 0) { - _screen.hLine(x + 1, y, x + width - 2, colorA); - _screen.hLine(x, y + 1, x + width - 1, colorA); - } - int drawY = y; - if (drawY < 0) { - height += drawY; - drawY = 0; - } - _screen.vLine(x, drawY + 1, drawY + height - 2, colorA); - _screen.vLine(x + 1, drawY, drawY + height - 1, colorA); - _screen.vLine(x + width - 1, drawY + 1, drawY + height - 2, colorB); - _screen.vLine(x + width - 2, drawY + 1, drawY + height - 1, colorB); - - if (y + height >= 0 && !skipLastRow) { - _screen.hLine(x + 1, drawY + height - 2, x + width - 1, colorB); - _screen.hLine(x + 1, drawY + height - 1, x + width - 2, colorB); - } -} - -void ThemeClassic::box(int x, int y, int w, int h) { - _screen.hLine(x, y, x + w - 1, _color); - _screen.hLine(x, y + h - 1, x +w - 1, _shadowcolor); - _screen.vLine(x, y, y + h - 1, _color); - _screen.vLine(x + w - 1, y, y + h - 1, _shadowcolor); -} - -OverlayColor ThemeClassic::getColor(State state) { - OverlayColor usedColor = _color; - switch (state) { - case kStateEnabled: - usedColor = _textcolor; - break; - - case kStateHighlight: - usedColor = _textcolorhi; - break; - - default: - break; - } - return usedColor; -} - -#ifndef CT_NO_TRANSPARENCY -void ThemeClassic::blendScreenToDialog() { - Common::Rect rect(0, 0, _screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - if (_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) { - int a, r, g, b; - uint8 aa, ar, ag, ab; - _system->colorToARGB(_bgcolor, aa, ar, ag, ab); - a = aa*3/(3+1); - if (a < 1) - return; - r = ar * a; - g = ag * a; - b = ab * a; - - OverlayColor *ptr = (OverlayColor*)_dialog->screen.getBasePtr(rect.left, rect.top); - - int h = rect.height(); - int w = rect.width(); - while (h--) { - for (int i = 0; i < w; i++) { - _system->colorToARGB(ptr[i], aa, ar, ag, ab); - int a2 = aa + a - (a*aa)/255; - ptr[i] = _system->ARGBToColor(a2, - ((255-a)*aa*ar/255+r)/a2, - ((255-a)*aa*ag/255+g)/a2, - ((255-a)*aa*ab/255+b)/a2); - } - ptr += _screen.w; - } - } else { - int r, g, b; - uint8 ar, ag, ab; - _system->colorToRGB(_bgcolor, ar, ag, ab); - r = ar * 3; - g = ag * 3; - b = ab * 3; - - OverlayColor *ptr = (OverlayColor*)_dialog->screen.getBasePtr(rect.left, rect.top); - - int h = rect.height(); - int w = rect.width(); - - while (h--) { - for (int i = 0; i < w; i++) { - _system->colorToRGB(ptr[i], ar, ag, ab); - ptr[i] = _system->RGBToColor((ar + r) / (3+1), - (ag + g) / (3+1), - (ab + b) / (3+1)); - } - ptr += _screen.w; - } - } -} -#endif - -void ThemeClassic::setupConfig() { - if (_configFile.hasSection("theme")) { - if (loadConfig()) - return; - } - - static const uint8 colors[][3] = { - { 104, 104, 104 }, - { 64, 64, 64 }, - { 0, 0, 0, }, - { 32, 160, 32 }, - { 0, 255, 0 } - }; - - memcpy(_colors, colors, sizeof(colors)); -} - -bool ThemeClassic::loadConfig() { - Common::String temp; - _configFile.getKey("version", "theme", temp); - if (atoi(temp.c_str()) != THEME_VERSION) { - // TODO: improve this detection and handle it nicer - warning("Theme config uses a different version (you have: '%s', needed is: '%d')", temp.c_str(), THEME_VERSION); - _configFile.clear(); - - // force a theme reload here - loadTheme(_defaultConfig); - return false; - } - - temp.clear(); - _configFile.getKey("type", "theme", temp); - if (0 != temp.compareToIgnoreCase("classic")) { - warning("Theme config is not for the classic style theme"); - _configFile.clear(); - - // force a theme reload here - loadTheme(_defaultConfig); - return false; - } - - getColorFromConfig("color", _colors[kColor][0], _colors[kColor][1], _colors[kColor][2]); - getColorFromConfig("shadowcolor", _colors[kShadowColor][0], _colors[kShadowColor][1], _colors[kShadowColor][2]); - getColorFromConfig("bgcolor", _colors[kBGColor][0], _colors[kBGColor][1], _colors[kBGColor][2]); - getColorFromConfig("textcolor", _colors[kTextColor][0], _colors[kTextColor][1], _colors[kTextColor][2]); - getColorFromConfig("textcolorhi", _colors[kTextColorHi][0], _colors[kTextColorHi][1], _colors[kTextColorHi][2]); - - temp.clear(); - temp = _evaluator->getStringVar("font"); - if (temp.empty() || 0 == temp.compareToIgnoreCase("builtin")) { - if (!_fontName.empty()) - delete _font; - _fontName.clear(); - } else if (temp != _fontName) { - if (!_fontName.empty()) - delete _font; - _font = loadFont(temp.c_str()); - _fontName = temp; - } - - _enableBlending = (_evaluator->getVar("blending") != 0); - - return true; -} - -} // end of namespace GUI - diff --git a/gui/ThemeClassic.h b/gui/ThemeClassic.h deleted file mode 100644 index 12dc8d8068..0000000000 --- a/gui/ThemeClassic.h +++ /dev/null @@ -1,127 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - */ - -#ifndef GUI_THEMECLASSIC_H -#define GUI_THEMECLASSIC_H - -#include "gui/theme.h" - -namespace GUI { - -// enable this to disable transparency support for the classic theme -//#define CT_NO_TRANSPARENCY - -class ThemeClassic : public Theme { -public: - ThemeClassic(OSystem *system, const Common::String &config = "classic", const Common::ConfigFile *cfg = 0); - virtual ~ThemeClassic(); - - bool init(); - void deinit(); - - void refresh(); - - void enable(); - void disable(); - - void openDialog(bool topDialog); - void closeAllDialogs(); - - void clearAll(); - void updateScreen(); - - void resetDrawArea(); - - const Graphics::Font *getFont(FontStyle font) const { return _font; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_initOk) return _font->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font) const { if (_initOk) return _font->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font) const { if (_initOk) return _font->getCharWidth(c); return 0; } - - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state); - - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state); - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans); - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state); - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align); - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state); - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state); - void restoreBackground(Common::Rect r, bool special = false); - bool addDirtyRect(Common::Rect r, bool save = false, bool special = false); - - int getTabSpacing() const; - int getTabPadding() const; - -private: - void box(int x, int y, int width, int height, OverlayColor colorA, OverlayColor colorB, bool skipLastRow = false); - void box(int x, int y, int width, int height); - - OverlayColor getColor(State state); - - OSystem *_system; - Graphics::Surface _screen; - -#ifndef CT_NO_TRANSPARENCY - struct DialogState { - Graphics::Surface screen; - } *_dialog; - - void blendScreenToDialog(); -#endif - bool _enableBlending; - - bool _forceRedraw; - bool _initOk; - bool _enabled; - - Common::String _fontName; - const Graphics::Font *_font; - OverlayColor _color, _shadowcolor; - OverlayColor _bgcolor; - OverlayColor _textcolor; - OverlayColor _textcolorhi; - - enum { - kColor = 0, - kShadowColor = 1, - kBGColor = 2, - kTextColor = 3, - kTextColorHi = 4, - kMaxColors = 5 - }; - uint8 _colors[kMaxColors][3]; - - void setupConfig(); - bool loadConfig(); -}; - -} // end of namespace GUI - -#endif - diff --git a/gui/ThemeEval.cpp b/gui/ThemeEval.cpp new file mode 100644 index 0000000000..614f2089d1 --- /dev/null +++ b/gui/ThemeEval.cpp @@ -0,0 +1,289 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" +#include "graphics/scaler.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" + +namespace GUI { + +bool ThemeLayoutWidget::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { + if (name == _name) { + x = _x; y = _y; + w = _w; h = _h; + return true; + } + + return false; +} + +bool ThemeLayout::getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { + for (uint i = 0; i < _children.size(); ++i) { + if (_children[i]->getWidgetData(name, x, y, w, h)) + return true; + } + + return false; +} + +void ThemeLayoutMain::reflowLayout() { + assert(_children.size() <= 1); + + if (_children.size()) { + _children[0]->resetLayout(); + _children[0]->setWidth(_w); + _children[0]->setHeight(_h); + _children[0]->reflowLayout(); + + if (_w == -1) + _w = _children[0]->getWidth(); + + if (_h == -1) + _h = _children[0]->getHeight(); + + if (_y == -1) + _y = (g_system->getOverlayHeight() >> 1) - (_h >> 1); + + if (_x == -1) + _x = (g_system->getOverlayWidth() >> 1) - (_w >> 1); + } +} + +void ThemeLayoutVertical::reflowLayout() { + int curX, curY; + int resize[8]; + int rescount = 0; + + curX = _paddingLeft; + curY = _paddingTop; + _h = _paddingTop + _paddingBottom; + + for (uint i = 0; i < _children.size(); ++i) { + + _children[i]->resetLayout(); + _children[i]->reflowLayout(); + + if (_children[i]->getWidth() == -1) + _children[i]->setWidth((_w == -1 ? getParentW() : _w) - _paddingLeft - _paddingRight); + + if (_children[i]->getHeight() == -1) { + resize[rescount++] = i; + _children[i]->setHeight(0); + } + + _children[i]->setY(curY); + + if (_centered && _children[i]->getWidth() < _w && _w != -1) { + _children[i]->setX((_w >> 1) - (_children[i]->getWidth() >> 1)); + } + else + _children[i]->setX(curX); + + curY += _children[i]->getHeight() + _spacing; + _w = MAX(_w, (int16)(_children[i]->getWidth() + _paddingLeft + _paddingRight)); + _h += _children[i]->getHeight() + _spacing; + } + + _h -= _spacing; + + if (rescount) { + int newh = (getParentH() - _h - _paddingBottom) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setHeight(newh); + _h += newh; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setY(newh); + } + } +} + +void ThemeLayoutHorizontal::reflowLayout() { + int curX, curY; + int resize[8]; + int rescount = 0; + + curX = _paddingLeft; + curY = _paddingTop; + _w = _paddingLeft + _paddingRight; + + for (uint i = 0; i < _children.size(); ++i) { + + _children[i]->resetLayout(); + _children[i]->reflowLayout(); + + if (_children[i]->getHeight() == -1) + _children[i]->setHeight((_h == -1 ? getParentH() : _h) - _paddingTop - _paddingBottom); + + if (_children[i]->getWidth() == -1) { + resize[rescount++] = i; + _children[i]->setWidth(0); + } + + _children[i]->setX(curX); + + if (_centered && _children[i]->getHeight() < _h && _h != -1) + _children[i]->setY((_h >> 1) - (_children[i]->getHeight() >> 1)); + else + _children[i]->setY(curY); + + curX += (_children[i]->getWidth() + _spacing); + _w += _children[i]->getWidth() + _spacing; + _h = MAX(_h, (int16)(_children[i]->getHeight() + _paddingTop + _paddingBottom)); + } + + _w -= _spacing; + + if (rescount) { + int neww = (getParentW() - _w - _paddingRight) / rescount; + + for (int i = 0; i < rescount; ++i) { + _children[resize[i]]->setWidth(neww); + _w += neww; + for (uint j = resize[i] + 1; j < _children.size(); ++j) + _children[j]->setX(neww); + } + } +} + +ThemeEval::~ThemeEval() { + reset(); +} + +void ThemeEval::buildBuiltinVars() { + _builtin["kThumbnailWidth"] = kThumbnailWidth; + _builtin["kThumbnailHeight"] = kThumbnailHeight1; + _builtin["kThumbnailHeight2"] = kThumbnailHeight2; + + _builtin["kButtonWidth"] = GUI::kButtonWidth; + _builtin["kButtonHeight"] = GUI::kButtonHeight; + _builtin["kSliderWidth"] = GUI::kSliderWidth; + _builtin["kSliderHeight"] = GUI::kSliderHeight; + _builtin["kBigButtonWidth"] = GUI::kBigButtonWidth; + _builtin["kBigButtonHeight"] = GUI::kBigButtonHeight; + _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; + _builtin["kBigSliderWidth"] = GUI::kBigSliderWidth; + _builtin["kBigSliderHeight"] = GUI::kBigSliderHeight; + + _builtin["kNormalWidgetSize"] = GUI::kNormalWidgetSize; + _builtin["kBigWidgetSize"] = GUI::kBigWidgetSize; +} + + +void ThemeEval::addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled) { + int typeW = -1; + int typeH = -1; + + if (!type.empty()) { + typeW = getVar("Globals." + type + ".Width", -1); + typeH = getVar("Globals." + type + ".Height", -1); + } + + ThemeLayoutWidget *widget = new ThemeLayoutWidget(_curLayout.top(), name, + typeW == -1 ? w : typeW, + typeH == -1 ? h : typeH); + + _curLayout.top()->addChild(widget); + setVar(_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; + + 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()); + + if (_layouts.contains(name)) + delete _layouts[name]; + + _layouts[name] = layout; + + layout->setPadding( + getVar("Globals.Padding.Left", 0), + getVar("Globals.Padding.Right", 0), + getVar("Globals.Padding.Top", 0), + getVar("Globals.Padding.Bottom", 0) + ); + + _curLayout.push(layout); + _curDialog = name; + setVar(name + ".Enabled", enabled ? 1 : 0); +} + +void ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, bool center) { + ThemeLayout *layout = 0; + + if (spacing == -1) + spacing = getVar("Globals.Layout.Spacing", 4); + + if (type == ThemeLayout::kLayoutVertical) + layout = new ThemeLayoutVertical(_curLayout.top(), spacing, center); + else if (type == ThemeLayout::kLayoutHorizontal) + layout = new ThemeLayoutHorizontal(_curLayout.top(), spacing, center); + + layout->setPadding( + getVar("Globals.Padding.Left", 0), + getVar("Globals.Padding.Right", 0), + getVar("Globals.Padding.Top", 0), + getVar("Globals.Padding.Bottom", 0) + ); + + _curLayout.top()->addChild(layout); + _curLayout.push(layout); +} + +void ThemeEval::addSpace(int size) { + ThemeLayout *space = new ThemeLayoutSpacing(_curLayout.top(), size); + _curLayout.top()->addChild(space); +} + +bool ThemeEval::addImportedLayout(const Common::String &name) { + if (!_layouts.contains(name)) + return false; + + _curLayout.top()->importLayout(_layouts[name]); + return true; +} + +} diff --git a/gui/ThemeEval.h b/gui/ThemeEval.h new file mode 100644 index 0000000000..8d55ff6066 --- /dev/null +++ b/gui/ThemeEval.h @@ -0,0 +1,404 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GUI_THEME_EVAL +#define GUI_THEME_EVAL + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/ThemeEval.h" + +namespace GUI { + +class ThemeLayout { + +public: + enum LayoutType { + kLayoutMain, + kLayoutVertical, + kLayoutHorizontal, + kLayoutWidget + }; + + ThemeLayout(ThemeLayout *p, const Common::String &name) : + _parent(p), _name(name), _x(0), _y(0), _w(-1), _h(-1), + _paddingLeft(0), _paddingRight(0), _paddingTop(0), _paddingBottom(0), + _centered(false), _defaultW(-1), _defaultH(-1) { } + + virtual ~ThemeLayout() { + for (uint i = 0; i < _children.size(); ++i) + delete _children[i]; + } + + virtual void reflowLayout() = 0; + + virtual void resetLayout() { + _x = 0; + _y = 0; + _w = _defaultW; + _h = _defaultH; + } + + void addChild(ThemeLayout *child) { _children.push_back(child); } + + void setPadding(int8 left, int8 right, int8 top, int8 bottom) { + _paddingLeft = left; + _paddingRight = right; + _paddingTop = top; + _paddingBottom = bottom; + } + + void setSpacing(int8 spacing) { + _spacing = spacing; + } + + int16 getParentX() { return _parent ? _parent->_x : 0; } + int16 getParentY() { return _parent ? _parent->_y : 0; } + + int16 getParentW() { + ThemeLayout *p = _parent; + int width = 0; + + while (p && p->getLayoutType() != kLayoutMain) { + width += p->_paddingRight + p->_paddingLeft; + if (p->getLayoutType() == kLayoutHorizontal) { + for (uint i = 0; i < p->_children.size(); ++i) + width += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; + } + + return p->getWidth() - width; + } + + int16 getParentH() { + ThemeLayout *p = _parent; + int height = 0; + + while (p && p->getLayoutType() != kLayoutMain) { + height += p->_paddingBottom + p->_paddingTop; + if (p->getLayoutType() == kLayoutVertical) { + for (uint i = 0; i < p->_children.size(); ++i) + height += p->_children[i]->getHeight() + p->_spacing; + } + p = p->_parent; + } + + return p->getHeight() - height; + } + + int16 getX() { return _x; } + int16 getY() { return _y; } + int16 getWidth() { return _w; } + int16 getHeight() { return _h; } + + void setX(int newX) { + _x += newX; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setX(newX); + } + + void setY(int newY) { + _y += newY; + for (uint i = 0; i < _children.size(); ++i) + _children[i]->setY(newY); + } + + void setWidth(int16 width) { _w = width; } + void setHeight(int16 height) { _h = height; } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + uint16 color = 0xFFFF; + font->drawString(screen, getName(), _x, _y, _w, color, Graphics::kTextAlignRight, 0, true); + screen->hLine(_x, _y, _x + _w, color); + screen->hLine(_x, _y + _h, _x + _w , color); + screen->vLine(_x, _y, _y + _h, color); + screen->vLine(_x + _w, _y, _y + _h, color); + + for (uint i = 0; i < _children.size(); ++i) + _children[i]->debugDraw(screen, font); + } + + virtual LayoutType getLayoutType() = 0; + virtual const char *getName() { return _name.c_str(); } + + virtual bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + + virtual bool getDialogData(int16 &x, int16 &y, uint16 &w, uint16 &h) { + assert(getLayoutType() == kLayoutMain); + x = _x; y = _y; + w = _w; h = _h; + return true; + } + + virtual ThemeLayout *buildCopy() = 0; + + void importLayout(ThemeLayout *layout) { + assert(layout->getLayoutType() == kLayoutMain); + + if (layout->_children.size() == 0) + return; + + layout = layout->_children[0]; + + if (getLayoutType() == layout->getLayoutType()) { + for (uint i = 0; i < layout->_children.size(); ++i) + _children.push_back(layout->_children[i]->buildCopy()); + } else { + _children.push_back(layout->buildCopy()); + } + } + +protected: + int16 _x, _y, _w, _h; + int16 _defaultW, _defaultH; + int8 _paddingTop, _paddingBottom, _paddingLeft, _paddingRight; + int8 _spacing; + Common::Array<ThemeLayout*> _children; + ThemeLayout *_parent; + bool _centered; + Common::String _name; +}; + +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; + } + void reflowLayout(); + + void resetLayout() { + ThemeLayout::resetLayout(); + _x = _defaultX; + _y = _defaultY; + } + + const char *getName() { return "Global Layout"; } + LayoutType getLayoutType() { return kLayoutMain; } + + ThemeLayout *buildCopy() { assert(!"Do not copy Main Layouts!"); return 0; } + +protected: + int16 _defaultX; + int16 _defaultY; +}; + +class ThemeLayoutVertical : public ThemeLayout { +public: + ThemeLayoutVertical(ThemeLayout *p, int spacing, bool center) : + ThemeLayout(p, "") { + _spacing = spacing; + _centered = center; + } + + void reflowLayout(); + const char *getName() { return "Vertical Layout"; } + LayoutType getLayoutType() { return kLayoutVertical; } + + + ThemeLayout *buildCopy() { + ThemeLayoutVertical *n = new ThemeLayoutVertical(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } +}; + +class ThemeLayoutHorizontal : public ThemeLayout { +public: + ThemeLayoutHorizontal(ThemeLayout *p, int spacing, bool center) : + ThemeLayout(p, "") { + _spacing = spacing; + _centered = center; + } + + void reflowLayout(); + const char *getName() { return "Horizontal Layout"; } + LayoutType getLayoutType() { return kLayoutHorizontal; } + + ThemeLayout *buildCopy() { + ThemeLayoutHorizontal *n = new ThemeLayoutHorizontal(*this); + + for (uint i = 0; i < n->_children.size(); ++ i) + n->_children[i] = n->_children[i]->buildCopy(); + + return n; + } +}; + +class ThemeLayoutWidget : public ThemeLayout { +public: + ThemeLayoutWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h) : ThemeLayout(p, name) { + _w = _defaultW = w; + _h = _defaultH = h; + } + + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h); + void reflowLayout() {} + LayoutType getLayoutType() { return kLayoutWidget; } + + ThemeLayout *buildCopy() { return new ThemeLayoutWidget(*this); } +}; + +class ThemeLayoutSpacing : public ThemeLayout { +public: + ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p, "") { + if (p->getLayoutType() == kLayoutHorizontal) { + _w = _defaultW = size; + _h = _defaultH = 1; + } else if (p->getLayoutType() == kLayoutVertical) { + _w = _defaultW = 1; + _h = _defaultH = size; + } + } + + bool getWidgetData(const Common::String &name, int16 &x, int16 &y, uint16 &w, uint16 &h) { return false; } + void reflowLayout() {} + LayoutType getLayoutType() { return kLayoutWidget; } + const char *getName() { return "SPACE"; } + + ThemeLayout *buildCopy() { return new ThemeLayoutSpacing(*this); } +}; + +class ThemeEval { + + typedef Common::HashMap<Common::String, int> VariablesMap; + typedef Common::HashMap<Common::String, ThemeLayout*> LayoutsMap; + +public: + ThemeEval() { + buildBuiltinVars(); + } + + ~ThemeEval(); + + void buildBuiltinVars(); + + int getVar(const Common::String &s) { + if (_vars.contains(s)) + return _vars[s]; + + if (_builtin.contains(s)) + return _builtin[s]; + + error("CRITICAL: Missing variable: '%s'", s.c_str()); + return -13375; //EVAL_UNDEF_VAR + } + + int getVar(const Common::String &s, int def) { + if (_vars.contains(s)) + return _vars[s]; + + if (_builtin.contains(s)) + return _builtin[s]; + + return def; + } + + void setVar(const String &name, int val) { _vars[name] = val; } + + bool hasVar(const Common::String &name) { return _vars.contains(name) || _builtin.contains(name); } + + void addDialog(const Common::String &name, const Common::String &overlays, bool enabled = true, int inset = 0); + void addLayout(ThemeLayout::LayoutType type, int spacing, bool center = false); + void addWidget(const Common::String &name, int w, int h, const Common::String &type, bool enabled = true); + bool addImportedLayout(const Common::String &name); + void addSpace(int size); + + 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(); } + + bool getWidgetData(const Common::String &widget, int16 &x, int16 &y, uint16 &w, uint16 &h) { + Common::StringTokenizer tokenizer(widget, "."); + + if (widget.hasPrefix("Dialog.")) + tokenizer.nextToken(); + + Common::String dialogName = "Dialog." + tokenizer.nextToken(); + Common::String widgetName = tokenizer.nextToken(); + + if (!_layouts.contains(dialogName)) + return false; + + if (widgetName.empty()) + return _layouts[dialogName]->getDialogData(x, y, w, h); + + return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h); + } + + void debugPrint() { + printf("Debug variable list:\n"); + + VariablesMap::const_iterator i; + for (i = _vars.begin(); i != _vars.end(); ++i) { + printf(" '%s' = %d\n", i->_key.c_str(), i->_value); + } + } + + void debugDraw(Graphics::Surface *screen, const Graphics::Font *font) { + _layouts["Dialog.Launcher"]->debugDraw(screen, font); +// _layouts["Dialog.GameOptions_Graphics"]->debugDraw(screen, font); + } + + void reset() { + _vars.clear(); + _curDialog.clear(); + _curLayout.clear(); + + for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i) + delete i->_value; + + _layouts.clear(); + } + +private: + VariablesMap _vars; + VariablesMap _builtin; + + LayoutsMap _layouts; + Common::Stack<ThemeLayout*> _curLayout; + Common::String _curDialog; +}; + + +} + +#endif diff --git a/gui/ThemeModern.cpp b/gui/ThemeModern.cpp deleted file mode 100644 index 177171b40c..0000000000 --- a/gui/ThemeModern.cpp +++ /dev/null @@ -1,1586 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - */ - -#ifndef DISABLE_FANCY_THEMES - -#include "gui/ThemeModern.h" -#include "gui/eval.h" - -#include "graphics/imageman.h" -#include "graphics/imagedec.h" -#include "graphics/colormasks.h" -#include "graphics/cursorman.h" - -#include "common/config-manager.h" -#include "common/file.h" - -#define kShadowTr0 8 -#define kShadowTr1 16 -#define kShadowTr2 32 -#define kShadowTr3 64 -#define kShadowTr35 96 -#define kShadowTr4 128 -#define kShadowTr5 192 - -using Graphics::Surface; - -/** Specifies the currently active 16bit pixel format, 555 or 565. */ -extern int gBitFormat; - -namespace GUI { - -// TODO: This should be moved to ThemeModern -OverlayColor getColorAlpha(OverlayColor col1, OverlayColor col2, int alpha); -OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos, int max, uint factor); -void getStateColor(OverlayColor &s, OverlayColor &e, OverlayColor enabledS, OverlayColor enabledE, OverlayColor highlightS, OverlayColor highlightE, Theme::WidgetStateInfo state); - -#pragma mark - - -ThemeModern::ThemeModern(OSystem *system, const Common::String &stylefile, const Common::ConfigFile *cfg) : Theme(), _system(system), _screen(), _initOk(false), -_forceRedraw(false), _lastUsedBitMask(0), _fonts(), _cursor(0), _imageHandles(), _images(0), _colors(), _gradientFactors() { - _stylefile = stylefile; - _initOk = false; - _enabled = false; - _useCursor = false; - memset(&_screen, 0, sizeof(_screen)); - memset(&_dialog, 0, sizeof(_dialog)); - memset(&_colors, 0, sizeof(_colors)); - memset(&_gradientFactors, 0, sizeof(_gradientFactors)); - - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - } - - if (cfg) { - _configFile = *cfg; - } else { - if (!loadConfigFile(stylefile)) { - warning("Can not find theme config file '%s'", (stylefile + ".ini").c_str()); - return; - } - } - - ImageMan.addArchive(stylefile + ".zip"); - - Common::String temp; - _configFile.getKey("version", "theme", temp); - if (atoi(temp.c_str()) != THEME_VERSION) { - // TODO: improve this detection and handle it nicer - warning("Theme config uses a different version (you have: '%s', needed is: '%d')", temp.c_str(), THEME_VERSION); - return; - } - - temp.clear(); - _configFile.getKey("type", "theme", temp); - if (0 != temp.compareToIgnoreCase("modern")) { - warning("Theme config is not for the modern style theme"); - return; - } - - if (_configFile.hasKey("name", "theme")) - _configFile.getKey("name", "theme", _stylename); - else - _stylename = _stylefile; - - _images = new const Graphics::Surface*[kImageHandlesMax]; - assert(_images); - - _lastUsedBitMask = gBitFormat; -} - -ThemeModern::~ThemeModern() { - deleteFonts(); - deinit(); - delete[] _images; - delete[] _cursor; - _images = 0; - for (int i = 0; i < kImageHandlesMax; ++i) { - ImageMan.unregisterSurface(_imageHandles[i]); - } - ImageMan.remArchive(_stylefile + ".zip"); -} - -bool ThemeModern::init() { - if (!_images) - return false; - - deinit(); - _screen.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - if (_screen.pixels) { - _initOk = true; - clearAll(); - resetDrawArea(); - } - - if (isThemeLoadingRequired()) { - loadTheme(_defaultConfig); - loadTheme(_configFile, false, true); // Don't reset - - processExtraValues(); - } - - for (int i = 0; i < kImageHandlesMax; ++i) { - if (!_images[i]) { - return false; - } - } - - return true; -} - -void ThemeModern::deinit() { - if (_initOk) { - _system->hideOverlay(); - _screen.free(); - _initOk = false; - } -} - -void ThemeModern::refresh() { - init(); - resetupGuiRenderer(); - if (_enabled) { - _system->showOverlay(); - CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - } -} - -void ThemeModern::enable() { - init(); - resetupGuiRenderer(); - resetDrawArea(); - if (_useCursor) - setUpCursor(); - _system->showOverlay(); - clearAll(); - _enabled = true; -} - -void ThemeModern::disable() { - _system->hideOverlay(); - if (_useCursor) { - CursorMan.popCursorPalette(); - CursorMan.popCursor(); - } - _enabled = false; -} - -void ThemeModern::openDialog(bool topDialog) { - if (!_dialog) { - _dialog = new DialogState; - assert(_dialog); - // first dialog - _dialog->screen.create(_screen.w, _screen.h, sizeof(OverlayColor)); - } - - if (_dialogShadingCallback && topDialog) { - OverlayColor *col = (OverlayColor*)_screen.pixels; - for (int y = 0; y < _screen.h; ++y) { - for (int x = 0; x < _screen.w; ++x) { - col[x] = (this->*(_dialogShadingCallback))(col[x]); - } - col += _screen.w; - } - } - - memcpy(_dialog->screen.pixels, _screen.pixels, _screen.pitch*_screen.h); - - if ((_dialogShadingCallback) && topDialog) - addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h), false, false); -} - -void ThemeModern::closeAllDialogs() { - if (_dialog) { - _dialog->screen.free(); - delete _dialog; - _dialog = 0; - } - _forceRedraw = true; -} - -void ThemeModern::clearAll() { - if (!_initOk) - return; - _system->clearOverlay(); - // FIXME: problem with the 'pitch' - _system->grabOverlay((OverlayColor*)_screen.pixels, _screen.w); -} - -void ThemeModern::updateScreen() { - // TODO: see ThemeModern::addDirtyRect - _forceRedraw = false; -} - -void ThemeModern::setDrawArea(const Common::Rect &r) { - if (_initOk) { - _drawArea = r; - _shadowDrawArea = Common::Rect(r.left-_shadowLeftWidth, r.top-_shadowTopHeight, r.right+_shadowRightWidth, r.bottom+_shadowBottomHeight); - _drawArea.clip(_screen.w, _screen.h); - _shadowDrawArea.clip(_screen.w, _screen.h); - } -} - -void ThemeModern::resetDrawArea() { - if (_initOk) { - _drawArea = Common::Rect(0, 0, _screen.w, _screen.h); - _shadowDrawArea = _drawArea; - } -} - -#define surface(x) (_images[x]) - -void ThemeModern::drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowFull); - - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - restoreBackground(r2, true); - addDirtyRect(r2); - return; - } - - if (hints & THEME_HINT_MAIN_DIALOG) { - colorFade(r, _colors[kMainDialogStart], _colors[kMainDialogEnd], _gradientFactors[kMainDialogFactor]); - } else if (hints & THEME_HINT_SPECIAL_COLOR) { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kMainDialogStart], _colors[kMainDialogEnd], _gradientFactors[kDialogSpecialFactor]); - } else if (hints & THEME_HINT_PLAIN_COLOR) { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kDialogEnd], _colors[kDialogEnd], _gradientFactors[kDialogFactor]); - } else { - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowFull); - - drawRectMasked(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), - 256, _colors[kDialogStart], _colors[kDialogEnd], _gradientFactors[kDialogFactor]); - } - - addDirtyRect(r2, (hints & THEME_HINT_SAVE_BACKGROUND) != 0, true); -} - -void ThemeModern::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { - if (!_initOk) - return; - - uint32 color; - - restoreBackground(r); - - if (inverted) { - _screen.fillRect(r, _colors[kTextInvertedBackground]); - color = _colors[kTextInvertedColor]; - } else { - color = getColor(state); - } - - getFont(font)->drawString(&_screen, str, r.left, r.top, r.width(), color, convertAligment(align), deltax, useEllipsis); - addDirtyRect(r); -} - -void ThemeModern::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { - if (!_initOk) - return; - restoreBackground(r); - font->drawChar(&_screen, ch, r.left, r.top, getColor(state)); - addDirtyRect(r); -} - -void ThemeModern::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r2; - - ImageHandles corner, top, left, bkgd; - ShadowStyles shadow; - ColorHandles start, end; - GradientFactors factor; - - switch (background) { - case kWidgetBackgroundBorderSmall: - corner = kWidgetSmallBkgdCorner; - top = kWidgetSmallBkgdTop; - left = kWidgetSmallBkgdLeft; - bkgd = kWidgetSmallBkgd; - shadow = kShadowSmall; - start = kWidgetBackgroundSmallStart; - end = kWidgetBackgroundSmallEnd; - factor = kWidgetSmallFactor; - break; - case kWidgetBackgroundEditText: - corner = kEditTextBkgdCorner; - top = kEditTextBkgdTop; - left = kEditTextBkgdLeft; - bkgd = kEditTextBkgd; - shadow = kShadowEmboss; - start = kEditTextBackgroundStart; - end = kEditTextBackgroundEnd; - factor = kEditTextFactor; - break; - case kWidgetBackgroundSlider: - corner = kSliderBkgdCorner; - top = kSliderBkgdTop; - left = kSliderBkgdLeft; - bkgd = kSliderBkgd; - shadow = kShadowEmboss; - start = kSliderBackgroundStart; - end = kSliderBackgroundEnd; - factor = kSliderBackground; - break; - default: - corner = kWidgetBkgdCorner; - top = kWidgetBkgdTop; - left = kWidgetBkgdLeft; - bkgd = kWidgetBkgd; - shadow = kShadowFull; - if (hints & THEME_HINT_PLAIN_COLOR) - start = kWidgetBackgroundEnd; - else - start = kWidgetBackgroundStart; - end = kWidgetBackgroundEnd; - factor = kWidgetFactor; - break; - } - - if ((hints & THEME_HINT_SAVE_BACKGROUND) && !(hints & THEME_HINT_FIRST_DRAW) && !_forceRedraw) { - restoreBackground((hints & THEME_HINT_USE_SHADOW) ? r2 : r); - addDirtyRect((hints & THEME_HINT_USE_SHADOW) ? r2 : r); - return; - } - - if ((hints & THEME_HINT_USE_SHADOW)) { - r2 = shadowRect(r, shadow); - restoreBackground(r2); - // shadow - drawShadow(r, surface(corner), surface(top), surface(left), surface(bkgd), shadow); - } - - drawRectMasked(r, surface(corner), surface(top), surface(left), surface(bkgd), - (state == kStateDisabled) ? -30 : 256, _colors[start], _colors[end], - _gradientFactors[factor]); - - addDirtyRect((hints & THEME_HINT_USE_SHADOW) ? r2 : r, (hints & THEME_HINT_SAVE_BACKGROUND) != 0); -} - -void ThemeModern::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowButton); - - if (!(hints & THEME_HINT_NO_BACKGROUND_RESTORE) || state == kStateDisabled) - restoreBackground(r2); - - // shadow - drawShadow(r, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), kShadowButton); - - OverlayColor start, end; - int alpha = 256; - - getStateColor(start, end, _colors[kButtonBackgroundStart], _colors[kButtonBackgroundEnd], - _colors[kButtonBackgroundHighlightStart], _colors[kButtonBackgroundHighlightEnd], state); - - if (state != kStateHighlight) - alpha = (state == kStateDisabled) ? -30 : 256; - - drawRectMasked(r, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), - alpha, start, end, _gradientFactors[kButtonFactor]); - - const int off = (r.height() - getFontHeight()) / 2; - - OverlayColor col = 0; - switch (state) { - case kStateEnabled: - col = _colors[kButtonTextEnabled]; - break; - - case kStateHighlight: - col = _colors[kButtonTextHighlight]; - break; - - default: - col = _colors[kButtonTextDisabled]; - break; - }; - - getFont()->drawString(&_screen, str, r.left, r.top + off, r.width(), col, Graphics::kTextAlignCenter, 0, true); - - addDirtyRect(r2); -} - -void ThemeModern::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { - if (!_initOk) - return; - - Common::Rect rect(r.left, r.top, r.left + surface.w, r.top + surface.h); - rect.clip(_screen.w, _screen.h); - - if (!rect.isValidRect()) - return; - - assert(surface.bytesPerPixel == sizeof(OverlayColor)); - - if (alpha != 256) - restoreBackground(rect); - - if (themeTrans) - drawSurface(rect, &surface, false, false, alpha); - else { - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(rect.left, rect.top); - const OverlayColor *src = (OverlayColor*)surface.pixels; - - int h = rect.height(); - if (alpha == 256) { - while (h--) { - memcpy(dst, src, surface.pitch); - dst += _screen.w; - src += surface.w; - } - } else { - int w = rect.width(); - while (h--) { - for (int i = 0; i < w; ++i) { - *dst = getColorAlpha(*src, *dst, alpha); - } - dst += _screen.w; - src += surface.w; - } - } - } - - addDirtyRect(rect); -} - -void ThemeModern::drawSlider(const Common::Rect &rr, int width, WidgetStateInfo state) { - if (!_initOk) - return; - - Common::Rect r = rr; - - r.left++; - r.right++; - - drawWidgetBackground(r, THEME_HINT_USE_SHADOW, kWidgetBackgroundSlider, kStateEnabled); - - Common::Rect r2 = r; - r2.left = r.left; - r2.top = r.top; - r2.bottom = r.bottom-1; - r2.right = r2.left + width-1; - if (r2.right > r.right) { - r2.right = r.right; - } - - drawShadow(r2, surface(kButtonBkgdCorner), surface(kButtonBkgdTop), surface(kButtonBkgdLeft), surface(kButtonBkgd), kShadowButton); - - OverlayColor start, end; - int alpha = 256; - - getStateColor(start, end, _colors[kSliderStart], _colors[kSliderEnd], _colors[kSliderHighStart], _colors[kSliderHighEnd], state); - - if (state != kStateHighlight) - alpha = (state == kStateDisabled) ? -30 : 256; - - drawRectMasked(r2, surface(kSliderCorner), surface(kSliderTop), surface(kSliderLeft), surface(kSliderBkgd), - alpha, start, end, _gradientFactors[kSliderFactor]); - - addDirtyRect(r); -} - -void ThemeModern::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { - if (!_initOk) - return; - - Common::Rect r2 = shadowRect(r, kShadowSmall); - restoreBackground(r2); - - OverlayColor start = _colors[kPopUpWidgetStart], end = _colors[kPopUpWidgetEnd]; - if (state == kStateHighlight) { - start = _colors[kPopUpWidgetHighlightStart]; - end = _colors[kPopUpWidgetHighlightEnd]; - } - - drawShadow(r, surface(kDialogBkgdCorner), surface(kDialogBkgdTop), surface(kDialogBkgdLeft), surface(kDialogBkgd), kShadowPopUp); - - drawRectMasked(r, surface(kPopUpWidgetBkgdCorner), surface(kPopUpWidgetBkgdTop), surface(kPopUpWidgetBkgdLeft), surface(kPopUpWidgetBkgd), - (state == kStateDisabled) ? -30 : 256, start, end, _gradientFactors[kPopUpWidgetFactor]); - - const Graphics::Surface *arrow = surface(kWidgetArrow); - - int yOff = r.height() / 2 - arrow->h; - if (yOff < 0) - yOff = 0; - - Common::Rect arrowRect(r.right - 4 - arrow->w, r.top + yOff, r.right - 4, r.top + yOff + arrow->h); - arrowRect.clip(r); - - drawSurface(arrowRect, arrow, false, false, (state == kStateDisabled) ? -30 : 256); - - arrowRect.top += arrow->h; - arrowRect.bottom += arrow->h; - arrowRect.clip(r); - drawSurface(arrowRect, arrow, true, false, (state == kStateDisabled) ? -30 : 256); - - if (!sel.empty()) { - Common::Rect text(r.left + 2, r.top + 3, r.right - 4, r.top + 3 + getFont()->getFontHeight()); - getFont()->drawString(&_screen, sel, text.left, text.top, text.width(), getColor(state), convertAligment(align), deltax, false); - } - - addDirtyRect(r2); -} - -void ThemeModern::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { - if (!_initOk) - return; - Common::Rect r2 = r; - - const Graphics::Surface *checkBox = surface(checked ? kCheckboxChecked : kCheckboxEmpty); - int checkBoxSize = checkBox->w; - - restoreBackground(Common::Rect(r.left, r.top, r.left+checkBox->w, r.top+checkBox->h)); - - drawSurface(Common::Rect(r.left, r.top, r.left+checkBox->w, r.top+checkBox->h), checkBox, false, false, (state == kStateDisabled) ? 128 : 256); - - r2.left += checkBoxSize + 5; - getFont()->drawString(&_screen, str, r2.left, r2.top, r2.width(), getColor(state), Graphics::kTextAlignLeft, 0, false); - - addDirtyRect(r); -} - -void ThemeModern::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - - // whole tab background - drawRectMasked(r, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - /*(state == kStateDisabled) ? -30 : */256, _colors[kTabBackgroundStart], _colors[kTabBackgroundEnd], - _gradientFactors[kTabFactor]); - - OverlayColor tabEnd = calcGradient(_colors[kTabActiveStart], _colors[kTabActiveEnd], tabHeight, r.height()-1, _gradientFactors[kTabFactor]); - - const int tabOffset = 1; - - // tab shadows - for (int i = 0; i < (int)tabs.size(); ++i) { - Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); - drawShadow(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - kShadowSmall, true); - } - - // inactive tabs - for (int i = 0; i < (int)tabs.size(); ++i) { - if (i == active) - continue; - - Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight + 5); - drawRectMasked(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - 256, _colors[kTabInactiveStart], _colors[kTabInactiveEnd], _gradientFactors[kTabFactor], true); - - getFont()->drawString(&_screen, tabs[i], tabRect.left, tabRect.top+titleVPad, tabRect.width(), getColor(kStateEnabled), Graphics::kTextAlignCenter, 0, true); - } - - // area shadow - Common::Rect widgetBackground = Common::Rect(r.left, r.top + tabHeight - 1, r.right, r.top - + tabHeight + 20); - drawShadow(widgetBackground, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - kShadowSmall); - - // area itself - widgetBackground = Common::Rect(r.left, r.top + tabHeight, r.right, r.bottom); - drawRectMasked(widgetBackground, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - /*(state == kStateDisabled) ? -30 : */256, tabEnd, _colors[kTabActiveEnd], - _gradientFactors[kTabFactor]); - addDirtyRect(widgetBackground, true); - - // active tab - if (active >= 0) { - Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight + 5); - - Common::Rect shadowRect2(tabRect.left, r.top, tabRect.right, tabRect.bottom - 6); - drawShadow(shadowRect2, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), kShadowSmall, false, true); - - drawRectMasked(tabRect, surface(kTabBkgdCorner), surface(kTabBkgdTop), surface(kTabBkgdLeft), surface(kTabBkgd), - 256, _colors[kTabActiveStart], tabEnd, _gradientFactors[kTabFactor], true); - - - getFont()->drawString(&_screen, tabs[active], tabRect.left, tabRect.top+titleVPad, tabRect.width(), getColor(kStateEnabled), Graphics::kTextAlignCenter, 0, true); - } - - addDirtyRect(Common::Rect(r.left, r.top-2, r.right, r.bottom)); -} - -void ThemeModern::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { - if (!_initOk) - return; - const int UP_DOWN_BOX_HEIGHT = r.width() + 1; - Common::Rect r2 = r; - - // draws the scrollbar background - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - _colors[kScrollbarBackgroundStart], _colors[kScrollbarBackgroundEnd], _gradientFactors[kScrollbarBkgdFactor]); - - // draws the 'up' button - OverlayColor buttonStart = _colors[kScrollbarButtonStart]; - OverlayColor buttonEnd = _colors[kScrollbarButtonEnd]; - - if (scrollState == kScrollbarStateUp) - getStateColor(buttonStart, buttonEnd, buttonStart, buttonEnd, _colors[kScrollbarButtonHighlightStart], _colors[kScrollbarButtonHighlightEnd], state); - - r2.bottom = r2.top + UP_DOWN_BOX_HEIGHT; - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - buttonStart, buttonEnd, _gradientFactors[kScrollbarBkgdFactor]); - - const Graphics::Surface *arrow = surface(kWidgetArrow); - r2.left += 1 + (r2.width() - arrow->w) / 2; - r2.right = r2.left + arrow->w; - r2.top += (r2.height() - arrow->h) / 2; - r2.bottom = r2.top + arrow->h; - drawSurface(r2, arrow, false, false, 256); - - // draws the slider - OverlayColor sliderStart = _colors[kScrollbarSliderStart]; - OverlayColor sliderEnd = _colors[kScrollbarSliderEnd]; - - if (scrollState == kScrollbarStateSlider) - getStateColor(sliderStart, sliderEnd, sliderStart, sliderEnd, _colors[kScrollbarSliderHighlightStart], _colors[kScrollbarSliderHighlightEnd], state); - - r2 = r; - r2.left += 1; - r2.right -= 1; - r2.top += sliderY; - r2.bottom = r2.top + sliderHeight - 1; - - drawShadow(r2, surface(kSliderCorner), surface(kSliderTop), surface(kSliderLeft), surface(kSliderBkgd), kShadowSmall); - - r2.left += 1; - r2.right -= 1; - - r2.bottom = r2.top + sliderHeight / 2 + surface(kScrollbarCorner)->h + 4; - drawRectMasked(r2, surface(kScrollbarCorner), surface(kScrollbarTop), surface(kScrollbarLeft), surface(kScrollbarBkgd), 256, - sliderStart, sliderEnd, _gradientFactors[kScrollbarFactor]); - r2.top += sliderHeight / 2; - r2.bottom += sliderHeight / 2 - surface(kScrollbarCorner)->h - 4; - drawRectMasked(r2, surface(kScrollbarCorner), surface(kScrollbarTop), surface(kScrollbarLeft), surface(kScrollbarBkgd), 256, - sliderEnd, sliderStart, _gradientFactors[kScrollbarFactor]); - - // draws the 'down' button - buttonStart = _colors[kScrollbarButtonStart]; - buttonEnd = _colors[kScrollbarButtonEnd]; - - if (scrollState == kScrollbarStateDown) - getStateColor(buttonStart, buttonEnd, buttonStart, buttonEnd, _colors[kScrollbarButtonHighlightStart], _colors[kScrollbarButtonHighlightEnd], state); - - r2 = r; - r2.top = r2.bottom - UP_DOWN_BOX_HEIGHT; - drawRectMasked(r2, surface(kScrollbarBkgdCorner), surface(kScrollbarBkgdTop), surface(kScrollbarBkgdLeft), surface(kScrollbarBkgd), 256, - buttonStart, buttonEnd, _gradientFactors[kScrollbarBkgdFactor]); - - r2.left += 1 + (r2.width() - arrow->w) / 2; - r2.right = r2.left + arrow->w; - r2.top += (r2.height() - arrow->h) / 2; - r2.bottom = r2.top + arrow->h; - drawSurface(r2, arrow, true, false, 256); - - addDirtyRect(r); -} - -void ThemeModern::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { - if (!_initOk) - return; - - restoreBackground(r); - if (!erase) { - _screen.vLine(r.left, r.top, r.bottom-1, _colors[kCaretColor]); - } else if (r.top >= 0) { - // FIXME: hack to restore the caret background correctly - const OverlayColor search = _colors[kTextInvertedBackground]; - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left-1, r.top-1); - int height = r.height() + 2; - if (r.top + height > _screen.h) { - height = _screen.h - r.top; - } - bool drawInvBackground = false; - while (height--) { - if (src[0] == search || src[1] == search || src[2] == search) { - drawInvBackground = true; - } - src += _screen.w; - } - if (drawInvBackground) { - _screen.vLine(r.left, r.top, r.bottom-1, search); - } - } - addDirtyRect(r); -} - -void ThemeModern::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { - if (!_initOk) - return; - _screen.hLine(r.left - 1, r.top + r.height() / 2, r.right, _system->RGBToColor(0, 0, 0)); - addDirtyRect(r); -} - -int ThemeModern::getTabSpacing() const { - return 0; -} -int ThemeModern::getTabPadding() const { - return 3; -} - -#pragma mark - intern drawing - -void ThemeModern::restoreBackground(Common::Rect r, bool special) { - r.clip(_screen.w, _screen.h); - if (special) { - r.clip(_shadowDrawArea); - } else { - r.clip(_drawArea); - } - if (_dialog) { - if (!_dialog->screen.pixels) { - return; - } - const OverlayColor *src = (const OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - - int h = r.height(); - int w = r.width(); - while (h--) { - memcpy(dst, src, w*sizeof(OverlayColor)); - src += _dialog->screen.w; - dst += _screen.w; - } - } -} - -bool ThemeModern::addDirtyRect(Common::Rect r, bool backup, bool special) { - // TODO: implement proper dirty rect handling - // FIXME: problem with the 'pitch' - r.clip(_screen.w, _screen.h); - if (special) { - r.clip(_shadowDrawArea); - } else { - r.clip(_drawArea); - } - _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(r.left, r.top), _screen.w, r.left, r.top, r.width(), r.height()); - if (_dialog && backup) { - if (_dialog->screen.pixels) { - OverlayColor *dst = (OverlayColor*)_dialog->screen.getBasePtr(r.left, r.top); - const OverlayColor *src = (const OverlayColor*)_screen.getBasePtr(r.left, r.top); - int h = r.height(); - while (h--) { - memcpy(dst, src, r.width()*sizeof(OverlayColor)); - dst += _dialog->screen.w; - src += _screen.w; - } - } - } - return true; -} - -void ThemeModern::colorFade(const Common::Rect &r, OverlayColor start, OverlayColor end, uint factor) { - OverlayColor *ptr = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - const int h = r.height(); - const int w = r.width(); - const int lastRow = r.height() - 1; - const int ptrAdd = _screen.w - r.width(); - for (int l = 0; l < h; ++l) { - OverlayColor col = calcGradient(start, end, l, lastRow, factor); - for (int i = 0; i < w; ++i) { - *ptr++ = col; - } - ptr += ptrAdd; - } -} - -void ThemeModern::drawRect(const Common::Rect &r, const Surface *corner, const Surface *top, const Surface *left, const Surface *fill, int alpha, bool skipLastRow) { - drawRectMasked(r, corner, top, left, fill, alpha, _system->RGBToColor(255, 255, 255), _system->RGBToColor(255, 255, 255), 1, skipLastRow); -} - -void ThemeModern::drawRectMasked(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, - OverlayColor start, OverlayColor end, uint factor, bool skipLastRow, bool skipTopRow) { - int drawWidth = MIN(corner->w, MIN(top->w, MIN(left->w, fill->w))); - int drawHeight = MIN(corner->h, MIN(top->h, MIN(left->h, fill->h))); - int partsH = r.height() / drawHeight; - int partsW = r.width() / drawWidth; - int yPos = r.top; - - int specialHeight = 0; - int specialWidth = 0; - - if (drawHeight*2 > r.height()) { - drawHeight = r.height() / 2; - partsH = 2; - } else { - specialHeight = r.height() % drawHeight; - if (specialHeight != 0) - ++partsH; - } - - if (drawWidth*2 > r.width()) { - drawWidth = r.width() / 2; - partsW = 2; - } else { - specialWidth = r.width() % drawWidth; - if (specialWidth != 0) - ++partsW; - } - - for (int y = 0; y < partsH; ++y) { - int xPos = r.left; - bool upDown = (y == partsH - 1); - - // calculate the correct drawing height - int usedHeight = drawHeight; - if (specialHeight && y == 1) { - usedHeight = specialHeight; - } - - OverlayColor startCol = calcGradient(start, end, yPos-r.top, r.height()-1, factor); - OverlayColor endCol = calcGradient(start, end, yPos-r.top+usedHeight, r.height()-1, factor); - - for (int i = 0; i < partsW; ++i) { - // calculate the correct drawing width - int usedWidth = drawWidth; - if (specialWidth && i == 1) { - usedWidth = specialWidth; - } - - // draw the right surface - if (!i || i == partsW - 1) { - if ((!y && !skipTopRow) || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), corner, upDown, (i == partsW - 1), alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), left, upDown, (i == partsW - 1), alpha, startCol, endCol); - } - } else if (!y || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), top, upDown, false, alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), fill, false, false, alpha, startCol, endCol); - } - xPos += usedWidth; - } - - yPos += usedHeight; - } -} - -Common::Rect ThemeModern::shadowRect(const Common::Rect &r, uint32 shadowStyle) { - switch (shadowStyle) { - case kShadowButton: - return Common::Rect(r.left - 1, r.top - 1, r.right + 1, r.bottom + 1); - - case kShadowEmboss: - return Common::Rect(r.left - 1, r.top - 1, r.right + 1, r.bottom + 1); - - case kShadowPopUp: - return Common::Rect(r.left - 1, r.top - 1, r.right + 3, r.bottom + 3); - - case kShadowFull: - return Common::Rect(r.left - 2, r.top - 2, r.right + 4, r.bottom + 4); - - default: - return Common::Rect(r.left - _shadowLeftWidth/2, r.top - _shadowTopHeight/2, r.right + _shadowRightWidth/2 + 1, r.bottom + _shadowBottomHeight/2 + 1); - } - - return Common::Rect(); -} - -void ThemeModern::drawShadow(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, uint32 shadowStyle, bool skipLastRow, bool skipTopRow) { - switch (shadowStyle) { - case kShadowFull: { - Common::Rect r2(r.left-1, r.top-1, r.right + 4, r.bottom + 4); - Common::Rect r3(r.left, r.top+1, r.right + 3, r.bottom + 3); - Common::Rect r4(r.left, r.top+1, r.right + 2, r.bottom + 2); - Common::Rect r5(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr0, skipLastRow, skipTopRow); - drawShadowRect(r3, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - drawShadowRect(r5, r, corner, top, left, fill, kShadowTr3, skipLastRow, skipTopRow); - //drawShadowRect(r5, r, corner, top, left, fill, kShadowTr35, skipLastRow); - } break; - - case kShadowSmall: { - Common::Rect r3(r.left - _shadowLeftWidth/2, r.top - _shadowTopHeight/2, r.right + _shadowRightWidth/2, r.bottom + _shadowBottomHeight/2); - Common::Rect r4(r.left - _shadowLeftWidth/2 + 1, r.top - _shadowTopHeight/2 + 1, r.right + _shadowRightWidth/2-1, r.bottom + _shadowBottomHeight/2-1); - - drawShadowRect(r3, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - } break; - - case kShadowButton: { - Common::Rect r2(r.left-1, r.top - 1, r.right, r.bottom); - Common::Rect r4(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, -kShadowTr35-256, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr4, skipLastRow, skipTopRow); - } break; - - case kShadowEmboss: { - Common::Rect r2(r.left - 1, r.top - 1, r.right, r.bottom); - Common::Rect r4(r.left + 1, r.top + 1, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr5, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - } break; - - case kShadowPopUp: { - Common::Rect r2(r.left, r.top, r.right + 3, r.bottom + 3); - Common::Rect r25(r.left-1, r.top-1, r.right + 2, r.bottom + 2); - Common::Rect r3(r.left - 1, r.top-1, r.right, r.bottom); - Common::Rect r4(r.left, r.top, r.right + 1, r.bottom + 1); - - drawShadowRect(r2, r, corner, top, left, fill, kShadowTr1, skipLastRow, skipTopRow); - drawShadowRect(r25, r, corner, top, left, fill, kShadowTr2, skipLastRow, skipTopRow); - drawShadowRect(r4, r, corner, top, left, fill, kShadowTr3, skipLastRow, skipTopRow); - drawShadowRect(r3, r, corner, top, left, fill, -kShadowTr35-256, skipLastRow, skipTopRow); - } break; - - default: - break; - } -} - -void ThemeModern::drawShadowRect(const Common::Rect &r, const Common::Rect &area, const Graphics::Surface *corner, - const Graphics::Surface *top, const Graphics::Surface *left, const Graphics::Surface *fill, - int alpha, bool skipLastRow, bool skipTopRow) { - int drawWidth = MIN(corner->w, MIN(top->w, MIN(left->w, fill->w))); - int drawHeight = MIN(corner->h, MIN(top->h, MIN(left->h, fill->h))); - int partsH = r.height() / drawHeight; - int partsW = r.width() / drawWidth; - int yPos = r.top; - - int yDrawTilesTop = 1 + (ABS(area.top - r.top) % drawHeight); - int xDrawTilesLeft = 1 + (ABS(area.left - r.left) % drawWidth); - int yDrawTilesBottom = 1 + (ABS(area.bottom - r.bottom) % drawHeight); - int xDrawTilesRight = 1 + (ABS(area.right - r.right) % drawWidth); - - int specialHeight = 0; - int specialWidth = 0; - - if (drawHeight*2 > r.height()) { - drawHeight = r.height() / 2; - partsH = 2; - } else { - specialHeight = r.height() % drawHeight; - if (specialHeight != 0) - ++partsH; - } - - if (drawWidth*2 > r.width()) { - drawWidth = r.width() / 2; - partsW = 2; - } else { - specialWidth = r.width() % drawWidth; - if (specialWidth != 0) - ++partsW; - } - - OverlayColor startCol = g_system->RGBToColor(0, 0, 0); - OverlayColor endCol = g_system->RGBToColor(0, 0, 0); - - for (int y = 0; y < partsH; ++y) { - // calculate the correct drawing height - int usedHeight = drawHeight; - if (specialHeight && y == 1) { - usedHeight = specialHeight; - } - - int xPos = r.left; - bool upDown = (y == partsH - 1); - - for (int i = 0; i < partsW; ++i) { - // calculate the correct drawing width - int usedWidth = drawWidth; - if (specialWidth && i == 1) { - usedWidth = specialWidth; - } - - if (i >= xDrawTilesLeft && i <= partsW - xDrawTilesRight && y >= yDrawTilesTop && y <= partsH - yDrawTilesBottom) { - xPos += usedWidth; - continue; - } - - // draw the right surface - if (!i || i == partsW - 1) { - if ((!y && !skipTopRow) || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), corner, upDown, (i == partsW - 1), alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), left, upDown, (i == partsW - 1), alpha, startCol, endCol); - } - } else if (!y || (y == partsH - 1 && !skipLastRow)) { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), top, upDown, false, alpha, startCol, endCol); - } else { - drawSurfaceMasked(Common::Rect(xPos, yPos, xPos+usedWidth, yPos+usedHeight), fill, upDown, false, alpha, startCol, endCol); - } - xPos += usedWidth; - } - yPos += usedHeight; - } -} - -void ThemeModern::drawSurface(const Common::Rect &r, const Surface *surf, bool upDown, bool leftRight, int alpha) { - drawSurfaceMasked(r, surf, upDown, leftRight, alpha, _system->RGBToColor(255, 255, 255), _system->RGBToColor(255, 255, 255)); -} - -void ThemeModern::drawSurfaceMasked(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, - int alpha, OverlayColor start, OverlayColor end, uint factor) { - OverlayColor *dst = (OverlayColor*)_screen.getBasePtr(r.left, r.top); - const OverlayColor *src = 0; - - const OverlayColor transparency = _colors[kColorTransparency]; - int drawWidth = (r.width() < surf->w) ? r.width() : surf->w; - if (r.left + drawWidth > _screen.w) - drawWidth = _screen.w - r.left; - - int srcAdd = 0; - if (upDown) { - src = (const OverlayColor*)surf->pixels + (surf->h - 1) * surf->w; - srcAdd = -surf->w; - } else { - src = (const OverlayColor*)surf->pixels; - srcAdd = surf->w; - } - - int h = r.height(); - if (r.top + h > _screen.h) - h = _screen.h - r.top; - - while (dst < _screen.pixels) { - dst += _screen.w; - src += srcAdd; - --h; - } - - if (h <= 0) - return; - -#define NO_EFFECT(x) ((x) & rowColor) -#define ALPHA_EFFECT(x) (getColorAlpha((x) & rowColor, *dst, alpha)) -#define DARKEN_EFFECT(x) (calcDimColor((x) & rowColor)) - -#define LEFT_RIGHT_OFFSET(x) (drawWidth-x-1) -#define NORMAL_OFFSET(x) (x) - -#define blitSurface(a, b) \ - const int dstAdd = _screen.w - drawWidth; \ - const int lastRow = r.height() - 1; \ - for (int i = 0; i < h; ++i) { \ - OverlayColor rowColor = calcGradient(start, end, i, lastRow, factor); \ - for (int x = 0; x < drawWidth; ++x, ++dst) { \ - OverlayColor col = src[a(x)]; \ - if (col != transparency) { \ - col = b(col); \ - *dst = col; \ - } \ - } \ - dst += dstAdd; \ - src += srcAdd; \ - } - if (alpha >= 256) { - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, NO_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, NO_EFFECT); - } - } else if (alpha < 0 && alpha >= -256) { - int backUp = _dimPercentValue; - _dimPercentValue = 256 * (100 - (-alpha)) / 100; - - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, DARKEN_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, DARKEN_EFFECT); - } - - _dimPercentValue = backUp; - } else { - if (leftRight) { - blitSurface(LEFT_RIGHT_OFFSET, ALPHA_EFFECT); - } else { - blitSurface(NORMAL_OFFSET, ALPHA_EFFECT); - } - } -#undef blitSurface - -#undef NORMAL_OFFSET -#undef LEFT_RIGHT_OFFSET - -#undef DARKEN_EFFECT -#undef ALPHA_EFFECT -#undef NO_EFFECT -} - -OverlayColor ThemeModern::getColor(State state) { - switch (state) { - case kStateDisabled: - return _colors[kColorStateDisabled]; - - case kStateHighlight: - return _colors[kColorStateHighlight]; - - default: - break; - }; - return _colors[kColorStateEnabled]; -} - -void ThemeModern::resetupGuiRenderer() { - if (_lastUsedBitMask == gBitFormat || !_initOk) { - // ok same format no need to reload - return; - } - - _lastUsedBitMask = gBitFormat; - - int i; - for (i = 0; i < kImageHandlesMax; ++i) { - ImageMan.unregisterSurface(_imageHandles[i]); - } - - for (i = 0; i < kImageHandlesMax; ++i) { - ImageMan.registerSurface(_imageHandles[i], 0); - _images[i] = ImageMan.getSurface(_imageHandles[i]); - } - - setupColors(); -} - -void ThemeModern::setupColors() { - // load the colors from the config file - getColorFromConfig("main_dialog_start", _colors[kMainDialogStart]); - getColorFromConfig("main_dialog_end", _colors[kMainDialogEnd]); - - getColorFromConfig("dialog_start", _colors[kDialogStart]); - getColorFromConfig("dialog_end", _colors[kDialogEnd]); - - getColorFromConfig("color_state_disabled", _colors[kColorStateDisabled]); - getColorFromConfig("color_state_highlight", _colors[kColorStateHighlight]); - getColorFromConfig("color_state_enabled", _colors[kColorStateEnabled]); - getColorFromConfig("color_transparency", _colors[kColorTransparency]); - - getColorFromConfig("text_inverted_background", _colors[kTextInvertedBackground]); - getColorFromConfig("text_inverted_color", _colors[kTextInvertedColor]); - - getColorFromConfig("widget_bkgd_start", _colors[kWidgetBackgroundStart]); - getColorFromConfig("widget_bkgd_end", _colors[kWidgetBackgroundEnd]); - getColorFromConfig("widget_bkgd_small_start", _colors[kWidgetBackgroundSmallStart]); - getColorFromConfig("widget_bkgd_small_end", _colors[kWidgetBackgroundSmallEnd]); - - getColorFromConfig("button_bkgd_start", _colors[kButtonBackgroundStart]); - getColorFromConfig("button_bkgd_end", _colors[kButtonBackgroundEnd]); - getColorFromConfig("button_bkgd_highlight_start", _colors[kButtonBackgroundHighlightStart]); - getColorFromConfig("button_bkgd_highlight_end", _colors[kButtonBackgroundHighlightEnd]); - getColorFromConfig("button_text_enabled", _colors[kButtonTextEnabled]); - getColorFromConfig("button_text_disabled", _colors[kButtonTextDisabled]); - getColorFromConfig("button_text_highlight", _colors[kButtonTextHighlight]); - - getColorFromConfig("slider_background_start", _colors[kSliderBackgroundStart]); - getColorFromConfig("slider_background_end", _colors[kSliderBackgroundEnd]); - getColorFromConfig("slider_start", _colors[kSliderStart]); - getColorFromConfig("slider_end", _colors[kSliderEnd]); - getColorFromConfig("slider_highlight_start", _colors[kSliderHighStart]); - getColorFromConfig("slider_highlight_end", _colors[kSliderHighEnd]); - - getColorFromConfig("tab_background_start", _colors[kTabBackgroundStart]); - getColorFromConfig("tab_background_end", _colors[kTabBackgroundEnd]); - - getColorFromConfig("tab_active_start", _colors[kTabActiveStart]); - getColorFromConfig("tab_active_end", _colors[kTabActiveEnd]); - getColorFromConfig("tab_inactive_start", _colors[kTabInactiveStart]); - getColorFromConfig("tab_inactive_end", _colors[kTabInactiveEnd]); - - getColorFromConfig("scrollbar_background_start", _colors[kScrollbarBackgroundStart]); - getColorFromConfig("scrollbar_background_end", _colors[kScrollbarBackgroundEnd]); - getColorFromConfig("scrollbar_button_start", _colors[kScrollbarButtonStart]); - getColorFromConfig("scrollbar_button_end", _colors[kScrollbarButtonEnd]); - getColorFromConfig("scrollbar_slider_start", _colors[kScrollbarSliderStart]); - getColorFromConfig("scrollbar_slider_end", _colors[kScrollbarSliderEnd]); - getColorFromConfig("scrollbar_button_highlight_start", _colors[kScrollbarButtonHighlightStart]); - getColorFromConfig("scrollbar_button_highlight_end", _colors[kScrollbarButtonHighlightEnd]); - getColorFromConfig("scrollbar_slider_highlight_start", _colors[kScrollbarSliderHighlightStart]); - getColorFromConfig("scrollbar_slider_highlight_end", _colors[kScrollbarSliderHighlightEnd]); - - getColorFromConfig("caret_color", _colors[kCaretColor]); - - getColorFromConfig("popupwidget_start", _colors[kPopUpWidgetStart]); - getColorFromConfig("popupwidget_end", _colors[kPopUpWidgetEnd]); - getColorFromConfig("popupwidget_highlight_start", _colors[kPopUpWidgetHighlightStart]); - getColorFromConfig("popupwidget_highlight_end", _colors[kPopUpWidgetHighlightEnd]); - - getColorFromConfig("edittext_background_start", _colors[kEditTextBackgroundStart]); - getColorFromConfig("edittext_background_end", _colors[kEditTextBackgroundEnd]); -} - -#define FONT_NAME_NORMAL "newgui_normal" -#define FONT_NAME_BOLD "newgui_bold" -#define FONT_NAME_ITALIC "newgui_italic" -#define FONT_NAME_FIXED_NORMAL "newgui_fixed_normal" -#define FONT_NAME_FIXED_BOLD "newgui_fixed_bold" -#define FONT_NAME_FIXED_ITALIC "newgui_fixed_italic" - -void ThemeModern::setupFonts() { - if (_screen.w >= 400 && _screen.h >= 270) { - setupFont("fontfile_bold", FONT_NAME_BOLD, kFontStyleBold); - setupFont("fontfile_normal", FONT_NAME_NORMAL, kFontStyleNormal); - setupFont("fontfile_italic", FONT_NAME_ITALIC, kFontStyleItalic); - - setupFont("fontfile_fixed_bold", FONT_NAME_FIXED_BOLD, kFontStyleFixedBold); - setupFont("fontfile_fixed_normal", FONT_NAME_FIXED_NORMAL, kFontStyleFixedNormal); - setupFont("fontfile_fixed_italic", FONT_NAME_FIXED_ITALIC, kFontStyleFixedItalic); - } else { - _fonts[kFontStyleBold] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - _fonts[kFontStyleNormal] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - _fonts[kFontStyleItalic] = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - } -} - -void ThemeModern::deleteFonts() { - const Graphics::Font *normal = FontMan.getFontByName(FONT_NAME_NORMAL); - const Graphics::Font *bold = FontMan.getFontByName(FONT_NAME_BOLD); - const Graphics::Font *italic = FontMan.getFontByName(FONT_NAME_ITALIC); - - delete normal; - delete bold; - delete italic; - - FontMan.removeFontName(FONT_NAME_NORMAL); - FontMan.removeFontName(FONT_NAME_BOLD); - FontMan.removeFontName(FONT_NAME_ITALIC); -} - -void ThemeModern::setupFont(const Common::String &key, const Common::String &name, FontStyle style) { - if (_evaluator->getVar(key) == EVAL_STRING_VAR) { - _fonts[style] = FontMan.getFontByName(name); - - if (!_fonts[style]) { - Common::String temp(_evaluator->getStringVar(key)); - - _fonts[style] = loadFont(temp.c_str()); - if (!_fonts[style]) - error("Couldn't load %s font '%s'", key.c_str(), temp.c_str()); - - FontMan.assignFontToName(name, _fonts[style]); - } - } else { - _fonts[style] = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - } -} - -#pragma mark - - -void ThemeModern::processExtraValues() { - // TODO: think of unloading all old graphic files first, instead of just - // loading new ones if needed when this is processed? - - // load the pixmap filenames from the config file -#define loadRectData(type, str) \ - _imageHandles[k##type##Corner] = _evaluator->getStringVar("pix_"str"_corner"); \ - _imageHandles[k##type##Top] = _evaluator->getStringVar("pix_"str"_top"); \ - _imageHandles[k##type##Left] = _evaluator->getStringVar("pix_"str"_left"); \ - _imageHandles[k##type] = _evaluator->getStringVar("pix_"str"_bkgd") - - loadRectData(DialogBkgd, "dialog"); - loadRectData(WidgetBkgd, "widget"); - loadRectData(WidgetSmallBkgd, "widget_small"); - loadRectData(TabBkgd, "tab"); - loadRectData(SliderBkgd, "slider_bkgd"); - loadRectData(Slider, "slider"); - loadRectData(ScrollbarBkgd, "scrollbar_bkgd"); - loadRectData(Scrollbar, "scrollbar"); - loadRectData(ButtonBkgd, "button"); - loadRectData(PopUpWidgetBkgd, "popupwidget"); - loadRectData(EditTextBkgd, "edittext_bkgd"); - -#undef loadRectData - - _imageHandles[kCheckboxEmpty] = _evaluator->getStringVar("pix_checkbox_empty"); - _imageHandles[kCheckboxChecked] = _evaluator->getStringVar("pix_checkbox_checked"); - - _imageHandles[kWidgetArrow] = _evaluator->getStringVar("pix_widget_arrow"); - - _imageHandles[kThemeLogo] = _evaluator->getStringVar("pix_theme_logo"); - - _imageHandles[kGUICursor] = _evaluator->getStringVar("pix_cursor_image"); - - for (int i = 0; i < kImageHandlesMax; ++i) { - ImageMan.registerSurface(_imageHandles[i], 0); - _images[i] = ImageMan.getSurface(_imageHandles[i]); - } - - // load the gradient factors from the config file - _gradientFactors[kMainDialogFactor] = _evaluator->getVar("gradient_dialog_main", 1); - _gradientFactors[kDialogFactor] = _evaluator->getVar("gradient_dialog", 1); - _gradientFactors[kDialogSpecialFactor] = _evaluator->getVar("gradient_dialog_special", 1); - - _gradientFactors[kWidgetSmallFactor] = _evaluator->getVar("gradient_widget_small", 1); - _gradientFactors[kWidgetFactor] = _evaluator->getVar("gradient_widget", 1); - - _gradientFactors[kButtonFactor] = _evaluator->getVar("gradient_button", 1); - - _gradientFactors[kSliderFactor] = _evaluator->getVar("gradient_slider", 1); - _gradientFactors[kSliderBackground] = _evaluator->getVar("gradient_silder_bkgd", 1); - - _gradientFactors[kTabFactor] = _evaluator->getVar("gradient_tab", 1); - - _gradientFactors[kScrollbarFactor] = _evaluator->getVar("gradient_scrollbar", 1); - _gradientFactors[kScrollbarBkgdFactor] = _evaluator->getVar("gradient_scrollbar_background", 1); - - _gradientFactors[kPopUpWidgetFactor] = _evaluator->getVar("gradient_popupwidget", 1); - - _gradientFactors[kEditTextFactor] = _evaluator->getVar("gradient_edittext", 1); - - // load values with default values from the config file - _shadowLeftWidth = _evaluator->getVar("shadow_left_width", 2); - _shadowRightWidth = _evaluator->getVar("shadow_right_width", 4); - _shadowTopHeight = _evaluator->getVar("shadow_top_height", 2); - _shadowBottomHeight = _evaluator->getVar("shadow_bottom_height", 4); - - _cursorHotspotX = _evaluator->getVar("cursor_hotspot_x", 0); - _cursorHotspotY = _evaluator->getVar("cursor_hotspot_y", 0); - - _cursorTargetScale = _evaluator->getVar("cursor_targetScale", 1); - - // inactive dialog shading stuff - - ShadingStyle shading = (ShadingStyle)_evaluator->getVar("inactive_dialog_shading", kShadingNone); - - switch (shading) { - case kShadingNone: - _dialogShadingCallback = 0; - break; - - case kShadingLuminance: - _dialogShadingCallback = &ThemeModern::calcLuminance; - break; - - case kShadingDim: - _dimPercentValue = _evaluator->getVar("shading_dim_percent", -1); - - if (_dimPercentValue < 0) { - _dimPercentValue = 0; - } else if (_dimPercentValue > 100) { - _dimPercentValue = 100; - } - - if (_dimPercentValue != 0) { - _dimPercentValue = 256 * (100 - _dimPercentValue) / 100; - _dialogShadingCallback = &ThemeModern::calcDimColor; - } - break; - - default: - warning("no valid 'inactive_dialog_shading' specified"); - } - - setupFonts(); - - // load the colors from the config file - setupColors(); - - // creates cursor image - if (_system->hasFeature(OSystem::kFeatureCursorHasPalette)) { - createCursor(); - } -} - -#pragma mark - - -OverlayColor ThemeModern::calcLuminance(OverlayColor col) { - uint8 r, g, b; - _system->colorToRGB(col, r, g, b); - - // A better (but slower) formula to calculate the luminance would be: - //uint lum = (byte)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5); - // Note that the approximation below will only produce values between - // (and including) 0 and 221. - uint lum = (r >> 2) + (g >> 1) + (b >> 3); - - return _system->RGBToColor(lum, lum, lum); -} - -OverlayColor ThemeModern::calcDimColor(OverlayColor col) { - uint8 r, g, b; - _system->colorToRGB(col, r, g, b); - - r = r * _dimPercentValue >> 8; - g = g * _dimPercentValue >> 8; - b = b * _dimPercentValue >> 8; - - return _system->RGBToColor(r, g, b); -} - -#pragma mark - - -void ThemeModern::setUpCursor() { - CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - CursorMan.showMouse(true); -} - -void ThemeModern::createCursor() { - const Surface *cursor = _images[kGUICursor]; - - _cursorWidth = cursor->w; - _cursorHeight = cursor->h; - - uint colorsFound = 0; - const OverlayColor *src = (const OverlayColor*)cursor->pixels; - - byte *table = new byte[65536]; - assert(table); - memset(table, 0, sizeof(byte)*65536); - - byte r, g, b; - - _system->colorToRGB(_colors[kColorTransparency], r, g, b); - uint16 transparency = RGBToColor<ColorMasks<565> >(r, g, b); - - delete[] _cursor; - - _cursor = new byte[_cursorWidth * _cursorHeight]; - assert(_cursor); - memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); - - for (uint y = 0; y < _cursorHeight; ++y) { - for (uint x = 0; x < _cursorWidth; ++x) { - _system->colorToRGB(src[x], r, g, b); - uint16 col = RGBToColor<ColorMasks<565> >(r, g, b); - if (!table[col] && col != transparency) { - table[col] = colorsFound++; - - uint index = table[col]; - _cursorPal[index * 4 + 0] = r; - _cursorPal[index * 4 + 1] = g; - _cursorPal[index * 4 + 2] = b; - _cursorPal[index * 4 + 3] = 0xFF; - - if (colorsFound > MAX_CURS_COLORS) - error("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); - } - - if (col != transparency) { - uint index = table[col]; - _cursor[y * _cursorWidth + x] = index; - } - } - src += _cursorWidth; - } - - _useCursor = true; - delete[] table; -} - -#pragma mark - - -template<class T> -inline OverlayColor getColorAlphaImpl(OverlayColor col1, OverlayColor col2, int alpha) { - OverlayColor output = 0; - output |= ((alpha * ((col1 & T::kRedMask) - (col2 & T::kRedMask)) >> 8) + (col2 & T::kRedMask)) & T::kRedMask; - output |= ((alpha * ((col1 & T::kGreenMask) - (col2 & T::kGreenMask)) >> 8) + (col2 & T::kGreenMask)) & T::kGreenMask; - output |= ((alpha * ((col1 & T::kBlueMask) - (col2 & T::kBlueMask)) >> 8) + (col2 & T::kBlueMask)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -// broken implementation! -template<class T> -inline OverlayColor getColorAlphaImp2(OverlayColor col1, OverlayColor col2, int alpha) { - OverlayColor output = 0; - output |= ((alpha * ((~col1 & T::kRedMask) - (col2 & T::kRedMask)) >> 8) + (col2 & T::kRedMask)) & T::kRedMask; - output |= ((alpha * ((~col1 & T::kGreenMask) - (col2 & T::kGreenMask)) >> 8) + (col2 & T::kGreenMask)) & T::kGreenMask; - output |= ((alpha * ((~col1 & T::kBlueMask) - (col2 & T::kBlueMask)) >> 8) + (col2 & T::kBlueMask)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -OverlayColor getColorAlpha(OverlayColor col1, OverlayColor col2, int alpha) { - if (alpha >= 0) { - if (gBitFormat == 565) { - return getColorAlphaImpl<ColorMasks<565> >(col1, col2, alpha); - } else { - return getColorAlphaImpl<ColorMasks<555> >(col1, col2, alpha); - } - } else { - if (gBitFormat == 565) { - return getColorAlphaImp2<ColorMasks<565> >(col1, col2, -alpha - 256); - } else { - return getColorAlphaImp2<ColorMasks<555> >(col1, col2, -alpha - 256); - } - } -} - -template<class T> -inline OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos) { - OverlayColor output = 0; - output |= (start + ((((end & T::kRedMask) - (start & T::kRedMask))) * pos >> 12)) & T::kRedMask; - output |= (start + ((((end & T::kGreenMask) - (start & T::kGreenMask))) * pos >> 12)) & T::kGreenMask; - output |= (start + ((((end & T::kBlueMask) - (start & T::kBlueMask))) * pos >> 12)) & T::kBlueMask; - output |= ~(T::kRedMask | T::kGreenMask | T::kBlueMask); - return output; -} - -OverlayColor calcGradient(OverlayColor start, OverlayColor end, int pos, int max, uint factor = 1) { - pos *= factor; - if (pos >= max) - return end; - - pos = (0x1000 * pos) / max; - - if (gBitFormat == 565) { - return calcGradient<ColorMasks<565> >(start, end, pos); - } else { - return calcGradient<ColorMasks<555> >(start, end, pos); - } -} - -void getStateColor(OverlayColor &s, OverlayColor &e, - OverlayColor enabledS, OverlayColor enabledE, - OverlayColor highlightS, OverlayColor highlightE, - Theme::WidgetStateInfo state) { - if (state == Theme::kStateHighlight) { - s = highlightS; - e = highlightE; - } else { - s = enabledS; - e = enabledE; - } -} - -} // end of namespace GUI - -#endif diff --git a/gui/ThemeModern.h b/gui/ThemeModern.h deleted file mode 100644 index a3cb71510c..0000000000 --- a/gui/ThemeModern.h +++ /dev/null @@ -1,340 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - */ - -#ifndef GUI_THEMEMODERN_H -#define GUI_THEMEMODERN_H - -#ifndef DISABLE_FANCY_THEMES - -#include "gui/theme.h" - -namespace GUI { - -class ThemeModern : public Theme { -public: - ThemeModern(OSystem *system, const Common::String &stylefile, const Common::ConfigFile *cfg = 0); - virtual ~ThemeModern(); - - bool init(); - void deinit(); - - void refresh(); - - bool ownCursor() const { return _useCursor; } - - void enable(); - void disable(); - - void openDialog(bool topDialog); - void closeAllDialogs(); - - void clearAll(); - void updateScreen(); - - void setDrawArea(const Common::Rect &r); - void resetDrawArea(); - - const Graphics::Font *getFont(FontStyle font = kFontStyleBold) const { return _fonts[font]; } - int getFontHeight(FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getFontHeight(); return 0; } - int getStringWidth(const Common::String &str, FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getStringWidth(str); return 0; } - int getCharWidth(byte c, FontStyle font = kFontStyleBold) const { if (_fonts[font]) return _fonts[font]->getCharWidth(c); return 0; } - - void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); - void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state); - - void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state); - void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints); - void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans); - void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state); - void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state); - void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state); - void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState, WidgetStateInfo state); - void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align); - void drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state); - void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state); - - void restoreBackground(Common::Rect r, bool special = false); - bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false); - - int getTabSpacing() const; - int getTabPadding() const; - - bool supportsImages() const { return true; } - const Graphics::Surface *getImageSurface(const kThemeImages n) const { return n == kImageLogo ? _images[kThemeLogo] : 0; } -private: - void colorFade(const Common::Rect &r, OverlayColor start, OverlayColor end, uint factor = 1); - void drawRect(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, bool skipLastRow = false); - void drawRectMasked(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, int alpha, - OverlayColor start, OverlayColor end, uint factor = 1, bool skipLastRow = false, bool skipTopRow = false); - void drawSurface(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, int alpha); - void drawSurfaceMasked(const Common::Rect &r, const Graphics::Surface *surf, bool upDown, bool leftRight, int alpha, - OverlayColor start, OverlayColor end, uint factor = 1); - - enum ShadowStyles { - kShadowFull = 0, - kShadowSmall = 1, - kShadowButton = 2, - kShadowEmboss = 3, - kShadowPopUp = 4 - }; - - Common::Rect shadowRect(const Common::Rect &r, uint32 shadowStyle); - void drawShadow(const Common::Rect &r, const Graphics::Surface *corner, const Graphics::Surface *top, - const Graphics::Surface *left, const Graphics::Surface *fill, uint32 shadowStyle, bool skipLastRow = false, - bool skipTopRow = false); - void drawShadowRect(const Common::Rect &r, const Common::Rect &area, const Graphics::Surface *corner, - const Graphics::Surface *top, const Graphics::Surface *left, const Graphics::Surface *fill, - int alpha, bool skipLastRow = false, bool skipTopRow = false); - - int _shadowLeftWidth, _shadowRightWidth; - int _shadowTopHeight, _shadowBottomHeight; - - OSystem *_system; - Graphics::Surface _screen; - Common::Rect _shadowDrawArea; - - bool _initOk; - bool _forceRedraw; - bool _enabled; - - int _lastUsedBitMask; - void resetupGuiRenderer(); - void setupColors(); - - OverlayColor getColor(State state); - - struct DialogState { - Graphics::Surface screen; - } *_dialog; - - void setupFonts(); - void deleteFonts(); - - void setupFont(const Common::String &key, const Common::String &name, FontStyle style); - - const Graphics::Font *_fonts[kFontStyleMax]; - -private: - void processExtraValues(); - - enum ImageHandles { - kDialogBkgdCorner = 0, - kDialogBkgdTop = 1, - kDialogBkgdLeft = 2, - kDialogBkgd = 3, - - kWidgetBkgdCorner = 4, - kWidgetBkgdTop = 5, - kWidgetBkgdLeft = 6, - kWidgetBkgd = 7, - - kCheckboxEmpty = 8, - kCheckboxChecked = 9, - - kWidgetArrow = 10, - - kTabBkgdCorner = 11, - kTabBkgdTop = 12, - kTabBkgdLeft = 13, - kTabBkgd = 14, - - kSliderBkgdCorner = 15, - kSliderBkgdTop = 16, - kSliderBkgdLeft = 17, - kSliderBkgd = 18, - - kSliderCorner = 19, - kSliderTop = 20, - kSliderLeft = 21, - kSlider = 22, - - kScrollbarBkgdCorner = 23, - kScrollbarBkgdTop = 24, - kScrollbarBkgdLeft = 25, - kScrollbarBkgd = 26, - - kScrollbarCorner = 27, - kScrollbarTop = 28, - kScrollbarLeft = 29, - kScrollbar = 30, - - kButtonBkgdCorner = 31, - kButtonBkgdTop = 32, - kButtonBkgdLeft = 33, - kButtonBkgd = 34, - - kWidgetSmallBkgdCorner = 35, - kWidgetSmallBkgdTop = 36, - kWidgetSmallBkgdLeft = 37, - kWidgetSmallBkgd = 38, - - kThemeLogo = 39, - - kPopUpWidgetBkgdCorner = 40, - kPopUpWidgetBkgdTop = 41, - kPopUpWidgetBkgdLeft = 42, - kPopUpWidgetBkgd = 43, - - kEditTextBkgdCorner = 44, - kEditTextBkgdTop = 45, - kEditTextBkgdLeft = 46, - kEditTextBkgd = 47, - - kGUICursor = 48, - - kImageHandlesMax - }; - -private: - int _dimPercentValue; - typedef OverlayColor (ThemeModern::*InactiveDialogCallback)(OverlayColor col); - InactiveDialogCallback _dialogShadingCallback; - - OverlayColor calcLuminance(OverlayColor col); - OverlayColor calcDimColor(OverlayColor col); - - bool _useCursor; - void setUpCursor(); - void createCursor(); - int _cursorHotspotX, _cursorHotspotY; - int _cursorTargetScale; -#define MAX_CURS_COLORS 255 - byte *_cursor; - bool _needPaletteUpdates; - uint _cursorWidth, _cursorHeight; - byte _cursorPal[4*MAX_CURS_COLORS]; - -private: - Common::String _imageHandles[kImageHandlesMax]; - const Graphics::Surface **_images; - - enum ColorHandles { - kMainDialogStart = 0, - kMainDialogEnd = 1, - - kDialogStart = 2, - kDialogEnd = 3, - - kColorStateDisabled = 4, - kColorStateHighlight = 5, - kColorStateEnabled = 6, - kColorTransparency = 7, - - kTextInvertedBackground = 8, - kTextInvertedColor = 9, - - kWidgetBackgroundStart = 10, - kWidgetBackgroundEnd = 11, - kWidgetBackgroundSmallStart = 12, - kWidgetBackgroundSmallEnd = 13, - - kButtonBackgroundStart = 14, - kButtonBackgroundEnd = 15, - kButtonTextEnabled = 16, - kButtonTextDisabled = 17, - kButtonTextHighlight = 18, - - kSliderBackgroundStart = 19, - kSliderBackgroundEnd = 20, - kSliderStart = 21, - kSliderEnd = 22, - - kTabBackgroundStart = 23, - kTabBackgroundEnd = 24, - - kScrollbarBackgroundStart = 25, - kScrollbarBackgroundEnd = 26, - kScrollbarButtonStart = 27, - kScrollbarButtonEnd = 28, - kScrollbarSliderStart = 29, - kScrollbarSliderEnd = 30, - - kCaretColor = 31, - - kSliderHighStart = 32, - kSliderHighEnd = 33, - - kButtonBackgroundHighlightStart = 34, - kButtonBackgroundHighlightEnd = 35, - - kScrollbarButtonHighlightStart = 36, - kScrollbarButtonHighlightEnd = 37, - kScrollbarSliderHighlightStart = 38, - kScrollbarSliderHighlightEnd = 39, - - kPopUpWidgetStart = 40, - kPopUpWidgetEnd = 41, - kPopUpWidgetHighlightStart = 42, - kPopUpWidgetHighlightEnd = 43, - - kEditTextBackgroundStart = 44, - kEditTextBackgroundEnd = 45, - - kTabActiveStart = 46, - kTabActiveEnd = 47, - kTabInactiveStart = 48, - kTabInactiveEnd = 49, - - kColorHandlesMax - }; - - OverlayColor _colors[kColorHandlesMax]; - - enum GradientFactors { - kMainDialogFactor = 0, - kDialogFactor = 1, - kDialogSpecialFactor = 2, - - kWidgetSmallFactor = 3, - kWidgetFactor = 4, - - kButtonFactor = 5, - - kSliderFactor = 6, - kSliderBackground = 7, - - kTabFactor = 7, - - kScrollbarFactor = 8, - kScrollbarBkgdFactor = 9, - - kPopUpWidgetFactor = 10, - - kEditTextFactor = 11, - - kMaxGradientFactors - }; - - uint _gradientFactors[kMaxGradientFactors]; -}; - -} // end of namespace GUI - -#endif - -#endif - diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp new file mode 100644 index 0000000000..2656f2a898 --- /dev/null +++ b/gui/ThemeParser.cpp @@ -0,0 +1,793 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "common/system.h" +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/xmlparser.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeParser.h" +#include "gui/newgui.h" +#include "graphics/VectorRenderer.h" + +namespace GUI { + +using namespace Graphics; +using namespace Common; + +ThemeParser::ThemeParser(ThemeRenderer *parent) : XMLParser() { + + _drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE; + _drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE; + _drawFunctions["roundedsq"] = &Graphics::VectorRenderer::drawCallback_ROUNDSQ; + _drawFunctions["bevelsq"] = &Graphics::VectorRenderer::drawCallback_BEVELSQ; + _drawFunctions["line"] = &Graphics::VectorRenderer::drawCallback_LINE; + _drawFunctions["triangle"] = &Graphics::VectorRenderer::drawCallback_TRIANGLE; + _drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE; + _drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB; + _drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID; + _drawFunctions["bitmap"] = &Graphics::VectorRenderer::drawCallback_BITMAP; + _drawFunctions["cross"] = &Graphics::VectorRenderer::drawCallback_CROSS; + + _defaultStepGlobal = defaultDrawStep(); + _defaultStepLocal = 0; + _theme = parent; +} + +void ThemeParser::cleanup() { + delete _defaultStepGlobal; + delete _defaultStepLocal; + + _defaultStepGlobal = defaultDrawStep(); + _defaultStepLocal = 0; + _palette.clear(); +} + +Graphics::DrawStep *ThemeParser::defaultDrawStep() { + Graphics::DrawStep *step = new DrawStep; + + step->fgColor.set = false; + step->bgColor.set = false; + step->gradColor1.set = false; + step->gradColor2.set = false; + + step->xAlign = Graphics::DrawStep::kVectorAlignManual; + step->yAlign = Graphics::DrawStep::kVectorAlignManual; + step->x = 0; + step->y = 0; + step->w = 0; + step->h = 0; + + step->extraData = 0; + step->factor = 1; + step->autoWidth = true; + step->autoHeight = true; + step->fillMode = Graphics::VectorRenderer::kFillDisabled; + step->scale = (1 << 16); + step->shadow = 0; + step->bevel = 0; + step->stroke = 0; + step->radius = 0xFF; + + return step; +} + +Graphics::DrawStep *ThemeParser::newDrawStep() { + assert(_defaultStepGlobal); + Graphics::DrawStep *step = 0 ; //new DrawStep; + + if (_defaultStepLocal) { + step = new DrawStep(*_defaultStepLocal); + } else { + step = new DrawStep(*_defaultStepGlobal); + } + + return step; +} + +bool ThemeParser::parserCallback_defaults(ParserNode *node) { + ParserNode *parentNode = getParentNode(node); + Graphics::DrawStep *step = 0; + + if (parentNode->name == "render_info") { + step = _defaultStepGlobal; + } else if (parentNode->name == "drawdata") { + if (_defaultStepLocal == 0) + _defaultStepLocal = new DrawStep(*_defaultStepLocal); + + step = _defaultStepLocal; + } else { + return parserError("<default> key out of scope. Must be inside <drawdata> or <render_info> keys."); + } + + return parseDrawStep(node, step, false); +} + +bool ThemeParser::parserCallback_font(ParserNode *node) { + int red, green, blue; + + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + if (_palette.contains(node->values["color"])) + getPaletteColor(node->values["color"], red, green, blue); + else if (!parseIntegerKey(node->values["color"].c_str(), 3, &red, &green, &blue)) + return parserError("Error when parsing color value for font definition."); + + if (!_theme->addFont(node->values["id"], node->values["file"], red, green, blue)) + return parserError("Error when loading Font in theme engine."); + + return true; +} + +bool ThemeParser::parserCallback_fonts(ParserNode *node) { + return true; +} + +bool ThemeParser::parserCallback_cursor(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + int spotx, spoty, scale; + + if (!parseIntegerKey(node->values["hotspot"].c_str(), 2, &spotx, &spoty)) + return parserError("Error when parsing cursor Hot Spot coordinates."); + + if (!parseIntegerKey(node->values["scale"].c_str(), 1, &scale)) + return parserError("Error when parsing cursor scale."); + + if (!_theme->createCursor(node->values["file"], spotx, spoty, scale)) + return parserError("Error when creating Bitmap Cursor."); + + return true; +} + +bool ThemeParser::parserCallback_bitmap(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + if (!_theme->addBitmap(node->values["filename"])) + return parserError("Error when loading Bitmap file '%s'", node->values["filename"].c_str()); + + return true; +} + +bool ThemeParser::parserCallback_text(ParserNode *node) { + GUI::Theme::TextAlign alignH; + GUI::Theme::TextAlignVertical alignV; + + if (node->values["horizontal_align"] == "left") + alignH = GUI::Theme::kTextAlignLeft; + else if (node->values["horizontal_align"] == "right") + alignH = GUI::Theme::kTextAlignRight; + else if (node->values["horizontal_align"] == "center") + alignH = GUI::Theme::kTextAlignCenter; + else return parserError("Invalid value for text alignment."); + + if (node->values["vertical_align"] == "top") + alignV = GUI::Theme::kTextAlignVTop; + else if (node->values["vertical_align"] == "center") + alignV = GUI::Theme::kTextAlignVCenter; + else if (node->values["vertical_align"] == "bottom") + alignV = GUI::Theme::kTextAlignVBottom; + else return parserError("Invalid value for text alignment."); + + if (!_theme->addTextData(getParentNode(node)->values["id"], node->values["font"], alignH, alignV)) + return parserError("Error when adding Text Data for '%s'.", getParentNode(node)->values["id"].c_str()); + + return true; +} + +bool ThemeParser::parserCallback_render_info(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) + node->ignore = true; + + return true; +} + +bool ThemeParser::parserCallback_layout_info(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) + node->ignore = true; + + return true; +} + +bool ThemeParser::parserCallback_palette(ParserNode *node) { + return true; +} + +bool ThemeParser::parserCallback_color(ParserNode *node) { + Common::String name = node->values["name"]; + + if (_palette.contains(name)) + return parserError("Color '%s' has already been defined.", name.c_str()); + + int red, green, blue; + + if (parseIntegerKey(node->values["rgb"].c_str(), 3, &red, &green, &blue) == false || + red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) + return parserError("Error when parsing RGB values for palette color '%s'", name.c_str());\ + + _palette[name].r = red; + _palette[name].g = green; + _palette[name].b = blue; + + return true; +} + + +bool ThemeParser::parserCallback_drawstep(ParserNode *node) { + Graphics::DrawStep *drawstep = newDrawStep(); + + Common::String functionName = node->values["func"]; + + if (_drawFunctions.contains(functionName) == false) + return parserError("%s is not a valid drawing function name", functionName.c_str()); + + drawstep->drawingCall = _drawFunctions[functionName]; + + if (!parseDrawStep(node, drawstep, true)) + return false; + + _theme->addDrawStep(getParentNode(node)->values["id"], *drawstep); + delete drawstep; + + return true; +} + +bool ThemeParser::parserCallback_drawdata(ParserNode *node) { + bool cached = false; + + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + if (node->values.contains("cache")) { + if (node->values["cache"] == "true") + cached = true; + else if (node->values["cache"] == "false") + cached = false; + else return parserError("'Parsed' value must be either true or false."); + } + + if (_theme->addDrawData(node->values["id"], cached) == false) + return parserError("Error when adding Draw Data set: Invalid DrawData name."); + + if (_defaultStepLocal) { + delete _defaultStepLocal; + _defaultStepLocal = 0; + } + + return true; +} + +bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific) { + int red, green, blue, x; + Common::String val; + +/** + * Helper macro to sanitize and assign an integer value from a key + * to the draw step. + * + * @param struct_name Name of the field of a DrawStep struct that must be + * assigned. + * @param key_name Name as STRING of the key identifier as it appears in the + * theme description format. + * @param force Sets if the key is optional or necessary. + */ +#define __PARSER_ASSIGN_INT(struct_name, key_name, force) \ + if (stepNode->values.contains(key_name)) { \ + if (!parseIntegerKey(stepNode->values[key_name].c_str(), 1, &x)) \ + return parserError("Error when parsing key value for '%s'.", key_name); \ + \ + drawstep->struct_name = x; \ + } else if (force) { \ + return parserError("Missing necessary key '%s'.", key_name); \ + } + +/** + * Helper macro to sanitize and assign a RGB value from a key to the draw + * step. RGB values have the following syntax: "R, G, B". + * + * @param struct_name Name of the field of a DrawStep struct that must be + * assigned. + * @param key_name Name as STRING of the key identifier as it appears in the + * theme description format. + */ +#define __PARSER_ASSIGN_RGB(struct_name, key_name) \ + if (stepNode->values.contains(key_name)) { \ + val = stepNode->values[key_name]; \ + if (_palette.contains(val)) { \ + red = _palette[val].r; \ + green = _palette[val].g; \ + blue = _palette[val].b; \ + } else if (parseIntegerKey(val.c_str(), 3, &red, &green, &blue) == false || \ + red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) \ + return parserError("Error when parsing color struct '%s'", val.c_str());\ + \ + drawstep->struct_name.r = red; \ + drawstep->struct_name.g = green; \ + drawstep->struct_name.b = blue; \ + drawstep->struct_name.set = true; \ + } + + __PARSER_ASSIGN_INT(stroke, "stroke", false); + __PARSER_ASSIGN_INT(bevel, "bevel", false); + __PARSER_ASSIGN_INT(shadow, "shadow", false); + __PARSER_ASSIGN_INT(factor, "gradient_factor", false); + + __PARSER_ASSIGN_RGB(fgColor, "fg_color"); + __PARSER_ASSIGN_RGB(bgColor, "bg_color"); + __PARSER_ASSIGN_RGB(gradColor1, "gradient_start"); + __PARSER_ASSIGN_RGB(gradColor2, "gradient_end"); + __PARSER_ASSIGN_RGB(bevelColor, "bevel_color"); + + if (functionSpecific) { + assert(stepNode->values.contains("func")); + Common::String functionName = stepNode->values["func"]; + + if (functionName == "bitmap") { + if (!stepNode->values.contains("file")) + return parserError("Need to specify a filename for Bitmap blitting."); + + drawstep->blitSrc = _theme->getBitmap(stepNode->values["file"]); + + if (!drawstep->blitSrc) + return parserError("The given filename hasn't been loaded into the GUI."); + } + + if (functionName == "roundedsq" || functionName == "circle" || functionName == "tab") { + if (stepNode->values.contains("radius") && stepNode->values["radius"] == "auto") { + drawstep->radius = 0xFF; + } else { + __PARSER_ASSIGN_INT(radius, "radius", true); + } + } + + if (functionName == "triangle") { + drawstep->extraData = VectorRenderer::kTriangleUp; + + if (stepNode->values.contains("orientation")) { + val = stepNode->values["orientation"]; + + if ( val == "top") + drawstep->extraData = VectorRenderer::kTriangleUp; + else if (val == "bottom") + drawstep->extraData = VectorRenderer::kTriangleDown; + else if (val == "left") + drawstep->extraData = VectorRenderer::kTriangleLeft; + else if (val == "right") + drawstep->extraData = VectorRenderer::kTriangleRight; + else + return parserError("'%s' is not a valid value for triangle orientation.", val.c_str()); + } + } + + if (stepNode->values.contains("size")) { + warning("The <size> keyword has been deprecated. Use <width> and <height> instead"); + } + + if (stepNode->values.contains("width") && stepNode->values["width"] != "auto") { + drawstep->autoWidth = false; + + val = stepNode->values["width"]; + if (parseIntegerKey(val.c_str(), 1, &x)) + drawstep->w = x; + else if (val == "height") + drawstep->w = -1; + else return parserError("Invalid value for vector width."); + + if (stepNode->values.contains("xpos")) { + val = stepNode->values["xpos"]; + + if (parseIntegerKey(val.c_str(), 1, &x)) + drawstep->x = x; + else if (val == "center") + drawstep->xAlign = Graphics::DrawStep::kVectorAlignCenter; + else if (val == "left") + drawstep->xAlign = Graphics::DrawStep::kVectorAlignLeft; + else if (val == "right") + drawstep->xAlign = Graphics::DrawStep::kVectorAlignRight; + else + return parserError("Invalid value for X Position"); + } else { + return parserError("When width is not set to 'auto', a <xpos> tag must be included."); + } + } + + if (stepNode->values.contains("height") && stepNode->values["height"] != "auto") { + drawstep->autoHeight = false; + + val = stepNode->values["height"]; + if (parseIntegerKey(val.c_str(), 1, &x)) + drawstep->h = x; + else if (val == "width") + drawstep->h = -1; + else return parserError("Invalid value for vector height."); + + if (stepNode->values.contains("ypos")) { + val = stepNode->values["ypos"]; + + if (parseIntegerKey(val.c_str(), 1, &x)) + drawstep->y = x; + else if (val == "center") + drawstep->yAlign = Graphics::DrawStep::kVectorAlignCenter; + else if (val == "top") + drawstep->yAlign = Graphics::DrawStep::kVectorAlignTop; + else if (val == "bottom") + drawstep->yAlign = Graphics::DrawStep::kVectorAlignBottom; + else + return parserError("Invalid value for Y Position"); + } else { + return parserError("When height is not set to 'auto', a <ypos> tag must be included."); + } + } + + if (drawstep->h == -1 && drawstep->w == -1) + return parserError("Cross-reference in Vector Size: Height is set to width and width is set to height."); + } + + if (stepNode->values.contains("fill")) { + val = stepNode->values["fill"]; + if (val == "none") + drawstep->fillMode = VectorRenderer::kFillDisabled; + else if (val == "foreground") + drawstep->fillMode = VectorRenderer::kFillForeground; + else if (val == "background") + drawstep->fillMode = VectorRenderer::kFillBackground; + else if (val == "gradient") + drawstep->fillMode = VectorRenderer::kFillGradient; + else + return parserError("'%s' is not a valid fill mode for a shape.", stepNode->values["fill"].c_str()); + } + +#undef __PARSER_ASSIGN_INT +#undef __PARSER_ASSIGN_RGB + + return true; +} + +bool ThemeParser::parserCallback_def(ParserNode *node) { + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + Common::String var = "Globals." + node->values["var"]; + int value; + + if (_theme->themeEval()->hasVar(node->values["value"]) == true) + value = _theme->themeEval()->getVar(node->values["value"]); + + else if (!parseIntegerKey(node->values["value"].c_str(), 1, &value)) + return parserError("Invalid definition for '%s'.", var.c_str()); + + _theme->themeEval()->setVar(var, value); + return true; +} + +bool ThemeParser::parserCallback_widget(ParserNode *node) { + Common::String var; + + if (getParentNode(node)->name == "globals") { + + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + var = "Globals." + node->values["name"] + "."; + if (!parseCommonLayoutProps(node, var)) + return parserError("Error when parsing Layout properties of '%s'.", var.c_str()); + + } else { + var = node->values["name"]; + int width = -1; + int height = -1; + bool enabled = true; + + if (node->values.contains("enabled")) { + if (node->values["enabled"] == "false") + enabled = false; + else if (node->values["enabled"] != "true") + return parserError("Invalid value for Widget enabling (expecting true/false)"); + } + + if (node->values.contains("width")) { + if (_theme->themeEval()->hasVar(node->values["width"]) == true) + width = _theme->themeEval()->getVar(node->values["width"]); + + else if (!parseIntegerKey(node->values["width"].c_str(), 1, &width)) + return parserError("Corrupted width value in key for %s", var.c_str()); + } + + if (node->values.contains("height")) { + if (_theme->themeEval()->hasVar(node->values["height"]) == true) + height = _theme->themeEval()->getVar(node->values["height"]); + + else if (!parseIntegerKey(node->values["height"].c_str(), 1, &height)) + return parserError("Corrupted height value in key for %s", var.c_str()); + } + + _theme->themeEval()->addWidget(var, width, height, node->values["type"], enabled); + } + + return true; +} + +bool ThemeParser::parserCallback_dialog(ParserNode *node) { + Common::String var = "Dialog." + node->values["name"]; + bool enabled = true; + int inset = 0; + + if (resolutionCheck(node->values["resolution"]) == false) { + node->ignore = true; + return true; + } + + if (node->values.contains("enabled")) { + if (node->values["enabled"] == "false") + enabled = false; + else if (node->values["enabled"] != "true") + return parserError("Invalid value for Dialog enabling (expecting true/false)"); + } + + if (node->values.contains("inset")) { + if (!parseIntegerKey(node->values["inset"].c_str(), 1, &inset)) + return false; + } + + _theme->themeEval()->addDialog(var, node->values["overlays"], enabled, inset); + + if (node->values.contains("shading")) { + int shading = 0; + if (node->values["shading"] == "dim") + shading = 1; + else if (node->values["shading"] == "luminance") + shading = 2; + else return parserError("Invalid value for Dialog background shading."); + + _theme->themeEval()->setVar(var + ".Shading", shading); + } + + return true; +} + +bool ThemeParser::parserCallback_import(ParserNode *node) { + + if (!_theme->themeEval()->addImportedLayout(node->values["layout"])) + return parserError("Error when importing external layout"); + return true; +} + +bool ThemeParser::parserCallback_layout(ParserNode *node) { + int spacing = -1; + + if (node->values.contains("spacing")) { + if (!parseIntegerKey(node->values["spacing"].c_str(), 1, &spacing)) + return false; + } + + if (node->values["type"] == "vertical") + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutVertical, spacing, node->values["center"] == "true"); + + else if (node->values["type"] == "horizontal") + _theme->themeEval()->addLayout(GUI::ThemeLayout::kLayoutHorizontal, spacing, node->values["center"] == "true"); + + if (node->values.contains("padding")) { + int paddingL, paddingR, paddingT, paddingB; + + if (!parseIntegerKey(node->values["padding"].c_str(), 4, &paddingL, &paddingR, &paddingT, &paddingB)) + return false; + + _theme->themeEval()->addPadding(paddingL, paddingR, paddingT, paddingB); + } + + return true; +} + +bool ThemeParser::parserCallback_space(ParserNode *node) { + int size = -1; + + if (node->values.contains("size")) { + if (_theme->themeEval()->hasVar(node->values["size"])) + size = _theme->themeEval()->getVar(node->values["size"]); + + else if (!parseIntegerKey(node->values["size"].c_str(), 1, &size)) + return parserError("Invalid value for Spacing size."); + } + + _theme->themeEval()->addSpace(size); + return true; +} + +bool ThemeParser::closedKeyCallback(ParserNode *node) { + if (node->name == "layout") + _theme->themeEval()->closeLayout(); + else if (node->name == "dialog") + _theme->themeEval()->closeDialog(); + + return true; +} + +bool ThemeParser::parseCommonLayoutProps(ParserNode *node, const Common::String &var) { + if (node->values.contains("size")) { + int width, height; + + if (!parseIntegerKey(node->values["size"].c_str(), 2, &width, &height)) { + Common::StringTokenizer tokenizer(node->values["size"], " ,"); + Common::String wtoken, htoken; + char *parseEnd; + + wtoken = tokenizer.nextToken(); + + if (_theme->themeEval()->hasVar(wtoken)) { + width = _theme->themeEval()->getVar(wtoken); + } else { + width = strtol(wtoken.c_str(), &parseEnd, 10); + + if (*parseEnd != 0 && !(*parseEnd == '%' && *(parseEnd + 1) == 0)) + return false; + + if (wtoken.lastChar() == '%') + width = g_system->getOverlayWidth() * width / 100; + } + + htoken = tokenizer.nextToken(); + + if (_theme->themeEval()->hasVar(htoken)) { + height = _theme->themeEval()->getVar(htoken); + } else { + height = strtol(htoken.c_str(), &parseEnd, 10); + + if (*parseEnd != 0 && !(*parseEnd == '%' && *(parseEnd + 1) == 0)) + return false; + + if (htoken.lastChar() == '%') + height = g_system->getOverlayHeight() * height / 100; + } + + if (!tokenizer.empty()) + return false; + } + + + _theme->themeEval()->setVar(var + "Width", width); + _theme->themeEval()->setVar(var + "Height", height); + } + + if (node->values.contains("pos")) { + int x, y; + + if (!parseIntegerKey(node->values["pos"].c_str(), 2, &x, &y)) { + Common::StringTokenizer tokenizer(node->values["pos"], " ,"); + Common::String xpos, ypos; + char *parseEnd; + + xpos = tokenizer.nextToken(); + + if (xpos == "center") { + if (!_theme->themeEval()->hasVar(var + "Width")) + return false; + + x = (g_system->getOverlayWidth() / 2) - (_theme->themeEval()->getVar(var + "Width") / 2); + + } else if (_theme->themeEval()->hasVar(xpos)) { + x = _theme->themeEval()->getVar(xpos); + } else { + x = strtol(xpos.c_str(), &parseEnd, 10); + + if (*parseEnd != 0 && !(*parseEnd == 'r' && *(parseEnd + 1) == 0)) + return false; + + if (xpos.lastChar() == 'r') + x = g_system->getOverlayWidth() - x; + } + + ypos = tokenizer.nextToken(); + + if (ypos == "center") { + if (!_theme->themeEval()->hasVar(var + "Height")) + return false; + + y = (g_system->getOverlayHeight() / 2) - (_theme->themeEval()->getVar(var + "Height") / 2); + + } else if (_theme->themeEval()->hasVar(ypos)) { + y = _theme->themeEval()->getVar(ypos); + } else { + y = strtol(ypos.c_str(), &parseEnd, 10); + + if (*parseEnd != 0 && !(*parseEnd == 'b' && *(parseEnd + 1) == 0)) + return false; + + if (ypos.lastChar() == 'b') + y = g_system->getOverlayHeight() - y; + } + + if (!tokenizer.empty()) + return false; + } + + _theme->themeEval()->setVar(var + "X", x); + _theme->themeEval()->setVar(var + "Y", y); + } + + if (node->values.contains("padding")) { + int paddingL, paddingR, paddingT, paddingB; + + if (!parseIntegerKey(node->values["padding"].c_str(), 4, &paddingL, &paddingR, &paddingT, &paddingB)) + return false; + + _theme->themeEval()->setVar(var + "Padding.Left", paddingL); + _theme->themeEval()->setVar(var + "Padding.Right", paddingR); + _theme->themeEval()->setVar(var + "Padding.Top", paddingT); + _theme->themeEval()->setVar(var + "Padding.Bottom", paddingB); + } + + return true; +} + +bool ThemeParser::resolutionCheck(const Common::String &resolution) { + if (resolution.empty()) + return true; + + Common::StringTokenizer globTokenizer(resolution, ", "); + Common::String cur, w, h; + bool definedRes = false; + + while (!globTokenizer.empty()) { + bool ignore = false; + cur = globTokenizer.nextToken(); + + if (cur[0] == '-') { + ignore = true; + cur.deleteChar(0); + } else { + definedRes = true; + } + + Common::StringTokenizer resTokenizer(cur, "x"); + w = resTokenizer.nextToken(); + h = resTokenizer.nextToken(); + + if ((w == "X" || atoi(w.c_str()) == g_system->getOverlayWidth()) && + (h == "Y" || atoi(h.c_str()) == g_system->getOverlayHeight())) + return !ignore; + } + + return !definedRes; +} + +} diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h new file mode 100644 index 0000000000..098bdb0540 --- /dev/null +++ b/gui/ThemeParser.h @@ -0,0 +1,278 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef THEME_PARSER_H +#define THEME_PARSER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" + +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/stack.h" +#include "common/xmlparser.h" + +#include "graphics/VectorRenderer.h" +#include "gui/ThemeRenderer.h" + +namespace GUI { + +using namespace Graphics; +using namespace Common; +class ThemeRenderer; + +class ThemeParser : public XMLParser { + typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const DrawStep &); + +public: + ThemeParser(GUI::ThemeRenderer *parent); + + virtual ~ThemeParser() { + delete _defaultStepGlobal; + delete _defaultStepLocal; + _palette.clear(); + _drawFunctions.clear(); + } + + bool getPaletteColor(const Common::String &name, int &r, int &g, int &b) { + if (!_palette.contains(name)) + return false; + + r = _palette[name].r; + g = _palette[name].g; + b = _palette[name].b; + + return true; + } + +protected: + ThemeRenderer *_theme; + + CUSTOM_XML_PARSER(ThemeParser) { + XML_KEY(render_info) + XML_PROP(resolution, false) + XML_KEY(palette) + XML_KEY(color) + XML_PROP(name, true) + XML_PROP(rgb, true) + KEY_END() + KEY_END() + + XML_KEY(fonts) + XML_KEY(font) + XML_PROP(id, true) + XML_PROP(file, true) + XML_PROP(color, true) + XML_PROP(resolution, false) + KEY_END() + KEY_END() + + XML_KEY(bitmaps) + XML_KEY(bitmap) + XML_PROP(filename, true) + XML_PROP(resolution, false) + KEY_END() + KEY_END() + + XML_KEY(cursor) + XML_PROP(file, true) + XML_PROP(hotspot, true) + XML_PROP(scale, true) + XML_PROP(resolution, false) + KEY_END() + + XML_KEY(defaults) + XML_PROP(stroke, false) + XML_PROP(shadow, false) + XML_PROP(bevel, false) + XML_PROP(factor, false) + XML_PROP(fg_color, false) + XML_PROP(bg_color, false) + XML_PROP(gradient_start, false) + XML_PROP(gradient_end, false) + XML_PROP(bevel_color, false) + XML_PROP(gradient_factor, false) + XML_PROP(fill, false) + KEY_END() + + XML_KEY(drawdata) + XML_PROP(id, true) + XML_PROP(cache, false) + XML_PROP(resolution, false) + + XML_KEY(defaults) + XML_PROP(stroke, false) + XML_PROP(shadow, false) + XML_PROP(bevel, false) + XML_PROP(factor, false) + XML_PROP(fg_color, false) + XML_PROP(bg_color, false) + XML_PROP(gradient_start, false) + XML_PROP(gradient_end, false) + XML_PROP(bevel_color, false) + XML_PROP(gradient_factor, false) + XML_PROP(fill, false) + KEY_END() + + XML_KEY(drawstep) + XML_PROP(func, true) + XML_PROP(stroke, false) + XML_PROP(shadow, false) + XML_PROP(bevel, false) + XML_PROP(factor, false) + XML_PROP(fg_color, false) + XML_PROP(bg_color, false) + XML_PROP(gradient_start, false) + XML_PROP(gradient_end, false) + XML_PROP(gradient_factor, false) + XML_PROP(bevel_color, false) + XML_PROP(fill, false) + XML_PROP(radius, false) + XML_PROP(width, false) + XML_PROP(height, false) + XML_PROP(xpos, false) + XML_PROP(ypos, false) + XML_PROP(orientation, false) + XML_PROP(file, false) + KEY_END() + + XML_KEY(text) + XML_PROP(font, true) + XML_PROP(vertical_align, true) + XML_PROP(horizontal_align, true) + KEY_END() + KEY_END() + + KEY_END() // render_info end + + XML_KEY(layout_info) + XML_PROP(resolution, false) + XML_KEY(globals) + XML_PROP(resolution, false) + XML_KEY(def) + XML_PROP(var, true) + XML_PROP(value, true) + XML_PROP(resolution, false) + KEY_END() + + XML_KEY(widget) + XML_PROP(name, true) + XML_PROP(size, false) + XML_PROP(pos, false) + XML_PROP(padding, false) + XML_PROP(resolution, false) + KEY_END() + KEY_END() + + XML_KEY(dialog) + XML_PROP(name, true) + XML_PROP(overlays, true) + XML_PROP(shading, false) + XML_PROP(enabled, false) + XML_PROP(resolution, false) + XML_PROP(inset, false) + XML_KEY(layout) + XML_PROP(type, true) + XML_PROP(center, false) + XML_PROP(padding, false) + XML_PROP(spacing, false) + + XML_KEY(import) + XML_PROP(layout, true) + KEY_END() + + XML_KEY(widget) + XML_PROP(name, true) + XML_PROP(width, false) + XML_PROP(height, false) + XML_PROP(type, false) + XML_PROP(enabled, false) + KEY_END() + + XML_KEY(space) + XML_PROP(size, false) + KEY_END() + + XML_KEY_RECURSIVE(layout) + KEY_END() + KEY_END() + KEY_END() + + } PARSER_END(); + + /** Render info callbacks */ + bool parserCallback_render_info(ParserNode *node); + bool parserCallback_defaults(ParserNode *node); + bool parserCallback_font(ParserNode *node); + bool parserCallback_fonts(ParserNode *node); + bool parserCallback_text(ParserNode *node); + bool parserCallback_palette(ParserNode *node); + bool parserCallback_color(ParserNode *node); + bool parserCallback_drawstep(ParserNode *node); + bool parserCallback_drawdata(ParserNode *node); + bool parserCallback_bitmaps(ParserNode *node) { return true; } + bool parserCallback_bitmap(ParserNode *node); + bool parserCallback_cursor(ParserNode *node); + + + /** Layout info callbacks */ + bool parserCallback_layout_info(ParserNode *node); + bool parserCallback_globals(ParserNode *node) { return true; } + bool parserCallback_def(ParserNode *node); + bool parserCallback_widget(ParserNode *node); + bool parserCallback_dialog(ParserNode *node); + bool parserCallback_layout(ParserNode *node); + bool parserCallback_space(ParserNode *node); + bool parserCallback_import(ParserNode *node); + + bool closedKeyCallback(ParserNode *node); + + bool resolutionCheck(const Common::String &resolution); + + void cleanup(); + + Graphics::DrawStep *newDrawStep(); + Graphics::DrawStep *defaultDrawStep(); + bool parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawstep, bool functionSpecific); + bool parseCommonLayoutProps(ParserNode *node, const Common::String &var); + + Graphics::DrawStep *_defaultStepGlobal; + Graphics::DrawStep *_defaultStepLocal; + + Common::HashMap<Common::String, DrawingFunctionCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _drawFunctions; + + struct PaletteColor { + uint8 r, g, b; + }; + + Common::HashMap<Common::String, PaletteColor, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _palette; +}; + + + +} + +#endif diff --git a/gui/ThemeRenderer.cpp b/gui/ThemeRenderer.cpp new file mode 100644 index 0000000000..5f12cf3fd4 --- /dev/null +++ b/gui/ThemeRenderer.cpp @@ -0,0 +1,1036 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/util.h" +#include "graphics/surface.h" +#include "graphics/colormasks.h" +#include "common/system.h" +#include "common/events.h" +#include "common/config-manager.h" +#include "common/fs.h" +#include "graphics/imageman.h" +#include "graphics/cursorman.h" +#include "gui/launcher.h" + +#include "gui/ThemeRenderer.h" +#include "gui/ThemeEval.h" +#include "graphics/VectorRenderer.h" + +#define GUI_ENABLE_BUILTIN_THEME + +namespace GUI { + +using namespace Graphics; + +const char *ThemeRenderer::rendererModeLabels[] = { + "Disabled GFX", + "Stardard Renderer (16bpp)", + "Antialiased Renderer (16bpp)" +}; + +const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = { + {kDDMainDialogBackground, "mainmenu_bg", true, kDDNone}, + {kDDSpecialColorBackground, "special_bg", true, kDDNone}, + {kDDPlainColorBackground, "plain_bg", true, kDDNone}, + {kDDDefaultBackground, "default_bg", true, kDDNone}, + {kDDTextSelectionBackground, "text_selection", false, kDDNone}, + + {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, + {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, + {kDDWidgetBackgroundEditText, "widget_textedit", true, kDDNone}, + {kDDWidgetBackgroundSlider, "widget_slider", true, kDDNone}, + + {kDDButtonIdle, "button_idle", true, kDDWidgetBackgroundSlider}, + {kDDButtonHover, "button_hover", false, kDDButtonIdle}, + {kDDButtonDisabled, "button_disabled", true, kDDNone}, + + {kDDSliderFull, "slider_full", false, kDDNone}, + {kDDSliderHover, "slider_hover", false, kDDNone}, + {kDDSliderDisabled, "slider_disabled", true, kDDNone}, + + {kDDCheckboxDefault, "checkbox_default", true, kDDNone}, + {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, + {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, + + {kDDTabActive, "tab_active", false, kDDTabInactive}, + {kDDTabInactive, "tab_inactive", true, kDDNone}, + {kDDTabBackground, "tab_background", true, kDDNone}, + + {kDDScrollbarBase, "scrollbar_base", true, kDDNone}, + + {kDDScrollbarButtonIdle, "scrollbar_button_idle", true, kDDNone}, + {kDDScrollbarButtonHover, "scrollbar_button_hover", false, kDDScrollbarButtonIdle}, + + {kDDScrollbarHandleIdle, "scrollbar_handle_idle", false, kDDNone}, + {kDDScrollbarHandleHover, "scrollbar_handle_hover", false, kDDScrollbarBase}, + + {kDDPopUpIdle, "popup_idle", true, kDDNone}, + {kDDPopUpHover, "popup_hover", false, kDDPopUpIdle}, + + {kDDCaret, "caret", false, kDDNone}, + {kDDSeparator, "separator", true, kDDNone}, +}; + +const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = { + {kTextDataDefault, "text_default"}, + {kTextDataHover, "text_hover"}, + {kTextDataDisabled, "text_disabled"}, + {kTextDataInverted, "text_inverted"}, + {kTextDataButton, "text_button"}, + {kTextDataButtonHover, "text_button_hover"}, + {kTextDataNormalFont, "text_normal"} +}; + + +ThemeRenderer::ThemeRenderer(Common::String fileName, GraphicsMode mode) : + _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _font(0), + _screen(0), _backBuffer(0), _bytesPerPixel(0), _initOk(false), + _themeOk(false), _enabled(false), _buffering(false), _cursor(0) { + _system = g_system; + _parser = new ThemeParser(this); + _themeEval = new GUI::ThemeEval(); + + _useCursor = false; + + for (int i = 0; i < kDrawDataMAX; ++i) { + _widgets[i] = 0; + } + + for (int i = 0; i < kTextDataMAX; ++i) { + _texts[i] = 0; + } + + _graphicsMode = mode; + _themeFileName = fileName; + _initOk = false; +} + +ThemeRenderer::~ThemeRenderer() { + freeRenderer(); + freeScreen(); + freeBackbuffer(); + unloadTheme(); + delete _parser; + delete _themeEval; + delete[] _cursor; + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) + ImageMan.unregisterSurface(i->_key); +} + +bool ThemeRenderer::init() { + // reset everything and reload the graphics + deinit(); + setGraphicsMode(_graphicsMode); + + if (_screen->pixels && _backBuffer->pixels) { + _initOk = true; + clearAll(); + resetDrawArea(); + } + + if (_screen->w >= 400 && _screen->h >= 300) { + _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + } else { + _font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + } + + if (isThemeLoadingRequired() || !_themeOk) { + loadTheme(_themeFileName); + } + + return true; +} + +void ThemeRenderer::deinit() { + if (_initOk) { + _system->hideOverlay(); + freeRenderer(); + freeScreen(); + freeBackbuffer(); + _initOk = false; + } +} + +void ThemeRenderer::unloadTheme() { + if (!_themeOk) + return; + + for (int i = 0; i < kDrawDataMAX; ++i) { + delete _widgets[i]; + _widgets[i] = 0; + } + + for (int i = 0; i < kTextDataMAX; ++i) { + delete _texts[i]; + _texts[i] = 0; + } + + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) + ImageMan.unregisterSurface(i->_key); + + ImageMan.remArchive(_themeFileName); + + _themeEval->reset(); + _themeOk = false; +} + +void ThemeRenderer::clearAll() { + if (!_initOk) + return; + + _system->clearOverlay(); + _system->grabOverlay((OverlayColor*)_screen->pixels, _screen->w); +} + +void ThemeRenderer::refresh() { + init(); + if (_enabled) { + _system->showOverlay(); + + if (_useCursor) { + CursorMan.replaceCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.replaceCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + } + } +} + +void ThemeRenderer::enable() { + init(); + resetDrawArea(); + + if (_useCursor) + setUpCursor(); + + _system->showOverlay(); + clearAll(); + _enabled = true; +} + +void ThemeRenderer::disable() { + _system->hideOverlay(); + + if (_useCursor) { + CursorMan.popCursorPalette(); + CursorMan.popCursor(); + } + + _enabled = false; +} + +template<typename PixelType> +void ThemeRenderer::screenInit(bool backBuffer) { + uint32 width = _system->getOverlayWidth(); + uint32 height = _system->getOverlayHeight(); + + if (backBuffer) { + freeBackbuffer(); + _backBuffer = new Surface; + _backBuffer->create(width, height, sizeof(PixelType)); + } + + freeScreen(); + _screen = new Surface; + _screen->create(width, height, sizeof(PixelType)); + _system->clearOverlay(); +} + +void ThemeRenderer::setGraphicsMode(GraphicsMode mode) { + switch (mode) { + case kGfxStandard16bit: + case kGfxAntialias16bit: + _bytesPerPixel = sizeof(uint16); + screenInit<uint16>(kEnableBackCaching); + break; + + default: + error("Invalid graphics mode"); + } + + freeRenderer(); + _vectorRenderer = createRenderer(mode); + _vectorRenderer->setSurface(_screen); +} + +void ThemeRenderer::addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step) { + DrawData id = getDrawDataId(drawDataId); + + assert(_widgets[id] != 0); + _widgets[id]->_steps.push_back(step); +} + +bool ThemeRenderer::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) { + DrawData id = getDrawDataId(drawDataId); + TextData textId = getTextDataId(textDataId); + + if (id == -1 || textId == -1 || !_widgets[id]) + return false; + + _widgets[id]->_textDataId = textId; + _widgets[id]->_textAlignH = alignH; + _widgets[id]->_textAlignV = alignV; + + return true; +} + +bool ThemeRenderer::addFont(const Common::String &fontId, const Common::String &file, int r, int g, int b) { + TextData textId = getTextDataId(fontId); + + if (textId == -1) + return false; + + if (_texts[textId] != 0) + delete _texts[textId]; + + _texts[textId] = new TextDrawData; + + if (file == "default") { + _texts[textId]->_fontPtr = _font; + } else { + _texts[textId]->_fontPtr = FontMan.getFontByName(file); + + if (!_texts[textId]->_fontPtr) { + _texts[textId]->_fontPtr = loadFont(file.c_str()); + + if (!_texts[textId]->_fontPtr) + error("Couldn't load %s font '%s'", fontId.c_str(), file.c_str()); + + FontMan.assignFontToName(file, _texts[textId]->_fontPtr); + } + } + + _texts[textId]->_color.r = r; + _texts[textId]->_color.g = g; + _texts[textId]->_color.b = b; + return true; + +} + +bool ThemeRenderer::addBitmap(const Common::String &filename) { + if (_bitmaps.contains(filename)) { + ImageMan.unregisterSurface(filename); + } + + ImageMan.registerSurface(filename, 0); + _bitmaps[filename] = ImageMan.getSurface(filename); + + return _bitmaps[filename] != 0; +} + +bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { + DrawData data_id = getDrawDataId(data); + + if (data_id == -1) + return false; + + if (_widgets[data_id] != 0) + delete _widgets[data_id]; + + _widgets[data_id] = new WidgetDrawData; + _widgets[data_id]->_cached = cached; + _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; + _widgets[data_id]->_surfaceCache = 0; + _widgets[data_id]->_textDataId = -1; + + return true; +} + +bool ThemeRenderer::loadTheme(Common::String fileName) { + unloadTheme(); + + if (fileName != "builtin") { + if (ConfMan.hasKey("themepath")) + Common::File::addDefaultDirectory(ConfMan.get("themepath")); + +#ifdef DATA_PATH + Common::File::addDefaultDirectoryRecursive(DATA_PATH); +#endif + if (ConfMan.hasKey("extrapath")) + Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + + ImageMan.addArchive(fileName); + } + + if (fileName == "builtin") { + if (!loadDefaultXML()) + error("Could not load default embeded theme"); + } + else if (!loadThemeXML(fileName)) { + warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str()); + + if (!loadDefaultXML()) // if we can't load the embeded theme, this is a complete failure + error("Could not load default embeded theme"); + } + + for (int i = 0; i < kDrawDataMAX; ++i) { + if (_widgets[i] == 0) { + warning("Missing data asset: '%s'", kDrawDataDefaults[i].name); + } else { + calcBackgroundOffset((DrawData)i); + + // TODO: draw the cached widget to the cache surface + if (_widgets[i]->_cached) {} + } + } + + _themeOk = true; + return true; +} + +bool ThemeRenderer::loadDefaultXML() { + + // The default XML theme is included on runtime from a pregenerated + // file inside the themes directory. + // Use the Python script "makedeftheme.py" to convert a normal XML theme + // into the "default.inc" file, which is ready to be included in the code. + +#ifdef GUI_ENABLE_BUILTIN_THEME + const char *defaultXML = +#include "themes/default.inc" + ; + + if (!parser()->loadBuffer((const byte*)defaultXML, strlen(defaultXML), false)) + return false; + + _themeName = "ScummVM Classic Theme (Builtin Version)"; + _themeFileName = "builtin"; + + return parser()->parse(); +#else + warning("The built-in theme is not enabled in the current build. Please load an external theme"); + return false; +#endif +} + +bool ThemeRenderer::loadThemeXML(Common::String themeName) { + assert(_parser); + _themeName.clear(); + + char fileNameBuffer[32]; + int parseCount = 0; + +#ifdef USE_ZLIB + unzFile zipFile = unzOpen(themeName.c_str()); + + if (zipFile && unzGoToFirstFile(zipFile) == UNZ_OK) { + while (true) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, fileNameBuffer, 32, NULL, 0, NULL, 0); + + if (matchString(fileNameBuffer, "*.stx") || !strcmp(fileNameBuffer, "THEMERC")) { + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + + Common::MemoryReadStream *stream = new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, true); + + if (!strcmp(fileNameBuffer, "THEMERC")) { + char stxHeader[128]; + stream->readLine(stxHeader, 128); + + if (!themeConfigParseHeader(stxHeader, _themeName)) + error("Corrupted 'THEMERC' file"); + + delete stream; + + } else { + parseCount++; + + if (parser()->loadStream(stream) == false || parser()->parse() == false) { + warning("Failed to load stream for zipped file '%s'", fileNameBuffer); + unzClose(zipFile); + return false; + } + } + } + + unzCloseCurrentFile(zipFile); + + if (unzGoToNextFile(zipFile) != UNZ_OK) + break; + } + } else { +#endif + FilesystemNode node(themeName); + if (node.exists() && node.isReadable() && node.isDirectory()) { + + FSList fslist; + if (!node.getChildren(fslist, FilesystemNode::kListFilesOnly)) + return false; + + for (FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) { + if (i->getName().hasSuffix(".stx")) { + + } else if (i->getName() == "THEMERC") { + + } + + } + + } +#ifdef USE_ZLIB + } + + unzClose(zipFile); + +#endif + + + return (parseCount > 0 && _themeName.empty() == false); +} + +bool ThemeRenderer::isWidgetCached(DrawData type, const Common::Rect &r) { + return _widgets[type] && _widgets[type]->_cached && + _widgets[type]->_surfaceCache->w == r.width() && + _widgets[type]->_surfaceCache->h == r.height(); +} + +void ThemeRenderer::drawCached(DrawData type, const Common::Rect &r) { + assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); + _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); +} + +void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) { + if (_widgets[type] == 0) + return; + + DrawQueue q; + q.type = type; + q.area = r; + q.area.clip(_screen->w, _screen->h); + q.dynData = dynamic; + + if (_buffering) { + if (_widgets[type]->_buffer) { + _bufferQueue.push_back(q); + } else { + if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type) + queueDD(kDrawDataDefaults[type].parent, r); + + _screenQueue.push_back(q); + } + } else { + drawDD(q, !_widgets[type]->_buffer, _widgets[type]->_buffer); + } +} + +void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, + bool ellipsis, TextAlign alignH, TextAlignVertical alignV, int deltax) { + + if (_texts[type] == 0) + return; + + DrawQueueText q; + q.type = type; + q.area = r; + q.area.clip(_screen->w, _screen->h); + q.text = text; + q.alignH = alignH; + q.alignV = alignV; + q.restoreBg = restoreBg; + q.deltax = deltax; + q.ellipsis = ellipsis; + + if (_buffering) { + _textQueue.push_back(q); + } else { + drawDDText(q); + } +} + +void ThemeRenderer::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &area, bool alpha) { + BitmapQueue q; + q.bitmap = bitmap; + q.area = area; + q.alpha = alpha; + + if (_buffering) { + _bitmapQueue.push_back(q); + } else { + drawBitmap(q); + } +} + +void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) { + Common::Rect extendedRect = q.area; + extendedRect.grow(kDirtyRectangleThreshold + _widgets[q.type]->_backgroundOffset); +// extendedRect.right += _widgets[q.type]->_backgroundOffset; +// extendedRect.bottom += _widgets[q.type]->_backgroundOffset; + + if (restore) + restoreBackground(extendedRect); + + if (draw) { + if (isWidgetCached(q.type, q.area)) { + drawCached(q.type, q.area); + } else { + for (Common::List<Graphics::DrawStep>::const_iterator step = _widgets[q.type]->_steps.begin(); + step != _widgets[q.type]->_steps.end(); ++step) + _vectorRenderer->drawStep(q.area, *step, q.dynData); + } + } + + addDirtyRect(extendedRect); +} + +void ThemeRenderer::drawDDText(const DrawQueueText &q) { + if (q.restoreBg) + restoreBackground(q.area); + + _vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b); + _vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV, q.deltax, q.ellipsis); + addDirtyRect(q.area); +} + +void ThemeRenderer::drawBitmap(const BitmapQueue &q) { + + if (q.alpha) + _vectorRenderer->blitAlphaBitmap(q.bitmap, q.area); + else + _vectorRenderer->blitSubSurface(q.bitmap, q.area); + + addDirtyRect(q.area); +} + +void ThemeRenderer::calcBackgroundOffset(DrawData type) { + uint maxShadow = 0; + for (Common::List<Graphics::DrawStep>::const_iterator step = _widgets[type]->_steps.begin(); + step != _widgets[type]->_steps.end(); ++step) { + if ((step->autoWidth || step->autoHeight) && step->shadow > maxShadow) + maxShadow = step->shadow; + + if (step->drawingCall == &Graphics::VectorRenderer::drawCallback_BEVELSQ && step->bevel > maxShadow) + maxShadow = step->bevel; + } + + _widgets[type]->_backgroundOffset = maxShadow; +} + +void ThemeRenderer::restoreBackground(Common::Rect r, bool special) { + r.clip(_screen->w, _screen->h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( + _vectorRenderer->blitSurface(_backBuffer, r); +} + +void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, uint16 hints) { + if (!ready()) + return; + + DrawData dd = kDDButtonIdle; + + if (state == kStateEnabled) + dd = kDDButtonIdle; + else if (state == kStateHighlight) + dd = kDDButtonHover; + else if (state == kStateDisabled) + dd = kDDButtonDisabled; + + queueDD(dd, r); + queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); +} + +void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { + if (!ready()) + return; + + queueDD(kDDSeparator, r); +} + +void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { + if (!ready()) + return; + + Common::Rect r2 = r; + DrawData dd = kDDCheckboxDefault; + + if (checked) + dd = kDDCheckboxSelected; + + if (state == kStateDisabled) + dd = kDDCheckboxDisabled; + + TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd); + const int checkBoxSize = MIN((int)r.height(), getFontHeight()); + + r2.bottom = r2.top + checkBoxSize; + r2.right = r2.left + checkBoxSize; + + queueDD(dd, r2); + + r2.left = r2.right + checkBoxSize; + r2.right = r.right; + + queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); +} + +void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { + if (!ready()) + return; + + DrawData dd = kDDSliderFull; + + if (state == kStateHighlight) + dd = kDDSliderHover; + else if (state == kStateDisabled) + dd = kDDSliderDisabled; + + Common::Rect r2 = r; + r2.setWidth(MIN((int16)width, r.width())); +// r2.top++; r2.bottom--; r2.left++; r2.right--; + + drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled); + + if (width > r.width() * 5 / 100) + queueDD(dd, r2); +} + +void ThemeRenderer::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) { + if (!ready()) + return; + + queueDD(kDDScrollbarBase, r); + + Common::Rect r2 = r; + const int buttonExtra = (r.width() * 120) / 100; + + r2.bottom = r2.top + buttonExtra; + queueDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp); + + r2.translate(0, r.height() - r2.height()); + queueDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown); + + r2 = r; + r2.left += 1; + r2.right -= 1; + r2.top += sliderY; + r2.bottom = r2.top + sliderHeight - 1; + + r2.top += r.width() / 5; + r2.bottom -= r.width() / 5; + queueDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2); +} + +void ThemeRenderer::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) { + if (!ready()) + return; + + switch (bgtype) { + case kDialogBackgroundMain: + queueDD(kDDMainDialogBackground, r); + break; + + case kDialogBackgroundSpecial: + queueDD(kDDSpecialColorBackground, r); + break; + + case kDialogBackgroundPlain: + queueDD(kDDPlainColorBackground, r); + break; + + case kDialogBackgroundDefault: + queueDD(kDDDefaultBackground, r); + break; + } +} + +void ThemeRenderer::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) { + if (!ready()) + return; + + if (erase) { + restoreBackground(r); + addDirtyRect(r); + } else + queueDD(kDDCaret, r); +} + +void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, TextAlign align) { + if (!ready()) + return; + + DrawData dd = (state == kStateHighlight) ? kDDPopUpHover : kDDPopUpIdle; + + queueDD(dd, r); + + if (!sel.empty()) { + Common::Rect text(r.left, r.top, r.right - 16, r.bottom); + queueDDText(getTextData(dd), text, sel, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV); + } +} + +void ThemeRenderer::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) { + if (!ready()) + return; + + queueBitmap(&surface, r, themeTrans); +} + +void ThemeRenderer::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) { + if (!ready()) + return; + + switch (background) { + case kWidgetBackgroundBorderSmall: + queueDD(kDDWidgetBackgroundSmall, r); + break; + + case kWidgetBackgroundEditText: + queueDD(kDDWidgetBackgroundEditText, r); + break; + + case kWidgetBackgroundSlider: + queueDD(kDDWidgetBackgroundSlider, r); + break; + + default: + queueDD(kDDWidgetBackgroundDefault, r); + break; + } +} + +void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) { + if (!ready()) + return; + + const int tabOffset = 2; + tabWidth -= tabOffset; + + queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight)); + + for (int i = 0; i < (int)tabs.size(); ++i) { + if (i == active) + continue; + + Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + queueDD(kDDTabInactive, tabRect); + queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV); + } + + if (active >= 0) { + Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); + const uint16 tabLeft = active * (tabWidth + tabOffset); + const uint16 tabRight = MAX(r.right - tabRect.right, 0); + queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); + queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV); + } +} + +void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { + if (!ready()) + return; + + if (inverted) { + queueDD(kDDTextSelectionBackground, r); + queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax); + return; + } + + switch (font) { + case kFontStyleNormal: + queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + default: + break; + } + + switch (state) { + case kStateDisabled: + queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + case kStateHighlight: + queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + + case kStateEnabled: + queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax); + return; + } +} + +void ThemeRenderer::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) { + if (!ready()) + return; + + restoreBackground(r); + font->drawChar(_screen, ch, r.left, r.top, 0); + addDirtyRect(r); +} + +void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { + _font->drawString(_screen, name, r.left, r.top, r.width(), 0xFFFF, Graphics::kTextAlignRight, 0, true); + _screen->hLine(r.left, r.top, r.right, 0xFFFF); + _screen->hLine(r.left, r.bottom, r.right, 0xFFFF); + _screen->vLine(r.left, r.top, r.bottom, 0xFFFF); + _screen->vLine(r.right, r.top, r.bottom, 0xFFFF); +} + +void ThemeRenderer::updateScreen() { + if (!_bufferQueue.empty()) { + _vectorRenderer->setSurface(_backBuffer); + + for (Common::List<DrawQueue>::const_iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) + drawDD(*q, true, false); + + _vectorRenderer->setSurface(_screen); + _vectorRenderer->blitSurface(_backBuffer, Common::Rect(0, 0, _screen->w, _screen->h)); + _bufferQueue.clear(); + } + + if (!_screenQueue.empty()) { + _vectorRenderer->disableShadows(); + for (Common::List<DrawQueue>::const_iterator q = _screenQueue.begin(); q != _screenQueue.end(); ++q) + drawDD(*q, true, false); + + _vectorRenderer->enableShadows(); + _screenQueue.clear(); + } + + if (!_bitmapQueue.empty()) { + for (Common::List<BitmapQueue>::const_iterator q = _bitmapQueue.begin(); q != _bitmapQueue.end(); ++q) + drawBitmap(*q); + + _bitmapQueue.clear(); + } + + if (!_textQueue.empty()) { + for (Common::List<DrawQueueText>::const_iterator q = _textQueue.begin(); q != _textQueue.end(); ++q) + drawDDText(*q); + + _textQueue.clear(); + } + + renderDirtyScreen(); + +// _vectorRenderer->fillSurface(); +// themeEval()->debugDraw(_screen, _font); +// _vectorRenderer->copyWholeFrame(_system); +} + +void ThemeRenderer::renderDirtyScreen() { + if (_dirtyScreen.empty()) + return; + + Common::List<Common::Rect>::const_iterator i, j; + for (i = _dirtyScreen.begin(); i != _dirtyScreen.end(); ++i) { + for (j = i; j != _dirtyScreen.end(); ++j) + if (j != i && i->contains(*j)) + j = _dirtyScreen.reverse_erase(j); + + _vectorRenderer->copyFrame(_system, *i); + } + + _dirtyScreen.clear(); +} + +void ThemeRenderer::openDialog(bool doBuffer, ShadingStyle style) { + if (doBuffer) + _buffering = true; + + if (style != kShadingNone) { + _vectorRenderer->applyScreenShading(style); + addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h)); + } + + _vectorRenderer->setSurface(_backBuffer); + _vectorRenderer->blitSurface(_screen, Common::Rect(0, 0, _screen->w, _screen->h)); + _vectorRenderer->setSurface(_screen); +} + +void ThemeRenderer::setUpCursor() { + CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + CursorMan.showMouse(true); +} + +bool ThemeRenderer::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { + if (!_system->hasFeature(OSystem::kFeatureCursorHasPalette)) + return false; + + const Surface *cursor = _bitmaps[filename]; + + if (!cursor) + return false; + + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; + _cursorTargetScale = scale; + + _cursorWidth = cursor->w; + _cursorHeight = cursor->h; + + uint colorsFound = 0; + const OverlayColor *src = (const OverlayColor*)cursor->pixels; + + byte *table = new byte[65536]; + assert(table); + memset(table, 0, sizeof(byte)*65536); + + byte r, g, b; + + uint16 transparency = RGBToColor<ColorMasks<565> >(255, 0, 255); + + delete[] _cursor; + + _cursor = new byte[_cursorWidth * _cursorHeight]; + assert(_cursor); + memset(_cursor, 255, sizeof(byte)*_cursorWidth*_cursorHeight); + + for (uint y = 0; y < _cursorHeight; ++y) { + for (uint x = 0; x < _cursorWidth; ++x) { + _system->colorToRGB(src[x], r, g, b); + uint16 col = RGBToColor<ColorMasks<565> >(r, g, b); + if (!table[col] && col != transparency) { + table[col] = colorsFound++; + + uint index = table[col]; + _cursorPal[index * 4 + 0] = r; + _cursorPal[index * 4 + 1] = g; + _cursorPal[index * 4 + 2] = b; + _cursorPal[index * 4 + 3] = 0xFF; + + if (colorsFound > MAX_CURS_COLORS) { + warning("Cursor contains too much colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS); + return false; + } + } + + if (col != transparency) { + uint index = table[col]; + _cursor[y * _cursorWidth + x] = index; + } + } + src += _cursorWidth; + } + + _useCursor = true; + delete[] table; + + return true; +} + +} // end of namespace GUI. diff --git a/gui/ThemeRenderer.h b/gui/ThemeRenderer.h new file mode 100644 index 0000000000..e8f6d76ee2 --- /dev/null +++ b/gui/ThemeRenderer.h @@ -0,0 +1,732 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef INTERFACE_MANAGER_H +#define INTERFACE_MANAGER_H + +#include "common/scummsys.h" +#include "graphics/surface.h" +#include "common/system.h" + +#include "graphics/surface.h" +#include "graphics/fontman.h" + +#include "gui/dialog.h" +#include "gui/ThemeParser.h" +#include "graphics/VectorRenderer.h" +#include "gui/ThemeEval.h" + + +namespace GUI { + +struct WidgetDrawData; +struct DrawDataInfo; +class ThemeEval; + +struct TextDrawData { + const Graphics::Font *_fontPtr; + + struct { + uint8 r, g, b; + } _color; +}; + +struct WidgetDrawData { + /** List of all the steps needed to draw this widget */ + Common::List<Graphics::DrawStep> _steps; + + int _textDataId; + GUI::Theme::TextAlign _textAlignH; + GUI::Theme::TextAlignVertical _textAlignV; + + /** Extra space that the widget occupies when it's drawn. + E.g. when taking into account rounded corners, drop shadows, etc + Used when restoring the widget background */ + uint16 _backgroundOffset; + + /** Sets whether the widget is cached beforehand. */ + bool _cached; + bool _buffer; + + /** Texture where the cached widget is stored. */ + Graphics::Surface *_surfaceCache; + + ~WidgetDrawData() { + _steps.clear(); + + if (_surfaceCache) { + _surfaceCache->free(); + delete _surfaceCache; + } + } +}; + +class ThemeRenderer : public Theme { + +protected: + typedef Common::String String; + typedef GUI::Dialog Dialog; + typedef Common::HashMap<Common::String, Graphics::Surface*> ImagesMap; + + friend class GUI::Dialog; + friend class GUI::GuiObject; + + /** Constant value to expand dirty rectangles, to make sure they are fully copied */ + static const int kDirtyRectangleThreshold = 1; + + /** Sets whether backcaching is enabled */ + static const bool kEnableBackCaching = true; + + /** + * DrawData sets enumeration. + * Each DD set corresponds to the actual looks + * of a widget in a given state. + */ + enum DrawData { + kDDMainDialogBackground, + kDDSpecialColorBackground, + kDDPlainColorBackground, + kDDDefaultBackground, + kDDTextSelectionBackground, + + kDDWidgetBackgroundDefault, + kDDWidgetBackgroundSmall, + kDDWidgetBackgroundEditText, + kDDWidgetBackgroundSlider, + + kDDButtonIdle, + kDDButtonHover, + kDDButtonDisabled, + + kDDSliderFull, + kDDSliderHover, + kDDSliderDisabled, + + kDDCheckboxDefault, + kDDCheckboxDisabled, + kDDCheckboxSelected, + + kDDTabActive, + kDDTabInactive, + kDDTabBackground, + + kDDScrollbarBase, + kDDScrollbarButtonIdle, + kDDScrollbarButtonHover, + kDDScrollbarHandleIdle, + kDDScrollbarHandleHover, + + kDDPopUpIdle, + kDDPopUpHover, + + kDDCaret, + kDDSeparator, + kDrawDataMAX, + kDDNone = -1 + }; + + /** + * Default values for each DrawData item. + * @see kDrawDataDefaults[] for implementation. + */ + static const struct DrawDataInfo { + DrawData id; /** The actual ID of the DrawData item. */ + const char *name; /** The name of the DrawData item as it appears in the Theme Description files */ + bool buffer; /** Sets whether this item is buffered on the backbuffer or drawn directly to the screen. */ + DrawData parent; /** Parent DrawData item, for items that overlay. E.g. kButtonIdle -> kButtonHover */ + } kDrawDataDefaults[]; + + /** + * Queue Node for the drawing queue. + * Specifies the exact drawing to be done when processing + * the drawing queues. + */ + struct DrawQueue { + DrawData type; /** DrawData item to draw. */ + Common::Rect area; /** Place on screen to draw it. */ + uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/ + }; + + enum TextData { + kTextDataNone = -1, + kTextDataDefault = 0, + kTextDataHover, + kTextDataDisabled, + kTextDataInverted, + kTextDataButton, + kTextDataButtonHover, + kTextDataNormalFont, + kTextDataMAX + }; + + static const struct TextDataInfo { + TextData id; + const char *name; + } kTextDataDefaults[]; + + struct DrawQueueText { + TextData type; + Common::Rect area; + Common::String text; + + GUI::Theme::TextAlign alignH; + GUI::Theme::TextAlignVertical alignV; + bool ellipsis; + bool restoreBg; + int deltax; + }; + + struct BitmapQueue { + const Graphics::Surface *bitmap; + Common::Rect area; + bool alpha; + }; + +public: + /** Graphics mode enumeration. + * Each item represents a set of BPP and Renderer modes for a given + * surface. + */ + enum GraphicsMode { + kGfxDisabled = 0, /** No GFX */ + kGfxStandard16bit, /** 2BPP with the standard (aliased) renderer. */ + kGfxAntialias16bit, /** 2BPP with the optimized AA renderer. */ + kGfxMAX + }; + + static const char *rendererModeLabels[]; + + /** Default constructor */ + ThemeRenderer(Common::String fileName, GraphicsMode mode); + + /** Default destructor */ + ~ThemeRenderer(); + + GUI::ThemeEval *themeEval() { return _themeEval; } + + /** + * VIRTUAL METHODS + * This is the implementation of the GUI::Theme API to allow + * the ThemeRenderer class to be plugged in as any other GUI + * theme. In fact, the renderer works like any other GUI theme, + * but supports extensive customization of the drawn widgets. + */ + bool init(); + void deinit(); + void clearAll(); + + void refresh(); + void enable(); + void disable(); + + /** + * Implementation of the GUI::Theme API. Called when a + * new dialog is opened. Note that the boolean parameter + * meaning has been changed. + * + * @param enableBuffering If set to true, buffering is enabled for + * drawing this dialog, and will continue enabled + * until disabled. + */ + void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); + + /** + * The updateScreen() method is called every frame. + * It processes all the drawing queues and then copies dirty rects + * in the current Screen surface to the overlay. + */ + void updateScreen(); + + /** Since the rendering pipeline changes, closing all dialogs causes no effect + TODO: remove this from the original GUI::Theme API */ + void closeAllDialogs() {} + + /** Drawing area has been removed: it was too hackish. A workaround is on the works. + TODO: finish the workaround for the credits dialog + TODO: remove this from the original GUI::Theme API */ + void resetDrawArea() {} + + + /** + * FONT MANAGEMENT METHODS + */ + + TextData fontStyleToData(FontStyle font) const { + switch (font) { + case kFontStyleNormal: + return kTextDataNormalFont; + + default: + return kTextDataDefault; + } + } + + const Graphics::Font *getFont(FontStyle font) const { return _texts[fontStyleToData(font)]->_fontPtr; } + + int getFontHeight(FontStyle font = kFontStyleBold) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getFontHeight() : 0; + } + + int getStringWidth(const Common::String &str, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getStringWidth(str) : 0; + } + + int getCharWidth(byte c, FontStyle font) const { + return ready() ? _texts[fontStyleToData(font)]->_fontPtr->getCharWidth(c) : 0; + } + + + /** + * WIDGET DRAWING METHODS + */ + void drawWidgetBackground(const Common::Rect &r, uint16 hints, + WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled); + + void drawButton(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state = kStateEnabled, uint16 hints = 0); + + void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, + WidgetStateInfo state = kStateEnabled, int alpha = 256, bool themeTrans = false); + + void drawSlider(const Common::Rect &r, int width, + WidgetStateInfo state = kStateEnabled); + + void drawCheckbox(const Common::Rect &r, const Common::String &str, + bool checked, WidgetStateInfo state = kStateEnabled); + + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, + const Common::Array<Common::String> &tabs, int active, uint16 hints, + int titleVPad, WidgetStateInfo state = kStateEnabled); + + void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, + ScrollbarState, WidgetStateInfo state = kStateEnabled); + + void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, + int deltax, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignLeft); + + void drawCaret(const Common::Rect &r, bool erase, + WidgetStateInfo state = kStateEnabled); + + void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled); + + void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state); + + void drawText(const Common::Rect &r, const Common::String &str, + WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font); + + void drawChar(const Common::Rect &r, byte ch, + const Graphics::Font *font, WidgetStateInfo state); + + /** + * Actual implementation of a Dirty Rect drawing routine. + * Dirty rectangles are queued on a list and are later merged/calculated + * before the actual drawing. + * + * @param r Area of the dirty rect. + * @param backup Deprecated. + * @param special Deprecated. + */ + bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { + _dirtyScreen.push_back(r); + return true; + } + + + /** + * Returns the DrawData enumeration value that represents the given string + * in the DrawDataDefaults enumeration. + * It's slow, but called sparsely. + * + * @returns The drawdata enum value, or -1 if not found. + * @param name The representing name, as found on Theme Description XML files. + * @see kDrawDataDefaults[] + */ + DrawData getDrawDataId(const Common::String &name) { + for (int i = 0; i < kDrawDataMAX; ++i) + if (name.compareToIgnoreCase(kDrawDataDefaults[i].name) == 0) + return kDrawDataDefaults[i].id; + + return kDDNone; + } + + TextData getTextDataId(const Common::String &name) { + for (int i = 0; i < kTextDataMAX; ++i) + if (name.compareToIgnoreCase(kTextDataDefaults[i].name) == 0) + return kTextDataDefaults[i].id; + + return kTextDataNone; + } + + /** + * Interface for ThemeParser class: Parsed DrawSteps are added via this function. + * There is no return type because DrawSteps can always be added, unless something + * goes horribly wrong. + * The specified step will be added to the Steps list of the given DrawData id. + * + * @param drawDataId The representing DrawData name, as found on Theme Description XML files. + * @param step The actual DrawStep struct to be added. + */ + void addDrawStep(const Common::String &drawDataId, Graphics::DrawStep step); + + /** + * Interfacefor the ThemeParser class: Parsed DrawData sets are added via this function. + * The goal of the function is to initialize each DrawData set before their DrawSteps can + * be added, hence this must be called for each DD set before addDrawStep() can be called + * for that given set. + * + * @param data The representing DrawData name, as found on Theme Description XML files. + * @param cached Whether this DD set will be cached beforehand. + */ + bool addDrawData(const Common::String &data, bool cached); + + + /** + * Interface for the ThemeParser class: Loads a font to use on the GUI from the given + * filename. + * + * @param fontName Identifier name for the font. + * @param file Name of the font file. + * @param r, g, b Color of the font. + */ + bool addFont(const Common::String &fontName, const Common::String &file, int r, int g, int b); + + + /** + * Interface for the ThemeParser class: Loads a bitmap file to use on the GUI. + * The filename is also used as its identifier. + * + * @param filename Name of the bitmap file. + */ + bool addBitmap(const Common::String &filename); + + /** + * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the + * new Font API is in place. + */ + bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV); + + /** Interface to the new Theme XML parser */ + ThemeParser *parser() { + return _parser; + } + + /** + * Returns if the Theme is ready to draw stuff on screen. + * Must be called instead of just checking _initOk, because + * this checks if the renderer is initialized AND if the theme + * is loaded. + */ + bool ready() const { + return _initOk && _themeOk; + } + + /** Custom implementation of the GUI::Theme API, changed to use the XML parser. */ + bool loadTheme(Common::String themeName); + + /** + * Changes the active graphics mode of the GUI; may be used to either + * initialize the GUI or to change the mode while the GUI is already running. + */ + void setGraphicsMode(GraphicsMode mode); + + + /** + * Finishes buffering: widgets from there one will be drawn straight on the screen + * without drawing queues. + */ + void finishBuffering() { _buffering = false; } + void startBuffering() { _buffering = true; } + + ThemeEval *evaluator() { return _themeEval; } + + bool supportsImages() const { return true; } + bool ownCursor() const { return _useCursor; } + + Graphics::Surface *getBitmap(const Common::String &name) { + return _bitmaps.contains(name) ? _bitmaps[name] : 0; + } + + const Graphics::Surface *getImageSurface(const kThemeImages n) const { + if (n == kImageLogo) + return _bitmaps.contains("logo.bmp") ? _bitmaps["logo.bmp"] : 0; + + return 0; + } + + /** + * Interface for the Theme Parser: Creates a new cursor by loading the given + * bitmap and sets it as the active cursor. + * + * @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); + +protected: + + const Common::String &getThemeName() const { return _themeName; } + const Common::String &getThemeFileName() const { return _themeFileName; } + int getThemeRenderer() const { return _graphicsMode; } + + /** + * Initializes the drawing screen surfaces, _screen and _backBuffer. + * If the surfaces already exist, they are cleared and re-initialized. + * + * @param backBuffer Sets whether the _backBuffer surface should be initialized. + * @template PixelType C type which specifies the size of each pixel. + * Defaults to uint16 (2 BPP for the surfaces) + */ + template<typename PixelType> void screenInit(bool backBuffer = true); + + /** + * Loads the given theme into the ThemeRenderer. + * Note that ThemeName is an identifier, not a filename. + * + * @param ThemeName Theme identifier. + * @returns True if the theme was succesfully loaded. + */ + bool loadThemeXML(Common::String themeName); + + /** + * Loads the default theme file (the embeded XML file found + * in ThemeDefaultXML.cpp). + * Called only when no other themes are available. + */ + bool loadDefaultXML(); + + /** + * Unloads the currently loaded theme so another one can + * be loaded. + */ + void unloadTheme(); + + /** + * Not implemented yet. + * TODO: reload themes, reload the renderer, recheck everything + */ + void screenChange() { + error("Screen Changes are not supported yet. Fix this!"); + } + + /** + * Actual Dirty Screen handling function. + * Handles all the dirty squares in the list, merges and optimizes + * them when possible and draws them to the screen. + * Called from updateScreen() + */ + void renderDirtyScreen(); + + /** + * Frees the vector renderer. + */ + void freeRenderer() { + delete _vectorRenderer; + _vectorRenderer = 0; + } + + /** + * Frees the Back buffer surface, only if it's available. + */ + void freeBackbuffer() { + if (_backBuffer != 0) { + _backBuffer->free(); + delete _backBuffer; + _backBuffer = 0; + } + } + + /** + * Frees the main screen drawing surface, only if it's available. + */ + void freeScreen() { + if (_screen != 0) { + _screen->free(); + delete _screen; + _screen = 0; + } + } + + TextData getTextData(DrawData ddId) { + return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone; + } + + /** + * Checks if a given DrawData set for a widget has been cached beforehand + * and is ready to be blit into the screen. + * + * @param type DrawData type of the widget. + * @param r Size of the widget which is expected to be cached. + */ + bool isWidgetCached(DrawData type, const Common::Rect &r); + + /** + * Draws a cached widget directly on the screen. Currently deprecated. + * + * @param type DrawData type of the widget. + * @param r Position on screen to draw the widget. + */ + void drawCached(DrawData type, const Common::Rect &r); + + /** + * Calculates the background threshold offset of a given DrawData item. + * After fully loading all DrawSteps of a DrawData item, this function must be + * called in order to calculate if such draw steps would be drawn outside of + * the actual widget drawing zone (e.g. shadows). If this is the case, a constant + * value will be added when restoring the background of the widget. + * + * @param type DrawData type of the widget. + */ + void calcBackgroundOffset(DrawData type); + + /** + * Draws a DrawQueue item (which contains DrawData information and a screen + * position) into the screen. + * + * This is the only way the Theme has to drawn on the screen. + * + * @param draw Sets if the DrawData info will be actually drawn. + * @param restore Sets if the background behind the widget will be restored before drawing. + */ + inline void drawDD(const DrawQueue &q, bool draw = true, bool restore = false); + inline void drawDDText(const DrawQueueText &q); + inline void drawBitmap(const BitmapQueue &q); + + /** + * Generates a DrawQueue item and enqueues it so it's drawn to the screen + * when the drawing queue is processed. + * + * If Buffering is enabled, the DrawQueue item will be automatically placed + * on its corresponding queue. + * If Buffering is disabled, the DrawQueue item will be processed immediately + * and drawn to the screen. + * + * This function is called from all the Widget Drawing methods. + */ + inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); + inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg, + bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); + inline void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); + + /** + * DEBUG: Draws a white square around the given position and writes the given next to it. + */ + inline void debugWidgetPosition(const char *name, const Common::Rect &r); + + + /** + * Wrapper for restoring data from the Back Buffer to the screen. + * The actual processing is done in the VectorRenderer. + * + * @param r Area to restore. + * @param special Deprecated. + */ + void restoreBackground(Common::Rect r, bool special = false); + + + /** + * Default values from GUI::Theme + */ + int getTabSpacing() const { return 0; } + int getTabPadding() const { return 3; } + + OSystem *_system; /** Global system object. */ + + /** Vector Renderer object, does the actual drawing on screen */ + Graphics::VectorRenderer *_vectorRenderer; + + /** XML Parser, does the Theme parsing instead of the default parser */ + GUI::ThemeParser *_parser; + + /** Theme evaluator (changed from GUI::Eval to add functionality) */ + GUI::ThemeEval *_themeEval; + + /** Main screen surface. This is blitted straight into the overlay. */ + Graphics::Surface *_screen; + + /** Backbuffer surface. Stores previous states of the screen to blit back */ + Graphics::Surface *_backBuffer; + + /** Sets whether the current drawing is being buffered (stored for later + processing) or drawn directly to the screen. */ + bool _buffering; + + /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ + int _bytesPerPixel; + + /** Current graphics mode */ + GraphicsMode _graphicsMode; + + /** Font info. */ + Common::String _fontName; + const Graphics::Font *_font; + + /** Array of all the DrawData elements than can be drawn to the screen. + Must be full so the renderer can work. */ + WidgetDrawData *_widgets[kDrawDataMAX]; + + /** Array of all the text fonts that can be drawn. */ + TextDrawData *_texts[kTextDataMAX]; + + ImagesMap _bitmaps; + + /** List of all the dirty screens that must be blitted to the overlay. */ + Common::List<Common::Rect> _dirtyScreen; + + /** Queue with all the drawing that must be done to the Back Buffer */ + Common::List<DrawQueue> _bufferQueue; + + /** Queue with all the drawing that must be done to the screen */ + Common::List<DrawQueue> _screenQueue; + + /** Queue with all the text drawing that must be done to the screen */ + Common::List<DrawQueueText> _textQueue; + + Common::List<BitmapQueue> _bitmapQueue; + + bool _initOk; /** Class and renderer properly initialized */ + bool _themeOk; /** Theme data successfully loaded. */ + bool _enabled; /** Whether the Theme is currently shown on the overlay */ + + Common::String _themeName; /** Name of the currently loaded theme */ + Common::String _themeFileName; + + /** Custom Cursor Management */ + void setUpCursor(); + + bool _useCursor; + int _cursorHotspotX, _cursorHotspotY; + int _cursorTargetScale; +#define MAX_CURS_COLORS 255 + byte *_cursor; + bool _needPaletteUpdates; + uint _cursorWidth, _cursorHeight; + byte _cursorPal[4*MAX_CURS_COLORS]; +}; + +} // end of namespace GUI. + +#endif diff --git a/gui/about.cpp b/gui/about.cpp index 758f3ee6a7..eeb2533e0d 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -29,10 +29,11 @@ #include "common/system.h" #include "common/util.h" #include "gui/about.h" -#include "gui/eval.h" #include "gui/newgui.h" #include "gui/widget.h" +#include "gui/ThemeEval.h" + namespace GUI { enum { @@ -85,9 +86,9 @@ AboutDialog::AboutDialog() const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - _xOff = g_gui.evaluator()->getVar("aboutXOff"); - _yOff = g_gui.evaluator()->getVar("aboutYOff"); - int outerBorder = g_gui.evaluator()->getVar("aboutOuterBorder"); + _xOff = g_gui.xmlEval()->getVar("Globals.About.XOffset", 5); + _yOff = g_gui.xmlEval()->getVar("Globals.About.YOffset", 5); + int outerBorder = g_gui.xmlEval()->getVar("Globals.About.OuterBorder"); _w = screenW - 2 * outerBorder; _h = screenH - 2 * outerBorder; @@ -203,7 +204,7 @@ void AboutDialog::close() { } void AboutDialog::drawDialog() { - g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h)); +// g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h)); Dialog::drawDialog(); // Draw text @@ -265,10 +266,10 @@ void AboutDialog::drawDialog() { while (*str && *str == ' ') str++; - g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, false, 0, false); + if (y > _y && y + g_gui.theme()->getFontHeight() < _y + _h) + g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, false, 0, false); y += _lineHeight; } - g_gui.theme()->resetDrawArea(); } void AboutDialog::handleTickle() { @@ -316,9 +317,9 @@ void AboutDialog::reflowLayout() { const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - _xOff = g_gui.evaluator()->getVar("aboutXOff"); - _yOff = g_gui.evaluator()->getVar("aboutYOff"); - int outerBorder = g_gui.evaluator()->getVar("aboutOuterBorder"); + _xOff = g_gui.xmlEval()->getVar("Globals.About.XOffset", 5); + _yOff = g_gui.xmlEval()->getVar("Globals.About.YOffset", 5); + int outerBorder = g_gui.xmlEval()->getVar("Globals.About.OuterBorder"); _w = screenW - 2 * outerBorder; _h = screenH - 2 * outerBorder; diff --git a/gui/browser.cpp b/gui/browser.cpp index 41d3d15bb6..a5c71e6987 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -133,29 +133,29 @@ int BrowserDialog::runModal() { */ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser) - : Dialog("browser") { + : Dialog("Browser") { _isDirBrowser = dirBrowser; _fileList = NULL; _currentPath = NULL; // Headline - TODO: should be customizable during creation time - new StaticTextWidget(this, "browser_headline", title); + new StaticTextWidget(this, "Browser.Headline", title); // Current path - TODO: handle long paths ? - _currentPath = new StaticTextWidget(this, "browser_path", "DUMMY"); + _currentPath = new StaticTextWidget(this, "Browser.Path", "DUMMY"); // Add file list - _fileList = new ListWidget(this, "browser_list"); + _fileList = new ListWidget(this, "Browser.List"); _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); - _fileList->setHints(THEME_HINT_PLAIN_COLOR); + _backgroundType = GUI::Theme::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "browser_up", "Go up", kGoUpCmd, 0); - new ButtonWidget(this, "browser_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "browser_choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Up", "Go up", kGoUpCmd, 0); + new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); } void BrowserDialog::open() { diff --git a/gui/console.cpp b/gui/console.cpp index 728724d76f..58c7404a19 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -24,7 +24,7 @@ #include "gui/console.h" #include "gui/ScrollBarWidget.h" -#include "gui/eval.h" +#include "gui/ThemeEval.h" #include "engines/engine.h" #include "base/version.h" @@ -97,17 +97,14 @@ ConsoleDialog::ConsoleDialog(float widthPercent, float heightPercent) void ConsoleDialog::init() { const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); - int f = g_gui.evaluator()->getVar("Console.font"); - if (f == EVAL_UNDEF_VAR) - _font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont); - else - _font = g_gui.theme()->getFont((Theme::FontStyle)f); + _font = FontMan.getFontByUsage((Graphics::FontManager::FontUsage) + g_gui.xmlEval()->getVar("Console.Font", Graphics::FontManager::kConsoleFont)); - _leftPadding = g_gui.evaluator()->getVar("Console.leftPadding", 0); - _rightPadding = g_gui.evaluator()->getVar("Console.rightPadding", 0); - _topPadding = g_gui.evaluator()->getVar("Console.topPadding", 0); - _bottomPadding = g_gui.evaluator()->getVar("Console.bottomPadding", 0); + _leftPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Left", 0); + _rightPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Right", 0); + _topPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Top", 0); + _bottomPadding = g_gui.xmlEval()->getVar("Globals.Console.Padding.Bottom", 0); // Calculate the real width/height (rounded to char/line multiples) _w = (uint16)(_widthPercent * screenW); @@ -122,8 +119,6 @@ void ConsoleDialog::init() { scrollBarWidth = kNormalScrollBarWidth; _scrollBar->resize(_w - scrollBarWidth - 1, 0, scrollBarWidth, _h); - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; - _pageWidth = (_w - scrollBarWidth - 2 - _leftPadding - _topPadding - scrollBarWidth) / kConsoleCharWidth; _linesPerPage = (_h - 2 - _topPadding - _bottomPadding) / kConsoleLineHeight; _linesInBuffer = kBufferSize / kCharsPerLine; @@ -154,8 +149,6 @@ void ConsoleDialog::open() { if (_w != w || _h != h) init(); - _drawingHints |= THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; - _y = -_h; _slideTime = g_system->getMillis(); _slideMode = kDownSlideMode; @@ -172,7 +165,7 @@ void ConsoleDialog::close() { } void ConsoleDialog::drawDialog() { - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _drawingHints); + g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); // FIXME: for the old theme the frame around the console vanishes // when any action is processed if we enable this // _drawingHints &= ~THEME_HINT_FIRST_DRAW; @@ -231,7 +224,6 @@ void ConsoleDialog::handleTickle() { // Perform the "slide animation". if (_slideMode != kNoSlideMode) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; const float tmp = (float)(g_system->getMillis() - _slideTime) / kConsoleSlideDownDuration; if (_slideMode == kUpSlideMode) { _y = (int)(_h * (0.0 - tmp)); diff --git a/gui/dialog.cpp b/gui/dialog.cpp index ef396301be..3b302ff36a 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -42,18 +42,15 @@ namespace GUI { * ... */ -Dialog::Dialog(int x, int y, int w, int h, bool dimsInactive_) +Dialog::Dialog(int x, int y, int w, int h) : GuiObject(x, y, w, h), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), _drawingHints(0), - _dimsInactive(dimsInactive_) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; -} + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _backgroundType(GUI::Theme::kDialogBackgroundDefault) {} -Dialog::Dialog(const Common::String &name, bool dimsInactive_) +Dialog::Dialog(const Common::String &name) : GuiObject(name), - _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), _drawingHints(0), - _dimsInactive(dimsInactive_) { - _drawingHints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; + _mouseWidget(0), _focusedWidget(0), _dragWidget(0), _visible(false), + _backgroundType(GUI::Theme::kDialogBackgroundDefault) { // It may happen that we have 3x scaler in launcher (960xY) and then 640x480 // game will be forced to 1x. At this stage GUI will not be aware of @@ -113,11 +110,9 @@ void Dialog::reflowLayout() { // changed, so any cached image may be invalid. The subsequent redraw // should be treated as the very first draw. - _drawingHints |= THEME_HINT_FIRST_DRAW; Widget *w = _firstWidget; while (w) { w->reflowLayout(); - w->setHints(THEME_HINT_FIRST_DRAW); w = w->_next; } @@ -132,7 +127,11 @@ void Dialog::releaseFocus() { } void Dialog::draw() { - g_gui._needRedraw = true; + //TANOKU - FIXME when is this enabled? what does this do? + // Update: called on tab drawing, mainly... + // we can pass this as open a new dialog or something +// g_gui._needRedraw = true; + g_gui._redrawStatus = GUI::NewGui::kRedrawTopDialog; } void Dialog::drawDialog() { @@ -140,12 +139,12 @@ void Dialog::drawDialog() { if (!isVisible()) return; - g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _drawingHints); - _drawingHints &= ~THEME_HINT_FIRST_DRAW; + g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); // Draw all children Widget *w = _firstWidget; while (w) { + //if (w->_debugVisible) w->draw(); w = w->_next; } diff --git a/gui/dialog.h b/gui/dialog.h index d17d3a5ad1..bc5ce6b6e0 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -42,21 +42,22 @@ enum { }; class Dialog : public GuiObject { + // TANOKU-TODO: remove newgui from here friend class NewGui; protected: Widget *_mouseWidget; Widget *_focusedWidget; Widget *_dragWidget; bool _visible; - uint16 _drawingHints; + + Theme::DialogBackground _backgroundType; private: int _result; - bool _dimsInactive; public: - Dialog(int x, int y, int w, int h, bool dimsInactive = true); - Dialog(const Common::String &name, bool dimsInactive = true); + Dialog(int x, int y, int w, int h); + Dialog(const Common::String &name); virtual int runModal(); @@ -90,9 +91,6 @@ protected: void setResult(int result) { _result = result; } int getResult() const { return _result; } - - // Whether dialog dims all underneath dialogs or not when active - bool dimsInactive() { return _dimsInactive; } }; } // End of namespace GUI diff --git a/gui/eval.cpp b/gui/eval.cpp deleted file mode 100644 index 716006c108..0000000000 --- a/gui/eval.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - * - */ - -#include "common/system.h" -#include "gui/eval.h" -#include "gui/widget.h" -#include "gui/newgui.h" - -#include "graphics/scaler.h" - -namespace GUI { - -static bool isdelim(char c) { - return strchr(" ;,+-<>/*%^=()", c) != 0 || c == 9 || c == '\n' || !c; -} - -Eval::Eval() { - loadConstants(); -} - -Eval::~Eval() { - _vars.clear(); - _aliases.clear(); -} - -int Eval::eval(const String &input, const String §ion, const String &name, int startpos) { - int result; - - debug(5, "%s=%s", name.c_str(), input.c_str()); - - strncpy(_input, input.c_str(), 256); - _section = section; - _name = name; - _startpos = startpos; - - _pos = 0; - - getToken(); - - if (_tokenType == tString) - return EVAL_STRING_VAR; - - if (!*_token) - exprError(eBadExpr); - - level2(&result); - - debug(5, "Result: %d", result); - - return result; -} - -void Eval::level2(int *result) { - char op; - int hold; - - level3(result); - - while ((op = *_token) == '+' || op == '-') { - getToken(); - level3(&hold); - arith(op, result, &hold); - } -} - -void Eval::level3(int *result) { - char op; - int hold; - - level4(result); - - while ((op = *_token) == '*' || op == '/' || op == '%') { - getToken(); - level4(&hold); - arith(op, result, &hold); - } -} - -void Eval::level4(int *result) { - char op; - - op = 0; - if ((_tokenType == tDelimiter) && (*_token == '+' || *_token == '-')) { - op = *_token; - getToken(); - } - - level5(result); - - if (op) - unary(op, result); -} - -void Eval::level5(int *result) { - if ((*_token == '(') && (_tokenType == tDelimiter)) { - getToken(); - - level2(result); - - if (*_token != ')') - exprError(eUnclosedBracket); - getToken(); - } else { - primitive(result); - } -} - -void Eval::primitive(int *result) { - if (*_token == ')') - exprError(eExtraBracket); - - switch (_tokenType) { - case tVariable: - *result = getVar_(_token); - if (*result == EVAL_UNDEF_VAR) - exprError(eUndefVar); - getToken(); - return; - case tNumber: - *result = atoi(_token); - getToken(); - return; - default: - exprError(eSyntaxError); - } -} - -void Eval::arith(char op, int *r, int *h) { - switch (op) { - case '-': - *r = *r - *h; - break; - case '+': - *r = *r + *h; - break; - case '*': - *r = *r * *h; - break; - case '/': - *r = (*r) / (*h); - break; - case '%': - *r = (*r) % (*h); - break; - } -} - -void Eval::unary(char op, int *r) { - if (op == '-') - *r = -(*r); -} - -void Eval::getToken() { - char *temp; - - _tokenType = tNone; - temp = _token; - - if (_input[_pos] == 0) { - *_token = 0; - _tokenType = tDelimiter; - return; - } - while (isspace(_input[_pos])) - _pos++; - - if (_input[_pos] == '"') { - _pos++; - while (_input[_pos] != '"' && _input[_pos] != '\n') - *temp++ = _input[_pos++]; - - if (_input[_pos] == '\n') - exprError(eMissingQuote); - - _pos++; - *temp = 0; - - _tokenType = tString; - return; - } - - if (isdigit(_input[_pos])) { - while (!isdelim(_input[_pos])) - *temp++ = _input[_pos++]; - *temp = 0; - - _tokenType = tNumber; - return; - } - - if (isalpha(_input[_pos])) { - while (!isdelim(_input[_pos])) - *temp++ = _input[_pos++]; - *temp = 0; - _tokenType = tVariable; - return; - } - - if (!_tokenType && isdelim(_input[_pos])) { - *temp++ = _input[_pos++]; - *temp = 0; - _tokenType = tDelimiter; - } -} - -void Eval::exprError(EvalErrors err) { - static const char *errors[] = { - "Syntax error", - "Extra ')'", - "Missing ')'", - "Bad expression", - "Undefined variable", - "Missing '\"'" - }; - - error("%s in section [%s] expression: \"%s\" start is at: %d near token '%s'", - errors[err], _section.c_str(), _name.c_str(), _pos + _startpos, _token); -} - -struct BuiltinConsts { - const char *name; - int value; -}; - -static const BuiltinConsts builtinConsts[] = { - {"kButtonWidth", GUI::kButtonWidth}, - {"kButtonHeight", GUI::kButtonHeight}, - {"kSliderWidth", GUI::kSliderWidth}, - {"kSliderHeight", GUI::kSliderHeight}, - - {"kBigButtonWidth", GUI::kBigButtonWidth}, - {"kBigButtonHeight", GUI::kBigButtonHeight}, - {"kBigSliderWidth", GUI::kBigSliderWidth}, - {"kBigSliderHeight", GUI::kBigSliderHeight}, - - {"kNormalWidgetSize", GUI::kNormalWidgetSize}, - {"kBigWidgetSize", GUI::kBigWidgetSize}, - - {"kThumbnailWidth", kThumbnailWidth}, - - {"kTextAlignLeft", kTextAlignLeft}, - {"kTextAlignRight", kTextAlignRight}, - {"kTextAlignCenter", kTextAlignCenter}, - - {"kFontStyleBold", Theme::kFontStyleBold}, - {"kFontStyleNormal", Theme::kFontStyleNormal}, - {"kFontStyleItalic", Theme::kFontStyleItalic}, - - {"kFontStyleFixedBold", Theme::kFontStyleFixedBold}, - {"kFontStyleFixedNormal", Theme::kFontStyleFixedNormal}, - {"kFontStyleFixedItalic", Theme::kFontStyleFixedItalic}, - - {"kShadingNone", Theme::kShadingNone}, - {"kShadingDim", Theme::kShadingDim}, - {"kShadingLuminance", Theme::kShadingLuminance}, - - {"false", 0}, - {"true", 1}, - {NULL, 0} -}; - -void Eval::loadConstants() { - int i; - - for (i = 0; builtinConsts[i].name; i++) - _vars[builtinConsts[i].name] = builtinConsts[i].value; -} - -int Eval::getBuiltinVar(const char *s) { - if (!strcmp(s, "w")) - return g_system->getOverlayWidth(); - - if (!strcmp(s, "h")) - return g_system->getOverlayHeight(); - - return EVAL_UNDEF_VAR; -} - -int Eval::getVar_(const Common::String &s, bool includeAliases) { - int val; - - val = getBuiltinVar(s.c_str()); - - if (val != EVAL_UNDEF_VAR) - return val; - - const Common::String *var = &s; - if (includeAliases) { - AliasesMap::const_iterator itera = _aliases.find(s); - if (itera != _aliases.end()) - var = &(itera->_value); - } - - VariablesMap::const_iterator iterv = _vars.find(*var); - if (iterv != _vars.end()) - return iterv->_value; - - return EVAL_UNDEF_VAR; -} - -void Eval::setVar(const String §ion, const String &name, const String &value) { - _vars[name.c_str() + 4] = eval(value, section, name, 0); -} - -void Eval::reset() { - _vars.clear(); - _aliases.clear(); - loadConstants(); -} - -} // end of namespace GUI diff --git a/gui/eval.h b/gui/eval.h deleted file mode 100644 index 47c8313903..0000000000 --- a/gui/eval.h +++ /dev/null @@ -1,125 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - * - */ - -#ifndef GUI_EVAL_H -#define GUI_EVAL_H - -#include "common/str.h" -#include "common/hashmap.h" -#include "common/hash-str.h" - -namespace GUI { - -using Common::String; -using Common::HashMap; - -enum { - EVAL_UNDEF_VAR = -13375, - EVAL_STRING_VAR = -13376 -}; - -class Eval { -public: - Eval(); - ~Eval(); - - int eval(const String &input, const String §ion, const String &name, int startpos); - void setVar(const String §ion, const String &name, const String &value); - - void setParent(const String &name); - - void setVar(const String &name, int val) { _vars[name] = val; } - void setStringVar(const String &name, const String &val) { _strings[name] = val; } - void setAlias(const Common::String &name, const String &val) { _aliases[name] = val; } - - int getVar(const Common::String &s) { return getVar_(s); } - int getVar(const Common::String &s, int def) { - int val = getVar_(s); - return (val == EVAL_UNDEF_VAR) ? def : val; - } - - const String &getStringVar(const Common::String &name) { return _strings[name]; } - - uint getNumVars() { return _vars.size(); } - - void reset(); - - char *lastToken() { return _token; } - - typedef HashMap<String, int> VariablesMap; - typedef HashMap<String, String> AliasesMap; - typedef HashMap<String, String> StringsMap; - -private: - enum TokenTypes { - tNone, - tDelimiter, - tVariable, - tNumber, - tString - }; - - enum EvalErrors { - eSyntaxError, - eExtraBracket, - eUnclosedBracket, - eBadExpr, - eUndefVar, - eMissingQuote - }; - - - void getToken(); - void level2(int *); - void level3(int *); - void level4(int *); - void level5(int *); - void primitive(int *); - void arith(char op, int *r, int *h); - void unary(char op, int *r); - void exprError(EvalErrors error); - int getVar_(const Common::String &s, bool includeAliases = true); - int getBuiltinVar(const char *s); - void loadConstants(); - - char _input[256]; - String _section; - String _name; - - int _startpos; - - TokenTypes _tokenType; - int _pos; - - char _token[256]; - - AliasesMap _aliases; - VariablesMap _vars; - StringsMap _strings; -}; - -} // end of namespace GUI - -#endif diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 7cfe3943a7..9ecdbfb6d4 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -34,7 +34,6 @@ #include "gui/about.h" #include "gui/browser.h" #include "gui/chooser.h" -#include "gui/eval.h" #include "gui/launcher.h" #include "gui/massadd.h" #include "gui/message.h" @@ -48,6 +47,7 @@ #include "sound/mididrv.h" +#include "gui/ThemeEval.h" using Common::ConfigManager; @@ -143,9 +143,9 @@ protected: }; EditGameDialog::EditGameDialog(const String &domain, const String &desc) - : OptionsDialog(domain, "gameoptions") { + : OptionsDialog(domain, "GameOptions") { - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w) String gamePath(ConfMan.get("path", _domain)); @@ -159,8 +159,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // GUI: Add tab widget - TabWidget *tab = new TabWidget(this, "gameoptions_tabwidget"); - tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); + TabWidget *tab = new TabWidget(this, "GameOptions.TabWidget"); // // 1) The game tab @@ -168,15 +167,15 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) tab->addTab("Game"); // GUI: Label & edit widget for the game ID - new StaticTextWidget(tab, "gameoptions_id", "ID:"); - _domainWidget = new DomainEditTextWidget(tab, "gameoptions_domain", _domain); + new StaticTextWidget(tab, "GameOptions_Game.Id", "ID:"); + _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain); // GUI: Label & edit widget for the description - new StaticTextWidget(tab, "gameoptions_name", "Name:"); - _descriptionWidget = new EditTextWidget(tab, "gameoptions_desc", description); + new StaticTextWidget(tab, "GameOptions_Game.Name", "Name:"); + _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description); // Language popup - _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language:", labelWidth); + _langPopUp = new PopUpWidget(tab, "GameOptions_Game.Lang", "Language:", labelWidth); _langPopUp->appendEntry("<default>"); _langPopUp->appendEntry(""); const Common::LanguageDescription *l = Common::g_languages; @@ -185,7 +184,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // Platform popup - _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform:", labelWidth); + _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.Platform", "Platform:", labelWidth); _platformPopUp->appendEntry("<default>"); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; @@ -196,39 +195,39 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 3) The graphics tab // - tab->addTab("Graphics"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); - _globalGraphicsOverride = new CheckboxWidget(tab, "gameoptions_graphicsCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); + _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); - addGraphicControls(tab, "gameoptions_"); + addGraphicControls(tab, "GameOptions_Graphics."); // // 4) The audio tab // tab->addTab("Audio"); - _globalAudioOverride = new CheckboxWidget(tab, "gameoptions_audioCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0); + _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0); - addAudioControls(tab, "gameoptions_"); - addSubtitleControls(tab, "gameoptions_"); + addAudioControls(tab, "GameOptions_Audio."); + addSubtitleControls(tab, "GameOptions_Audio."); // // 5) The volume tab // tab->addTab("Volume"); - _globalVolumeOverride = new CheckboxWidget(tab, "gameoptions_volumeCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0); + _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0); - addVolumeControls(tab, "gameoptions_"); + addVolumeControls(tab, "GameOptions_Volume."); // // 6) The MIDI tab // tab->addTab("MIDI"); - _globalMIDIOverride = new CheckboxWidget(tab, "gameoptions_midiCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); + _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); - addMIDIControls(tab, "gameoptions_"); + addMIDIControls(tab, "GameOptions_MIDI."); // // 2) The 'Path' tab @@ -239,35 +238,36 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // in the small version of the GUI. // GUI: Button + Label for the game path - new ButtonWidget(tab, "gameoptions_gamepath", "Game Path:", kCmdGameBrowser, 0); - _gamePathWidget = new StaticTextWidget(tab, "gameoptions_gamepathText", gamePath); + new ButtonWidget(tab, "GameOptions_Paths.Gamepath", "Game Path:", kCmdGameBrowser, 0); + _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath); // GUI: Button + Label for the additional path - new ButtonWidget(tab, "gameoptions_extrapath", "Extra Path:", kCmdExtraBrowser, 0); - _extraPathWidget = new StaticTextWidget(tab, "gameoptions_extrapathText", extraPath); + new ButtonWidget(tab, "GameOptions_Paths.Extrapath", "Extra Path:", kCmdExtraBrowser, 0); + _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath); if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) { _extraPathWidget->setLabel("None"); } // GUI: Button + Label for the save path - new ButtonWidget(tab, "gameoptions_savepath", "Save Path:", kCmdSaveBrowser, 0); - _savePathWidget = new StaticTextWidget(tab, "gameoptions_savepathText", savePath); + new ButtonWidget(tab, "GameOptions_Paths.Savepath", "Save Path:", kCmdSaveBrowser, 0); + _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath); if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { _savePathWidget->setLabel("Default"); } - + // Activate the first tab tab->setActiveTab(0); + _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "gameoptions_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "gameoptions_ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GameOptions.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "GameOptions.Ok", "OK", kOKCmd, 0); } void EditGameDialog::reflowLayout() { OptionsDialog::reflowLayout(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); if (_langPopUp) _langPopUp->changeLabelWidth(labelWidth); @@ -473,7 +473,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat LauncherDialog::LauncherDialog() : Dialog(0, 0, 320, 200) { - _drawingHints |= THEME_HINT_MAIN_DIALOG; + _backgroundType = GUI::Theme::kDialogBackgroundMain; const int screenW = g_system->getOverlayWidth(); const int screenH = g_system->getOverlayHeight(); @@ -483,36 +483,36 @@ LauncherDialog::LauncherDialog() #ifndef DISABLE_FANCY_THEMES _logo = 0; - if (g_gui.evaluator()->getVar("launcher_logo.visible") == 1 && g_gui.theme()->supportsImages()) { - _logo = new GraphicsWidget(this, "launcher_logo"); + if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) { + _logo = new GraphicsWidget(this, "Launcher.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(Theme::kImageLogo)); - new StaticTextWidget(this, "launcher_version", gScummVMVersionDate); + new StaticTextWidget(this, "Launcher.Version", gScummVMVersionDate); } else - new StaticTextWidget(this, "launcher_version", gScummVMFullVersion); + new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #else // Show ScummVM version - new StaticTextWidget(this, "launcher_version", gScummVMFullVersion); + new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #endif - new ButtonWidget(this, "launcher_quit_button", "Quit", kQuitCmd, 'Q'); - new ButtonWidget(this, "launcher_about_button", "About", kAboutCmd, 'B'); - new ButtonWidget(this, "launcher_options_button", "Options", kOptionsCmd, 'O'); + new ButtonWidget(this, "Launcher.QuitButton", "Quit", kQuitCmd, 'Q'); + new ButtonWidget(this, "Launcher.AboutButton", "About", kAboutCmd, 'B'); + new ButtonWidget(this, "Launcher.OptionsButton", "Options", kOptionsCmd, 'O'); _startButton = - new ButtonWidget(this, "launcher_start_button", "Start", kStartCmd, 'S'); + new ButtonWidget(this, "Launcher.StartButton", "Start", kStartCmd, 'S'); // Above the lowest button rows: two more buttons (directly below the list box) _addButton = - new ButtonWidget(this, "launcher_addGame_button", "Add Game...", kAddGameCmd, 'A'); + new ButtonWidget(this, "Launcher.AddGameButton", "Add Game...", kAddGameCmd, 'A'); _editButton = - new ButtonWidget(this, "launcher_editGame_button", "Edit Game...", kEditGameCmd, 'E'); + new ButtonWidget(this, "Launcher.EditGameButton", "Edit Game...", kEditGameCmd, 'E'); _removeButton = - new ButtonWidget(this, "launcher_removeGame_button", "Remove Game", kRemoveGameCmd, 'R'); + new ButtonWidget(this, "Launcher.RemoveGameButton", "Remove Game", kRemoveGameCmd, 'R'); // Add list with game titles - _list = new ListWidget(this, "launcher_list"); + _list = new ListWidget(this, "Launcher.GameList"); _list->setEditable(false); _list->setNumberingMode(kListNumberingOff); @@ -881,21 +881,21 @@ void LauncherDialog::updateButtons() { void LauncherDialog::reflowLayout() { #ifndef DISABLE_FANCY_THEMES - if (g_gui.evaluator()->getVar("launcher_logo.visible") == 1 && g_gui.theme()->supportsImages()) { - StaticTextWidget *ver = (StaticTextWidget*)findWidget("launcher_version"); + if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) { + StaticTextWidget *ver = (StaticTextWidget*)findWidget("Launcher.Version"); if (ver) { - ver->setAlign((Graphics::TextAlignment)g_gui.evaluator()->getVar("launcher_version.align")); + ver->setAlign((Graphics::TextAlignment)g_gui.xmlEval()->getVar("Launcher.Version.Align", Graphics::kTextAlignCenter)); ver->setLabel(gScummVMVersionDate); } if (!_logo) - _logo = new GraphicsWidget(this, "launcher_logo"); + _logo = new GraphicsWidget(this, "Launcher.Logo"); _logo->useThemeTransparency(true); _logo->setGfx(g_gui.theme()->getImageSurface(Theme::kImageLogo)); } else { - StaticTextWidget *ver = (StaticTextWidget*)findWidget("launcher_version"); + StaticTextWidget *ver = (StaticTextWidget*)findWidget("Launcher.Version"); if (ver) { - ver->setAlign((Graphics::TextAlignment)g_gui.evaluator()->getVar("launcher_version.align")); + ver->setAlign((Graphics::TextAlignment)g_gui.xmlEval()->getVar("Launcher.Version.Align", Graphics::kTextAlignCenter)); ver->setLabel(gScummVMFullVersion); } diff --git a/gui/module.mk b/gui/module.mk index c572dcbeea..f1ba840459 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -9,7 +9,7 @@ MODULE_OBJS := \ dialog.o \ editable.o \ EditTextWidget.o \ - eval.o \ + ThemeRenderer.o \ launcher.o \ ListWidget.o \ massadd.o \ @@ -23,9 +23,8 @@ MODULE_OBJS := \ themebrowser.o \ widget.o \ theme.o \ - ThemeClassic.o \ - ThemeModern.o \ - theme-config.o + ThemeEval.o \ + ThemeParser.o # Include common rules include $(srcdir)/rules.mk diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 618c7bc873..fc781f731d 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -28,9 +28,7 @@ #include "graphics/cursorman.h" #include "gui/newgui.h" #include "gui/dialog.h" -#include "gui/eval.h" -#include "gui/ThemeModern.h" -#include "gui/ThemeClassic.h" +#include "gui/ThemeRenderer.h" #include "common/config-manager.h" @@ -57,15 +55,12 @@ enum { void GuiObject::reflowLayout() { if (!_name.empty()) { - if ((_x = g_gui.evaluator()->getVar(_name + ".x")) == EVAL_UNDEF_VAR) - error("Undefined variable %s.x", _name.c_str()); - if ((_y = g_gui.evaluator()->getVar(_name + ".y")) == EVAL_UNDEF_VAR) - error("Undefined variable %s.y", _name.c_str()); - _w = g_gui.evaluator()->getVar(_name + ".w"); - _h = g_gui.evaluator()->getVar(_name + ".h"); + if (!g_gui.xmlEval()->getWidgetData(_name, _x, _y, _w, _h)) { + warning("Could not load widget position for '%s'", _name.c_str()); + } if (_x < 0) - error("Widget <%s> has x < 0", _name.c_str()); + error("Widget <%s> has x < 0: %d", _name.c_str(), _x); if (_x >= g_system->getOverlayWidth()) error("Widget <%s> has x > %d", _name.c_str(), g_system->getOverlayWidth()); if (_x + _w > g_system->getOverlayWidth()) @@ -80,7 +75,7 @@ void GuiObject::reflowLayout() { } // Constructor -NewGui::NewGui() : _needRedraw(false), +NewGui::NewGui() : _redrawStatus(kRedrawDisabled), _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { _theme = 0; _useStdCursor = false; @@ -91,33 +86,19 @@ NewGui::NewGui() : _needRedraw(false), // Clear the cursor memset(_cursor, 0xFF, sizeof(_cursor)); - bool loadClassicTheme = true; -#ifndef DISABLE_FANCY_THEMES - ConfMan.registerDefault("gui_theme", "default"); - Common::String style(ConfMan.get("gui_theme")); - // The default theme for now is the 'modern' theme. - if (style.compareToIgnoreCase("default") == 0) - style = "modern"; - - Common::String styleType; - Common::ConfigFile cfg; - if (loadNewTheme(style)) { - loadClassicTheme = false; - } else { - loadClassicTheme = true; - warning("falling back to classic style"); - } -#endif - - if (loadClassicTheme) { - _theme = new ThemeClassic(_system); - assert(_theme); - if (!_theme->init()) { - error("Couldn't initialize classic theme"); - } - } - _theme->resetDrawArea(); + ConfMan.registerDefault("gui_theme", "default"); + Common::String themefile(ConfMan.get("gui_theme")); + if (themefile.compareToIgnoreCase("default") == 0) + themefile = "builtin"; + + if (themefile != "builtin" && !themefile.hasSuffix(".zip")) + themefile += ".zip"; + + ConfMan.registerDefault("gui_renderer", 2); + ThemeRenderer::GraphicsMode gfxMode = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); + + loadNewTheme(themefile, gfxMode); _themeChange = false; } @@ -125,11 +106,14 @@ NewGui::~NewGui() { delete _theme; } -bool NewGui::loadNewTheme(const Common::String &style) { - Common::String styleType; - Common::ConfigFile cfg; - - Common::String oldTheme = (_theme != 0) ? _theme->getStylefileName() : ""; +bool NewGui::loadNewTheme(const Common::String &filename, ThemeRenderer::GraphicsMode gfx) { + if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getThemeRenderer()) + return true; + + Common::String oldTheme = (_theme != 0) ? _theme->getThemeFileName() : ""; + + if (gfx == ThemeRenderer::kGfxDisabled) + gfx = (ThemeRenderer::GraphicsMode)ConfMan.getInt("gui_renderer"); if (_theme) _theme->disable(); @@ -142,36 +126,12 @@ bool NewGui::loadNewTheme(const Common::String &style) { delete _theme; _theme = 0; - if (style.compareToIgnoreCase("classic (builtin)") == 0 || - style.compareToIgnoreCase("classic") == 0) { - _theme = new ThemeClassic(_system, style); - } else { - if (Theme::themeConfigUseable(style, "", &styleType, &cfg)) { - if (0 == styleType.compareToIgnoreCase("classic")) - _theme = new ThemeClassic(_system, style, &cfg); -#ifndef DISABLE_FANCY_THEMES - else if (0 == styleType.compareToIgnoreCase("modern")) - _theme = new ThemeModern(_system, style, &cfg); -#endif - else - warning("Unsupported theme type '%s'", styleType.c_str()); - } else { - warning("Config '%s' is NOT usable for themes or not found", style.c_str()); - } - } - cfg.clear(); + _theme = new ThemeRenderer(filename, gfx); if (!_theme) return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); - if (!_theme->init()) { - warning("Could not initialize your preferred theme"); - delete _theme; - _theme = 0; - loadNewTheme(oldTheme); - return false; - } - _theme->resetDrawArea(); + _theme->init(); if (!oldTheme.empty()) screenChange(); @@ -184,29 +144,35 @@ bool NewGui::loadNewTheme(const Common::String &style) { void NewGui::redraw() { int i; - // Restore the overlay to its initial state, then draw all dialogs. - // This is necessary to get the blending right. - _theme->clearAll(); - - _theme->closeAllDialogs(); - //for (i = 0; i < _dialogStack.size(); ++i) - // _theme->closeDialog(); + if (_redrawStatus == kRedrawDisabled) + return; - for (i = 0; i < _dialogStack.size(); i++) { - // Special treatment when topmost dialog has dimsInactive() set to false - // This is the case for PopUpWidget which should not dim a dialog - // which it belongs to - if ((i == _dialogStack.size() - 2) && !_dialogStack[i + 1]->dimsInactive()) - _theme->openDialog(true); - else if ((i != (_dialogStack.size() - 1)) || !_dialogStack[i]->dimsInactive()) - _theme->openDialog(false); - else + switch (_redrawStatus) { + case kRedrawCloseDialog: + case kRedrawFull: + case kRedrawTopDialog: + _theme->clearAll(); _theme->openDialog(true); - _dialogStack[i]->drawDialog(); + for (i = 0; i < _dialogStack.size() - 1; i++) { + _dialogStack[i]->drawDialog(); + } + + _theme->finishBuffering(); + _theme->updateScreen(); + + case kRedrawOpenDialog: + _theme->openDialog(true, (Theme::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0)); + _dialogStack.top()->drawDialog(); + _theme->finishBuffering(); + break; + + default: + return; } _theme->updateScreen(); + _redrawStatus = kRedrawDisabled; } Dialog *NewGui::getTopDialog() const { @@ -235,12 +201,11 @@ void NewGui::runLoop() { } Common::EventManager *eventMan = _system->getEventManager(); + uint32 lastRedraw = 0; + const uint32 waitTime = 1000 / 45; while (!_dialogStack.empty() && activeDialog == getTopDialog()) { - if (_needRedraw) { - redraw(); - _needRedraw = false; - } + redraw(); // Don't "tickle" the dialog until the theme has had a chance // to re-allocate buffers in case of a scaler change. @@ -249,9 +214,15 @@ void NewGui::runLoop() { if (_useStdCursor) animateCursor(); - _theme->updateScreen(); - _system->updateScreen(); - +// _theme->updateScreen(); +// _system->updateScreen(); + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } + Common::Event event; while (eventMan->pollEvent(event)) { @@ -271,8 +242,15 @@ void NewGui::runLoop() { _theme->refresh(); _themeChange = false; + _redrawStatus = kRedrawFull; redraw(); } + + if (lastRedraw + waitTime < _system->getMillis()) { + _theme->updateScreen(); + _system->updateScreen(); + lastRedraw = _system->getMillis(); + } switch (event.type) { case Common::EVENT_KEYDOWN: @@ -327,11 +305,6 @@ void NewGui::runLoop() { _system->delayMillis(10); } - // HACK: since we reopen all dialogs anyway on redraw - // we for now use Theme::closeAllDialogs here, until - // we properly add (and implement) Theme::closeDialog - _theme->closeAllDialogs(); - if (didSaveState) { _theme->disable(); restoreState(); @@ -363,7 +336,7 @@ void NewGui::restoreState() { void NewGui::openDialog(Dialog *dialog) { _dialogStack.push(dialog); - _needRedraw = true; + _redrawStatus = kRedrawOpenDialog; // We reflow the dialog just before opening it. If the screen changed // since the last time we looked, also refresh the loaded theme, @@ -390,7 +363,7 @@ void NewGui::closeTopDialog() { // Remove the dialog from the stack _dialogStack.pop(); - _needRedraw = true; + _redrawStatus = kRedrawCloseDialog; } void NewGui::setupCursor() { @@ -428,7 +401,7 @@ void NewGui::animateCursor() { } WidgetSize NewGui::getWidgetSize() { - return (WidgetSize)(_theme->_evaluator->getVar("widgetSize")); + return (WidgetSize)(g_gui.xmlEval()->getVar("Globals.WidgetSize")); } void NewGui::clearDragWidget() { @@ -448,7 +421,10 @@ void NewGui::screenChange() { // We need to redraw immediately. Otherwise // some other event may cause a widget to be // redrawn before redraw() has been called. + _redrawStatus = kRedrawFull; redraw(); + _system->showOverlay(); + _system->updateScreen(); } } // End of namespace GUI diff --git a/gui/newgui.h b/gui/newgui.h index 4cf082c877..cc9e6b9f3c 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -33,12 +33,15 @@ #include "gui/theme.h" #include "gui/widget.h" +#include "gui/ThemeRenderer.h" + class OSystem; namespace GUI { class Dialog; class Eval; +class ThemeEval; #define g_gui (GUI::NewGui::instance()) @@ -75,9 +78,10 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(const Common::String &file); + bool loadNewTheme(const Common::String &file, ThemeRenderer::GraphicsMode gfx = ThemeRenderer::kGfxDisabled); Theme *theme() { return _theme; } - Eval *evaluator() { return _theme->_evaluator; } + + ThemeEval *xmlEval() { return _theme->evaluator(); } const Graphics::Font &getFont(Theme::FontStyle style = Theme::kFontStyleBold) const { return *(_theme->getFont(style)); } int getFontHeight(Theme::FontStyle style = Theme::kFontStyleBold) const { return _theme->getFontHeight(style); } @@ -90,12 +94,21 @@ public: void screenChange(); + enum RedrawStatus { + kRedrawDisabled = 0, + kRedrawOpenDialog, + kRedrawCloseDialog, + kRedrawTopDialog, + kRedrawFull + }; + protected: OSystem *_system; Theme *_theme; - bool _needRedraw; +// bool _needRedraw; + RedrawStatus _redrawStatus; int _lastScreenChangeID; DialogStack _dialogStack; diff --git a/gui/options.cpp b/gui/options.cpp index d6f5306ce2..c24b338af6 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -25,9 +25,9 @@ #include "gui/browser.h" #include "gui/themebrowser.h" #include "gui/chooser.h" -#include "gui/eval.h" #include "gui/message.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" #include "gui/options.h" #include "gui/PopUpWidget.h" #include "gui/TabWidget.h" @@ -73,12 +73,12 @@ static const int outputRateValues[] = { 0, 22050, 8000, 11025, 44100, 48000, -1 OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h) - : Dialog(x, y, w, h), _domain(domain) { + : Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _tabWidget(0) { init(); } OptionsDialog::OptionsDialog(const String &domain, const String &name) - : Dialog(name), _domain(domain) { + : Dialog(name), _domain(domain), _graphicsTabId(-1), _tabWidget(0) { init(); } @@ -88,6 +88,12 @@ const char *OptionsDialog::_subModeDesc[] = { "Subtitles Only" }; +const char *OptionsDialog::_lowresSubModeDesc[] = { + "Speech Only", + "Speech & Subs", + "Subtitles Only" +}; + void OptionsDialog::init() { _enableGraphicSettings = false; _gfxPopUp = 0; @@ -417,7 +423,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data else _subMode = 0; - _subToggleButton->setLabel(_subModeDesc[_subMode]); + _subToggleButton->setLabel(g_system->getOverlayWidth() > 320 ? _subModeDesc[_subMode] : _lowresSubModeDesc[_subMode]); _subToggleButton->draw(); _subSpeedDesc->draw(); _subSpeedSlider->draw(); @@ -500,7 +506,7 @@ void OptionsDialog::setSubtitleSettingsState(bool enabled) { void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // The GFX mode popup _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:", labelWidth); @@ -537,7 +543,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { } void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); // The MIDI mode popup & a label _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:", labelWidth); @@ -643,7 +649,10 @@ int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { void OptionsDialog::reflowLayout() { Dialog::reflowLayout(); - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); + + if (_graphicsTabId != -1 && _tabWidget) + _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); if (_midiPopUp) _midiPopUp->changeLabelWidth(labelWidth); @@ -659,27 +668,26 @@ void OptionsDialog::reflowLayout() { GlobalOptionsDialog::GlobalOptionsDialog() - : OptionsDialog(Common::ConfigManager::kApplicationDomain, "globaloptions") { + : OptionsDialog(Common::ConfigManager::kApplicationDomain, "GlobalOptions") { // The tab widget - TabWidget *tab = new TabWidget(this, "globaloptions_tabwidget"); - tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); + TabWidget *tab = new TabWidget(this, "GlobalOptions.TabWidget"); // // 1) The graphics tab // - tab->addTab("Graphics"); - addGraphicControls(tab, "globaloptions_"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); + addGraphicControls(tab, "GlobalOptions_Graphics."); // // 2) The audio tab // tab->addTab("Audio"); - addAudioControls(tab, "globaloptions_"); - addSubtitleControls(tab, "globaloptions_"); + addAudioControls(tab, "GlobalOptions_Audio."); + addSubtitleControls(tab, "GlobalOptions_Audio."); tab->addTab("Volume"); - addVolumeControls(tab, "globaloptions_"); + addVolumeControls(tab, "GlobalOptions_Volume."); // TODO: cd drive setting @@ -687,7 +695,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() // 3) The MIDI tab // tab->addTab("MIDI"); - addMIDIControls(tab, "globaloptions_"); + addMIDIControls(tab, "GlobalOptions_MIDI."); // // 4) The miscellaneous tab @@ -699,33 +707,40 @@ GlobalOptionsDialog::GlobalOptionsDialog() // truncated in the small version of the GUI. // Save game path - new ButtonWidget(tab, "globaloptions_savebutton", "Save Path: ", kChooseSaveDirCmd, 0); - _savePath = new StaticTextWidget(tab, "globaloptions_savepath", "/foo/bar"); + new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", "Save Path: ", kChooseSaveDirCmd, 0); + _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar"); - new ButtonWidget(tab, "globaloptions_themebutton", "Theme Path:", kChooseThemeDirCmd, 0); - _themePath = new StaticTextWidget(tab, "globaloptions_themepath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", "Theme Path:", kChooseThemeDirCmd, 0); + _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", "None"); - new ButtonWidget(tab, "globaloptions_extrabutton", "Extra Path:", kChooseExtraDirCmd, 0); - _extraPath = new StaticTextWidget(tab, "globaloptions_extrapath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", "Extra Path:", kChooseExtraDirCmd, 0); + _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", "None"); #ifdef DYNAMIC_MODULES - new ButtonWidget(tab, "globaloptions_pluginsbutton", "Plugins Path:", kChoosePluginsDirCmd, 0); - _pluginsPath = new StaticTextWidget(tab, "globaloptions_pluginspath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", "Plugins Path:", kChoosePluginsDirCmd, 0); + _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", "None"); #endif #endif #ifdef SMALL_SCREEN_DEVICE - new ButtonWidget(tab, "globaloptions_keysbutton", "Keys", kChooseKeyMappingCmd, 0); + new ButtonWidget(tab, "GlobalOptions.KeysButton", "Keys", kChooseKeyMappingCmd, 0); #endif tab->addTab("Misc"); - new ButtonWidget(tab, "globaloptions_themebutton2", "Theme:", kChooseThemeCmd, 0); - _curTheme = new StaticTextWidget(tab, "globaloptions_curtheme", g_gui.theme()->getThemeName()); - - int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); + new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0); + _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); + - _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave:", labelWidth); + int labelWidth = g_gui.xmlEval()->getVar("Globals.TabLabelWidth"); + + _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.Renderer", "GUI Renderer:", labelWidth); + + for (int i = 1; i < GUI::ThemeRenderer::kGfxMAX; ++i) { + _rendererPopUp->appendEntry(GUI::ThemeRenderer::rendererModeLabels[i], i); + } + + _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriod", "Autosave:", labelWidth); for (int i = 0; savePeriodLabels[i]; i++) { _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]); @@ -736,10 +751,11 @@ GlobalOptionsDialog::GlobalOptionsDialog() // Activate the first tab tab->setActiveTab(0); + _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "globaloptions_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "globaloptions_ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "GlobalOptions.Ok", "OK", kOKCmd, 0); #ifdef SMALL_SCREEN_DEVICE _keysDialog = new KeysDialog(); @@ -796,6 +812,8 @@ void GlobalOptionsDialog::open() { if (value == savePeriodValues[i]) _autosavePeriodPopUp->setSelected(i); } + + _rendererPopUp->setSelected(ConfMan.getInt("gui_renderer") - 1); } void GlobalOptionsDialog::close() { @@ -825,6 +843,11 @@ void GlobalOptionsDialog::close() { #endif ConfMan.setInt("autosave_period", _autosavePeriodPopUp->getSelectedTag(), _domain); + + if ((int)_rendererPopUp->getSelectedTag() != ConfMan.getInt("gui_renderer")) { + g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), (GUI::ThemeRenderer::GraphicsMode)_rendererPopUp->getSelectedTag()); + ConfMan.setInt("gui_renderer", _rendererPopUp->getSelectedTag(), _domain); + } } OptionsDialog::close(); } @@ -906,7 +929,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 if (browser.runModal() > 0) { // User made his choice... const Common::String &theme = browser.selected(); - if (0 != theme.compareToIgnoreCase(g_gui.theme()->getStylefileName())) + if (0 != theme.compareToIgnoreCase(g_gui.theme()->getThemeFileName())) if (g_gui.loadNewTheme(theme)) { _curTheme->setLabel(g_gui.theme()->getThemeName()); ConfMan.set("gui_theme", theme); diff --git a/gui/options.h b/gui/options.h index 8f4496c753..187e163b79 100644 --- a/gui/options.h +++ b/gui/options.h @@ -26,6 +26,7 @@ #define OPTIONS_DIALOG_H #include "gui/dialog.h" +#include "gui/TabWidget.h" #include "common/str.h" #ifdef SMALL_SCREEN_DEVICE @@ -80,6 +81,9 @@ protected: void setMIDISettingsState(bool enabled); void setVolumeSettingsState(bool enabled); void setSubtitleSettingsState(bool enabled); + + TabWidget *_tabWidget; + int _graphicsTabId; private: // @@ -118,6 +122,7 @@ private: ButtonWidget *_subToggleButton; int _subMode; static const char *_subModeDesc[]; + static const char *_lowresSubModeDesc[]; StaticTextWidget *_subSpeedDesc; SliderWidget *_subSpeedSlider; StaticTextWidget *_subSpeedLabel; @@ -166,7 +171,7 @@ protected: // Misc controls // StaticTextWidget *_curTheme; - + PopUpWidget *_rendererPopUp; PopUpWidget *_autosavePeriodPopUp; }; diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp deleted file mode 100644 index 47f60d3d7b..0000000000 --- a/gui/theme-config.cpp +++ /dev/null @@ -1,784 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - */ - -#include "gui/theme.h" -#include "gui/eval.h" - -namespace GUI { - -const char *Theme::_defaultConfigINI = -"# Define our classic greenish theme here\n" -"[320xY]\n" -"def_widgetSize=kNormalWidgetSize\n" -"def_buttonWidth=kButtonWidth\n" -"def_buttonHeight=kButtonHeight\n" -"def_sliderWidth=kSliderWidth\n" -"def_sliderHeight=kSliderHeight\n" -"def_kLineHeight=12\n" -"def_kFontHeight=10\n" -"def_insetX=10\n" -"def_insetY=10\n" -"def_insetW=(w - 2 * 10)\n" -"def_insetH=(h - 30)\n" -"def_gameOptionsLabelWidth=60\n" -"def_tabPopupsLabelW=100\n" -"def_aboutXOff=3\n" -"def_aboutYOff=2\n" -"def_aboutOuterBorder=10\n" -"def_scummmainHOffset=8\n" -"def_scummmainVSpace=5\n" -"def_scummmainVAddOff=2\n" -"def_scummmainButtonWidth=90\n" -"def_scummmainButtonHeight=16\n" -"def_scummhelpX=5\n" -"def_scummhelpW=(w - 2 * 5)\n" -"def_midiControlsSpacing=1\n" -"def_vcAudioTabIndent=0\n" -"def_vcAudioTabSpacing=2\n" -"use=XxY\n" -"\n" -"# Override audio tab\n" -"set_parent=gameoptions\n" -"vBorder=5\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=audioControls globaloptions_\n" -"useWithPrefix=subtitleControls globaloptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=volumeControls globaloptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"useWithPrefix=audioControls gameoptions_\n" -"useWithPrefix=subtitleControls gameoptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"useWithPrefix=volumeControls gameoptions_\n" -"\n" -"TabWidget.tabWidth=0\n" -"TabWidget.tabHeight=16\n" -"TabWidget.titleVPad=2\n" -"# Scumm Saveload dialog\n" -"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n" -"set_parent=scummsaveload\n" -"scummsaveload_title=10 2 (parent.w - 2 * 10) kLineHeight\n" -"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n" -"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18\n" -"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"scummsaveload_extinfo.visible=false\n" -"\n" -"# MM NES resolution\n" -"[256x240]\n" -"useAsIs=320xY\n" -"\n" -"[XxY]\n" -"def_widgetSize=kBigWidgetSize\n" -"def_buttonWidth=kBigButtonWidth\n" -"def_buttonHeight=kBigButtonHeight\n" -"def_sliderWidth=kBigSliderWidth\n" -"def_sliderHeight=kBigSliderHeight\n" -"def_kLineHeight=16\n" -"def_kFontHeight=14\n" -"def_insetX=10\n" -"def_insetY=20\n" -"def_insetW=(w - 2 * 10)\n" -"def_insetH=(h - 2 * 40)\n" -"def_gameOptionsLabelWidth=90\n" -"def_tabPopupsLabelW=150\n" -"def_aboutXOff=8\n" -"def_aboutYOff=5\n" -"def_aboutOuterBorder=80\n" -"def_scummmainHOffset=12\n" -"def_scummmainVSpace=7\n" -"def_scummmainVAddOff=3\n" -"def_scummmainButtonWidth=160\n" -"def_scummmainButtonHeight=28\n" -"def_scummhelpW=370\n" -"def_scummhelpX=((w - scummhelpW) / 2)\n" -"def_midiControlsSpacing=2\n" -"def_vcAudioTabIndent=10\n" -"def_vcAudioTabSpacing=4\n" -"##### Widgets config\n" -"ListWidget.leftPadding=4\n" -"ListWidget.rightPadding=0\n" -"ListWidget.topPadding=2\n" -"ListWidget.bottomPadding=2\n" -"ListWidget.hlLeftPadding=2\n" -"ListWidget.hlRightPadding=1\n" -"PopUpWidget.leftPadding=4\n" -"PopUpWidget.rightPadding=0\n" -"TabWidget.tabWidth=70\n" -"TabWidget.tabHeight=21\n" -"TabWidget.titleVPad=2\n" -"\n" -"###### chooser\n" -"opHeight=(h * 7 / 10)\n" -"useWithPrefix=chooser defaultChooser_\n" -"\n" -"##### browser\n" -"brW=((w * 7) / 8)\n" -"brH=((h * 9) / 10)\n" -"browser=((w - brW) / 2) ((h - brH) / 2) brW brH\n" -"set_parent=browser\n" -"browser_headline=10 kLineHeight (parent.w - 2 * 10) kLineHeight\n" -"browser_headline.align=kTextAlignCenter\n" -"browser_path=10 prev.y2 prev.w prev.h\n" -"browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14)\n" -"browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"browser_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"##### launcher\n" -"hBorder=10\n" -"launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight\n" -"launcher_version.align=kTextAlignCenter\n" -"top=(h - 8 - buttonHeight)\n" -"numButtons=4\n" -"space=8\n" -"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n" -"launcher_quit_button=hBorder top butWidth buttonHeight\n" -"launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"top=(top - buttonHeight * 2)\n" -"numButtons=3\n" -"space=10\n" -"butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons)\n" -"launcher_addGame_button=hBorder top butWidth buttonHeight\n" -"launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h\n" -"launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20)\n" -"\n" -"### global options\n" -"globaloptions=insetX insetY insetW insetH\n" -"set_parent=globaloptions\n" -"vBorder=5\n" -"globaloptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" -"\n" -"# graphics tab\n" -"opYoffset=vBorder\n" -"opXoffset=0\n" -"useWithPrefix=graphicsControls globaloptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=audioControls globaloptions_\n" -"useWithPrefix=subtitleControls globaloptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=volumeControls globaloptions_\n" -"\n" -"# MIDI tab\n" -"opYoffset=vBorder\n" -"useWithPrefix=midiControls globaloptions_\n" -"\n" -"# paths tab\n" -"yoffset=vBorder\n" -"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"globaloptions_savebutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_extrabutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_themebutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_pluginsbutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"globaloptions_pluginspath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight\n" -"\n" -"# Misc options\n" -"yoffset=vBorder\n" -"glOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight\n" -"globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight\n" -"yoffset=(yoffset + buttonHeight + 4)\n" -"globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) (kLineHeight + 2)\n" -"\n" -"globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"### game options\n" -"gameoptions=insetX insetY insetW insetH\n" -"set_parent=gameoptions\n" -"vBorder=5\n" -"gox=5\n" -"gow=(parent.w - 15)\n" -"\n" -"gameoptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder)\n" -"\n" -"# game tab\n" -"opYoffset=vBorder\n" -"gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n" -"gameoptions_id.align=kTextAlignRight\n" -"gameoptions_domain=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight\n" -"gameoptions_name.align=kTextAlignRight\n" -"gameoptions_desc=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2)\n" -"opYoffset=(opYoffset + prev.h + 7)\n" -"gameoptions_lang=gox (opYoffset - 1) gow (kLineHeight + 2)\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"gameoptions_platform=prev.x opYoffset prev.w prev.h\n" -"opYoffset=(opYoffset + prev.h + 5)\n" -"\n" -"# paths tab\n" -"opYoffset=vBorder\n" -"goOff=((buttonHeight - kLineHeight) / 2 + 2)\n" -"gameoptions_savepath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"gameoptions_extrapath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"gameoptions_gamepath=gox opYoffset (buttonWidth + 5) buttonHeight\n" -"gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"\n" -"# graphics tab\n" -"opYoffset=vBorder\n" -"opXoffset=gox\n" -"gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=graphicsControls gameoptions_\n" -"\n" -"# audio tab\n" -"opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=audioControls gameoptions_\n" -"useWithPrefix=subtitleControls gameoptions_\n" -"\n" -"# volume tab\n" -"opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=volumeControls gameoptions_\n" -"\n" -"# midi tab\n" -"opYoffset=vBorder\n" -"gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"useWithPrefix=midiControls gameoptions_\n" -"\n" -"gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"### keys dialog\n" -"keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 4)\n" -"set_parent=keysdialog\n" -"keysdialog_map=(parent.w - buttonWidth - 10) (10 + 2 * kLineHeight) buttonWidth buttonHeight\n" -"keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h\n" -"keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h\n" -"keysdialog_action=10 10 (parent.w - 20) kLineHeight\n" -"keysdialog_action.align=kTextAlignCenter\n" -"keysdialog_list=prev.x (prev.y + 2 * kLineHeight) (parent.w - buttonWidth - 30) (parent.h - kLineHeight * 6)\n" -"keysdialog_mapping=prev.x (prev.y + prev.h + kLineHeight) (parent.w - buttonWidth - 20) kLineHeight\n" -"\n" -"### mass add dialog\n" -"massadddialog=10 20 300 174\n" -"set_parent=massadddialog\n" -"massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_caption.align=kTextAlignCenter\n" -"massadddialog_dirprogress=10 (10 + 3 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_dirprogress.align=kTextAlignCenter\n" -"massadddialog_gameprogress=10 (10 + 4 * kLineHeight) (parent.w - 2*10) kLineHeight\n" -"massadddialog_gameprogress.align=kTextAlignCenter\n" -"massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"\n" -"##### SCUMM dialogs\n" -"scummDummyDialog=0 80 0 16\n" -"\n" -"use=scummmain\n" -"## Engine config\n" -"# note that scummconfig size depends on overall height\n" -"# hence it is on the end of the list\n" -"opYoffset=8\n" -"useWithPrefix=volumeControls scummconfig_\n" -"useWithPrefix=subtitleControls scummconfig_\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"soWidth=(39 + 3 * buttonWidth)\n" -"scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight\n" -"scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h\n" -"scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8)\n" -"\n" -"## Help\n" -"scummHelpNumLines=15\n" -"shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7)\n" -"scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH\n" -"scummhelp_title=10 5 scummhelpW kFontHeight\n" -"scummhelp_key.x=10\n" -"scummhelp_key.yoffset=5\n" -"scummhelp_key.w=80\n" -"scummhelp_key.h=kFontHeight\n" -"scummhelp_dsc.x=90\n" -"scummhelp_dsc.yoffset=5\n" -"scummhelp_dsc.w=(scummhelpW - 10 - 90)\n" -"scummhelp_dsc.h=kFontHeight\n" -"scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) buttonWidth buttonHeight\n" -"scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h\n" -"scummhelp_close=(scummhelpW - 8 - buttonWidth) prev.y prev.w prev.h\n" -"\n" -"# Saveload dialog\n" -"scummsaveload=8 8 (w - 2 * 8) (h - 16)\n" -"set_parent=scummsaveload\n" -"scummsaveload_title=10 2 (parent.w - 2 * 10 - 180) kLineHeight\n" -"scummsaveload_title.align=kTextAlignCenter\n" -"scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y)\n" -"scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 18)) 22\n" -"scummsaveload_thumbnail.hPad=4\n" -"scummsaveload_thumbnail.vPad=4\n" -"scummsaveload_thumbnail.fillR=0\n" -"scummsaveload_thumbnail.fillG=0\n" -"scummsaveload_thumbnail.fillB=0\n" -"scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight\n" -"scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h\n" -"scummsaveload_extinfo.visible=true\n" -"\n" -"############################################\n" -"[chooser]\n" -"chooserW=(w - 2 * 8)\n" -"chooser=((w - chooserW) / 2) ((h - opHeight) / 2) chooserW opHeight\n" -"chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight)\n" -"chooser_headline.align=kTextAlignCenter\n" -"chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12)\n" -"chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight\n" -"chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h\n" -"\n" -"[graphicsControls]\n" -"gcx=10\n" -"gcw=(parent.w - 2 * 10)\n" -"grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + kLineHeight + 4)\n" -"grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h\n" -"opYoffset=(opYoffset + kLineHeight + 4)\n" -"grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"grAspectCheckbox=prev.x opYoffset prev.w prev.h\n" -"opYoffset=(opYoffset + buttonHeight)\n" -"\n" -"[audioControls]\n" -"aux=10\n" -"auw=(parent.w - 2 * 10)\n" -"auMidiPopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"auSampleRatePopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2)\n" -"opYoffset=(opYoffset + buttonHeight + 4)\n" -"\n" -"[volumeControls]\n" -"vctextw=(95 + vcAudioTabIndent)\n" -"vcxoff=(opXoffset + vctextw + 15)\n" -"vcx=(opXoffset + 10)\n" -"vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcMusicText.align=kTextAlignRight\n" -"vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcSfxText.align=kTextAlignRight\n" -"vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight\n" -"vcSpeechText.align=kTextAlignRight\n" -"vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight\n" -"vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing)\n" -"\n" -"[midiControls]\n" -"mcx=10\n" -"mcFontButton=mcx opYoffset buttonWidth buttonHeight\n" -"mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - 15 - kLineHeight - 10) kLineHeight\n" -"mcFontClearButton=(prev.x2 + 10) (opYoffset + 2) kLineHeight kLineHeight\n" -"opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)\n" -"mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcMt32Checkbox=mcx opYoffset prev.w buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcGSCheckbox=mcx opYoffset prev.w buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight\n" -"mcMidiGainText.align=kTextAlignRight\n" -"mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight\n" -"mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + midiControlsSpacing)\n" -"\n" -"[subtitleControls]\n" -"sbx=(opXoffset + 10)\n" -"sbYoff=(buttonHeight / 8)\n" -"sbOff=((sliderHeight - kLineHeight) / 2 + 2)\n" -"sbtextw=(100 + vcAudioTabIndent)\n" -"opYoffset=(opYoffset + sbYoff)\n" -"subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight\n" -"subToggleDesc.align=kTextAlignRight\n" -"subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight\n" -"opYoffset=(opYoffset + buttonHeight + 6)\n" -"subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight\n" -"subSubtitleSpeedDesc.align=kTextAlignRight\n" -"subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight\n" -"subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight\n" -"opYoffset=(opYoffset + sliderHeight + 8)\n" -"\n" -"[scummmain]\n" -"## Main dialog\n" -"# note that scummmain size depends on overall height\n" -"smY=(scummmainVSpace + scummmainVAddOff)\n" -"scummmain_resume=scummmainHOffset smY scummmainButtonWidth scummmainButtonHeight\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_load=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_save=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_options=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_about=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"scummmain_help=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smY=(smY + scummmainVSpace)\n" -"scummmain_quit=prev.x smY prev.w prev.h\n" -"smY=(smY + scummmainButtonHeight + scummmainVAddOff)\n" -"smW=(scummmainButtonWidth + 2 * scummmainHOffset)\n" -"smH=(smY + scummmainVSpace)\n" -"scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH\n" -"\n" -"# PSP GUI\n" -"[480x272]\n" -"def_buttonWidth=100\n" -"def_buttonHeight=23\n" -"def_insetX=20\n" -"def_insetY=10\n" -"def_insetW=(w - 2 * insetX)\n" -"def_insetH=(h - 13 - insetY)\n" -"def_launcherVersionX=50\n" -"def_launcherVersionY=5\n" -"def_midiControlsSpacing=2\n" -"def_gameOptionsOverrideVPad=10\n" -"def_aboutXOff=3\n" -"def_aboutYOff=2\n" -"def_aboutOuterBorder=10\n" -"\n" -"use=XxY\n" -""; - -using Common::String; - -void Theme::processSingleLine(const String §ion, const String &prefix, const String &name, const String &str) { - int level = 0; - int start = 0; - uint i; - int value; - const char *selfpostfixes[] = {"self.x", "self.y", "self.w", "self.h"}; - const char *postfixesXYWH[] = {".x", ".y", ".w", ".h"}; - const char *postfixesRGB[] = {".r", ".g", ".b"}; - int npostfix = 0; - const String prefixedname(prefix + name); - - // Make self.BLAH work, but not self.ANYTHING.BLAH - if (!strchr(prefixedname.c_str(), '.')) { - for (i = 0; i < ARRAYSIZE(postfixesXYWH); i++) { - String to(prefixedname); - - to += postfixesXYWH[i]; - - _evaluator->setAlias(selfpostfixes[i], to); - _evaluator->setVar(to, EVAL_UNDEF_VAR); - } - } - - // Count the number of parameters, so that we know if they're meant to - // be XY[WH] or RGB. - - int ntmppostfix = 0; - - for (i = 0; i < str.size(); i++) { - if (isspace(str[i]) && level == 0) { - ntmppostfix++; - } - - if (str[i] == '(') - level++; - else if (str[i] == ')') { - if (level == 0) { - error("Extra ')' in section: [%s] expression: \"%s\" start is at: %d", - section.c_str(), name.c_str(), start); - } - level--; - } - } - - if (level > 0) - error("Missing ')' in section: [%s] expression: \"%s\" start is at: %d", - section.c_str(), name.c_str(), start); - - const char **postfixes = (ntmppostfix == 2) ? postfixesRGB : postfixesXYWH; - - // Now do it for real, only this time we already know the parentheses - // are balanced. - - for (i = 0; i < str.size(); i++) { - if (isspace(str[i]) && level == 0) { - value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start); - _evaluator->setVar(prefixedname + postfixes[npostfix++], value); - start = i + 1; - } - if (str[i] == '(') - level++; - else if (str[i] == ')') - level--; - } - - value = _evaluator->eval(String(&(str.c_str()[start]), i - start), section, name + postfixes[npostfix], start); - - if (value == EVAL_STRING_VAR) - _evaluator->setStringVar(prefixedname, _evaluator->lastToken()); - - // process VAR=VALUE construct - if (npostfix == 0) { - _evaluator->setVar(name, value); - - // Fix bug #1742561: "GUI: Missaligned text" - // "blah.align=foo" should be prefixed too - _evaluator->setVar(prefixedname, value); - } else { - _evaluator->setVar(prefixedname + postfixes[npostfix], value); - } - - // If we have all 4 parameters, set .x2 and .y2 - if (npostfix == 3) { - _evaluator->setVar(prefixedname + ".x2", - _evaluator->getVar(prefixedname + ".x") + _evaluator->getVar(prefixedname + ".w")); - _evaluator->setVar(prefixedname + ".y2", - _evaluator->getVar(prefixedname + ".y") + _evaluator->getVar(prefixedname + ".h")); - } - - if (npostfix != 0) - setSpecialAlias("prev", prefixedname); -} - - -void Theme::processResSection(Common::ConfigFile &config, const String &name, bool skipDefs, const String &prefix) { - debug(3, "Reading section: [%s]", name.c_str()); - - const Common::ConfigFile::SectionKeyList &keys = config.getKeys(name); - - Common::ConfigFile::SectionKeyList::const_iterator iterk; - for (iterk = keys.begin(); iterk != keys.end(); ++iterk) { - if (iterk->key == "set_parent") { - setSpecialAlias("parent", prefix + iterk->value); - continue; - } - if (iterk->key.hasPrefix("set_")) { - _evaluator->setAlias(iterk->key.c_str() + 4, prefix + iterk->value); - continue; - } - if (iterk->key.hasPrefix("def_")) { - if (!skipDefs) - _evaluator->setVar(name, prefix + iterk->key, iterk->value); - continue; - } - if (iterk->key == "use") { - if (iterk->value == name) - error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(iterk->value)) - error("Undefined use of section [%s]", iterk->value.c_str()); - processResSection(config, iterk->value, true); - continue; - } - if (iterk->key == "useAsIs") { - if (iterk->value == name) - error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(iterk->value)) - error("Undefined use of section [%s]", iterk->value.c_str()); - processResSection(config, iterk->value); - continue; - } - if (iterk->key == "useWithPrefix") { - const char *temp = iterk->value.c_str(); - const char *pos = strrchr(temp, ' '); - - if (pos == NULL) - error("2 arguments required for useWithPrefix keyword"); - - String n(temp, strchr(temp, ' ') - temp); - String pref(pos + 1); - - if (n == name) - error("Theme section [%s]: cannot use itself", n.c_str()); - if (!config.hasSection(n)) - error("Undefined use of section [%s]", n.c_str()); - processResSection(config, n, true, pref); - continue; - } - processSingleLine(name, prefix, iterk->key, iterk->value); - } -} - -void Theme::setSpecialAlias(const String &alias, const String &name) { - const char *postfixes[] = {".x", ".y", ".w", ".h", ".x2", ".y2"}; - int i; - - for (i = 0; i < ARRAYSIZE(postfixes); i++) { - String from(alias + postfixes[i]); - String to(name + postfixes[i]); - - _evaluator->setAlias(from.c_str(), to); - } -} - -bool Theme::isThemeLoadingRequired() { - int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - - if (_loadedThemeX == x && _loadedThemeY == y) - return false; - - _loadedThemeX = x; - _loadedThemeY = y; - - return true; -} - -bool Theme::sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h) { - if (!config.hasKey("skipFor", name)) - return false; - - String res; - - config.getKey("skipFor", name, res); - - int x, y; - int phase = 0; - const char *ptr = res.c_str(); - - x = y = 0; - - while (phase != 3) { - switch (phase) { - case 0: - if (*ptr >= '0' && *ptr <= '9') { - x = x * 10 + *ptr - '0'; - } else if (*ptr == 'X') { - phase = 1; - } else if (*ptr == 'x') { - phase = 1; - } else { - error("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - case 1: - if (*ptr >= '0' && *ptr <= '9') { - y = y * 10 + *ptr - '0'; - } else if (*ptr == 'Y' || !*ptr || *ptr == ',') { - phase = 2; - - if ((x == w || x == 0) && (y == h || y == 0)) - return true; - if (!*ptr) - return false; - if (*ptr == ',') { - phase = x = y = 0; - } - } else { - error("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - case 2: - if (*ptr == ',') { - phase = x = y = 0; - } else if (!*ptr) { - if ((x == w || x == 0) && (y == h || y == 0)) - return true; - return false; - } else { - error ("Syntax error. Wrong resolution in skipFor in section %s", name); - } - break; - default: - break; - } - - ptr++; - } - - return false; -} - -void Theme::loadTheme(Common::ConfigFile &config, bool reset) { - char name[80]; - int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - - if (reset) - _evaluator->reset(); - - strcpy(name, "XxY"); - if (config.hasSection(name) && !sectionIsSkipped(config, "XxY", x, y)) - processResSection(config, name); - - sprintf(name, "%dxY", x); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - sprintf(name, "Xx%d", y); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - sprintf(name, "%dx%d", x, y); - if (config.hasSection(name) && !sectionIsSkipped(config, name, x, y)) - processResSection(config, name); - - debug(3, "Number of variables: %d", _evaluator->getNumVars()); -} - -void Theme::loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing) { - loadTheme(config, reset); - - if (doBackendSpecificPostProcessing && !g_system->getExtraThemeConfig().empty()) { - Common::ConfigFile myConfig; - Common::String myConfigINI = g_system->getExtraThemeConfig(); - Common::MemoryReadStream s((const byte *)myConfigINI.c_str(), myConfigINI.size()); - myConfig.loadFromStream(s); - loadTheme(myConfig, false); - } -} - -} // End of namespace GUI diff --git a/gui/theme.cpp b/gui/theme.cpp index c8501c4f91..45fc047c45 100644 --- a/gui/theme.cpp +++ b/gui/theme.cpp @@ -23,38 +23,13 @@ */ #include "gui/theme.h" -#include "gui/eval.h" - #include "common/unzip.h" namespace GUI { -Theme::Theme() : _drawArea(), _stylefile(""), _configFile(), _loadedThemeX(0), _loadedThemeY(0) { - Common::MemoryReadStream s((const byte *)_defaultConfigINI, strlen(_defaultConfigINI)); - _defaultConfig.loadFromStream(s); - - _evaluator = new Eval(); -} - -Theme::~Theme() { - delete _evaluator; -} - -void Theme::getColorFromConfig(const Common::String &value, OverlayColor &color) { - const char *postfixes[] = {".r", ".g", ".b"}; - int rgb[3]; - - for (int cnt = 0; cnt < 3; cnt++) - rgb[cnt] = _evaluator->getVar(value + postfixes[cnt], 0); +Theme::Theme() : _loadedThemeX(0), _loadedThemeY(0) {} - color = g_system->RGBToColor(rgb[0], rgb[1], rgb[2]); -} - -void Theme::getColorFromConfig(const Common::String &value, uint8 &r, uint8 &g, uint8 &b) { - r = _evaluator->getVar(value + ".r", 0); - g = _evaluator->getVar(value + ".g", 0); - b = _evaluator->getVar(value + ".b", 0); -} +Theme::~Theme() {} const Graphics::Font *Theme::loadFont(const char *filename) { const Graphics::NewFont *font = 0; @@ -68,7 +43,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { return font; #ifdef USE_ZLIB - unzFile zipFile = unzOpen((_stylefile + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName()).c_str()); if (zipFile && unzLocateFile(zipFile, cacheFilename.c_str(), 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); @@ -98,7 +73,7 @@ const Graphics::Font *Theme::loadFont(const char *filename) { #ifdef USE_ZLIB if (!font) { - unzFile zipFile = unzOpen((_stylefile + ".zip").c_str()); + unzFile zipFile = unzOpen((getThemeFileName()).c_str()); if (zipFile && unzLocateFile(zipFile, filename, 2) == UNZ_OK) { unz_file_info fileInfo; unzOpenCurrentFile(zipFile); @@ -146,51 +121,39 @@ Common::String Theme::genCacheFilename(const char *filename) { return ""; } -bool Theme::loadConfigFile(const Common::String &stylefile) { - if (ConfMan.hasKey("themepath")) - Common::File::addDefaultDirectory(ConfMan.get("themepath")); +bool Theme::isThemeLoadingRequired() { + int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); -#ifdef DATA_PATH - Common::File::addDefaultDirectoryRecursive(DATA_PATH); -#endif + if (_loadedThemeX == x && _loadedThemeY == y) + return false; - if (ConfMan.hasKey("extrapath")) - Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); + _loadedThemeX = x; + _loadedThemeY = y; - if (!_configFile.loadFromFile(stylefile + ".ini")) { -#ifdef USE_ZLIB - // Maybe find a nicer solution to this - unzFile zipFile = unzOpen((stylefile + ".zip").c_str()); - if (zipFile && unzLocateFile(zipFile, (stylefile + ".ini").c_str(), 2) == UNZ_OK) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); - if (!_configFile.loadFromStream(stream)) { - unzClose(zipFile); - return false; - } - delete[] buffer; - buffer = 0; - } else { - unzClose(zipFile); - return false; - } - unzClose(zipFile); -#else + return true; +} + +bool Theme::themeConfigParseHeader(Common::String header, Common::String &themeName) { + header.trim(); + + if (header[0] != '[' || header.lastChar() != ']') return false; -#endif - } + + header.deleteChar(0); + header.deleteLastChar(); + + Common::StringTokenizer tok(header, ":"); + + if (tok.nextToken() != SCUMMVM_THEME_VERSION_STR) + return false; + + themeName = tok.nextToken(); + Common::String author = tok.nextToken(); - return true; + return tok.empty(); } -bool Theme::themeConfigUseable(const Common::String &stylefile, const Common::String &style, Common::String *cStyle, Common::ConfigFile *cfg) { +bool Theme::themeConfigUseable(const Common::String &filename, Common::String &themeName) { if (ConfMan.hasKey("themepath")) Common::File::addDefaultDirectory(ConfMan.get("themepath")); @@ -200,62 +163,39 @@ bool Theme::themeConfigUseable(const Common::String &stylefile, const Common::St if (ConfMan.hasKey("extrapath")) Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); - - Common::File file; - Common::ConfigFile configFile; - if (!cfg && (cStyle || !style.empty())) - cfg = &configFile; - - if (!file.open(stylefile + ".ini")) { + #ifdef USE_ZLIB - // Maybe find a nicer solution to this - unzFile zipFile = unzOpen((stylefile + ".zip").c_str()); - if (zipFile && unzLocateFile(zipFile, (stylefile + ".ini").c_str(), 2) == UNZ_OK) { - if (!style.empty() || cStyle || cfg) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); - if (!cfg->loadFromStream(stream)) { - unzClose(zipFile); - return false; - } - delete[] buffer; - buffer = 0; - } - } else { - unzClose(zipFile); - return false; - } - unzClose(zipFile); -#else - return false; -#endif + unzFile zipFile = unzOpen(filename.c_str()); + char stxHeader[128]; + bool foundHeader = false; + + if (zipFile && unzLocateFile(zipFile, "THEMERC", 2) == UNZ_OK) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + uint8 *buffer = new uint8[fileInfo.uncompressed_size+1]; + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(uint8)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + Common::MemoryReadStream stream(buffer, fileInfo.uncompressed_size+1); + stream.readLine(stxHeader, 128); + + if (themeConfigParseHeader(stxHeader, themeName)) + foundHeader = true; + + delete[] buffer; + buffer = 0; } + unzClose(zipFile); +#else + return false; +#endif - if (!style.empty() || cStyle || cfg) { - if (file.isOpen()) { - if (!cfg->loadFromStream(file)) - return false; - file.close(); - } + return foundHeader; +} - Common::String temp; - if (!cfg->getKey("type", "theme", temp)) - return false; - if (cStyle) - *cStyle = temp; - if (0 != temp.compareToIgnoreCase(style) && !style.empty()) - return false; - } - return true; -} } // End of namespace GUI diff --git a/gui/theme.h b/gui/theme.h index 4f61609fbd..f4709067ef 100644 --- a/gui/theme.h +++ b/gui/theme.h @@ -35,43 +35,11 @@ #include "graphics/fontman.h" #define THEME_VERSION 23 +#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_THEME_V23" namespace GUI { -class Eval; - -//! Hint to the theme engine that the widget is used in a non-standard way. -enum ThemeHint { - //! Indicates that this is the first time the widget is drawn. - THEME_HINT_FIRST_DRAW = 1 << 0, - - /** - * Indicates that the widget will be redrawn often, e.g. list widgets. - * It may therefore be a good idea to save the background so that it - * can be redrawn quickly. - */ - THEME_HINT_SAVE_BACKGROUND = 1 << 1, - - //! Indicates that this is the launcher dialog (maybe delete this in the future) - THEME_HINT_MAIN_DIALOG = 1 << 2, - - //! Indicates special colorfade - THEME_HINT_SPECIAL_COLOR = 1 << 3, - - //! Indicates no colorfade - THEME_HINT_PLAIN_COLOR = 1 << 4, - - //! Indictaes that a shadows should be drawn around the background - THEME_HINT_USE_SHADOW = 1 << 5, - - /** - * Indicates that no background should be restored when drawing the widget - * (note that this can be silently ignored if for example the theme does - * alpha blending and would blend over an already drawn widget) - * TODO: currently only ThemeModern::drawButton supports this - */ - THEME_HINT_NO_BACKGROUND_RESTORE = 1 << 6 -}; +class ThemeEval; /** * Our theme renderer class. @@ -92,6 +60,13 @@ public: kTextAlignCenter, //! Text should be centered kTextAlignRight //! Text should be aligned to the right }; + + //! Vertical alignment of the text. + enum TextAlignVertical { + kTextAlignVBottom, + kTextAlignVCenter, + kTextAlignVTop + }; //! Widget background type enum WidgetBackground { @@ -102,6 +77,14 @@ public: kWidgetBackgroundEditText, //! Background used for edit text fields kWidgetBackgroundSlider //! Background used for sliders }; + + //! Dialog background type + enum DialogBackground { + kDialogBackgroundMain, + kDialogBackgroundSpecial, + kDialogBackgroundPlain, + kDialogBackgroundDefault + }; //! State of the widget to be drawn enum State { @@ -222,7 +205,7 @@ public: * * @see closeAllDialogs */ - virtual void openDialog(bool topDialog) = 0; + virtual void openDialog(bool topDialog, ShadingStyle shading = kShadingNone) = 0; /** * This indicates that all dialogs have been closed. @@ -232,6 +215,21 @@ public: virtual void closeAllDialogs() = 0; /** + * Closes the topmost dialog, and redraws the screen + * accordingly. + * + * TODO: Make this purely virtual by making ThemeClassic + * and ThemeModern implement it too. + * + * @returns True if the dialog was sucessfully closed. + * If we weren't able to restore the screen after closing + * the dialog, we return false, which means we need to redraw + * the dialog stack from scratch. + */ + virtual void startBuffering() = 0; + virtual void finishBuffering() = 0; + + /** * Clear the complete GUI screen. */ virtual void clearAll() = 0; @@ -244,42 +242,12 @@ public: */ virtual void updateScreen() = 0; - /** - * Set the active screen area, in which the renderer is able to - * draw. - * - * This does not affect the coordinates for the draw* functions, - * it just marks the screen rect given in param r as writeable. - * - * This is for example used in the credits dialog, which, if not - * just a part of the screen would be marked as writeable, would - * draw parts of the scrolling text outside the dialog box and - * thus would look strange. - * - * The active area defaults to the whole screen, so there is just - * need to use this function if you want to limit it. - * - * @param r rect of the screen, which should be writeable - * - * @see resetDrawArea - */ - virtual void setDrawArea(const Common::Rect &r) { _drawArea = r; } - - /** - * Resets the draw area to the whole screen. - * - * @see setDrawArea - */ - virtual void resetDrawArea() = 0; - - virtual const Common::ConfigFile &getConfigFile() const { return _configFile; } - virtual const Graphics::Font *getFont(FontStyle font = kFontStyleBold) const = 0; virtual int getFontHeight(FontStyle font = kFontStyleBold) const = 0; virtual int getStringWidth(const Common::String &str, FontStyle font = kFontStyleBold) const = 0; virtual int getCharWidth(byte c, FontStyle font = kFontStyleBold) const = 0; - virtual void drawDialogBackground(const Common::Rect &r, uint16 hints, WidgetStateInfo state = kStateEnabled) = 0; + virtual void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled) = 0; virtual void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, TextAlign align = kTextAlignCenter, bool inverted = false, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold) = 0; // this should ONLY be used by the debugger until we get a nicer solution virtual void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled) = 0; @@ -333,20 +301,16 @@ public: return kTextAlignCenter; } - void processResSection(Common::ConfigFile &config, const Common::String &name, bool skipDefs = false, const Common::String &prefix = ""); - void processSingleLine(const Common::String §ion, const Common::String &prefix, const Common::String &name, const Common::String &str); - void setSpecialAlias(const Common::String &alias, const Common::String &name); bool isThemeLoadingRequired(); - bool sectionIsSkipped(Common::ConfigFile &config, const char *name, int w, int h); - void loadTheme(Common::ConfigFile &config, bool reset = true); - void loadTheme(Common::ConfigFile &config, bool reset, bool doBackendSpecificPostProcessing); - Eval *_evaluator; + virtual ThemeEval *evaluator() = 0; - static bool themeConfigUseable(const Common::String &file, const Common::String &style="", Common::String *cStyle=0, Common::ConfigFile *cfg=0); + static bool themeConfigUseable(const Common::String &file, Common::String &themeName); + static bool themeConfigParseHeader(Common::String header, Common::String &themeName); - const Common::String &getStylefileName() const { return _stylefile; } - const Common::String &getThemeName() const { return _stylename; } + virtual const Common::String &getThemeFileName() const = 0; + virtual const Common::String &getThemeName() const = 0; + virtual int getThemeRenderer() const = 0; /** * Checks if the theme renderer supports drawing of images. @@ -370,19 +334,10 @@ public: */ virtual const Graphics::Surface *getImageSurface(const kThemeImages n) const { return 0; } protected: - bool loadConfigFile(const Common::String &file); - void getColorFromConfig(const Common::String &name, OverlayColor &col); - void getColorFromConfig(const Common::String &value, uint8 &r, uint8 &g, uint8 &b); const Graphics::Font *loadFont(const char *filename); Common::String genCacheFilename(const char *filename); - Common::String _stylefile, _stylename; - - Common::Rect _drawArea; - Common::ConfigFile _configFile; - Common::ConfigFile _defaultConfig; - public: bool needThemeReload() { return ((_loadedThemeX != g_system->getOverlayWidth()) || (_loadedThemeY != g_system->getOverlayHeight())); } diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 98e6df8565..490248619b 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -43,21 +43,21 @@ enum { // but for now this simple browser works, // also it will get its own theme config values // and not use 'browser_' anymore -ThemeBrowser::ThemeBrowser() : Dialog("browser") { +ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _fileList = 0; - new StaticTextWidget(this, "browser_headline", "Select a Theme"); + new StaticTextWidget(this, "Browser.Headline", "Select a Theme"); // Add file list - _fileList = new ListWidget(this, "browser_list"); + _fileList = new ListWidget(this, "Browser.List"); _fileList->setNumberingMode(kListNumberingOff); _fileList->setEditable(false); - _fileList->setHints(THEME_HINT_PLAIN_COLOR); + _backgroundType = GUI::Theme::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "browser_cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "browser_choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); } void ThemeBrowser::open() { @@ -91,9 +91,8 @@ void ThemeBrowser::updateListing() { // classic is always build in Entry th; - th.name = "Classic (Builtin)"; - th.type = "Classic"; - th.file = "Classic (Builtin)"; + th.name = "ScummVM Classic Theme (Builtin Version)"; + th.file = "builtin"; _themes.push_back(th); // we are using only the paths 'themepath', 'extrapath', DATA_PATH and '.' @@ -172,28 +171,14 @@ void ThemeBrowser::addDir(ThList &list, const Common::String &dir, int level) { } bool ThemeBrowser::isTheme(const FilesystemNode &node, Entry &out) { - Common::ConfigFile cfg; - Common::String type; - out.file = node.getName(); - for (int i = out.file.size()-1; out.file[i] != '.' && i > 0; --i) { - out.file.deleteLastChar(); - } - out.file.deleteLastChar(); - - if (out.file.empty()) + + if (!out.file.hasSuffix(".zip")) return false; - - if (!Theme::themeConfigUseable(out.file, "", &type, &cfg)) + + if (!Theme::themeConfigUseable(out.file, out.name)) return false; - out.type = type; - - if (cfg.hasKey("name", "theme")) - cfg.getKey("name", "theme", out.name); - else - out.name = out.file; - return true; } diff --git a/gui/themebrowser.h b/gui/themebrowser.h index 9351648d24..7a3bc2ca7d 100644 --- a/gui/themebrowser.h +++ b/gui/themebrowser.h @@ -46,7 +46,6 @@ public: private: struct Entry { Common::String name; - Common::String type; Common::String file; }; diff --git a/gui/themes/classic080.ini b/gui/themes/classic080.ini deleted file mode 100644 index b5c911bada..0000000000 --- a/gui/themes/classic080.ini +++ /dev/null @@ -1,466 +0,0 @@ -# $URL$ -# $Id$ -[theme] -version=23 -type=classic -name=Classic (ScummVM 0.8.0) - -[colors] -color=104 104 104 -shadowcolor=64 64 64 -bgcolor=0 0 0 -textcolor=32 160 32 -textcolorhi=0 255 0 - -[extra] -font="builtin" -blending=true - -[XxY] -def_widgetSize=kBigWidgetSize -def_buttonWidth=kBigButtonWidth -def_buttonHeight=kBigButtonHeight -def_sliderWidth=kBigSliderWidth -def_sliderHeight=kBigSliderHeight -def_kLineHeight=16 -def_kFontHeight=14 -def_insetX=10 -def_insetY=20 -def_insetW=(w - 2 * 10) -def_insetH=(h - 2 * 40) -def_gameOptionsLabelWidth=90 -def_tabPopupsLabelW=150 -def_aboutXOff=8 -def_aboutYOff=5 -def_aboutOuterBorder=80 -def_scummmainHOffset=12 -def_scummmainVSpace=7 -def_scummmainVAddOff=3 -def_scummmainButtonWidth=160 -def_scummmainButtonHeight=28 -def_scummhelpW=370 -def_scummhelpX=((w - scummhelpW) / 2) -def_midiControlsSpacing=2 -def_vcAudioTabIndent=10 -def_vcAudioTabSpacing=4 - -use=colors -use=extra - -##### Widgets config -ListWidget.leftPadding=4 -ListWidget.rightPadding=0 -ListWidget.topPadding=2 -ListWidget.bottomPadding=2 -ListWidget.hlLeftPadding=2 -ListWidget.hlRightPadding=1 -PopUpWidget.leftPadding=4 -PopUpWidget.rightPadding=0 -TabWidget.tabWidth=70 -TabWidget.tabHeight=21 -TabWidget.titleVPad=2 - -###### chooser -opHeight=(h * 7 / 10) -useWithPrefix=chooser defaultChooser_ - -##### browser -brW=((w * 7) / 8) -brH=((h * 9) / 10) -browser=((w - brW) / 2) ((h - brH) / 2) brW brH -set_parent=browser -browser_headline=10 kLineHeight (parent.w - 2 * 10) kLineHeight -browser_headline.align=kTextAlignCenter -browser_path=10 prev.y2 prev.w prev.h -browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) -browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_choose=(prev.x2 + 10) prev.y prev.w prev.h - -##### launcher -hBorder=10 -launcher_version=hBorder 8 (w - 2 * hBorder) kLineHeight -launcher_version.align=kTextAlignCenter -top=(h - 8 - buttonHeight) -numButtons=4 -space=8 -butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons) -launcher_quit_button=hBorder top butWidth buttonHeight -launcher_about_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_options_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_start_button=(prev.x2 + space) prev.y prev.w prev.h -top=(top - buttonHeight * 2) -numButtons=3 -space=10 -butWidth=((w - 2 * hBorder - space * (numButtons - 1)) / numButtons) -launcher_addGame_button=hBorder top butWidth buttonHeight -launcher_editGame_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_removeGame_button=(prev.x2 + space) prev.y prev.w prev.h -launcher_list=hBorder (kLineHeight + 16) (w - 2 * hBorder) (top - kLineHeight - 20) - -### global options -globaloptions=insetX insetY insetW insetH -set_parent=globaloptions -vBorder=5 -globaloptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder) - -# graphics tab -opYoffset=vBorder -opXoffset=0 -useWithPrefix=graphicsControls globaloptions_ - -# audio tab -opYoffset=vBorder -useWithPrefix=audioControls globaloptions_ -useWithPrefix=subtitleControls globaloptions_ - -# volume tab -opYoffset=vBorder -useWithPrefix=volumeControls globaloptions_ - -# MIDI tab -opYoffset=vBorder -useWithPrefix=midiControls globaloptions_ - -# paths tab -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_savebutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_extrabutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_themebutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_pluginsbutton=10 yoffset (buttonWidth + 5) buttonHeight -globaloptions_pluginspath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 15) kLineHeight -yoffset=(yoffset + buttonHeight + 4) -globaloptions_keysbutton=10 yoffset (buttonWidth + 5) buttonHeight - -# Misc options -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight -globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 12) -globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) (kLineHeight + 2) - -globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h - -### game options -gameoptions=insetX insetY insetW insetH -set_parent=gameoptions -vBorder=5 -gox=5 -gow=(parent.w - 15) - -gameoptions_tabwidget=0 vBorder parent.w (parent.h - buttonHeight - 8 - 2 * vBorder) - -# game tab -opYoffset=vBorder -gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight -gameoptions_id.align=kTextAlignRight -gameoptions_domain=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2) -opYoffset=(opYoffset + prev.h + 5) -gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight -gameoptions_name.align=kTextAlignRight -gameoptions_desc=prev.x2 (prev.y - 1) (parent.w - gameOptionsLabelWidth - 10 - gox) (prev.h + 2) -opYoffset=(opYoffset + prev.h + 7) -gameoptions_lang=gox (opYoffset - 1) gow (kLineHeight + 2) -opYoffset=(opYoffset + prev.h + 5) -gameoptions_platform=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + prev.h + 5) - -# paths tab -opYoffset=vBorder -goOff=((buttonHeight - kLineHeight) / 2 + 2) -gameoptions_savepath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) -gameoptions_extrapath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) -gameoptions_gamepath=gox opYoffset (buttonWidth + 5) buttonHeight -gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 4) - -# graphics tab -opYoffset=vBorder -opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=graphicsControls gameoptions_ - -# audio tab -opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=audioControls gameoptions_ -useWithPrefix=subtitleControls gameoptions_ - -# volume tab -opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=volumeControls gameoptions_ - -# midi tab -opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -useWithPrefix=midiControls gameoptions_ - -gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h - -### keys dialog -keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5) -set_parent=keysdialog -keysdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight -keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y) -keysdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight -keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h - -### mass add dialog -massadddialog=10 20 300 174 -set_parent=massadddialog -massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight -massadddialog_caption.align=kTextAlignCenter -massadddialog_dirprogress=10 (10 + 3 * kLineHeight) prev.w prev.h -massadddialog_dirprogress.align=kTextAlignCenter -massadddialog_gameprogress=10 (10 + 4 * kLineHeight) prev.w prev.h -massadddialog_gameprogress.align=kTextAlignCenter -massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h - - -##### SCUMM dialogs -scummDummyDialog=0 80 0 16 - -use=scummmain -## Engine config -# note that scummconfig size depends on overall height -# hence it is on the end of the list -opYoffset=8 -useWithPrefix=volumeControls scummconfig_ -useWithPrefix=subtitleControls scummconfig_ -opYoffset=(opYoffset + buttonHeight) -opYoffset=(opYoffset + buttonHeight + 4) -soWidth=(39 + 3 * buttonWidth) -scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight -scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h -scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h -opYoffset=(opYoffset + buttonHeight) -scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8) - -## Help -scummHelpNumLines=15 -shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7) -scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH -scummhelp_title=10 5 scummhelpW kFontHeight -scummhelp_key.x=10 -scummhelp_key.yoffset=5 -scummhelp_key.w=80 -scummhelp_key.h=kFontHeight -scummhelp_dsc.x=90 -scummhelp_dsc.yoffset=5 -scummhelp_dsc.w=(scummhelpW - 10 - 90) -scummhelp_dsc.h=kFontHeight -scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) buttonWidth buttonHeight -scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h -scummhelp_close=(scummhelpW - 8 - buttonWidth) prev.y prev.w prev.h - -# Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10 - 180) kLineHeight -scummsaveload_title.align=kTextAlignCenter -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 18)) 22 -scummsaveload_thumbnail.hPad=4 -scummsaveload_thumbnail.vPad=4 -scummsaveload_thumbnail.fillR=0 -scummsaveload_thumbnail.fillG=0 -scummsaveload_thumbnail.fillB=0 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=true - -############################################ -[chooser] -chooserW=(w - 2 * 8) -chooser=((w - chooserW) / 2) ((h - opHeight) / 2) chooserW opHeight -chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight) -chooser_headline.align=kTextAlignCenter -chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12) -chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight -chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h - -[graphicsControls] -gcx=10 -gcw=(parent.w - 2 * 10) -grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + kLineHeight + 4) -grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h -opYoffset=(opYoffset + kLineHeight + 4) -grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight) -grAspectCheckbox=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + buttonHeight) - -[audioControls] -aux=10 -auw=(parent.w - 2 * 10) -auMidiPopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + buttonHeight + 4) -auSampleRatePopup=(aux - 5) (opYoffset - 1) (auw + 5) (kLineHeight + 2) -opYoffset=(opYoffset + buttonHeight + 4) - -[volumeControls] -vctextw=(95 + vcAudioTabIndent) -vcxoff=(opXoffset + vctextw + 15) -vcx=(opXoffset + 10) -vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight -vcMusicText.align=kTextAlignRight -vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight -vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) -vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight -vcSfxText.align=kTextAlignRight -vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) -vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight -vcSpeechText.align=kTextAlignRight -vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + vcAudioTabSpacing) - -[midiControls] -mcx=10 -mcFontButton=mcx opYoffset buttonWidth buttonHeight -mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight -mcFontClearButton=(prev.x2 + 10) (opYoffset + 3) kLineHeight kLineHeight -opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing) -mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMt32Checkbox=mcx opYoffset prev.w buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcGSCheckbox=mcx opYoffset prev.w buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight -mcMidiGainText.align=kTextAlignRight -mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight -mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight -opYoffset=(opYoffset + sliderHeight + midiControlsSpacing) - -[subtitleControls] -sbx=(opXoffset + 10) -sbYoff=(buttonHeight / 8) -sbOff=((sliderHeight - kLineHeight) / 2 + 2) -sbtextw=(100 + vcAudioTabIndent) -opYoffset=(opYoffset + sbYoff) -subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight -subToggleDesc.align=kTextAlignRight -subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) -subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight -subSubtitleSpeedDesc.align=kTextAlignRight -subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight -subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 8) - -[scummmain] -## Main dialog -# note that scummmain size depends on overall height -smY=(scummmainVSpace + scummmainVAddOff) -scummmain_resume=scummmainHOffset smY scummmainButtonWidth scummmainButtonHeight -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_load=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_save=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_options=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_about=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -scummmain_help=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_quit=prev.x smY prev.w prev.h -smY=(smY + scummmainButtonHeight + scummmainVAddOff) -smW=(scummmainButtonWidth + 2 * scummmainHOffset) -smH=(smY + scummmainVSpace) -scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH - -# Define our classic greenish theme here -[320xY] -def_widgetSize=kNormalWidgetSize -def_buttonWidth=kButtonWidth -def_buttonHeight=kButtonHeight -def_sliderWidth=kSliderWidth -def_sliderHeight=kSliderHeight -def_kLineHeight=12 -def_kFontHeight=10 -def_insetX=10 -def_insetY=10 -def_insetW=(w - 2 * 10) -def_insetH=(h - 30) -def_gameOptionsLabelWidth=60 -def_tabPopupsLabelW=100 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 -def_scummmainHOffset=8 -def_scummmainVSpace=5 -def_scummmainVAddOff=2 -def_scummmainButtonWidth=90 -def_scummmainButtonHeight=16 -def_scummhelpX=5 -def_scummhelpW=(w - 2 * 5) -def_midiControlsSpacing=1 -def_vcAudioTabIndent=0 -def_vcAudioTabSpacing=2 -use=XxY - -TabWidget.tabWidth=0 -TabWidget.tabHeight=16 -TabWidget.titleVPad=2 -# Scumm Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10) kLineHeight -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=false - -# MM NES resolution -[256x240] -useAsIs=320xY - -# PSP GUI -[480x272] -def_buttonWidth=100 -def_buttonHeight=23 -def_insetX=20 -def_insetY=10 -def_insetW=(w - 2 * insetX) -def_insetH=(h - 13 - insetY) -def_launcherVersionX=50 -def_launcherVersionY=5 -def_midiControlsSpacing=2 -def_gameOptionsOverrideVPad=10 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 - -use=XxY diff --git a/gui/themes/default.inc b/gui/themes/default.inc new file mode 100644 index 0000000000..ce7fc16cfc --- /dev/null +++ b/gui/themes/default.inc @@ -0,0 +1,1378 @@ +"<render_info> " +"<palette> " +"<color name = 'black' " +"rgb = '0, 0, 0' " +"/> " +"<color name = 'lightgrey' " +"rgb = '104, 104, 104' " +"/> " +"<color name = 'darkgrey' " +"rgb = '64, 64, 64' " +"/> " +"<color name = 'green' " +"rgb = '32, 160, 32' " +"/> " +"<color name = 'green2' " +"rgb = '0, 255, 0' " +"/> " +"</palette> " +"<fonts> " +"<font id = 'text_default' " +"file = 'default' " +"color = 'green' " +"/> " +"<font id = 'text_hover' " +"file = 'default' " +"color = 'green2' " +"/> " +"<font id = 'text_disabled' " +"file = 'default' " +"color = 'lightgrey' " +"/> " +"<font id = 'text_inverted' " +"file = 'default' " +"color = 'black' " +"/> " +"<font id = 'text_button' " +"file = 'default' " +"color = 'green' " +"/> " +"<font id = 'text_button_hover' " +"file = 'default' " +"color = 'green2' " +"/> " +"<font id = 'text_normal' " +"file = 'default' " +"color = 'green' " +"/> " +"</fonts> " +"<defaults fill = 'foreground' fg_color = 'darkgrey' bg_color = 'black' shadow = '0' bevel_color = 'lightgrey'/> " +"<drawdata id = 'text_selection' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'green' " +"/> " +"</drawdata> " +"<drawdata id = 'mainmenu_bg' cache = false> " +"<drawstep func = 'fill' " +"fill = 'foreground' " +"fg_color = 'black' " +"/> " +"</drawdata> " +"<drawdata id = 'special_bg' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"/> " +"</drawdata> " +"<drawdata id = 'separator' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"height = '2' " +"ypos = 'center' " +"fg_color = 'lightgrey' " +"/> " +"</drawdata> " +"<drawdata id = 'scrollbar_base' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"/> " +"</drawdata> " +"<drawdata id = 'scrollbar_handle_hover' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'green2' " +"/> " +"</drawdata> " +"<drawdata id = 'scrollbar_handle_idle' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'green' " +"/> " +"</drawdata> " +"<drawdata id = 'scrollbar_button_idle' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"<drawstep func = 'triangle' " +"fg_color = 'green' " +"fill = 'foreground' " +"width = 'auto' " +"height = 'auto' " +"xpos = 'center' " +"ypos = 'center' " +"orientation = 'top' " +"/> " +"</drawdata> " +"<drawdata id = 'scrollbar_button_hover' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"<drawstep func = 'triangle' " +"fg_color = 'green2' " +"fill = 'foreground' " +"width = 'auto' " +"height = 'auto' " +"xpos = 'center' " +"ypos = 'center' " +"orientation = 'top' " +"/> " +"</drawdata> " +"<drawdata id = 'tab_active' cache = false> " +"<text font = 'text_hover' " +"vertical_align = 'center' " +"horizontal_align = 'center' " +"/> " +"<drawstep func = 'tab' " +"bevel = '2' " +"radius = '0' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'tab_inactive' cache = false> " +"<text font = 'text_default' " +"vertical_align = 'center' " +"horizontal_align = 'center' " +"/> " +"<drawstep func = 'tab' " +"bevel = '2' " +"radius = '0' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'tab_background' cache = false> " +"</drawdata> " +"<drawdata id = 'widget_slider' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'slider_disabled' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'lightgrey' " +"/> " +"</drawdata> " +"<drawdata id = 'slider_full' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'green' " +"/> " +"</drawdata> " +"<drawdata id = 'slider_hover' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'green2' " +"/> " +"</drawdata> " +"<drawdata id = 'widget_small' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'popup_idle' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"<drawstep func = 'triangle' " +"fg_color = 'green' " +"fill = 'foreground' " +"width = 'height' " +"height = 'auto' " +"xpos = 'right' " +"ypos = 'center' " +"orientation = 'bottom' " +"/> " +"<text font = 'text_default' " +"vertical_align = 'center' " +"horizontal_align = 'right' " +"/> " +"</drawdata> " +"<drawdata id = 'popup_hover' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"<drawstep func = 'triangle' " +"fg_color = 'green2' " +"fill = 'foreground' " +"width = 'height' " +"height = 'auto' " +"xpos = 'right' " +"ypos = 'center' " +"orientation = 'bottom' " +"/> " +"<text font = 'text_hover' " +"vertical_align = 'center' " +"horizontal_align = 'right' " +"/> " +"</drawdata> " +"<drawdata id = 'widget_textedit' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'plain_bg' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"/> " +"</drawdata> " +"<drawdata id = 'caret' cache = false> " +"<drawstep func = 'square' " +"fill = 'foreground' " +"fg_color = 'lightgrey' " +"/> " +"</drawdata> " +"<drawdata id = 'default_bg' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"/> " +"</drawdata> " +"<drawdata id = 'button_idle' cache = false> " +"<text font = 'text_button' " +"vertical_align = 'center' " +"horizontal_align = 'center' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'button_hover' cache = false> " +"<text font = 'text_button_hover' " +"vertical_align = 'center' " +"horizontal_align = 'center' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'button_disabled' cache = false> " +"<text font = 'text_disabled' " +"vertical_align = 'center' " +"horizontal_align = 'center' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'checkbox_disabled' cache = false> " +"<text font = 'text_disabled' " +"vertical_align = 'top' " +"horizontal_align = 'left' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'checkbox_selected' cache = false> " +"<text font = 'text_default' " +"vertical_align = 'top' " +"horizontal_align = 'left' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"<drawstep func = 'cross' " +"fill = 'foreground' " +"stroke = '2' " +"fg_color = 'green' " +"/> " +"</drawdata> " +"<drawdata id = 'checkbox_default' cache = false> " +"<text font = 'text_default' " +"vertical_align = 'top' " +"horizontal_align = 'left' " +"/> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"fill = 'none' " +"/> " +"</drawdata> " +"<drawdata id = 'widget_default' cache = false> " +"<drawstep func = 'bevelsq' " +"bevel = '2' " +"/> " +"</drawdata> " +"</render_info> " +"<layout_info resolution = '-320xY, -256x240'> " +"<globals> " +"<def var = 'Line.Height' value = '16' /> " +"<def var = 'Font.Height' value = '16' /> " +"<def var = 'TabLabelWidth' value = '110' /> " +"<def var = 'WidgetSize' value = 'kBigWidgetSize' /> " +"<def var = 'About.OuterBorder' value = '80'/> " +"<def var = 'PopUpWidget.labelSpacing' value = '10' /> " +"<def var = 'Layout.Spacing' value = '8' /> " +"<def var = 'ShowLauncherLogo' value = '0'/> " +"<def var = 'ScummSaveLoad.ExtInfo.Visible' value = '1'/> " +"<widget name = 'OptionsLabel' " +"size = '110, Globals.Line.Height' " +"/> " +"<widget name = 'SmallLabel' " +"size = '24, Globals.Line.Height' " +"/> " +"<widget name = 'ShortOptionsLabel' " +"size = '60, Globals.Line.Height' " +"/> " +"<widget name = 'Button' " +"size = 'kBigButtonWidth, kBigButtonHeight' " +"/> " +"<widget name = 'Slider' " +"size = 'kBigSliderWidth, kBigSliderHeight' " +"/> " +"<widget name = 'PopUp' " +"size = '-1, 19' " +"/> " +"<widget name = 'Checkbox' " +"size = '-1, 14' " +"/> " +"<widget name = 'ListWidget' " +"padding = '5, 0, 8, 0' " +"/> " +"<widget name = 'PopUpWidget' " +"padding = '7, 5, 0, 0' " +"/> " +"<widget name = 'EditTextWidget' " +"padding = '5, 5, 0, 0' " +"/> " +"<widget name = 'Console' " +"padding = '7, 5, 5, 5' " +"/> " +"<widget name = 'TabWidget.Tab' " +"size = '75, 27' " +"padding = '0, 0, 8, 0' " +"/> " +"<widget name = 'TabWidget.NavButton' " +"size = '15, 18' " +"padding = '0, 3, 4, 0' " +"/> " +"</globals> " +"<dialog name = 'Launcher' overlays = 'screen'> " +"<layout type = 'vertical' center = 'true' padding = '16, 16, 8, 8'> " +"<widget name = 'Version' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'GameList'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> " +"<widget name = 'AddGameButton' " +"height = '20' " +"/> " +"<widget name = 'EditGameButton' " +"height = '20' " +"/> " +"<widget name = 'RemoveGameButton' " +"height = '20' " +"/> " +"</layout> " +"<space size = '12'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> " +"<widget name = 'QuitButton' " +"height = '20' " +"/> " +"<widget name = 'AboutButton' " +"height = '20' " +"/> " +"<widget name = 'OptionsButton' " +"height = '20' " +"/> " +"<widget name = 'StartButton' " +"height = '20' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'Browser' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<widget name = 'Headline' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'Path' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'List'/> " +"<layout type = 'horizontal' padding = '0, 0, 16, 0'> " +"<widget name = 'Up' " +"type = 'Button' " +"/> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Choose' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> " +"<layout type = 'vertical' padding = '0, 0, 0, 0'> " +"<widget name = 'TabWidget'/> " +"<layout type = 'horizontal' padding = '16, 16, 16, 16'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'grModePopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'grRenderPopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'grAspectCheckbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'grFullscreenCheckbox' " +"type = 'Checkbox' " +"/> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'auMidiPopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'auSampleRatePopup' " +"type = 'PopUp' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'subToggleDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subToggleButton' " +"width = '150' " +"height = 'Globals.Slider.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'subSubtitleSpeedDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subSubtitleSpeedSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'subSubtitleSpeedLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"</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'> " +"<widget name = 'vcMusicText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcMusicSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcMusicLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'vcSfxText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSfxSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSfxLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'vcSpeechText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSpeechSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSpeechLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'mcFontButton' " +"type = 'Button' " +"/> " +"<widget name = 'mcFontClearButton' " +"height = 'Globals.Line.Height' " +"width = 'Globals.Line.Height' " +"/> " +"<widget name = 'mcFontPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<widget name = 'mcMixedCheckbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'mcMt32Checkbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'mcGSCheckbox' " +"type = 'Checkbox' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'mcMidiGainText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'mcMidiGainSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'mcMidiGainLabel' " +"width = '32' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'SaveButton' " +"type = 'Button' " +"/> " +"<widget name = 'SavePath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'ThemeButton' " +"type = 'Button' " +"/> " +"<widget name = 'ThemePath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'ExtraButton' " +"type = 'Button' " +"/> " +"<widget name = 'ExtraPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'PluginsButton' " +"type = 'Button' " +"/> " +"<widget name = 'PluginsPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'ThemeButton' " +"type = 'Button' " +"/> " +"<widget name = 'CurTheme' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<widget name = 'Renderer' " +"type = 'PopUp' " +"/> " +"<widget name = 'AutosavePeriod' " +"type = 'PopUp' " +"/> " +"</layout> " +"</dialog> " +"<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 = '16, 16, 16, 4'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Graphics' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Audio' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_MIDI' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Volume' /> " +"</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 = '16'> " +"<widget name = 'Id' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'Domain' " +"type = 'PopUp' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'Name' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'Desc' " +"type = 'PopUp' " +"/> " +"</layout> " +"<widget name = 'Lang' " +"type = 'PopUp' " +"/> " +"<widget name = 'Platform' " +"type = 'PopUp' " +"/> " +"</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 = '16' center = 'true'> " +"<widget name = 'Savepath' " +"type = 'Button' " +"/> " +"<widget name = 'SavepathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> " +"<widget name = 'Extrapath' " +"type = 'Button' " +"/> " +"<widget name = 'ExtrapathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> " +"<widget name = 'Gamepath' " +"type = 'Button' " +"/> " +"<widget name = 'GamepathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummMain' overlays = 'screen_center'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<widget name = 'Resume' " +"type = 'Button' " +"/> " +"<space size = '15'/> " +"<widget name = 'Load' " +"type = 'Button' " +"/> " +"<widget name = 'Save' " +"type = 'Button' " +"/> " +"<space size = '15'/> " +"<widget name = 'Options' " +"type = 'Button' " +"/> " +"<widget name = 'Help' " +"type = 'Button' " +"/> " +"<widget name = 'About' " +"type = 'Button' " +"/> " +"<space size = '15'/> " +"<widget name = 'Quit' " +"type = 'Button' " +"/> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummConfig' overlays = 'screen_center'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcMusicText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcMusicSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcMusicLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcSfxText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSfxSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSfxLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcSpeechText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSpeechSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSpeechLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'subToggleDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subToggleButton' " +"width = '158' " +"height = 'Globals.Slider.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'subSubtitleSpeedDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subSubtitleSpeedSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'subSubtitleSpeedLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<space size = '60'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<space size = 'Globals.Button.Width' /> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> " +"<layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'> " +"<widget name = 'Title' " +"height = 'Globals.Line.Height' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'> " +"<widget name = 'List' /> " +"<widget name = 'Thumbnail' " +"width = '180' " +"height = '200' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Choose' " +"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 = '320' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'HelpText' " +"height = '220' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 16, 0'> " +"<widget name = 'Prev' " +"type = 'Button' " +"/> " +"<widget name = 'Next' " +"type = 'Button' " +"/> " +"<space size = '32'/> " +"<widget name = 'Close' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"</layout_info> " +"<layout_info resolution = '320xY, 256x240'> " +"<globals> " +"<def var = 'Line.Height' value = '12' /> " +"<def var = 'Font.Height' value = '10' /> " +"<def var = 'TabLabelWidth' value = '100' /> " +"<def var = 'WidgetSize' value = 'kNormalWidgetSize' /> " +"<def var = 'About.OuterBorder' value = '10'/> " +"<def var = 'PopUpWidget.labelSpacing' value = '6' /> " +"<def var = 'Layout.Spacing' value = '8'/> " +"<def var = 'ShowLauncherLogo' value = '0'/> " +"<def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> " +"<widget name = 'Button' " +"size = 'kButtonWidth, kButtonHeight' " +"/> " +"<widget name = 'Slider' " +"size = 'kSliderWidth, kSliderHeight' " +"/> " +"<widget name = 'OptionsLabel' " +"size = '110, Globals.Line.Height' " +"/> " +"<widget name = 'SmallLabel' " +"size = '18, Globals.Line.Height' " +"/> " +"<widget name = 'PopUp' " +"size = '-1, 15' " +"/> " +"<widget name = 'Checkbox' " +"size = '-1, Globals.Line.Height' " +"/> " +"<widget name = 'ListWidget' " +"padding = '5, 0, 8, 0' " +"/> " +"<widget name = 'PopUpWidget' " +"padding = '7, 5, 0, 0' " +"/> " +"<widget name = 'EditTextWidget' " +"padding = '5, 5, 0, 0' " +"/> " +"<widget name = 'Console' " +"padding = '7, 5, 5, 5' " +"/> " +"<widget name = 'TabWidget.Tab' " +"size = '45, 16' " +"padding = '0, 0, 2, 0' " +"/> " +"<widget name = 'TabWidget.NavButton' " +"size = '32, 18' " +"padding = '0, 3, 4, 0' " +"/> " +"</globals> " +"<dialog name = 'Launcher' overlays = 'screen'> " +"<layout type = 'vertical' center = 'true' padding = '8, 8, 4, 4'> " +"<widget name = 'Version' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'GameList'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> " +"<widget name = 'AddGameButton' " +"height = '12' " +"/> " +"<widget name = 'EditGameButton' " +"height = '12' " +"/> " +"<widget name = 'RemoveGameButton' " +"height = '12' " +"/> " +"</layout> " +"<space size = '4'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> " +"<widget name = 'QuitButton' " +"height = '12' " +"/> " +"<widget name = 'AboutButton' " +"height = '12' " +"/> " +"<widget name = 'OptionsButton' " +"height = '12' " +"/> " +"<widget name = 'StartButton' " +"height = '12' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'Browser' overlays = 'screen' inset = '16' shading = 'dim'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<widget name = 'Headline' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'Path' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'List'/> " +"<layout type = 'horizontal' padding = '0, 0, 16, 0'> " +"<widget name = 'Up' " +"type = 'Button' " +"/> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Choose' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions' overlays = 'screen' inset = '16' shading = 'dim'> " +"<layout type = 'vertical' padding = '0, 0, 0, 0'> " +"<widget name = 'TabWidget'/> " +"<layout type = 'horizontal' padding = '8, 8, 8, 8'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'grModePopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'grRenderPopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'grAspectCheckbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'grFullscreenCheckbox' " +"type = 'Checkbox' " +"/> " +"</layout> " +"</dialog> " +"<dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'auMidiPopup' " +"type = 'PopUp' " +"/> " +"<widget name = 'auSampleRatePopup' " +"type = 'PopUp' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'subToggleDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subToggleButton' " +"width = 'Globals.Slider.Width' " +"height = 'Globals.Slider.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'subSubtitleSpeedDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subSubtitleSpeedSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'subSubtitleSpeedLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"</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'> " +"<widget name = 'vcMusicText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcMusicSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcMusicLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'vcSfxText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSfxSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSfxLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'vcSpeechText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSpeechSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSpeechLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'mcFontButton' " +"type = 'Button' " +"/> " +"<widget name = 'mcFontClearButton' " +"height = 'Globals.Line.Height' " +"width = 'Globals.Line.Height' " +"/> " +"<widget name = 'mcFontPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<widget name = 'mcMixedCheckbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'mcMt32Checkbox' " +"type = 'Checkbox' " +"/> " +"<widget name = 'mcGSCheckbox' " +"type = 'Checkbox' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0'> " +"<widget name = 'mcMidiGainText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'mcMidiGainSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'mcMidiGainLabel' " +"width = '32' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'SaveButton' " +"type = 'Button' " +"/> " +"<widget name = 'SavePath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'ThemeButton' " +"type = 'Button' " +"/> " +"<widget name = 'ThemePath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'ExtraButton' " +"type = 'Button' " +"/> " +"<widget name = 'ExtraPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'PluginsButton' " +"type = 'Button' " +"/> " +"<widget name = 'PluginsPath' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</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'> " +"<widget name = 'ThemeButton' " +"type = 'Button' " +"/> " +"<widget name = 'CurTheme' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<widget name = 'Renderer' " +"type = 'PopUp' " +"/> " +"<widget name = 'AutosavePeriod' " +"type = 'PopUp' " +"/> " +"</layout> " +"</dialog> " +"<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 = '8, 8, 8, 8'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Graphics' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Audio' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_MIDI' /> " +"</layout> " +"</dialog> " +"<dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> " +"<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> " +"<widget name = 'EnableTabCheckbox' " +"type = 'Checkbox' " +"/> " +"<import layout = 'Dialog.GlobalOptions_Volume' /> " +"</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 = '16'> " +"<widget name = 'Id' " +"width = '35' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'Domain' " +"type = 'PopUp' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> " +"<widget name = 'Name' " +"width = '35' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'Desc' " +"type = 'PopUp' " +"/> " +"</layout> " +"<space size = '8'/> " +"<widget name = 'Lang' " +"type = 'PopUp' " +"/> " +"<widget name = 'Platform' " +"type = 'PopUp' " +"/> " +"</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 = '16' center = 'true'> " +"<widget name = 'Savepath' " +"type = 'Button' " +"/> " +"<widget name = 'SavepathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> " +"<widget name = 'Extrapath' " +"type = 'Button' " +"/> " +"<widget name = 'ExtrapathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> " +"<widget name = 'Gamepath' " +"type = 'Button' " +"/> " +"<widget name = 'GamepathText' " +"height = 'Globals.Line.Height' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummMain' overlays = 'screen_center'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<widget name = 'Resume' " +"type = 'Button' " +"/> " +"<space size = '4'/> " +"<widget name = 'Load' " +"type = 'Button' " +"/> " +"<widget name = 'Save' " +"type = 'Button' " +"/> " +"<space size = '4'/> " +"<widget name = 'Options' " +"type = 'Button' " +"/> " +"<widget name = 'Help' " +"type = 'Button' " +"/> " +"<widget name = 'About' " +"type = 'Button' " +"/> " +"<space size = '4'/> " +"<widget name = 'Quit' " +"type = 'Button' " +"/> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummConfig' overlays = 'screen_center'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcMusicText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcMusicSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcMusicLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcSfxText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSfxSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSfxLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'vcSpeechText' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'vcSpeechSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'vcSpeechLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'subToggleDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subToggleButton' " +"width = '92' " +"height = 'Globals.Slider.Height' " +"/> " +"</layout> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<widget name = 'subSubtitleSpeedDesc' " +"type = 'OptionsLabel' " +"/> " +"<widget name = 'subSubtitleSpeedSlider' " +"type = 'Slider' " +"/> " +"<widget name = 'subSubtitleSpeedLabel' " +"type = 'SmallLabel' " +"/> " +"</layout> " +"<space size = '20'/> " +"<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> " +"<space size = 'Globals.Button.Width' /> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Ok' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> " +"<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'> " +"<space/> " +"<widget name = 'Cancel' " +"type = 'Button' " +"/> " +"<widget name = 'Choose' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"<dialog name = 'ScummHelp' overlays = 'screen_center'> " +"<layout type = 'vertical' padding = '8, 8, 8, 8'> " +"<widget name = 'Title' " +"width = '180' " +"height = 'Globals.Line.Height' " +"/> " +"<widget name = 'HelpText' " +"height = '170' " +"/> " +"<layout type = 'horizontal' padding = '0, 0, 4, 0'> " +"<widget name = 'Prev' " +"type = 'Button' " +"/> " +"<widget name = 'Next' " +"type = 'Button' " +"/> " +"<space size = '32'/> " +"<widget name = 'Close' " +"type = 'Button' " +"/> " +"</layout> " +"</layout> " +"</dialog> " +"</layout_info> " diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini deleted file mode 100644 index 87ef0bcbb9..0000000000 --- a/gui/themes/modern.ini +++ /dev/null @@ -1,622 +0,0 @@ -# $URL$ -# $Id$ -[theme] -version=23 -type=modern -name=Modern Style - -[pixmaps] -pix_dialog_corner="dialog_bkgd_corner.bmp" -pix_dialog_top="dialog_bkgd_top.bmp" -pix_dialog_left="dialog_bkgd_left.bmp" -pix_dialog_bkgd="dialog_bkgd.bmp" - -pix_widget_corner="widget_bkgd_corner.bmp" -pix_widget_top="widget_bkgd_top.bmp" -pix_widget_left="widget_bkgd_left.bmp" -pix_widget_bkgd="widget_bkgd.bmp" - -pix_widget_small_corner="widget_small_bkgd_corner.bmp" -pix_widget_small_top="widget_small_bkgd_top.bmp" -pix_widget_small_left="widget_small_bkgd_left.bmp" -pix_widget_small_bkgd="widget_small_bkgd.bmp" - -pix_checkbox_empty="checkbox_empty.bmp" -pix_checkbox_checked="checkbox_checked.bmp" - -pix_widget_arrow="widget_arrow.bmp" - -pix_tab_corner="button_bkgd_corner.bmp" -pix_tab_top="widget_bkgd_top.bmp" -pix_tab_left="widget_bkgd_left.bmp" -pix_tab_bkgd="widget_bkgd.bmp" - -pix_slider_bkgd_corner="button_bkgd_corner.bmp" -pix_slider_bkgd_top="button_bkgd_top.bmp" -pix_slider_bkgd_left="button_bkgd_left.bmp" -pix_slider_bkgd_bkgd="button_bkgd.bmp" - -pix_slider_corner="button_bkgd_corner.bmp" -pix_slider_top="button_bkgd_top.bmp" -pix_slider_left="button_bkgd_left.bmp" -pix_slider_bkgd="button_bkgd.bmp" - -pix_scrollbar_bkgd_corner="widget_small_bkgd_corner.bmp" -pix_scrollbar_bkgd_top="widget_small_bkgd_top.bmp" -pix_scrollbar_bkgd_left="widget_small_bkgd_left.bmp" -pix_scrollbar_bkgd_bkgd="widget_small_bkgd.bmp" - -pix_scrollbar_corner="widget_bkgd_corner.bmp" -pix_scrollbar_top="widget_bkgd_top.bmp" -pix_scrollbar_left="widget_bkgd_left.bmp" -pix_scrollbar_bkgd="widget_bkgd.bmp" - -pix_button_corner="button_bkgd_corner.bmp" -pix_button_top="button_bkgd_top.bmp" -pix_button_left="button_bkgd_left.bmp" -pix_button_bkgd="button_bkgd.bmp" - -pix_popupwidget_corner="button_bkgd_corner.bmp" -pix_popupwidget_top="button_bkgd_top.bmp" -pix_popupwidget_left="button_bkgd_left.bmp" -pix_popupwidget_bkgd="button_bkgd.bmp" - -pix_edittext_bkgd_corner="button_bkgd_corner.bmp" -pix_edittext_bkgd_top="button_bkgd_top.bmp" -pix_edittext_bkgd_left="button_bkgd_left.bmp" -pix_edittext_bkgd_bkgd="button_bkgd.bmp" - -pix_theme_logo="logo.bmp" - -pix_cursor_image="cursor.bmp" - -[colors] -main_dialog_start=210 114 10 -main_dialog_end=239 196 24 - -dialog_start=246 224 139 -dialog_end=251 241 206 - -color_state_disabled=192 192 192 -color_state_highlight=100 162 8 -color_state_enabled=0 0 0 - -color_transparency=255 0 255 - -text_inverted_background=100 162 8 -text_inverted_color=0 0 0 - -widget_bkgd_start=246 224 139 -widget_bkgd_end=251 241 206 -widget_bkgd_small_start=246 224 139 -widget_bkgd_small_end=251 241 206 - -button_bkgd_start=203 126 107 -button_bkgd_end=169 42 12 -button_bkgd_highlight_start=255 210 200 -button_bkgd_highlight_end=200 70 50 -button_text_enabled=255 255 255 -button_text_disabled=192 192 192 -button_text_highlight=255 214 84 - -slider_background_start=247 228 166 -slider_background_end=247 228 166 -slider_start=203 126 107 -slider_end=169 42 12 -slider_highlight_start=255 210 200 -slider_highlight_end=200 70 50 - -tab_background_start=232 180 80 -tab_background_end=232 180 80 - -tab_active_start=246 224 139 -tab_active_end=251 241 206 -tab_inactive_start=239 202 109 -tab_inactive_end=239 202 109 - -scrollbar_background_start=247 228 166 -scrollbar_background_end=247 228 166 -scrollbar_button_start=247 228 166 -scrollbar_button_end=247 228 166 -scrollbar_slider_start=203 126 107 -scrollbar_slider_end=169 42 12 -scrollbar_button_highlight_start=255 210 200 -scrollbar_button_highlight_end=200 70 50 -scrollbar_slider_highlight_start=255 210 200 -scrollbar_slider_highlight_end=200 70 50 - -popupwidget_start=251 241 206 -popupwidget_end=251 241 206 -popupwidget_highlight_start=246 224 139 -popupwidget_highlight_end=251 241 206 - -edittext_background_start=247 228 166 -edittext_background_end=247 228 166 - -caret_color=0 0 0 - -[gradients] -gradient_dialog_main=1 -gradient_dialog=4 -gradient_dialog_special=4 - -gradient_widget_small=9 -gradient_widget=9 - -gradient_button=1 - -gradient_slider=1 -gradient_slider_bkgd=1 - -gradient_tab=4 - -gradient_scrollbar=1 -gradient_scrollbar_background=1 - -gradient_popupwidget=1 - -gradient_edittext=1 - -[extra] -shadow_left_width=2 -shadow_right_width=4 -shadow_top_height=2 -shadow_bottom_height=4 -inactive_dialog_shading=kShadingDim -shading_dim_percent=50 -fontfile_normal="helvr12-l1.bdf" -fontfile_fixed_normal="courr12-l1.bdf" -cursor_hotspot_x=0 -cursor_hotspot_y=0 -cursor_targetScale=3 - -[XxY] -skipFor=320xY,256x240 -def_widgetSize=kBigWidgetSize -def_buttonWidth=120 -def_buttonHeight=25 -def_sliderWidth=kBigSliderWidth -def_sliderHeight=kBigSliderHeight -def_kLineHeight=16 -def_kFontHeight=14 -def_kPopUpHeight=(kLineHeight + 3) -def_insetX=23 -def_insetY=94 -def_insetW=(w - buttonWidth - 17 * 2 - insetX) -def_insetH=(h - 23 - insetY) -def_optionsVPad=20 -def_optionsLabelWidth=110 -def_gameOptionsOverrideVPad=20 -def_tabPopupsLabelW=optionsLabelWidth -def_aboutXOff=8 -def_aboutYOff=5 -def_aboutOuterBorder=80 -def_scummmainHOffset=12 -def_scummmainVSpace=15 -def_scummmainVAddOff=5 -def_scummhelpW=370 -def_scummhelpX=((w - scummhelpW) / 2) -def_launcherVersionX=(w / 2 - 283 / 2 - 90) -def_launcherVersionY=21 - -def_xSeparation=10 -def_ySeparation=10 -def_xBorder=15 - -use=pixmaps -use=colors -use=gradients -use=extra - -##### Widgets config -ListWidget.leftPadding=7 -ListWidget.rightPadding=5 -ListWidget.topPadding=5 -ListWidget.bottomPadding=5 -ListWidget.hlLeftPadding=0 -ListWidget.hlRightPadding=0 -PopUpWidget.leftPadding=7 -PopUpWidget.rightPadding=5 -PopUpWidget.labelSpacing=xSeparation -EditTextWidget.font=kFontStyleNormal -EditTextWidget.leftPadding=7 -EditTextWidget.rightPadding=5 -Console.font=kFontStyleFixedNormal -Console.leftPadding=7 -Console.rightPadding=5 -Console.topPadding=5 -Console.bottomPadding=5 -TabWidget.tabWidth=75 -TabWidget.tabHeight=27 -TabWidget.titleVPad=8 -TabWidget.navButtonRightPad=3 -TabWidget.navButtonTopPad=4 -TabWidget.navButtonW=15 -TabWidget.navButtonH=18 - -###### chooser -opHeight=insetH -useWithPrefix=chooser defaultChooser_ - -##### browser -use=browser - -##### launcher -launcher_version=launcherVersionX launcherVersionY 247 kLineHeight -launcher_version.align=kTextAlignRight -launcher_logo=(w / 2 - 283 / 2) 5 283 80 -launcher_logo.visible=true -space1=20 -space2=5 -launcher_list=insetX insetY insetW insetH -launcher_start_button=(prev.x2 + 17) prev.y buttonWidth buttonHeight -launcher_addGame_button=prev.x (prev.y2 + space1) prev.w prev.h -launcher_editGame_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_removeGame_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_options_button=prev.x (prev.y2 + space1) prev.w prev.h -launcher_about_button=prev.x (prev.y2 + space2) prev.w prev.h -launcher_quit_button=prev.x (prev.y2 + space1) prev.w prev.h - -use=scummmain - -### global options -globaloptions=insetX insetY insetW insetH -set_parent=globaloptions -vBorder=optionsVPad -globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) - -# graphics tab -opYoffset=vBorder -opXoffset=0 -useWithPrefix=graphicsControls globaloptions_ - -# audio tab -opYoffset=vBorder -useWithPrefix=audioControls globaloptions_ -useWithPrefix=subtitleControls globaloptions_ - -# volume tab -opYoffset=vBorder -useWithPrefix=volumeControls globaloptions_ - -# MIDI tab -opYoffset=vBorder -useWithPrefix=midiControls globaloptions_ - -# paths tab -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_savebutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_savepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_extrabutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_extrapath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_themebutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_themepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_pluginsbutton=xBorder yoffset buttonWidth buttonHeight -globaloptions_pluginspath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_keysbutton=xBorder yoffset buttonWidth buttonHeight - -# Misc options -yoffset=vBorder -glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_themebutton2=xBorder yoffset buttonWidth buttonHeight -globaloptions_curtheme=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight -yoffset=(yoffset + buttonHeight + ySeparation) -globaloptions_autosaveperiod=xBorder yoffset (parent.w - self.x - xBorder) kPopUpHeight - -globaloptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -globaloptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -### game options -gameoptions=insetX insetY insetW insetH -set_parent=gameoptions -vBorder=gameOptionsOverrideVPad -gox=xBorder -gow=(parent.w - gox - xBorder) - -gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) - -# game tab -opYoffset=optionsVPad -glOff=((kPopUpHeight - kLineHeight) / 2 + 2) -gameoptions_id=gox (opYoffset + glOff) optionsLabelWidth kLineHeight -gameoptions_id.align=kTextAlignRight -gameoptions_domain=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_name=gox (opYoffset + glOff) optionsLabelWidth kLineHeight -gameoptions_name.align=kTextAlignRight -gameoptions_desc=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_lang=gox opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -gameoptions_platform=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + prev.h + ySeparation) - -# paths tab -opYoffset=optionsVPad -goOff=((buttonHeight - kLineHeight) / 2 + 2) -gameoptions_savepath=gox opYoffset buttonWidth buttonHeight -gameoptions_savepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -gameoptions_extrapath=gox opYoffset buttonWidth buttonHeight -gameoptions_extrapathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -gameoptions_gamepath=gox opYoffset buttonWidth buttonHeight -gameoptions_gamepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) - -# graphics tab -opYoffset=vBorder -opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=graphicsControls gameoptions_ - -# audio tab -opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=audioControls gameoptions_ -useWithPrefix=subtitleControls gameoptions_ - -# volume tab -opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=volumeControls gameoptions_ - -# midi tab -opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight -opYoffset=(prev.y2 + ySeparation) -useWithPrefix=midiControls gameoptions_ - -gameoptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -gameoptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -### keys dialog -keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5) -set_parent=keysdialog -keysdialog_map=(parent.w - buttonWidth - 10) 20 buttonWidth buttonHeight -keysdialog_ok=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_cancel=prev.x (prev.y2 + 4) prev.w prev.h -keysdialog_list=10 10 (prev.x - 20) (parent.h - kLineHeight * 4 - self.y) -keysdialog_action=prev.x (parent.h - kLineHeight * 3) (parent.w - self.x * 2) kLineHeight -keysdialog_action.align=kTextAlignCenter -keysdialog_mapping=prev.x (prev.y + kLineHeight) prev.w prev.h -keysdialog_mapping.align=kTextAlignCenter - -### mass add dialog -massadddialog=10 20 300 174 -set_parent=massadddialog -massadddialog_caption=xBorder (10 + 1 * kLineHeight) (parent.w - 2 * xBorder) kLineHeight -massadddialog_caption.align=kTextAlignCenter -massadddialog_dirprogress=xBorder (10 + 3 * kLineHeight) prev.w prev.h -massadddialog_dirprogress.align=kTextAlignCenter -massadddialog_gameprogress=xBorder (10 + 4 * kLineHeight) prev.w prev.h -massadddialog_gameprogress.align=kTextAlignCenter -massadddialog_ok=((parent.w - (buttonWidth * 2) - xSeparation) / 2) (parent.h - buttonHeight - ySeparation) buttonWidth buttonHeight -massadddialog_cancel=(prev.x2 + xSeparation) prev.y prev.w prev.h - - -##### SCUMM dialogs -scummDummyDialog=0 80 0 16 - -use=scummmain -## Engine config -# note that scummconfig size depends on overall height -# hence it is on the end of the list -opYoffset=8 -useWithPrefix=volumeControls scummconfig_ -opYoffset=(opYoffset + 2) -useWithPrefix=subtitleControls scummconfig_ -opYoffset=(opYoffset + buttonHeight) -opYoffset=(opYoffset + buttonHeight + 4) -soWidth=(8 + 3 * buttonWidth + 4) -scummconfig_keys=(soWidth - 3 * (buttonWidth + 4) + 6) opYoffset (buttonWidth - 10) buttonHeight -scummconfig_cancel=(prev.x2 + 4) prev.y (prev.w + 10) prev.h -scummconfig_ok=(prev.x2 + 4) prev.y prev.w prev.h -opYoffset=(opYoffset + buttonHeight) -scummconfig=((w - soWidth) / 2) ((h - opYoffset) / 2) soWidth (opYoffset + 8) - -## Help -scummHelpNumLines=15 -shH=(5 + (2 + scummHelpNumLines) * kFontHeight + buttonHeight + 7) -shButtonWidth=(buttonWidth - 20) -scummhelp=scummhelpX ((h - shH) / 2) scummhelpW shH -scummhelp_title=10 5 scummhelpW kFontHeight -scummhelp_title.align=kTextAlignCenter -scummhelp_key.x=10 -scummhelp_key.yoffset=5 -scummhelp_key.w=80 -scummhelp_key.h=kFontHeight -scummhelp_dsc.x=90 -scummhelp_dsc.yoffset=5 -scummhelp_dsc.w=(scummhelpW - 10 - 90) -scummhelp_dsc.h=kFontHeight -scummhelp_prev=10 (5 + kFontHeight * (scummHelpNumLines + 2) + 2) shButtonWidth buttonHeight -scummhelp_next=(prev.x2 + 8) prev.y prev.w prev.h -scummhelp_close=(scummhelpW - 8 - shButtonWidth) prev.y prev.w prev.h - -# Saveload dialog -scummsaveload=8 8 (w - 2 * 8) (h - 16) -set_parent=scummsaveload -scummsaveload_title=10 2 (parent.w - 2 * 10 - 180-20) kLineHeight -scummsaveload_title.align=kTextAlignCenter -scummsaveload_list=10 18 prev.w (parent.h - 17 - buttonHeight - 8 - self.y) -scummsaveload_thumbnail=(parent.w - (kThumbnailWidth + 22)) 18 -scummsaveload_thumbnail.hPad=10 -scummsaveload_thumbnail.vPad=10 -scummsaveload_thumbnail.fillR=0 -scummsaveload_thumbnail.fillG=0 -scummsaveload_thumbnail.fillB=0 -scummsaveload_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -scummsaveload_choose=(prev.x2 + 10) prev.y prev.w prev.h -scummsaveload_extinfo.visible=true - -############################################ -[chooser] -chooserW=insetW -chooser=insetX insetY chooserW opHeight -chooser_headline=xBorder 6 (chooserW - 2 * xBorder) kLineHeight -chooser_list=prev.x (prev.y2 + 2) prev.w (opHeight - self.y - buttonHeight - 12) -#JVPRAT: next Y doesn't seem right -chooser_cancel=(chooserW - 2 * buttonWidth - xSeparation - xBorder) (opHeight - buttonHeight - 8) buttonWidth buttonHeight -chooser_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h - -[browser] -browser=insetX insetY insetW insetH -set_parent=browser -browser_headline=xBorder 5 (parent.w - 2 * xBorder) kLineHeight -browser_headline.align=kTextAlignCenter -browser_path=prev.x (prev.y2 + 5) prev.w prev.h -browser_list=prev.x prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) -browser_up=prev.x (parent.h - buttonHeight - 8) buttonWidth buttonHeight -#JVPRAT: doesn't it lack insetx?: -browser_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_choose=(prev.x2 + xSeparation) prev.y prev.w prev.h - -[graphicsControls] -gcx=(opXoffset + xBorder) -grModePopup=gcx opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(prev.y2 + ySeparation) -grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h -opYoffset=(prev.y2 + ySeparation) -grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - xBorder) kLineHeight -opYoffset=(prev.y2 + ySeparation) -grAspectCheckbox=prev.x opYoffset prev.w prev.h -opYoffset=(prev.y2 + ySeparation) - -[audioControls] -aux=(opXoffset + xBorder) -auMidiPopup=aux opYoffset (parent.w - self.x - xBorder) kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) -auSampleRatePopup=aux (opYoffset - 1) prev.w kPopUpHeight -opYoffset=(opYoffset + prev.h + ySeparation) - -[volumeControls] -vcx=(opXoffset + xBorder) -vcOff=((sliderHeight - kLineHeight) / 2 + 2) -vcMusicText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcMusicText.align=kTextAlignRight -vcMusicSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcMusicLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) -vcSfxText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcSfxText.align=kTextAlignRight -vcSfxSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcSfxLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) -vcSpeechText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight -vcSpeechText.align=kTextAlignRight -vcSpeechSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -vcSpeechLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[midiControls] -mcx=(opXoffset + xBorder) -mcOff=((buttonHeight - kLineHeight) / 2 + 2) -mcFontButton=mcx opYoffset buttonWidth buttonHeight -mcFontPath=(prev.x2 + xSeparation) (opYoffset + mcOff) (parent.w - self.x - xSeparation - kLineHeight - xBorder) kLineHeight -mcFontClearButton=(prev.x2 + xSeparation) prev.y kLineHeight kLineHeight -opYoffset=(opYoffset + buttonHeight + ySeparation) -mcMixedCheckbox=mcx opYoffset (parent.w - self.x - xBorder) kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcMt32Checkbox=mcx opYoffset prev.w kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcGSCheckbox=mcx opYoffset prev.w kLineHeight -opYoffset=(opYoffset + prev.h + ySeparation) -mcOff=((sliderHeight - kLineHeight) / 2 + 2) -mcMidiGainText=mcx (opYoffset + mcOff) optionsLabelWidth kLineHeight -mcMidiGainText.align=kTextAlignRight -mcMidiGainSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -mcMidiGainLabel=(prev.x2 + xSeparation) (opYoffset + mcOff) 40 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[subtitleControls] -sbx=(opXoffset + xBorder) -sbOff=((sliderHeight - kLineHeight) / 2 + 2) -subToggleDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight -subToggleDesc.align=kTextAlignRight -subToggleButton=(prev.x2 + xSeparation) opYoffset (buttonWidth + 34) sliderHeight -opYoffset=(prev.y2 + ySeparation) -subSubtitleSpeedDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight -subSubtitleSpeedDesc.align=kTextAlignRight -subSubtitleSpeedSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight -subSubtitleSpeedLabel=(prev.x2 + xSeparation) (opYoffset + sbOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + ySeparation) - -[scummmain] -## Main dialog -# note that scummmain size depends on overall height -smY=scummmainHOffset -scummmain_resume=scummmainHOffset smY buttonWidth buttonHeight -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_load=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_save=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_options=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_about=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -scummmain_help=prev.x smY prev.w prev.h -smY=(smY + buttonHeight + scummmainVAddOff) -smY=(smY + scummmainVSpace) -scummmain_quit=prev.x smY prev.w prev.h -smH=(smY + buttonHeight + scummmainHOffset) -smW=(buttonWidth + 2 * scummmainHOffset) -scummmain=((w - smW) / 2) ((h - smH) / 2) smW smH - -[320xY] -use=pixmaps -use=colors -use=gradients -use=extra -shadow_right_width=1 -pix_checkbox_empty="checkbox_empty320.bmp" -pix_checkbox_checked="checkbox_checked320.bmp" -pix_cursor_image="cursor320.bmp" - -# NES resoltuion -[256x240] -use=320xY - -# PSP GUI -[480x272] -def_buttonWidth=100 -def_buttonHeight=23 -def_insetX=20 -def_insetY=10 -def_insetW=(w - buttonWidth - 17 * 2 - insetX) -def_insetH=(h - 13 - insetY) -def_launcherVersionX=50 -def_launcherVersionY=5 -def_gameOptionsOverrideVPad=10 -def_aboutXOff=3 -def_aboutYOff=2 -def_aboutOuterBorder=10 - -use=XxY - -TabWidget.tabWidth=75 - -# Override launcher -launcher_list=insetX 103 (w - buttonWidth - 17 * 2 - self.x) (h - 15 - self.y) -launcher_version=50 80 247 kLineHeight -launcher_version.align=kTextAlignCenter -launcher_logo=40 2 283 80 -launcher_logo.visible=true - -# Override extras -inactive_dialog_shading=kShadingNone - -# Override browser -def_buttonWidth=90 -use=browser diff --git a/gui/themes/modern.zip b/gui/themes/modern.zip Binary files differdeleted file mode 100644 index 739c6d23ac..0000000000 --- a/gui/themes/modern.zip +++ /dev/null diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differnew file mode 100644 index 0000000000..3211ca2cd9 --- /dev/null +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC new file mode 100644 index 0000000000..df6c0508b2 --- /dev/null +++ b/gui/themes/scummclassic/THEMERC @@ -0,0 +1 @@ +[SCUMMVM_THEME_V23:ScummVM Classic Theme:No Author]
\ No newline at end of file diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx new file mode 100644 index 0000000000..6c96dcebdb --- /dev/null +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -0,0 +1,364 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<render_info> + <palette> + <color name = 'black' + rgb = '0, 0, 0' + /> + <color name = 'lightgrey' + rgb = '104, 104, 104' + /> + <color name = 'darkgrey' + rgb = '64, 64, 64' + /> + <color name = 'green' + rgb = '32, 160, 32' + /> + <color name = 'green2' + rgb = '0, 255, 0' + /> + </palette> + + <fonts> + <font id = 'text_default' + file = 'default' + color = 'green' + /> + <font id = 'text_hover' + file = 'default' + color = 'green2' + /> + <font id = 'text_disabled' + file = 'default' + color = 'lightgrey' + /> + <font id = 'text_inverted' + file = 'default' + color = 'black' + /> + <font id = 'text_button' + file = 'default' + color = 'green' + /> + <font id = 'text_button_hover' + file = 'default' + color = 'green2' + /> + <font id = 'text_normal' + file = 'default' + color = 'green' + /> + </fonts> + + <defaults fill = 'foreground' fg_color = 'darkgrey' bg_color = 'black' shadow = '0' bevel_color = 'lightgrey'/> + + <drawdata id = 'text_selection' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'green' + /> + </drawdata> + + <drawdata id = 'mainmenu_bg' cache = false> + <drawstep func = 'fill' + fill = 'foreground' + fg_color = 'black' + /> + </drawdata> + + <drawdata id = 'special_bg' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + /> + </drawdata> + + <drawdata id = 'separator' cache = false> + <drawstep func = 'square' + fill = 'foreground' + height = '2' + ypos = 'center' + fg_color = 'lightgrey' + /> + </drawdata> + + <drawdata id = 'scrollbar_base' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + /> + </drawdata> + + <drawdata id = 'scrollbar_handle_hover' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'green2' + /> + </drawdata> + + <drawdata id = 'scrollbar_handle_idle' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'green' + /> + </drawdata> + + <drawdata id = 'scrollbar_button_idle' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + <drawstep func = 'triangle' + fg_color = 'green' + fill = 'foreground' + width = 'auto' + height = 'auto' + xpos = 'center' + ypos = 'center' + orientation = 'top' + /> + </drawdata> + + <drawdata id = 'scrollbar_button_hover' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + <drawstep func = 'triangle' + fg_color = 'green2' + fill = 'foreground' + width = 'auto' + height = 'auto' + xpos = 'center' + ypos = 'center' + orientation = 'top' + /> + </drawdata> + + <drawdata id = 'tab_active' cache = false> + <text font = 'text_hover' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'tab' + bevel = '2' + radius = '0' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'tab_inactive' cache = false> + <text font = 'text_default' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'tab' + bevel = '2' + radius = '0' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'tab_background' cache = false> + </drawdata> + + <drawdata id = 'widget_slider' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'slider_disabled' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'lightgrey' + /> + </drawdata> + + <drawdata id = 'slider_full' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'green' + /> + </drawdata> + + <drawdata id = 'slider_hover' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'green2' + /> + </drawdata> + + <drawdata id = 'widget_small' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'popup_idle' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + <drawstep func = 'triangle' + fg_color = 'green' + fill = 'foreground' + width = 'height' + height = 'auto' + xpos = 'right' + ypos = 'center' + orientation = 'bottom' + /> + <text font = 'text_default' + vertical_align = 'center' + horizontal_align = 'right' + /> + </drawdata> + + + <drawdata id = 'popup_hover' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + <drawstep func = 'triangle' + fg_color = 'green2' + fill = 'foreground' + width = 'height' + height = 'auto' + xpos = 'right' + ypos = 'center' + orientation = 'bottom' + /> + <text font = 'text_hover' + vertical_align = 'center' + horizontal_align = 'right' + /> + </drawdata> + + <drawdata id = 'widget_textedit' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'plain_bg' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + /> + </drawdata> + + <drawdata id = 'caret' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'lightgrey' + /> + </drawdata> + + <drawdata id = 'default_bg' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + /> + </drawdata> + + <drawdata id = 'button_idle' cache = false> + <text font = 'text_button' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'button_hover' cache = false> + <text font = 'text_button_hover' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'button_disabled' cache = false> + <text font = 'text_disabled' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'checkbox_disabled' cache = false> + <text font = 'text_disabled' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'checkbox_selected' cache = false> + <text font = 'text_default' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + <drawstep func = 'cross' + fill = 'foreground' + stroke = '2' + fg_color = 'green' + /> + </drawdata> + + <drawdata id = 'checkbox_default' cache = false> + <text font = 'text_default' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'bevelsq' + bevel = '2' + fill = 'none' + /> + </drawdata> + + <drawdata id = 'widget_default' cache = false> + <drawstep func = 'bevelsq' + bevel = '2' + /> + </drawdata> +</render_info>
\ No newline at end of file diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx new file mode 100644 index 0000000000..005ebb89f3 --- /dev/null +++ b/gui/themes/scummclassic/classic_layout.stx @@ -0,0 +1,592 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<layout_info resolution = '-320xY, -256x240'> + <globals> + <def var = 'Line.Height' value = '16' /> + <def var = 'Font.Height' value = '16' /> + <def var = 'TabLabelWidth' value = '110' /> + + <def var = 'WidgetSize' value = 'kBigWidgetSize' /> + <def var = 'About.OuterBorder' value = '80'/> + <def var = 'PopUpWidget.labelSpacing' value = '10' /> + + <def var = 'Layout.Spacing' value = '8' /> + <def var = 'ShowLauncherLogo' value = '0'/> + + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '1'/> + + <widget name = 'OptionsLabel' + size = '110, Globals.Line.Height' + /> + <widget name = 'SmallLabel' + size = '24, Globals.Line.Height' + /> + + <widget name = 'ShortOptionsLabel' + size = '60, Globals.Line.Height' + /> + + <widget name = 'Button' + size = 'kBigButtonWidth, kBigButtonHeight' + /> + <widget name = 'Slider' + size = 'kBigSliderWidth, kBigSliderHeight' + /> + + <widget name = 'PopUp' + size = '-1, 19' + /> + <widget name = 'Checkbox' + size = '-1, 14' + /> + <widget name = 'ListWidget' + padding = '5, 0, 8, 0' + /> + <widget name = 'PopUpWidget' + padding = '7, 5, 0, 0' + /> + <widget name = 'EditTextWidget' + padding = '5, 5, 0, 0' + /> + <widget name = 'Console' + padding = '7, 5, 5, 5' + /> + <widget name = 'TabWidget.Tab' + size = '75, 27' + padding = '0, 0, 8, 0' + /> + <widget name = 'TabWidget.NavButton' + size = '15, 18' + padding = '0, 3, 4, 0' + /> + </globals> + + <dialog name = 'Launcher' overlays = 'screen'> + <layout type = 'vertical' center = 'true' padding = '16, 16, 8, 8'> + <widget name = 'Version' + height = 'Globals.Line.Height' + /> + <widget name = 'GameList'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <widget name = 'AddGameButton' + height = '20' + /> + <widget name = 'EditGameButton' + height = '20' + /> + <widget name = 'RemoveGameButton' + height = '20' + /> + </layout> + <space size = '12'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <widget name = 'QuitButton' + height = '20' + /> + <widget name = 'AboutButton' + height = '20' + /> + <widget name = 'OptionsButton' + height = '20' + /> + <widget name = 'StartButton' + height = '20' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'Browser' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Path' + height = 'Globals.Line.Height' + /> + <widget name = 'List'/> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Up' + type = 'Button' + /> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> + <layout type = 'vertical' padding = '0, 0, 0, 0'> + <widget name = 'TabWidget'/> + <layout type = 'horizontal' padding = '16, 16, 16, 16'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'grModePopup' + type = 'PopUp' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + <widget name = 'grAspectCheckbox' + type = 'Checkbox' + /> + <widget name = 'grFullscreenCheckbox' + type = 'Checkbox' + /> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '150' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + </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'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + </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'> + <widget name = 'mcFontButton' + type = 'Button' + /> + <widget name = 'mcFontPath' + height = 'Globals.Line.Height' + /> + <widget name = 'mcFontClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + </layout> + <widget name = 'mcMixedCheckbox' + type = 'Checkbox' + /> + <widget name = 'mcMt32Checkbox' + type = 'Checkbox' + /> + <widget name = 'mcGSCheckbox' + type = 'Checkbox' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'mcMidiGainText' + type = 'OptionsLabel' + /> + <widget name = 'mcMidiGainSlider' + type = 'Slider' + /> + <widget name = 'mcMidiGainLabel' + width = '32' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'SaveButton' + type = 'Button' + /> + <widget name = 'SavePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'ThemePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ExtraButton' + type = 'Button' + /> + <widget name = 'ExtraPath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'PluginsButton' + type = 'Button' + /> + <widget name = 'PluginsPath' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'CurTheme' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'Renderer' + type = 'PopUp' + /> + <widget name = 'AutosavePeriod' + type = 'PopUp' + /> + </layout> + </dialog> + + <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 = '16, 16, 16, 4'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Graphics' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Audio' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_MIDI' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Volume' /> + </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 = '16'> + <widget name = 'Id' + type = 'OptionsLabel' + /> + <widget name = 'Domain' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'Name' + type = 'OptionsLabel' + /> + <widget name = 'Desc' + type = 'PopUp' + /> + </layout> + <widget name = 'Lang' + type = 'PopUp' + /> + <widget name = 'Platform' + type = 'PopUp' + /> + </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 = '16' center = 'true'> + <widget name = 'Savepath' + type = 'Button' + /> + <widget name = 'SavepathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Extrapath' + type = 'Button' + /> + <widget name = 'ExtrapathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Gamepath' + type = 'Button' + /> + <widget name = 'GamepathText' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummMain' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Resume' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Load' + type = 'Button' + /> + <widget name = 'Save' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Options' + type = 'Button' + /> + <widget name = 'Help' + type = 'Button' + /> + <widget name = 'About' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Quit' + type = 'Button' + /> + </layout> + </dialog> + + <dialog name = 'ScummConfig' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '158' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + <space size = '60'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = 'Globals.Button.Width' /> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> + <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'> + <widget name = 'Title' + height = 'Globals.Line.Height' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'> + <widget name = 'List' /> + <widget name = 'Thumbnail' + width = '180' + height = '200' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + 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 = '320' + height = 'Globals.Line.Height' + /> + <widget name = 'HelpText' + height = '220' + /> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Prev' + type = 'Button' + /> + <widget name = 'Next' + type = 'Button' + /> + <space size = '32'/> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </layout> + </dialog> +</layout_info>
\ No newline at end of file diff --git a/gui/themes/scummclassic/classic_layout_320.stx b/gui/themes/scummclassic/classic_layout_320.stx new file mode 100644 index 0000000000..1a6f8afa04 --- /dev/null +++ b/gui/themes/scummclassic/classic_layout_320.stx @@ -0,0 +1,585 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<layout_info resolution = "320xY, 256x240"> + <globals> + <def var = 'Line.Height' value = '12' /> + <def var = 'Font.Height' value = '10' /> + <def var = 'TabLabelWidth' value = '100' /> + + <def var = 'WidgetSize' value = 'kNormalWidgetSize' /> + <def var = 'About.OuterBorder' value = '10'/> + <def var = 'PopUpWidget.labelSpacing' value = '6' /> + + <def var = 'Layout.Spacing' value = '8'/> + + <def var = 'ShowLauncherLogo' value = '0'/> + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> + + <widget name = 'Button' + size = 'kButtonWidth, kButtonHeight' + /> + + <widget name = 'Slider' + size = 'kSliderWidth, kSliderHeight' + /> + + <widget name = 'OptionsLabel' + size = '110, Globals.Line.Height' + /> + <widget name = 'SmallLabel' + size = '18, Globals.Line.Height' + /> + <widget name = 'PopUp' + size = '-1, 15' + /> + <widget name = 'Checkbox' + size = '-1, Globals.Line.Height' + /> + <widget name = 'ListWidget' + padding = '5, 0, 8, 0' + /> + <widget name = 'PopUpWidget' + padding = '7, 5, 0, 0' + /> + <widget name = 'EditTextWidget' + padding = '5, 5, 0, 0' + /> + <widget name = 'Console' + padding = '7, 5, 5, 5' + /> + <widget name = 'TabWidget.Tab' + size = '45, 16' + padding = '0, 0, 2, 0' + /> + <widget name = 'TabWidget.NavButton' + size = '32, 18' + padding = '0, 3, 4, 0' + /> + </globals> + + <dialog name = 'Launcher' overlays = 'screen'> + <layout type = 'vertical' center = 'true' padding = '8, 8, 4, 4'> + <widget name = 'Version' + height = 'Globals.Line.Height' + /> + <widget name = 'GameList'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <widget name = 'AddGameButton' + height = '12' + /> + <widget name = 'EditGameButton' + height = '12' + /> + <widget name = 'RemoveGameButton' + height = '12' + /> + </layout> + <space size = '4'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <widget name = 'QuitButton' + height = '12' + /> + <widget name = 'AboutButton' + height = '12' + /> + <widget name = 'OptionsButton' + height = '12' + /> + <widget name = 'StartButton' + height = '12' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'Browser' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Path' + height = 'Globals.Line.Height' + /> + <widget name = 'List'/> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Up' + type = 'Button' + /> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '0, 0, 0, 0'> + <widget name = 'TabWidget'/> + <layout type = 'horizontal' padding = '8, 8, 8, 8'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'grModePopup' + type = 'PopUp' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + <widget name = 'grAspectCheckbox' + type = 'Checkbox' + /> + <widget name = 'grFullscreenCheckbox' + type = 'Checkbox' + /> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = 'Globals.Slider.Width' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + </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'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + </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'> + <widget name = 'mcFontButton' + type = 'Button' + /> + <widget name = 'mcFontPath' + height = 'Globals.Line.Height' + /> + <widget name = 'mcFontClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + </layout> + <widget name = 'mcMixedCheckbox' + type = 'Checkbox' + /> + <widget name = 'mcMt32Checkbox' + type = 'Checkbox' + /> + <widget name = 'mcGSCheckbox' + type = 'Checkbox' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'mcMidiGainText' + type = 'OptionsLabel' + /> + <widget name = 'mcMidiGainSlider' + type = 'Slider' + /> + <widget name = 'mcMidiGainLabel' + width = '32' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'SaveButton' + type = 'Button' + /> + <widget name = 'SavePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'ThemePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ExtraButton' + type = 'Button' + /> + <widget name = 'ExtraPath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'PluginsButton' + type = 'Button' + /> + <widget name = 'PluginsPath' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'CurTheme' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'Renderer' + type = 'PopUp' + /> + <widget name = 'AutosavePeriod' + type = 'PopUp' + /> + </layout> + </dialog> + + <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 = '8, 8, 8, 8'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Graphics' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Audio' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_MIDI' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Volume' /> + </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 = '16'> + <widget name = 'Id' + width = '35' + height = 'Globals.Line.Height' + /> + <widget name = 'Domain' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'Name' + width = '35' + height = 'Globals.Line.Height' + /> + <widget name = 'Desc' + type = 'PopUp' + /> + </layout> + <space size = '8'/> + <widget name = 'Lang' + type = 'PopUp' + /> + <widget name = 'Platform' + type = 'PopUp' + /> + </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 = '16' center = 'true'> + <widget name = 'Savepath' + type = 'Button' + /> + <widget name = 'SavepathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Extrapath' + type = 'Button' + /> + <widget name = 'ExtrapathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Gamepath' + type = 'Button' + /> + <widget name = 'GamepathText' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummMain' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Resume' + type = 'Button' + /> + <space size = '4'/> + <widget name = 'Load' + type = 'Button' + /> + <widget name = 'Save' + type = 'Button' + /> + <space size = '4'/> + <widget name = 'Options' + type = 'Button' + /> + <widget name = 'Help' + type = 'Button' + /> + <widget name = 'About' + type = 'Button' + /> + <space size = '4'/> + <widget name = 'Quit' + type = 'Button' + /> + </layout> + </dialog> + + <dialog name = 'ScummConfig' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '92' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + <space size = '20'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = 'Globals.Button.Width' /> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> + <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'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummHelp' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Title' + width = '180' + height = 'Globals.Line.Height' + /> + <widget name = 'HelpText' + height = '170' + /> + <layout type = 'horizontal' padding = '0, 0, 4, 0'> + <widget name = 'Prev' + type = 'Button' + /> + <widget name = 'Next' + type = 'Button' + /> + <space size = '32'/> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </layout> + </dialog> +</layout_info>
\ No newline at end of file diff --git a/gui/themes/scummodern.zip b/gui/themes/scummodern.zip Binary files differnew file mode 100644 index 0000000000..ff08f25dd3 --- /dev/null +++ b/gui/themes/scummodern.zip diff --git a/gui/themes/scummodern/THEMERC b/gui/themes/scummodern/THEMERC new file mode 100644 index 0000000000..d11c959867 --- /dev/null +++ b/gui/themes/scummodern/THEMERC @@ -0,0 +1 @@ +[SCUMMVM_THEME_V23:ScummVM Modern Theme:No Author]
\ No newline at end of file diff --git a/gui/themes/scummodern/checkbox.bmp b/gui/themes/scummodern/checkbox.bmp Binary files differnew file mode 100644 index 0000000000..a0b91b569f --- /dev/null +++ b/gui/themes/scummodern/checkbox.bmp diff --git a/gui/themes/scummodern/cursor.bmp b/gui/themes/scummodern/cursor.bmp Binary files differnew file mode 100644 index 0000000000..e7bdb60cad --- /dev/null +++ b/gui/themes/scummodern/cursor.bmp diff --git a/gui/themes/scummodern/cursor_small.bmp b/gui/themes/scummodern/cursor_small.bmp Binary files differnew file mode 100644 index 0000000000..5f25f32f1a --- /dev/null +++ b/gui/themes/scummodern/cursor_small.bmp diff --git a/gui/themes/scummodern/helvr12-l1.fcc b/gui/themes/scummodern/helvr12-l1.fcc Binary files differnew file mode 100644 index 0000000000..651a25934a --- /dev/null +++ b/gui/themes/scummodern/helvr12-l1.fcc diff --git a/gui/themes/scummodern/logo.bmp b/gui/themes/scummodern/logo.bmp Binary files differnew file mode 100644 index 0000000000..659ec47d03 --- /dev/null +++ b/gui/themes/scummodern/logo.bmp diff --git a/gui/themes/scummodern/scummodern_gfx.stx b/gui/themes/scummodern/scummodern_gfx.stx new file mode 100644 index 0000000000..37d6590e3c --- /dev/null +++ b/gui/themes/scummodern/scummodern_gfx.stx @@ -0,0 +1,475 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<render_info> + <palette> + <color name = 'darkred' + rgb = '169, 42, 12' + /> + <color name = 'brightred' + rgb = '203, 126, 107' + /> + <color name = 'xtrabrightred' + rgb = '255, 210, 200' + /> + <color name = 'blandyellow' + rgb = '247, 228, 166' + /> + <color name = 'bgreen' + rgb = '100, 162, 8' + /> + <color name = 'black' + rgb = '0, 0, 0' + /> + <color name = 'white' + rgb = '255, 255, 255' + /> + <color name = 'shadowcolor' + rgb = '63, 60, 17' + /> + </palette> + + <bitmaps> + <bitmap filename = 'logo.bmp'/> + <bitmap filename = 'cursor.bmp'/> + <bitmap filename = 'cursor_small.bmp'/> + <bitmap filename = 'checkbox.bmp'/> + </bitmaps> + + <fonts> + <font id = 'text_default' + file = 'default' + color = 'black' + /> + <font id = 'text_hover' + file = 'default' + color = 'bgreen' + /> + <font id = 'text_disabled' + file = 'default' + color = '128, 128, 128' + /> + <font id = 'text_inverted' + file = 'default' + color = '0, 0, 0' + /> + <font id = 'text_button' + file = 'default' + color = 'white' + /> + <font id = 'text_button_hover' + file = 'default' + color = 'blandyellow' + /> + <font id = 'text_normal' + file = 'helvr12-l1.bdf' + color = 'black' + /> + </fonts> + + <defaults fill = 'gradient' fg_color = 'white' bevel_color = '237, 169, 72'/> + + <cursor file = 'cursor.bmp' hotspot = '0, 0' scale = '3'/> + <cursor resolution = '320xY, 256x240' file = 'cursor_small.bmp' hotspot = '0, 0' scale = '3'/> + + <drawdata id = 'text_selection' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'bgreen' + /> + </drawdata> + + <drawdata id = 'mainmenu_bg' cache = false> + <drawstep func = 'fill' + fill = 'gradient' + gradient_start = '208, 112, 8' + gradient_end = '232, 192, 16' + /> + </drawdata> + + <drawdata id = 'special_bg' cache = false> + <drawstep func = 'roundedsq' + radius = '4' + fill = 'gradient' + stroke = '0' + gradient_start = '208, 112, 8' + gradient_end = '232, 192, 16' + shadow = '3' + /> + </drawdata> + + <drawdata id = 'separator' cache = false> + <drawstep func = 'square' + fill = 'foreground' + height = '1' + ypos = 'center' + fg_color = 'black' + /> + </drawdata> + + <drawdata id = 'scrollbar_base' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 6 + fill = 'background' + fg_color = '176, 164, 160' + bg_color = '240, 228, 160' + /> + </drawdata> + + <drawdata id = 'scrollbar_handle_hover' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 6 + fill = 'gradient' + fg_color = 'blandyellow' + gradient_start = 'xtrabrightred' + gradient_end = 'darkred' + /> + </drawdata> + + <drawdata id = 'scrollbar_handle_idle' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 6 + fill = 'gradient' + fg_color = 'blandyellow' + gradient_start = 'brightred' + gradient_end = 'darkred' + /> + </drawdata> + + <drawdata id = 'scrollbar_button_idle' cache = false> + <drawstep func = 'roundedsq' + radius = '4' + fill = 'none' + fg_color = '176, 164, 160' + stroke = 1 + /> + <drawstep func = 'triangle' + fg_color = '0, 0, 0' + fill = 'foreground' + width = 'auto' + height = 'auto' + xpos = 'center' + ypos = 'center' + orientation = 'top' + /> + </drawdata> + + <drawdata id = 'scrollbar_button_hover' cache = false> + <drawstep func = 'roundedsq' + radius = '4' + fill = 'background' + fg_color = '120, 120, 120' + bg_color = '206, 121, 99' + stroke = 1 + /> + <drawstep func = 'triangle' + fg_color = '0, 0, 0' + fill = 'foreground' + width = 'auto' + height = 'auto' + xpos = 'center' + ypos = 'center' + orientation = 'top' + /> + </drawdata> + + <drawdata id = 'tab_active' cache = false> + <text font = 'text_default' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'tab' + radius = '4' + stroke = '0' + fill = 'gradient' + gradient_end = 'xtrabrightred' + gradient_start = 'blandyellow' + shadow = 3 + /> + </drawdata> + + <drawdata id = 'tab_inactive' cache = false> + <text font = 'text_default' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'tab' + radius = '4' + stroke = '0' + fill = 'foreground' + fg_color = '240, 205, 118' + shadow = 3 + /> + </drawdata> + + <drawdata id = 'tab_background' cache = false> + <drawstep func = 'tab' + radius = '6' + stroke = '0' + fill = 'foreground' + fg_color = '232, 180, 81' + shadow = 3 + /> + </drawdata> + + <drawdata id = 'widget_slider' cache = false> + <drawstep func = 'roundedsq' + stroke = 0 + radius = 4 + fill = 'foreground' + fg_color = 'blandyellow' + bevel = 1 + bevel_color = 'shadowcolor' + /> + </drawdata> + + <drawdata id = 'slider_full' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 4 + fill = 'gradient' + fg_color = '123, 112, 56' + gradient_start = 'brightred' + gradient_end = 'darkred' + /> + </drawdata> + + <drawdata id = 'slider_hover' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 4 + fill = 'gradient' + fg_color = '123, 112, 56' + gradient_start = 'xtrabrightred' + gradient_end = 'darkred' + /> + </drawdata> + + <drawdata id = 'slider_disabled' cache = false> + <drawstep func = 'roundedsq' + stroke = 1 + radius = 4 + fill = 'gradient' + fg_color = '123, 112, 56' + gradient_start = 'xtrabrightred' + gradient_end = 'darkred' + /> + </drawdata> + + <drawdata id = 'popup_idle' cache = false> + <drawstep func = 'roundedsq' + stroke = 0 + radius = 4 + fill = 'foreground' + fg_color = '250, 237, 190' + shadow = 2 + /> + <drawstep func = 'triangle' + fg_color = '63, 60, 52' + fill = 'foreground' + width = 'height' + height = 'auto' + xpos = 'right' + ypos = 'center' + orientation = 'bottom' + /> + <text font = 'text_default' + vertical_align = 'center' + horizontal_align = 'right' + /> + </drawdata> + + + <drawdata id = 'popup_hover' cache = false> + <drawstep func = 'roundedsq' + stroke = 0 + radius = 4 + fill = 'gradient' + gradient_start = 'blandyellow' + gradient_end = '250, 237, 190' + shadow = 0 + /> + <drawstep func = 'triangle' + fg_color = '63, 60, 52' + fill = 'foreground' + width = 'height' + height = 'auto' + xpos = 'right' + ypos = 'center' + orientation = 'bottom' + /> + <text font = 'text_hover' + vertical_align = 'center' + horizontal_align = 'right' + /> + </drawdata> + + <drawdata id = 'widget_textedit' cache = false> + <drawstep func = 'roundedsq' + fill = 'foreground' + radius = 4 + fg_color = 'blandyellow' + shadow = 0 + bevel = 1 + bevel_color = 'shadowcolor' + /> + </drawdata> + + <drawdata id = 'plain_bg' cache = false> + <drawstep func = 'roundedsq' + radius = 6 + stroke = 0 + gradient_start = 'blandyellow' + gradient_end = 'xtrabrightred' + fill = 'gradient' + shadow = 3 + /> + </drawdata> + + <drawdata id = 'caret' cache = false> + <drawstep func = 'square' + fill = 'foreground' + fg_color = 'black' + /> + </drawdata> + + <drawdata id = 'default_bg' cache = false> + <drawstep func = 'roundedsq' + radius = 12 + stroke = 0 + fg_color = 'xtrabrightred' + fill = 'foreground' + shadow = 3 + /> + </drawdata> + + <drawdata id = 'button_idle' cache = false> + <text font = 'text_button' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'roundedsq' + radius = '3' + stroke = 1 + fill = 'gradient' + shadow = 0 + fg_color = 'shadowcolor' + gradient_start = 'brightred' + gradient_end = 'darkred' + bevel = 1 + /> + </drawdata> + + <drawdata id = 'button_hover' cache = false> + <text font = 'text_button_hover' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'roundedsq' + radius = '3' + gradient_factor = 1 + stroke = 1 + fill = 'gradient' + shadow = 0 + fg_color = 'shadowcolor' + gradient_start = 'xtrabrightred' + gradient_end = 'darkred' + bevel_color = 'xtrabrightred' + bevel = 1 + /> + </drawdata> + + <drawdata id = 'button_disabled' cache = false> + <text font = 'text_disabled' + vertical_align = 'center' + horizontal_align = 'center' + /> + <drawstep func = 'roundedsq' + radius = '3' + stroke = 1 + fill = 'gradient' + shadow = 0 + fg_color = 'shadowcolor' + gradient_start = 'brightred' + gradient_end = 'darkred' + bevel = 1 + /> + </drawdata> + + <drawdata id = 'checkbox_disabled' cache = false> + <text font = 'text_disabled' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'roundedsq' + fill = 'none' + radius = 4 + fg_color = 'black' + shadow = 0 + bevel = 1 + bevel_color = 'shadowcolor' + /> + </drawdata> + + <drawdata id = 'checkbox_selected' cache = false> + <text font = 'text_default' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'bitmap' + file = 'checkbox.bmp' + /> + </drawdata> + + <drawdata id = 'checkbox_default' cache = false> + <text font = 'text_default' + vertical_align = 'top' + horizontal_align = 'left' + /> + <drawstep func = 'roundedsq' + fill = 'foreground' + radius = 4 + fg_color = 'blandyellow' + shadow = 0 + bevel = 1 + bevel_color = 'shadowcolor' + /> + </drawdata> + + <drawdata id = 'widget_default' cache = false> + <drawstep func = 'roundedsq' + radius = 8 + stroke = 0 + gradient_start = 'blandyellow' + gradient_end = 'xtrabrightred' + gradient_factor = '6' + fill = 'gradient' + shadow = 3 + /> + </drawdata> +</render_info>
\ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout.stx b/gui/themes/scummodern/scummodern_layout.stx new file mode 100644 index 0000000000..61545d0ffa --- /dev/null +++ b/gui/themes/scummodern/scummodern_layout.stx @@ -0,0 +1,604 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<layout_info resolution = '-320xY, -256x240'> + <globals> + <def var = 'Line.Height' value = '16' /> + <def var = 'Font.Height' value = '16' /> + <def var = 'TabLabelWidth' value = '110' /> + + <def var = 'WidgetSize' value = 'kBigWidgetSize' /> + + <def var = 'Padding.Bottom' value = '16' /> + <def var = 'Padding.Left' value = '16' /> + <def var = 'Padding.Right' value = '16' /> + <def var = 'Padding.Top' value = '16' /> + + <def var = 'About.OuterBorder' value = '80'/> + + <def var = 'ListWidget.hlLeftPadding' value = '0'/> + <def var = 'ListWidget.hlRightPadding' value = '0'/> + <def var = 'PopUpWidget.labelSpacing' value = '10' /> + + <def var = 'ShowLauncherLogo' value = '1'/> + + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '1'/> + + <widget name = 'OptionsLabel' + size = '110, Globals.Line.Height' + /> + <widget name = 'SmallLabel' + size = '24, Globals.Line.Height' + /> + + <widget name = 'Button' + size = 'kBigButtonWidth, kBigButtonHeight' + /> + + + <widget name = 'Slider' + size = 'kBigSliderWidth, kBigSliderHeight' + /> + <widget name = 'PopUp' + size = '-1, 19' + /> + <widget name = 'Checkbox' + size = '-1, Globals.Line.Height' + /> + <widget name = 'ListWidget' + padding = '5, 0, 8, 0' + /> + <widget name = 'PopUpWidget' + padding = '7, 5, 0, 0' + /> + <widget name = 'EditTextWidget' + padding = '5, 5, 0, 0' + /> + <widget name = 'Console' + padding = '7, 5, 5, 5' + /> + <widget name = 'TabWidget.Tab' + size = '75, 27' + padding = '0, 0, 8, 0' + /> + <widget name = 'TabWidget.NavButton' + size = '15, 18' + padding = '0, 3, 4, 0' + /> + </globals> + + <dialog name = 'Launcher' overlays = 'screen'> + <layout type = 'vertical' center = 'true' padding = '23, 23, 8, 23'> + <widget name = 'Version' + width = '247' + height = 'Globals.Line.Height' + /> + <widget name = 'Logo' + width = '283' + height = '80' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'GameList'/> + <layout type = 'vertical' padding = '10, 0, 0, 0'> + <widget name = 'StartButton' + type = 'Button' + /> + <space size = '16' /> + <widget name = 'AddGameButton' + type = 'Button' + /> + <widget name = 'EditGameButton' + type = 'Button' + /> + <widget name = 'RemoveGameButton' + type = 'Button' + /> + <space size = '16' /> + <widget name = 'OptionsButton' + type = 'Button' + /> + <widget name = 'AboutButton' + type = 'Button' + /> + <space size = '16' /> + <widget name = 'QuitButton' + type = 'Button' + /> + </layout> + </layout> + </layout> + </dialog> + + <dialog name = 'Browser' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Path' + height = 'Globals.Line.Height' + /> + <widget name = 'List'/> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Up' + type = 'Button' + /> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions' overlays = 'Dialog.Launcher.GameList' shading = 'dim'> + <layout type = 'vertical' padding = '0, 0, 0, 0'> + <widget name = 'TabWidget'/> + <layout type = 'horizontal' padding = '16, 16, 16, 16'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'grModePopup' + type = 'PopUp' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + <widget name = 'grAspectCheckbox' + type = 'Checkbox' + /> + <widget name = 'grFullscreenCheckbox' + type = 'Checkbox' + /> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '150' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + </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'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + </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'> + <widget name = 'mcFontButton' + type = 'Button' + /> + <widget name = 'mcFontClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + <widget name = 'mcFontPath' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'mcMixedCheckbox' + type = 'Checkbox' + /> + <widget name = 'mcMt32Checkbox' + type = 'Checkbox' + /> + <widget name = 'mcGSCheckbox' + type = 'Checkbox' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'mcMidiGainText' + type = 'OptionsLabel' + /> + <widget name = 'mcMidiGainSlider' + type = 'Slider' + /> + <widget name = 'mcMidiGainLabel' + width = '32' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'SaveButton' + type = 'Button' + /> + <widget name = 'SavePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'ThemePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ExtraButton' + type = 'Button' + /> + <widget name = 'ExtraPath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'PluginsButton' + type = 'Button' + /> + <widget name = 'PluginsPath' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'CurTheme' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'Renderer' + type = 'PopUp' + /> + <widget name = 'AutosavePeriod' + type = 'PopUp' + /> + </layout> + </dialog> + + <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 = '16, 16, 16, 4'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Graphics' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Audio' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_MIDI' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Volume' /> + </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 = '16'> + <widget name = 'Id' + type = 'OptionsLabel' + /> + <widget name = 'Domain' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'Name' + type = 'OptionsLabel' + /> + <widget name = 'Desc' + type = 'PopUp' + /> + </layout> + <widget name = 'Lang' + type = 'PopUp' + /> + <widget name = 'Platform' + type = 'PopUp' + /> + </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 = '16' center = 'true'> + <widget name = 'Savepath' + type = 'Button' + /> + <widget name = 'SavepathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Extrapath' + type = 'Button' + /> + <widget name = 'ExtrapathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Gamepath' + type = 'Button' + /> + <widget name = 'GamepathText' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummMain' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Resume' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Load' + type = 'Button' + /> + <widget name = 'Save' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Options' + type = 'Button' + /> + <widget name = 'Help' + type = 'Button' + /> + <widget name = 'About' + type = 'Button' + /> + <space size = '15'/> + <widget name = 'Quit' + type = 'Button' + /> + </layout> + </dialog> + + <dialog name = 'ScummConfig' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '158' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + <space size = '60'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = 'Globals.Button.Width' /> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> + <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'> + <widget name = 'Title' + height = 'Globals.Line.Height' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'> + <widget name = 'List' /> + <widget name = 'Thumbnail' + width = '180' + height = '200' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + 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 = '320' + height = 'Globals.Line.Height' + /> + <widget name = 'HelpText' + height = '220' + /> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Prev' + type = 'Button' + /> + <widget name = 'Next' + type = 'Button' + /> + <space size = '32'/> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </layout> + </dialog> +</layout_info>
\ No newline at end of file diff --git a/gui/themes/scummodern/scummodern_layout_320.stx b/gui/themes/scummodern/scummodern_layout_320.stx new file mode 100644 index 0000000000..9d689e5c8d --- /dev/null +++ b/gui/themes/scummodern/scummodern_layout_320.stx @@ -0,0 +1,582 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +<layout_info resolution = "320xY, 256x240"> + <globals> + <def var = 'Line.Height' value = '12' /> + <def var = 'Font.Height' value = '10' /> + <def var = 'TabLabelWidth' value = '100' /> + + <def var = 'WidgetSize' value = 'kNormalWidgetSize' /> + <def var = 'About.OuterBorder' value = '10'/> + <def var = 'PopUpWidget.labelSpacing' value = '6' /> + + <def var = 'ShowLauncherLogo' value = '0'/> + <def var = 'ScummSaveLoad.ExtInfo.Visible' value = '0'/> + + <widget name = 'Button' + size = 'kButtonWidth, kButtonHeight' + /> + + <widget name = 'Slider' + size = 'kSliderWidth, kSliderHeight' + /> + + <widget name = 'OptionsLabel' + size = '110, Globals.Line.Height' + /> + <widget name = 'SmallLabel' + size = '18, Globals.Line.Height' + /> + <widget name = 'PopUp' + size = '-1, 15' + /> + <widget name = 'Checkbox' + size = '-1, Globals.Line.Height' + /> + <widget name = 'ListWidget' + padding = '5, 0, 8, 0' + /> + <widget name = 'PopUpWidget' + padding = '7, 5, 0, 0' + /> + <widget name = 'EditTextWidget' + padding = '5, 5, 0, 0' + /> + <widget name = 'Console' + padding = '7, 5, 5, 5' + /> + <widget name = 'TabWidget.Tab' + size = '45, 16' + padding = '0, 0, 2, 0' + /> + <widget name = 'TabWidget.NavButton' + size = '32, 18' + padding = '0, 3, 4, 0' + /> + </globals> + + <dialog name = 'Launcher' overlays = 'screen'> + <layout type = 'vertical' center = 'true' padding = '8, 8, 8, 4' spacing = '8'> + <widget name = 'Version' + height = 'Globals.Line.Height' + /> + <widget name = 'GameList'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'> + <widget name = 'AddGameButton' + height = 'Globals.Button.Height' + /> + <widget name = 'EditGameButton' + height = 'Globals.Button.Height' + /> + <widget name = 'RemoveGameButton' + height = 'Globals.Button.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'QuitButton' + height = 'Globals.Button.Height' + /> + <widget name = 'AboutButton' + height = 'Globals.Button.Height' + /> + <widget name = 'OptionsButton' + height = 'Globals.Button.Height' + /> + <widget name = 'StartButton' + height = 'Globals.Button.Height' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'Browser' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Headline' + height = 'Globals.Line.Height' + /> + <widget name = 'Path' + height = 'Globals.Line.Height' + /> + <widget name = 'List'/> + <layout type = 'horizontal' padding = '0, 0, 16, 0'> + <widget name = 'Up' + type = 'Button' + /> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions' overlays = 'screen' inset = '16' shading = 'dim'> + <layout type = 'vertical' padding = '0, 0, 0, 0'> + <widget name = 'TabWidget'/> + <layout type = 'horizontal' padding = '8, 8, 8, 8'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'grModePopup' + type = 'PopUp' + /> + <widget name = 'grRenderPopup' + type = 'PopUp' + /> + <widget name = 'grAspectCheckbox' + type = 'Checkbox' + /> + <widget name = 'grFullscreenCheckbox' + type = 'Checkbox' + /> + </layout> + </dialog> + + <dialog name = 'GlobalOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'auMidiPopup' + type = 'PopUp' + /> + <widget name = 'auSampleRatePopup' + type = 'PopUp' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = 'Globals.Slider.Width' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + </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'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + </layout> + </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'> + <widget name = 'mcFontButton' + type = 'Button' + /> + <widget name = 'mcFontPath' + height = 'Globals.Line.Height' + /> + <widget name = 'mcFontClearButton' + height = 'Globals.Line.Height' + width = 'Globals.Line.Height' + /> + </layout> + <widget name = 'mcMixedCheckbox' + type = 'Checkbox' + /> + <widget name = 'mcMt32Checkbox' + type = 'Checkbox' + /> + <widget name = 'mcGSCheckbox' + type = 'Checkbox' + /> + <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <widget name = 'mcMidiGainText' + type = 'OptionsLabel' + /> + <widget name = 'mcMidiGainSlider' + type = 'Slider' + /> + <widget name = 'mcMidiGainLabel' + width = '32' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'SaveButton' + type = 'Button' + /> + <widget name = 'SavePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'ThemePath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'ExtraButton' + type = 'Button' + /> + <widget name = 'ExtraPath' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'PluginsButton' + type = 'Button' + /> + <widget name = 'PluginsPath' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </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'> + <widget name = 'ThemeButton' + type = 'Button' + /> + <widget name = 'CurTheme' + height = 'Globals.Line.Height' + /> + </layout> + <widget name = 'Renderer' + type = 'PopUp' + /> + <widget name = 'AutosavePeriod' + type = 'PopUp' + /> + </layout> + </dialog> + + <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 = '8, 8, 8, 8'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Graphics' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Audio' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Audio' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_MIDI' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_MIDI' /> + </layout> + </dialog> + + <dialog name = 'GameOptions_Volume' overlays = 'Dialog.GlobalOptions.TabWidget'> + <layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'> + <widget name = 'EnableTabCheckbox' + type = 'Checkbox' + /> + <import layout = 'Dialog.GlobalOptions_Volume' /> + </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 = '16'> + <widget name = 'Id' + width = '35' + height = 'Globals.Line.Height' + /> + <widget name = 'Domain' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16'> + <widget name = 'Name' + width = '35' + height = 'Globals.Line.Height' + /> + <widget name = 'Desc' + type = 'PopUp' + /> + </layout> + <space size = '8'/> + <widget name = 'Lang' + type = 'PopUp' + /> + <widget name = 'Platform' + type = 'PopUp' + /> + </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 = '16' center = 'true'> + <widget name = 'Savepath' + type = 'Button' + /> + <widget name = 'SavepathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Extrapath' + type = 'Button' + /> + <widget name = 'ExtrapathText' + height = 'Globals.Line.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '16' center = 'true'> + <widget name = 'Gamepath' + type = 'Button' + /> + <widget name = 'GamepathText' + height = 'Globals.Line.Height' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummMain' overlays = 'screen_center'> + <layout type = 'vertical' padding = '4, 4, 4, 4'> + <widget name = 'Resume' + type = 'Button' + /> + <space size = '8'/> + <widget name = 'Load' + type = 'Button' + /> + <widget name = 'Save' + type = 'Button' + /> + <space size = '8'/> + <widget name = 'Options' + type = 'Button' + /> + <widget name = 'Help' + type = 'Button' + /> + <widget name = 'About' + type = 'Button' + /> + <space size = '8'/> + <widget name = 'Quit' + type = 'Button' + /> + </layout> + </dialog> + + <dialog name = 'ScummConfig' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcMusicText' + type = 'OptionsLabel' + /> + <widget name = 'vcMusicSlider' + type = 'Slider' + /> + <widget name = 'vcMusicLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSfxText' + type = 'OptionsLabel' + /> + <widget name = 'vcSfxSlider' + type = 'Slider' + /> + <widget name = 'vcSfxLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'vcSpeechText' + type = 'OptionsLabel' + /> + <widget name = 'vcSpeechSlider' + type = 'Slider' + /> + <widget name = 'vcSpeechLabel' + type = 'SmallLabel' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subToggleDesc' + type = 'OptionsLabel' + /> + <widget name = 'subToggleButton' + width = '92' + height = 'Globals.Slider.Height' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <widget name = 'subSubtitleSpeedDesc' + type = 'OptionsLabel' + /> + <widget name = 'subSubtitleSpeedSlider' + type = 'Slider' + /> + <widget name = 'subSubtitleSpeedLabel' + type = 'SmallLabel' + /> + </layout> + <space size = '20'/> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> + <space size = 'Globals.Button.Width' /> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Ok' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummSaveLoad' overlays = 'screen' inset = '16'> + <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'> + <space/> + <widget name = 'Cancel' + type = 'Button' + /> + <widget name = 'Choose' + type = 'Button' + /> + </layout> + </layout> + </dialog> + + <dialog name = 'ScummHelp' overlays = 'screen_center'> + <layout type = 'vertical' padding = '8, 8, 8, 8'> + <widget name = 'Title' + width = '180' + height = 'Globals.Line.Height' + /> + <widget name = 'HelpText' + height = '170' + /> + <layout type = 'horizontal' padding = '0, 0, 4, 0'> + <widget name = 'Prev' + type = 'Button' + /> + <widget name = 'Next' + type = 'Button' + /> + <space size = '32'/> + <widget name = 'Close' + type = 'Button' + /> + </layout> + </layout> + </dialog> +</layout_info> diff --git a/gui/themes/scummtheme.py b/gui/themes/scummtheme.py new file mode 100644 index 0000000000..da0b88cf61 --- /dev/null +++ b/gui/themes/scummtheme.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# encoding: utf-8 +import sys +import re +import os +import zipfile + +def buildTheme(themeName): + if not os.path.isdir(themeName) or not os.path.isfile(os.path.join(themeName, "THEMERC")): + print "Invalid theme name: " + themeName + return + + zf = zipfile.ZipFile(themeName + ".zip", 'w') + + print "Building '" + themeName + "' theme:" + os.chdir(themeName) + + for filename in os.listdir('.'): + if os.path.isfile(filename) and not filename[0] == '.': + zf.write(filename, './' + filename) + print " Adding file: " + filename + + os.chdir('../') + + zf.close() + +def buildAllThemes(): + for f in os.listdir('.'): + if os.path.isdir(os.path.join('.', f)) and not f[0] == '.': + buildTheme(f) + +def parseSTX(theme_file, def_file): + comm = re.compile("\/\*(.*?)\*\/", re.DOTALL) + + output = "" + for line in theme_file: + output += line.rstrip("\r\n\t ").lstrip() + " \n" + + output = re.sub(comm, "", output).replace("\t", " ").replace(" ", " ").replace("\"", "'").splitlines() + + for line in output: + if line and not line.isspace(): + def_file.write("\"" + line + "\"\n") + +def buildDefTheme(themeName): + def_file = open("default.inc", "w") + + if not os.path.isdir(themeName): + print "Cannot open default theme dir." + + for filename in os.listdir(themeName): + filename = os.path.join(themeName, filename) + if os.path.isfile(filename) and filename.endswith(".stx"): + theme_file = open(filename, "r") + parseSTX(theme_file, def_file) + theme_file.close() + + def_file.close() + +def printUsage(): + print "===============================" + print "ScummVM Theme Generation Script" + print "===============================" + print "Usage:" + print "scummtheme.py makeall" + print " Builds all the available themes.\n" + print "scummtheme.py make [themename]" + print " Builds the theme called 'themename'.\n" + print "scummtheme.py default [themename]" + print " Creates a 'default.inc' file to embed the given theme in the source code.\n" + +def main(): + + if len(sys.argv) == 2 and sys.argv[1] == "makeall": + buildAllThemes() + + elif len(sys.argv) == 3 and sys.argv[1] == "make": + buildTheme(sys.argv[2]) + + elif len(sys.argv) == 3 and sys.argv[1] == "default": + buildDefTheme(sys.argv[2]) + + else: + printUsage() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/gui/widget.cpp b/gui/widget.cpp index e9afc30301..685b6dfc65 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -26,22 +26,21 @@ #include "graphics/fontman.h" #include "gui/widget.h" #include "gui/dialog.h" -#include "gui/eval.h" #include "gui/newgui.h" +#include "gui/ThemeEval.h" + namespace GUI { Widget::Widget(GuiObject *boss, int x, int y, int w, int h) : GuiObject(x, y, w, h), _type(0), _boss(boss), - _id(0), _flags(0), _hints(THEME_HINT_FIRST_DRAW), - _hasFocus(false), _state(Theme::kStateEnabled) { + _id(0), _flags(0), _hasFocus(false), _state(Theme::kStateEnabled) { init(); } Widget::Widget(GuiObject *boss, const Common::String &name) : GuiObject(name), _type(0), _boss(boss), - _id(0), _flags(0), _hints(THEME_HINT_FIRST_DRAW), - _hasFocus(false), _state(Theme::kStateDisabled) { + _id(0), _flags(0), _hasFocus(false), _state(Theme::kStateDisabled) { init(); } @@ -49,8 +48,6 @@ void Widget::init() { // Insert into the widget list of the boss _next = _boss->_firstWidget; _boss->_firstWidget = this; - // HACK: we enable background saving for all widgets by default for now - _hints = THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND; } Widget::~Widget() { @@ -99,7 +96,7 @@ void Widget::draw() { // Draw border if (_flags & WIDGET_BORDER) { - gui->theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _hints, Theme::kWidgetBackgroundBorder); + gui->theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, Theme::kWidgetBackgroundBorder); _x += 4; _y += 4; _w -= 8; @@ -126,8 +123,6 @@ void Widget::draw() { w->draw(); w = w->_next; } - - clearHints(THEME_HINT_FIRST_DRAW); } Widget *Widget::findWidgetInChain(Widget *w, int x, int y) { @@ -153,14 +148,14 @@ Widget *Widget::findWidgetInChain(Widget *w, const char *name) { } bool Widget::isEnabled() const { - if (g_gui.evaluator()->getVar(_name + ".enabled") == 0) { + if (g_gui.xmlEval()->getVar("Dialog." + _name + ".Enabled", 1) == 0) { return false; } return ((_flags & WIDGET_ENABLED) != 0); } bool Widget::isVisible() const { - if (g_gui.evaluator()->getVar(_name + ".visible") == 0) + if (g_gui.xmlEval()->getVar("Dialog." + _name + ".Visible", 1) == 0) return false; return !(_flags & WIDGET_INVISIBLE); @@ -181,10 +176,7 @@ StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, _type = kStaticTextWidget; _label = text; - _align = (Graphics::TextAlignment)g_gui.evaluator()->getVar(name + ".align"); - - if (_align == (int)EVAL_UNDEF_VAR) - _align = kTextAlignLeft; + _align = (Graphics::TextAlignment)g_gui.xmlEval()->getVar(name + ".Align", kTextAlignLeft); } void StaticTextWidget::setValue(int value) { @@ -226,7 +218,6 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co : StaticTextWidget(boss, name, label), CommandSender(boss), _cmd(cmd), _hotkey(hotkey) { setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG); - _hints = THEME_HINT_USE_SHADOW; _type = kButtonWidget; } @@ -236,7 +227,7 @@ void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) { } void ButtonWidget::drawWidget() { - g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, _hints); + g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, 0); } #pragma mark - @@ -336,20 +327,12 @@ GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h) : Widget(boss, x, y, w, h), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; - // HACK: Don't save the background. We want to be sure that redrawing - // the widget updates the screen, even when there isn't any image - // to draw. - _hints &= ~THEME_HINT_SAVE_BACKGROUND; } GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name) : Widget(boss, name), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; - // HACK: Don't save the background. We want to be sure that redrawing - // the widget updates the screen, even when there isn't any image - // to draw. - _hints &= ~THEME_HINT_SAVE_BACKGROUND; } GraphicsWidget::~GraphicsWidget() { @@ -404,7 +387,7 @@ ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) : } void ContainerWidget::drawWidget() { - g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _hints, Theme::kWidgetBackgroundBorder); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, Theme::kWidgetBackgroundBorder); } } // End of namespace GUI diff --git a/gui/widget.h b/gui/widget.h index 00bf800857..3e111f28d4 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -93,7 +93,6 @@ protected: GuiObject *_boss; Widget *_next; uint16 _id; - uint16 _hints; bool _hasFocus; Theme::WidgetStateInfo _state; @@ -142,10 +141,6 @@ public: void clearFlags(int flags); int getFlags() const { return _flags; } - void setHints(int hints) { _hints |= hints; } - void clearHints(int hints) { _hints &= ~hints; } - int getHints() const { return _hints; } - void setEnabled(bool e) { if (e) setFlags(WIDGET_ENABLED); else clearFlags(WIDGET_ENABLED); } bool isEnabled() const; bool isVisible() const; |