diff options
author | Max Horn | 2009-01-01 21:41:55 +0000 |
---|---|---|
committer | Max Horn | 2009-01-01 21:41:55 +0000 |
commit | 97e9b28c8ac480e7ba9819c5525a1d8bec45d2f4 (patch) | |
tree | cdf664f30b7df331b6247494d5af5629df67f290 /gui | |
parent | 9752882f8bbe6070f69638d3c54156a1c0e61204 (diff) | |
download | scummvm-rg350-97e9b28c8ac480e7ba9819c5525a1d8bec45d2f4.tar.gz scummvm-rg350-97e9b28c8ac480e7ba9819c5525a1d8bec45d2f4.tar.bz2 scummvm-rg350-97e9b28c8ac480e7ba9819c5525a1d8bec45d2f4.zip |
Revamping the handling of GUI themes a bit:
* Moved the code which handles fallback to the built-in theme from ThemeEngine to GuiManager
* Changed ThemeEngine::init() to only init&load the theme; no more messing with the overlay
* Commented to a somewhat obscure line in the GuiManager event loop (taking eriktorbjorn's original commit message for that change as comment text)
* Cleaned up the way the Dialog constructor ensures that the current Theme is correctly setup
* Got rid of varios members of ThemeEngine
* Changed ThemeEngine members _screen and _backBuffer from Surface pointers to just plain Surfaces
* Changed ThemeEngine::loadFontFromArchive to use _themeArchive instead of creating an Archive from scratch
* Renamed ThemeEngine::getThemeFileName() to getThemeId() (and some associated tweaks)
* Lots of further cleanup and tweaks
svn-id: r35653
Diffstat (limited to 'gui')
-rw-r--r-- | gui/ThemeEngine.cpp | 266 | ||||
-rw-r--r-- | gui/ThemeEngine.h | 48 | ||||
-rw-r--r-- | gui/dialog.cpp | 5 | ||||
-rw-r--r-- | gui/newgui.cpp | 72 | ||||
-rw-r--r-- | gui/newgui.h | 17 | ||||
-rw-r--r-- | gui/options.cpp | 2 |
6 files changed, 177 insertions, 233 deletions
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 3b6791d281..b3721011f3 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -51,10 +51,9 @@ namespace GUI { * ThemeEngine class *********************************************************/ ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) : - _system(0), _vectorRenderer(0), _screen(0), _backBuffer(0), + _system(0), _vectorRenderer(0), _buffering(false), _bytesPerPixel(0), _graphicsMode(kGfxDisabled), - _font(0), _initOk(false), _themeOk(false), _enabled(false), _cursor(0), - _loadedThemeX(0), _loadedThemeY(0) { + _font(0), _initOk(false), _themeOk(false), _enabled(false), _cursor(0) { _system = g_system; _parser = new ThemeParser(this); @@ -71,13 +70,17 @@ ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) : } _graphicsMode = mode; - _themeFileName = fileName; + _themeId = fileName; _themeArchive = 0; _initOk = false; } ThemeEngine::~ThemeEngine() { - deinit(); + delete _vectorRenderer; + _vectorRenderer = 0; + _screen.free(); + _backBuffer.free(); + unloadTheme(); delete _parser; delete _themeEval; @@ -133,82 +136,31 @@ const char *ThemeEngine::findModeConfigName(GraphicsMode mode) { *********************************************************/ bool ThemeEngine::init() { // reset everything and reload the graphics - if (_initOk) - _system->hideOverlay(); - deinit(); + _initOk = false; setGraphicsMode(_graphicsMode); - if (_screen->pixels && _backBuffer->pixels) { + if (_screen.pixels && _backBuffer.pixels) { _initOk = true; - clearAll(); } - if (_screen->w >= 400 && _screen->h >= 300) { + // TODO: Instead of hard coding the font here, it should be possible + // to specify the fonts to be used for each resolution in the theme XML. + 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 ThemeEngine::deinit() { - delete _vectorRenderer; - _vectorRenderer = 0; - if (_screen != 0) { - _screen->free(); - delete _screen; - _screen = 0; - } - if (_backBuffer != 0) { - _backBuffer->free(); - delete _backBuffer; - _backBuffer = 0; - } - _initOk = false; -} - -void ThemeEngine::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; - } - - // Release all graphics surfaces - for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) { - Graphics::Surface *surf = i->_value; - if (surf) { - surf->free(); - delete surf; - } - } - _bitmaps.clear(); + loadTheme(_themeId); - delete _themeArchive; - _themeArchive = 0; - - _themeEval->reset(); - _themeOk = false; + return ready(); } void ThemeEngine::clearAll() { - if (!_initOk) - return; - - _system->clearOverlay(); - _system->grabOverlay((OverlayColor *)_screen->pixels, _screen->w); + if (_initOk) { + _system->clearOverlay(); + _system->grabOverlay((OverlayColor *)_screen.pixels, _screen.w); + } } void ThemeEngine::refresh() { @@ -226,8 +178,11 @@ void ThemeEngine::refresh() { void ThemeEngine::enable() { init(); - if (_useCursor) - setUpCursor(); + if (_useCursor) { + CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); + CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); + CursorMan.showMouse(true); + } _system->showOverlay(); clearAll(); @@ -245,28 +200,6 @@ void ThemeEngine::disable() { _enabled = false; } -template<typename PixelType> -void ThemeEngine::screenInit(bool backBuffer) { - uint32 width = _system->getOverlayWidth(); - uint32 height = _system->getOverlayHeight(); - - if (backBuffer) { - if (_backBuffer) - _backBuffer->free(); - else - _backBuffer = new Graphics::Surface; - _backBuffer->create(width, height, sizeof(PixelType)); - } - - - if (_screen) - _screen->free(); - else - _screen = new Graphics::Surface; - _screen->create(width, height, sizeof(PixelType)); - _system->clearOverlay(); -} - void ThemeEngine::setGraphicsMode(GraphicsMode mode) { switch (mode) { case kGfxStandard16bit: @@ -274,16 +207,24 @@ void ThemeEngine::setGraphicsMode(GraphicsMode mode) { case kGfxAntialias16bit: #endif _bytesPerPixel = sizeof(uint16); - screenInit<uint16>(kEnableBackCaching); break; default: error("Invalid graphics mode"); } + uint32 width = _system->getOverlayWidth(); + uint32 height = _system->getOverlayHeight(); + + _backBuffer.free(); + _backBuffer.create(width, height, _bytesPerPixel); + + _screen.free(); + _screen.create(width, height, _bytesPerPixel); + delete _vectorRenderer; _vectorRenderer = Graphics::createRenderer(mode); - _vectorRenderer->setSurface(_screen); + _vectorRenderer->setSurface(&_screen); } bool ThemeEngine::isWidgetCached(DrawData type, const Common::Rect &r) { @@ -293,7 +234,7 @@ bool ThemeEngine::isWidgetCached(DrawData type, const Common::Rect &r) { } void ThemeEngine::drawCached(DrawData type, const Common::Rect &r) { - assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen->bytesPerPixel); + assert(_widgets[type]->_surfaceCache->bytesPerPixel == _screen.bytesPerPixel); _vectorRenderer->blitSurface(_widgets[type]->_surfaceCache, r); } @@ -312,23 +253,10 @@ void ThemeEngine::calcBackgroundOffset(DrawData type) { } void ThemeEngine::restoreBackground(Common::Rect r) { - r.clip(_screen->w, _screen->h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( - _vectorRenderer->blitSurface(_backBuffer, r); + r.clip(_screen.w, _screen.h); // AHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA... Oh god. :( + _vectorRenderer->blitSurface(&_backBuffer, r); } -bool ThemeEngine::isThemeLoadingRequired() { - int x = g_system->getOverlayWidth(), y = g_system->getOverlayHeight(); - - if (_loadedThemeX == x && _loadedThemeY == y) - return false; - - _loadedThemeX = x; - _loadedThemeY = y; - - return true; -} - - /********************************************************** @@ -434,21 +362,19 @@ bool ThemeEngine::addDrawData(const Common::String &data, bool cached) { /********************************************************** * Theme XML loading *********************************************************/ -bool ThemeEngine::loadTheme(const Common::String &fileName) { +void ThemeEngine::loadTheme(const Common::String &themeid) { unloadTheme(); - bool tryAgain = false; - if (fileName != "builtin") { + if (themeid == "builtin") { + _themeOk = loadDefaultXML(); + } else { // Load the archive containing image and XML data - if (!loadThemeXML(fileName)) { - warning("Could not parse custom theme '%s'. Falling back to default theme", fileName.c_str()); - tryAgain = true; // Fall back to default builtin theme - } + _themeOk = loadThemeXML(themeid); } - - if (fileName == "builtin" || tryAgain) { - if (!loadDefaultXML()) // if we can't load the embedded theme, this is a complete failure - error("Could not load default embedded theme"); + + if (!_themeOk) { + warning("Failed to load theme '%s'", themeid.c_str()); + return; } for (int i = 0; i < kDrawDataMAX; ++i) { @@ -461,9 +387,37 @@ bool ThemeEngine::loadTheme(const Common::String &fileName) { if (_widgets[i]->_cached) {} } } +} - _themeOk = true; - return true; +void ThemeEngine::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; + } + + // Release all graphics surfaces + for (ImagesMap::iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) { + Graphics::Surface *surf = i->_value; + if (surf) { + surf->free(); + delete surf; + } + } + _bitmaps.clear(); + + delete _themeArchive; + _themeArchive = 0; + + _themeEval->reset(); + _themeOk = false; } bool ThemeEngine::loadDefaultXML() { @@ -483,7 +437,7 @@ bool ThemeEngine::loadDefaultXML() { return false; _themeName = "ScummVM Classic Theme (Builtin Version)"; - _themeFileName = "builtin"; + _themeId = "builtin"; result = _parser->parse(); _parser->close(); @@ -535,7 +489,7 @@ bool ThemeEngine::loadThemeXML(const Common::String &themeName) { Common::String stxHeader = themercFile.readLine(); if (!themeConfigParseHeader(stxHeader, _themeName) || _themeName.empty()) { delete archive; - warning("Corrupted 'THEMERC' file in theme '%s'", _themeFileName.c_str()); + warning("Corrupted 'THEMERC' file in theme '%s'", _themeId.c_str()); return false; } @@ -585,7 +539,7 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic) return; Common::Rect area = r; - area.clip(_screen->w, _screen->h); + area.clip(_screen.w, _screen.h); ThemeItemDrawData *q = new ThemeItemDrawData(this, _widgets[type], area, dynamic); @@ -611,7 +565,7 @@ void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common return; Common::Rect area = r; - area.clip(_screen->w, _screen->h); + area.clip(_screen.w, _screen.h); ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], area, text, alignH, alignV, ellipsis, restoreBg, deltax); @@ -626,7 +580,7 @@ void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common void ThemeEngine::queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha) { Common::Rect area = r; - area.clip(_screen->w, _screen->h); + area.clip(_screen.w, _screen.h); ThemeItemBitmap *q = new ThemeItemBitmap(this, area, bitmap, alpha); @@ -891,22 +845,22 @@ void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font return; Common::Rect charArea = r; - charArea.clip(_screen->w, _screen->h); + charArea.clip(_screen.w, _screen.h); Graphics::PixelFormat format = _system->getOverlayFormat(); uint32 color = Graphics::RGBToColor(_texts[kTextDataDefault]->_color.r, _texts[kTextDataDefault]->_color.g, _texts[kTextDataDefault]->_color.b, format); restoreBackground(charArea); - font->drawChar(_screen, ch, charArea.left, charArea.top, color); + font->drawChar(&_screen, ch, charArea.left, charArea.top, color); addDirtyRect(charArea); } void ThemeEngine::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); + _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); } @@ -916,15 +870,15 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { *********************************************************/ void ThemeEngine::updateScreen() { if (!_bufferQueue.empty()) { - _vectorRenderer->setSurface(_backBuffer); + _vectorRenderer->setSurface(&_backBuffer); for (Common::List<ThemeItem*>::iterator q = _bufferQueue.begin(); q != _bufferQueue.end(); ++q) { (*q)->drawSelf(true, false); delete *q; } - _vectorRenderer->setSurface(_screen); - memcpy(_screen->getBasePtr(0,0), _backBuffer->getBasePtr(0,0), _screen->pitch * _screen->h); + _vectorRenderer->setSurface(&_screen); + memcpy(_screen.getBasePtr(0,0), _backBuffer.getBasePtr(0,0), _screen.pitch * _screen.h); _bufferQueue.clear(); } @@ -964,17 +918,11 @@ void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) { if (style != kShadingNone) { _vectorRenderer->applyScreenShading(style); - addDirtyRect(Common::Rect(0, 0, _screen->w, _screen->h)); + addDirtyRect(Common::Rect(0, 0, _screen.w, _screen.h)); } - memcpy(_backBuffer->getBasePtr(0,0), _screen->getBasePtr(0,0), _screen->pitch * _screen->h); - _vectorRenderer->setSurface(_screen); -} - -void ThemeEngine::setUpCursor() { - CursorMan.pushCursorPalette(_cursorPal, 0, MAX_CURS_COLORS); - CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, _cursorTargetScale); - CursorMan.showMouse(true); + memcpy(_backBuffer.getBasePtr(0,0), _screen.getBasePtr(0,0), _screen.pitch * _screen.h); + _vectorRenderer->setSurface(&_screen); } bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) { @@ -1077,36 +1025,16 @@ ThemeEngine::TextData ThemeEngine::getTextData(DrawData ddId) { *********************************************************/ const Graphics::Font *ThemeEngine::loadFontFromArchive(const Common::String &filename) { - Common::Archive *arch = 0; + Common::SeekableReadStream *stream = 0; const Graphics::Font *font = 0; - Common::FSNode node(getThemeFileName()); - - if (node.getName().hasSuffix(".zip")) { -#ifdef USE_ZLIB - Common::ZipArchive *zip = new Common::ZipArchive(node); - if (!zip || !zip->isOpen()) - return 0; - - arch = zip; -#else - return 0; -#endif - } else { - Common::FSDirectory *dir = new Common::FSDirectory(node); - if (!dir || !dir->getFSNode().isDirectory()) - return 0; - - arch = dir; - } - - Common::SeekableReadStream *stream(arch->openFile(filename)); + if (_themeArchive) + stream = _themeArchive->openFile(filename); if (stream) { font = Graphics::NewFont::loadFromCache(*stream); delete stream; } - delete arch; return font; } diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index b96cc47d7e..1067d11b11 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -57,9 +57,6 @@ protected: friend class GUI::Dialog; friend class GUI::GuiObject; - /** Sets whether backcaching is enabled */ - static const bool kEnableBackCaching = true; - /** * DrawData sets enumeration. * Each DD set corresponds to the actual looks @@ -244,7 +241,6 @@ public: ~ThemeEngine(); bool init(); - void deinit(); void clearAll(); void refresh(); @@ -343,7 +339,7 @@ public: * @param special Deprecated. */ bool addDirtyRect(Common::Rect r, bool backup = false, bool special = false) { - r.clip(_screen->w, _screen->h); + r.clip(_screen.w, _screen.h); _dirtyScreen.push_back(r); return true; } @@ -422,6 +418,7 @@ public: */ bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, Graphics::TextAlign alignH, TextAlignVertical alignV); +protected: /** * Returns if the Theme is ready to draw stuff on screen. * Must be called instead of just checking _initOk, because @@ -433,7 +430,7 @@ public: } /** Load the them from the file with the specified name. */ - bool loadTheme(const Common::String &fileName); + void loadTheme(const Common::String &themeid); /** * Changes the active graphics mode of the GUI; may be used to either @@ -441,7 +438,7 @@ public: */ void setGraphicsMode(GraphicsMode mode); - +public: /** * Finishes buffering: widgets from then on will be drawn straight on the screen * without drawing queues. @@ -497,7 +494,7 @@ public: bool isWidgetCached(DrawData type, const Common::Rect &r); const Common::String &getThemeName() const { return _themeName; } - const Common::String &getThemeFileName() const { return _themeFileName; } + const Common::String &getThemeId() const { return _themeId; } int getGraphicsMode() const { return _graphicsMode; } protected: @@ -513,12 +510,11 @@ protected: /** * Loads the given theme into the ThemeEngine. - * Note that ThemeName is an identifier, not a filename. * - * @param ThemeName Theme identifier. + * @param themeId Theme identifier. * @returns true if the theme was successfully loaded. */ - bool loadThemeXML(const Common::String &themeName); + bool loadThemeXML(const Common::String &themeId); /** * Loads the default theme file (the embedded XML file found @@ -533,6 +529,10 @@ protected: */ void unloadTheme(); + const Graphics::Font *loadFont(const Common::String &filename); + const Graphics::Font *loadFontFromArchive(const Common::String &filename); + Common::String genCacheFilename(const char *filename); + /** * Actual Dirty Screen handling function. * Handles all the dirty squares in the list, merges and optimizes @@ -586,19 +586,9 @@ protected: public: /** - * LEGACY: Old GUI::Theme API + * @name LEGACY: Old GUI::Theme API */ - - bool needThemeReload() { - return ((_loadedThemeX != g_system->getOverlayWidth()) || - (_loadedThemeY != g_system->getOverlayHeight())); - } - - const Graphics::Font *loadFont(const Common::String &filename); - const Graphics::Font *loadFontFromArchive(const Common::String &filename); - Common::String genCacheFilename(const char *filename); - - bool isThemeLoadingRequired(); + //@{ static bool themeConfigUseable(const Common::FSNode &node, Common::String &themeName); static bool themeConfigParseHeader(Common::String header, Common::String &themeName); @@ -606,6 +596,8 @@ public: int getTabSpacing() const { return 0; } int getTabPadding() const { return 3; } + //@} + protected: OSystem *_system; /** Global system object. */ @@ -619,10 +611,10 @@ protected: GUI::ThemeEval *_themeEval; /** Main screen surface. This is blitted straight into the overlay. */ - Graphics::Surface *_screen; + Graphics::Surface _screen; /** Backbuffer surface. Stores previous states of the screen to blit back */ - Graphics::Surface *_backBuffer; + Graphics::Surface _backBuffer; /** Sets whether the current drawing is being buffered (stored for later processing) or drawn directly to the screen. */ @@ -663,12 +655,9 @@ protected: bool _enabled; //!< Whether the Theme is currently shown on the overlay Common::String _themeName; //!< Name of the currently loaded theme - Common::String _themeFileName; + Common::String _themeId; Common::Archive *_themeArchive; - /** Custom Cursor Management */ - void setUpCursor(); - bool _useCursor; int _cursorHotspotX, _cursorHotspotY; int _cursorTargetScale; @@ -679,7 +668,6 @@ protected: bool _needPaletteUpdates; uint _cursorWidth, _cursorHeight; byte _cursorPal[4*MAX_CURS_COLORS]; - int _loadedThemeX, _loadedThemeY; }; } // end of namespace GUI. diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 1296ef7bbe..ebfdb9d634 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -59,10 +59,7 @@ Dialog::Dialog(const Common::String &name) // // Fixes bug #1590596: "HE: When 3x graphics are choosen, F5 crashes game" // and bug #1595627: "SCUMM: F5 crashes game (640x480)" - if (g_gui.theme()->needThemeReload()) { - debug(2, "Theme forced to reload"); - g_gui.screenChange(); - } + g_gui.checkScreenChange(); } int Dialog::runModal() { diff --git a/gui/newgui.cpp b/gui/newgui.cpp index 9ae0db6470..167a281ab0 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -64,7 +64,14 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), ConfMan.registerDefault("gui_renderer", ThemeEngine::findModeConfigName(ThemeEngine::_defaultRendererMode)); ThemeEngine::GraphicsMode gfxMode = (ThemeEngine::GraphicsMode)ThemeEngine::findMode(ConfMan.get("gui_renderer")); - loadNewTheme(themefile, gfxMode); + // Try to load the theme + if (!loadNewTheme(themefile, gfxMode)) { + // Loading the theme failed, try to load the built-in theme + if (!loadNewTheme("builtin", gfxMode)) { + // Loading the built-in theme failed as well. Bail out + error("Failed to load any GUI theme, aborting"); + } + } _themeChange = false; } @@ -73,33 +80,40 @@ GuiManager::~GuiManager() { } bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode gfx) { - if (_theme && filename == _theme->getThemeFileName() && gfx == _theme->getGraphicsMode()) + // If we are asked to reload the currently active theme, just do nothing + // FIXME: Actually, why? It might be desirable at times to force a theme reload... + if (_theme && filename == _theme->getThemeId() && gfx == _theme->getGraphicsMode()) return true; - Common::String oldTheme = (_theme != 0) ? _theme->getThemeFileName() : ""; + ThemeEngine *newTheme = 0; if (gfx == ThemeEngine::kGfxDisabled) gfx = ThemeEngine::_defaultRendererMode; + // Try to load the new theme + newTheme = new ThemeEngine(filename, gfx); + assert(newTheme); + + if (!newTheme->init()) + return false; + + // + // Disable and delete the old theme + // if (_theme) _theme->disable(); + delete _theme; if (_useStdCursor) { CursorMan.popCursorPalette(); CursorMan.popCursor(); } - delete _theme; - _theme = new ThemeEngine(filename, gfx); - - if (!_theme) - return (!oldTheme.empty() ? loadNewTheme(oldTheme) : false); - - _theme->init(); - - if (!oldTheme.empty()) - screenChange(); - + // + // Enable the new theme + // + _theme = newTheme; + screenChange(); _themeChange = true; return true; @@ -191,8 +205,14 @@ void GuiManager::runLoop() { } Common::Event event; - while (eventMan->pollEvent(event)) { + + // The top dialog can change during the event loop. In that case, flush all the + // dialog-related events since they were probably generated while the old dialog + // was still visible, and therefore note intended for the new one. + // + // This hopefully fixes strange behaviour/crashes with pop-up widgets. (Most easy + // to trigger in 3x mode or when running ScummVM under Valgrind.) if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED) continue; @@ -307,19 +327,8 @@ void GuiManager::openDialog(Dialog *dialog) { // We reflow the dialog just before opening it. If the screen changed // since the last time we looked, also refresh the loaded theme, // and reflow all other open dialogs, too. - int tmpScreenChangeID = _system->getScreenChangeID(); - if (_lastScreenChangeID != tmpScreenChangeID) { - _lastScreenChangeID = tmpScreenChangeID; - - // reinit the whole theme - _theme->refresh(); - // refresh all dialogs - for (int i = 0; i < _dialogStack.size(); ++i) { - _dialogStack[i]->reflowLayout(); - } - } else { + if (!checkScreenChange()) dialog->reflowLayout(); - } } void GuiManager::closeTopDialog() { @@ -371,6 +380,15 @@ void GuiManager::clearDragWidget() { _dialogStack.top()->_dragWidget = 0; } +bool GuiManager::checkScreenChange() { + int tmpScreenChangeID = _system->getScreenChangeID(); + if (_lastScreenChangeID != tmpScreenChangeID) { + GuiManager::screenChange(); + return true; + } + return false; +} + void GuiManager::screenChange() { _lastScreenChangeID = _system->getScreenChangeID(); diff --git a/gui/newgui.h b/gui/newgui.h index 948edc3ec2..c6313feedd 100644 --- a/gui/newgui.h +++ b/gui/newgui.h @@ -82,10 +82,20 @@ public: int getStringWidth(const Common::String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); } int getCharWidth(byte c, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getCharWidth(c, style); } + // FIXME: clearDragWidget is apparently there for the sake of PopUpWidget::handleMouseDown. + // This seems to be an ugly hack. At the very least, it should be thoroughly documented. + // Better would be to replace it with a proper solution. void clearDragWidget(); - void screenChange(); + /** + * Tell the GuiManager to check whether the screen resolution has changed. + * If that is the case, the GuiManager will reload/refresh the active theme. + * + * @return true if the a screen change indeed occurred, false otherwise + */ + bool checkScreenChange(); +protected: enum RedrawStatus { kRedrawDisabled = 0, kRedrawOpenDialog, @@ -94,7 +104,8 @@ public: kRedrawFull }; -protected: + + OSystem *_system; ThemeEngine *_theme; @@ -136,6 +147,8 @@ protected: void animateCursor(); Dialog *getTopDialog() const; + + void screenChange(); }; } // End of namespace GUI diff --git a/gui/options.cpp b/gui/options.cpp index 98d8bbea76..d435db85a5 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -849,7 +849,7 @@ void GlobalOptionsDialog::close() { if (!ConfMan.get("gui_renderer").equalsIgnoreCase(cfg)) { // FIXME: Actually, any changes (including the theme change) should // only become active *after* the options dialog has closed. - g_gui.loadNewTheme(g_gui.theme()->getThemeFileName(), selected); + g_gui.loadNewTheme(g_gui.theme()->getThemeId(), selected); ConfMan.set("gui_renderer", cfg, _domain); } } |