1
0
Fork 0

Lazy GUI dialog loading, for slightly faster startup.

This commit is contained in:
James Turner 2012-09-21 10:16:44 +01:00
parent f0927fc06d
commit 666a68c742
2 changed files with 80 additions and 41 deletions

View file

@ -19,6 +19,7 @@
#include <simgear/misc/sg_dir.hxx>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/foreach.hpp>
#include <Main/fg_props.hxx>
@ -36,6 +37,9 @@
#include "FGFontCache.hxx"
#include "FGColor.hxx"
// ignore the word Navaid here, it's a DataCache
#include <Navaids/NavDataCache.hxx>
using std::map;
using std::string;
@ -92,14 +96,13 @@ void
NewGUI::reset (bool reload)
{
map<string,FGDialog *>::iterator iter;
std::vector<string> dlg;
string_list openDialogs;
// close all open dialogs and remember them ...
for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); ++iter)
dlg.push_back(iter->first);
openDialogs.push_back(iter->first);
unsigned int i;
for (i = 0; i < dlg.size(); i++)
closeDialog(dlg[i]);
BOOST_FOREACH(string d, openDialogs)
closeDialog(d);
setStyle();
@ -110,6 +113,7 @@ NewGUI::reset (bool reload)
if (reload) {
_dialog_props.clear();
_dialog_names.clear();
init();
} else {
_menubar->init();
@ -118,8 +122,8 @@ NewGUI::reset (bool reload)
bind();
// open dialogs again
for (i = 0; i < dlg.size(); i++)
showDialog(dlg[i]);
BOOST_FOREACH(string d, openDialogs)
showDialog(d);
}
void
@ -146,14 +150,18 @@ NewGUI::update (double delta_time_sec)
bool
NewGUI::showDialog (const string &name)
{
if (_dialog_props.find(name) == _dialog_props.end()) {
// first, check if it's already shown
if (_active_dialogs.find(name) != _active_dialogs.end())
return true;
// check we know about the dialog by name
if (_dialog_names.find(name) == _dialog_names.end()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
return false;
} else {
if(!_active_dialogs[name])
_active_dialogs[name] = new FGPUIDialog(_dialog_props[name]);
return true;
}
_active_dialogs[name] = new FGPUIDialog(getDialogProperties(name));
return true;
}
bool
@ -195,11 +203,27 @@ NewGUI::closeDialog (const string& name)
SGPropertyNode_ptr
NewGUI::getDialogProperties (const string &name)
{
if(_dialog_props.find(name) != _dialog_props.end())
return _dialog_props[name];
if (_dialog_names.find(name) == _dialog_names.end()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
return NULL;
}
NameDialogDict::iterator it = _dialog_props.find(name);
if (it == _dialog_props.end()) {
// load the XML
SGPath path = _dialog_names[name];
SGPropertyNode_ptr props = new SGPropertyNode;
try {
readProperties(path.str(), props);
} catch (const sg_exception &) {
SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog " << path);
return NULL;
}
it = _dialog_props.insert(it, std::make_pair(name, props));
}
SG_LOG(SG_GENERAL, SG_DEBUG, "dialog '" << name << "' missing");
return 0;
return it->second;
}
FGDialog *
@ -254,8 +278,12 @@ NewGUI::newDialog (SGPropertyNode* props)
return;
}
string name = cname;
if(_active_dialogs.find(name) == _active_dialogs.end())
if(_active_dialogs.find(name) == _active_dialogs.end()) {
_dialog_props[name] = props;
// add a dummy path entry, so we believe the dialog exists
_dialog_names[name] = SGPath();
}
}
void
@ -264,30 +292,37 @@ NewGUI::readDir (const SGPath& path)
simgear::Dir dir(path);
simgear::PathList xmls = dir.children(simgear::Dir::TYPE_FILE, ".xml");
for (unsigned int i=0; i<xmls.size(); ++i) {
SGPropertyNode * props = new SGPropertyNode;
try {
readProperties(xmls[i].str(), props);
} catch (const sg_exception &) {
SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
<< xmls[i].str());
delete props;
continue;
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
BOOST_FOREACH(SGPath xmlPath, xmls) {
if (!cache->isCachedFileModified(xmlPath)) {
// cached, easy
string name = cache->readStringProperty(xmlPath.str());
_dialog_names[name] = xmlPath;
continue;
}
// we need to parse the actual XML
SGPropertyNode_ptr props = new SGPropertyNode;
try {
readProperties(xmlPath.str(), props);
} catch (const sg_exception &) {
SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog " << xmlPath);
continue;
}
SGPropertyNode *nameprop = props->getNode("name");
if (!nameprop) {
SG_LOG(SG_INPUT, SG_WARN, "dialog " << xmls[i].str()
<< " has no name; skipping.");
delete props;
continue;
SG_LOG(SG_INPUT, SG_WARN, "dialog " << xmlPath << " has no name; skipping.");
continue;
}
string name = nameprop->getStringValue();
_dialog_props[name] = props;
}
}
_dialog_names[name] = xmlPath;
// update cached values
cache->stampCacheFile(xmlPath);
cache->writeStringProperty(xmlPath.str(), name);
} // of directory children iteration
}
////////////////////////////////////////////////////////////////////////
// Style handling.
////////////////////////////////////////////////////////////////////////

View file

@ -7,14 +7,10 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_path.hxx>
#include <string.h>
#include <functional>
#include <vector>
#include <map>
#include <memory> // for auto_ptr on some systems
class SGBinding;
class FGMenuBar;
class FGDialog;
class FGColor;
@ -223,7 +219,15 @@ private:
std::auto_ptr<FGMenuBar> _menubar;
FGDialog * _active_dialog;
std::map<std::string,FGDialog *> _active_dialogs;
std::map<std::string,SGPropertyNode_ptr> _dialog_props;
typedef std::map<std::string, SGPath> NamePathDict;
// mapping from dialog names to the corresponding XML property list
// which defines them
NamePathDict _dialog_names;
// cache of loaded dialog proeprties
typedef std::map<std::string,SGPropertyNode_ptr> NameDialogDict;
NameDialogDict _dialog_props;
};