diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/GuiManager.cpp | 160 | ||||
-rw-r--r-- | gui/GuiManager.h | 20 | ||||
-rw-r--r-- | gui/ThemeEngine.cpp | 207 | ||||
-rw-r--r-- | gui/ThemeEngine.h | 24 | ||||
-rw-r--r-- | gui/themebrowser.cpp | 4 | ||||
-rw-r--r-- | gui/themebrowser.h | 4 |
6 files changed, 223 insertions, 196 deletions
diff --git a/gui/GuiManager.cpp b/gui/GuiManager.cpp index 95ab7e9fac..4b84901e7d 100644 --- a/gui/GuiManager.cpp +++ b/gui/GuiManager.cpp @@ -81,17 +81,10 @@ GuiManager::~GuiManager() { delete _theme; } -bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode gfx) { - // We currently allow two different ways of theme selection in our config file: - // 1) Via full path - // 2) Via a basename, which will need to be translated into a full path - // This function assures we have a correct path to pass to the ThemeEngine - // constructor. - filename = findThemeFile(filename); - +bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx) { // 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()) + if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode()) return true; ThemeEngine *newTheme = 0; @@ -100,7 +93,7 @@ bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode gfx = ThemeEngine::_defaultRendererMode; // Try to load the new theme - newTheme = new ThemeEngine(filename, gfx); + newTheme = new ThemeEngine(id, gfx); assert(newTheme); if (!newTheme->init()) @@ -139,153 +132,6 @@ bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode return true; } -namespace { - -struct TDComparator { - const Common::String _id; - TDComparator(const Common::String &id) : _id(id) {} - - bool operator()(const GuiManager::ThemeDescriptor &r) { return _id == r.id; } -}; - -} // end of anonymous namespace - -void GuiManager::listUsableThemes(Common::List<ThemeDescriptor> &list) { - ThemeDescriptor th; - th.name = "ScummVM Classic Theme (Builtin Version)"; - th.id = "builtin"; - th.filename = "builtin"; - list.push_back(th); - - if (ConfMan.hasKey("themepath")) - listUsableThemes(Common::FSNode(ConfMan.get("themepath")), list); - -#ifdef DATA_PATH - listUsableThemes(Common::FSNode(DATA_PATH), list); -#endif - -#ifdef MACOSX - CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); - if (resourceUrl) { - char buf[256]; - if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) { - Common::FSNode resourcePath(buf); - listUsableThemes(resourcePath, list); - } - CFRelease(resourceUrl); - } -#endif - - if (ConfMan.hasKey("extrapath")) - listUsableThemes(Common::FSNode(ConfMan.get("extrapath")), list); - - listUsableThemes(Common::FSNode("."), list); - - // Now we need to strip all duplicates - // TODO: It might not be the best idea to strip duplicates. The user might - // have different versions of a specific theme in his paths, thus this code - // might show him the wrong version. The problem is we have no ways of checking - // a theme version currently. Also since we want to avoid saving the full path - // in the config file we can not do any better currently. - Common::List<ThemeDescriptor> output; - - for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) { - if (find_if(output.begin(), output.end(), TDComparator(i->id)) == output.end()) - output.push_back(*i); - } - - list = output; - output.clear(); -} - -void GuiManager::listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list) { - if (!node.exists() || !node.isReadable() || !node.isDirectory()) - return; - - ThemeDescriptor td; - - // Check whether we point to a valid theme directory. - if (ThemeEngine::themeConfigUseable(node, td.name)) { - td.filename = node.getPath(); - td.id = node.getName(); - - list.push_back(td); - - // A theme directory should never contain any other themes - // thus we just return to the caller here. - return; - } - - Common::FSList fileList; -#ifdef USE_ZLIB - // Check all files. We need this to find all themes inside ZIP archives. - if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly)) - return; - - for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { - // We will only process zip files for now - if (!i->getPath().hasSuffix(".zip")) - continue; - - td.name.clear(); - if (ThemeEngine::themeConfigUseable(*i, td.name)) { - td.filename = i->getPath(); - td.id = i->getName(); - - // If the name of the node object also contains - // the ".zip" suffix, we will strip it. - if (td.id.hasSuffix(".zip")) { - for (int j = 0; j < 4; ++j) - td.id.deleteLastChar(); - } - - list.push_back(td); - } - } - - fileList.clear(); -#endif - - // As next step we will search all subdirectories - if (!node.getChildren(fileList, Common::FSNode::kListDirectoriesOnly)) - return; - - for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) - listUsableThemes(*i, list); -} - -Common::String GuiManager::findThemeFile(const Common::String &id) { - // FIXME: Actually "default" rather sounds like it should use - // our default theme which would me "scummmodern" instead - // of the builtin one. - if (id.equalsIgnoreCase("default")) - return "builtin"; - - Common::FSNode node(id); - - // If the given id is a full path we'll just use it - if (node.exists() && (node.isDirectory() || (node.getName().hasSuffix(".zip") && !node.isDirectory()))) - return id; - - // FIXME: - // A very ugly hack to map a id to a filename, this will generate - // a complete theme list, thus it is slower than it could be. - // But it is the easiest solution for now. - Common::List<ThemeDescriptor> list; - listUsableThemes(list); - - for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) { - if (id.equalsIgnoreCase(i->id)) - return i->filename; - } - - warning("Could not find theme '%s' falling back to builtin", id.c_str()); - - // If no matching id has been found we will - // just fall back to the builtin theme - return "builtin"; -} - void GuiManager::redraw() { int i; diff --git a/gui/GuiManager.h b/gui/GuiManager.h index 2f3f3711ab..ecaf680423 100644 --- a/gui/GuiManager.h +++ b/gui/GuiManager.h @@ -29,8 +29,6 @@ #include "common/singleton.h" #include "common/stack.h" #include "common/str.h" -#include "common/list.h" -#include "common/fs.h" #include "graphics/fontman.h" @@ -75,7 +73,7 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(Common::String file, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); + bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); ThemeEngine *theme() { return _theme; } ThemeEval *xmlEval() { return _theme->getEvaluator(); } @@ -92,17 +90,6 @@ public: * @return true if the a screen change indeed occurred, false otherwise */ bool checkScreenChange(); - - struct ThemeDescriptor { - Common::String name; - Common::String id; - Common::String filename; - }; - - /** - * Lists all theme files useable. - */ - static void listUsableThemes(Common::List<ThemeDescriptor> &list); protected: enum RedrawStatus { kRedrawDisabled = 0, @@ -112,8 +99,6 @@ protected: kRedrawFull }; - - OSystem *_system; ThemeEngine *_theme; @@ -157,9 +142,6 @@ protected: Dialog *getTopDialog() const; void screenChange(); - - Common::String findThemeFile(const Common::String &id); - static void listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list); }; } // End of namespace GUI diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 4d20ef6dd1..4ee8bc2332 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -50,7 +50,7 @@ namespace GUI { /********************************************************** * ThemeEngine class *********************************************************/ -ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) : +ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) : _system(0), _vectorRenderer(0), _buffering(false), _bytesPerPixel(0), _graphicsMode(kGfxDisabled), _font(0), _initOk(false), _themeOk(false), _enabled(false), _cursor(0) { @@ -69,8 +69,17 @@ ThemeEngine::ThemeEngine(Common::String fileName, GraphicsMode mode) : _texts[i] = 0; } + // We currently allow two different ways of theme selection in our config file: + // 1) Via full path + // 2) Via a basename, which will need to be translated into a full path + // This function assures we have a correct path to pass to the ThemeEngine + // constructor. + _themeFile = getThemeFile(id); + // We will use getThemeId to retrive the theme id from the given filename + // here, since the user could have passed a fixed filename as 'id'. + _themeId = getThemeId(_themeFile); + _graphicsMode = mode; - _themeId = fileName; _themeArchive = 0; _initOk = false; } @@ -164,10 +173,10 @@ bool ThemeEngine::init() { } // Try to create a Common::Archive with the files of the theme. - if (!_themeArchive && _themeId != "builtin") { - Common::FSNode node(_themeId); + if (!_themeArchive && !_themeFile.empty()) { + Common::FSNode node(_themeFile); if (node.getName().hasSuffix(".zip") && !node.isDirectory()) { - #ifdef USE_ZLIB +#ifdef USE_ZLIB Common::ZipArchive *zipArchive = new Common::ZipArchive(node); if (!zipArchive || !zipArchive->isOpen()) { @@ -176,15 +185,20 @@ bool ThemeEngine::init() { warning("Failed to open Zip archive '%s'.", node.getPath().c_str()); } _themeArchive = zipArchive; - - #endif +#else + warning("Trying to load theme '%s' in a Zip archive without zLib support", _themeFile.c_str()); + return false; +#endif } else if (node.isDirectory()) { _themeArchive = new Common::FSDirectory(node); } } // Load the theme - loadTheme(_themeId); + // We pass the theme file here by default, so the user will + // have a descriptive error message. The only exception will + // be the builtin theme which has no filename. + loadTheme(_themeFile.empty() ? _themeId : _themeFile); return ready(); } @@ -448,8 +462,6 @@ bool ThemeEngine::loadDefaultXML() { // 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. - bool result; - #ifdef GUI_ENABLE_BUILTIN_THEME const char *defaultXML = #include "themes/default.inc" @@ -460,8 +472,9 @@ bool ThemeEngine::loadDefaultXML() { _themeName = "ScummVM Classic Theme (Builtin Version)"; _themeId = "builtin"; + _themeFile.clear(); - result = _parser->parse(); + bool result = _parser->parse(); _parser->close(); return result; @@ -1114,7 +1127,7 @@ bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String & return tok.empty(); } -bool ThemeEngine::themeConfigUseable(const Common::FSNode &node, Common::String &themeName) { +bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &themeName) { Common::File stream; bool foundHeader = false; @@ -1140,5 +1153,175 @@ bool ThemeEngine::themeConfigUseable(const Common::FSNode &node, Common::String return foundHeader; } +namespace { + +struct TDComparator { + const Common::String _id; + TDComparator(const Common::String &id) : _id(id) {} + + bool operator()(const ThemeEngine::ThemeDescriptor &r) { return _id == r.id; } +}; + +} // end of anonymous namespace + +void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) { +#ifdef GUI_ENABLE_BUILTIN_THEME + ThemeDescriptor th; + th.name = "ScummVM Classic Theme (Builtin Version)"; + th.id = "builtin"; + th.filename = ""; + list.push_back(th); +#endif + + if (ConfMan.hasKey("themepath")) + listUsableThemes(Common::FSNode(ConfMan.get("themepath")), list); + +#ifdef DATA_PATH + listUsableThemes(Common::FSNode(DATA_PATH), list); +#endif + +#ifdef MACOSX + CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + if (resourceUrl) { + char buf[256]; + if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) { + Common::FSNode resourcePath(buf); + listUsableThemes(resourcePath, list); + } + CFRelease(resourceUrl); + } +#endif + + if (ConfMan.hasKey("extrapath")) + listUsableThemes(Common::FSNode(ConfMan.get("extrapath")), list); + + listUsableThemes(Common::FSNode("."), list); + + // Now we need to strip all duplicates + // TODO: It might not be the best idea to strip duplicates. The user might + // have different versions of a specific theme in his paths, thus this code + // might show him the wrong version. The problem is we have no ways of checking + // a theme version currently. Also since we want to avoid saving the full path + // in the config file we can not do any better currently. + Common::List<ThemeDescriptor> output; + + for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) { + if (find_if(output.begin(), output.end(), TDComparator(i->id)) == output.end()) + output.push_back(*i); + } + + list = output; + output.clear(); +} + +void ThemeEngine::listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list) { + if (!node.exists() || !node.isReadable() || !node.isDirectory()) + return; + + ThemeDescriptor td; + + // Check whether we point to a valid theme directory. + if (themeConfigUsable(node, td.name)) { + td.filename = node.getPath(); + td.id = node.getName(); + + list.push_back(td); + + // A theme directory should never contain any other themes + // thus we just return to the caller here. + return; + } + + Common::FSList fileList; +#ifdef USE_ZLIB + // Check all files. We need this to find all themes inside ZIP archives. + if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly)) + return; + + for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { + // We will only process zip files for now + if (!i->getPath().hasSuffix(".zip")) + continue; + + td.name.clear(); + if (themeConfigUsable(*i, td.name)) { + td.filename = i->getPath(); + td.id = i->getName(); + + // If the name of the node object also contains + // the ".zip" suffix, we will strip it. + if (td.id.hasSuffix(".zip")) { + for (int j = 0; j < 4; ++j) + td.id.deleteLastChar(); + } + + list.push_back(td); + } + } + + fileList.clear(); +#endif + + // As next step we will search all subdirectories + if (!node.getChildren(fileList, Common::FSNode::kListDirectoriesOnly)) + return; + + for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) + listUsableThemes(*i, list); +} + +Common::String ThemeEngine::getThemeFile(const Common::String &id) { + // FIXME: Actually "default" rather sounds like it should use + // our default theme which would mean "scummmodern" instead + // of the builtin one. + if (id.equalsIgnoreCase("default")) + return ""; + + Common::FSNode node(id); + + // If the given id is a full path we'll just use it + if (node.exists() && (node.isDirectory() || (node.getName().hasSuffix(".zip") && !node.isDirectory()))) + return id; + + // FIXME: + // A very ugly hack to map a id to a filename, this will generate + // a complete theme list, thus it is slower than it could be. + // But it is the easiest solution for now. + Common::List<ThemeDescriptor> list; + listUsableThemes(list); + + for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) { + if (id.equalsIgnoreCase(i->id)) + return i->filename; + } + + warning("Could not find theme '%s' falling back to builtin", id.c_str()); + + // If no matching id has been found we will + // just fall back to the builtin theme + return ""; +} + +Common::String ThemeEngine::getThemeId(const Common::String &filename) { + // If no filename has been given we will initialize the builtin theme + if (filename.empty()) + return "builtin"; + + Common::FSNode node(filename); + if (!node.exists()) + return "builtin"; + + if (node.getName().hasSuffix(".zip")) { + Common::String id = node.getName(); + + for (int i = 0; i < 4; ++i) + id.deleteLastChar(); + + return id; + } else { + return node.getName(); + } +} + } // end of namespace GUI. diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 1067d11b11..434730da51 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -235,7 +235,7 @@ public: static const char *findModeConfigName(GraphicsMode mode); /** Default constructor */ - ThemeEngine(Common::String fileName, GraphicsMode mode); + ThemeEngine(Common::String id, GraphicsMode mode); /** Default destructor */ ~ThemeEngine(); @@ -584,15 +584,30 @@ protected: void debugWidgetPosition(const char *name, const Common::Rect &r); public: + struct ThemeDescriptor { + Common::String name; + Common::String id; + Common::String filename; + }; /** + * Lists all theme files useable. + */ + static void listUsableThemes(Common::List<ThemeDescriptor> &list); +private: + static bool themeConfigUsable(const Common::FSNode &node, Common::String &themeName); + static bool themeConfigParseHeader(Common::String header, Common::String &themeName); + + static Common::String getThemeFile(const Common::String &id); + static Common::String getThemeId(const Common::String &filename); + static void listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list); + +public: + /** * @name LEGACY: Old GUI::Theme API */ //@{ - static bool themeConfigUseable(const Common::FSNode &node, Common::String &themeName); - static bool themeConfigParseHeader(Common::String header, Common::String &themeName); - int getTabSpacing() const { return 0; } int getTabPadding() const { return 3; } @@ -656,6 +671,7 @@ protected: Common::String _themeName; //!< Name of the currently loaded theme Common::String _themeId; + Common::String _themeFile; Common::Archive *_themeArchive; bool _useCursor; diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index b3db9a3405..d20320ad3e 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -73,7 +73,7 @@ void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) break; // TODO: - // Currently GuiManager::listUseableThemes uses a + // Currently ThemeEngine::listUseableThemes uses a // list. Thus we can not use operator[] here but // need to iterate through the list. We might want // to think of changing it, but it should not be @@ -95,7 +95,7 @@ void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) void ThemeBrowser::updateListing() { _themes.clear(); - GuiManager::listUsableThemes(_themes); + ThemeEngine::listUsableThemes(_themes); Common::StringList list; for (ThemeDescList::const_iterator i = _themes.begin(); i != _themes.end(); ++i) diff --git a/gui/themebrowser.h b/gui/themebrowser.h index b6327253ca..32fef16ce0 100644 --- a/gui/themebrowser.h +++ b/gui/themebrowser.h @@ -26,7 +26,7 @@ #define GUI_THEMEBROWSER_H #include "gui/dialog.h" -#include "gui/GuiManager.h" +#include "gui/ThemeEngine.h" #include "common/str.h" #include "common/list.h" @@ -48,7 +48,7 @@ private: ListWidget *_fileList; Common::String _select; - typedef Common::List<GuiManager::ThemeDescriptor> ThemeDescList; + typedef Common::List<ThemeEngine::ThemeDescriptor> ThemeDescList; ThemeDescList _themes; void updateListing(); |