#include <simgear/misc/sg_dir.hxx>
#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/foreach.hpp>
#include <Main/fg_props.hxx>
#include "FGCocoaMenuBar.hxx"
#endif
+#if defined(SG_WINDOWS)
+#include "FGWindowsMenuBar.hxx"
+#endif
+
#include "FGPUIDialog.hxx"
#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;
NewGUI::NewGUI () :
_active_dialog(0)
{
-#if defined(SG_MAC)
- if (fgGetBool("/sim/menubar/native", true)) {
- _menubar.reset(new FGCocoaMenuBar);
- return;
- }
-#endif
- _menubar.reset(new FGPUIMenuBar);
}
NewGUI::~NewGUI ()
{
- _dialog_props.clear();
for (_itt_t it = _colors.begin(); it != _colors.end(); ++it)
delete it->second;
}
void
NewGUI::init ()
{
+ createMenuBarImplementation();
+ fgTie("/sim/menubar/visibility", this,
+ &NewGUI::getMenuBarVisible, &NewGUI::setMenuBarVisible);
+
setStyle();
SGPath p(globals->get_fg_root(), "gui/dialogs");
readDir(p);
- const std::string aircraft_dir(fgGetString("/sim/aircraft-dir"));
- readDir( SGPath(aircraft_dir, "gui/dialogs") );
+
+ SGPath aircraftDialogDir(string(fgGetString("/sim/aircraft-dir")), "gui/dialogs");
+ if (aircraftDialogDir.exists()) {
+ readDir(aircraftDialogDir);
+ }
+
+ // Fix for http://code.google.com/p/flightgear-bugs/issues/detail?id=947
+ fgGetNode("sim/menubar")->setAttribute(SGPropertyNode::PRESERVE, true);
_menubar->init();
}
+void
+NewGUI::shutdown()
+{
+ DialogDict::iterator it = _active_dialogs.begin();
+ for (; it != _active_dialogs.end(); ++it) {
+ delete it->second;
+ }
+ _active_dialogs.clear();
+
+ fgUntie("/sim/menubar/visibility");
+ _menubar.reset();
+ _dialog_props.clear();
+}
+
void
NewGUI::reinit ()
{
reset(false);
}
+void
+NewGUI::createMenuBarImplementation()
+{
+#if defined(SG_MAC)
+ if (fgGetBool("/sim/menubar/native", true)) {
+ _menubar.reset(new FGCocoaMenuBar);
+ }
+#endif
+#if defined(SG_WINDOWS)
+ if (fgGetBool("/sim/menubar/native", true)) {
+ // Windows-native menubar disabled for the moment, fall-through
+ // to PUI version
+ // _menubar.reset(new FGWindowsMenuBar);
+ }
+#endif
+ if (!_menubar.get()) {
+ _menubar.reset(new FGPUIMenuBar);
+ }
+}
+
void
NewGUI::reset (bool reload)
{
- map<string,FGDialog *>::iterator iter;
- std::vector<string> dlg;
+ DialogDict::iterator iter;
+ 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();
unbind();
-#if !defined(SG_MAC)
- _menubar.reset(new FGPUIMenuBar);
-#endif
if (reload) {
_dialog_props.clear();
+ _dialog_names.clear();
init();
} else {
+ createMenuBarImplementation();
_menubar->init();
}
bind();
// open dialogs again
- for (i = 0; i < dlg.size(); i++)
- showDialog(dlg[i]);
+ BOOST_FOREACH(string d, openDialogs)
+ showDialog(d);
}
void
NewGUI::bind ()
{
- fgTie("/sim/menubar/visibility", this,
- &NewGUI::getMenuBarVisible, &NewGUI::setMenuBarVisible);
}
void
NewGUI::unbind ()
{
- fgUntie("/sim/menubar/visibility");
}
void
NewGUI::update (double delta_time_sec)
{
+ SG_UNUSED(delta_time_sec);
map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
for(/**/; iter != _active_dialogs.end(); iter++)
iter->second->update();
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
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 *
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
NewGUI::readDir (const SGPath& path)
{
simgear::Dir dir(path);
+ if( !dir.exists() )
+ {
+ SG_LOG(SG_INPUT, SG_INFO, "directory does not exist: " << path.str());
+ return;
+ }
+
+ flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
+ flightgear::NavDataCache::Transaction txn(cache);
simgear::PathList xmls = dir.children(simgear::Dir::TYPE_FILE, ".xml");
- for (unsigned int i=0; i<xmls.size(); ++i) {
- SGPropertyNode * props = new SGPropertyNode;
+ 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(xmls[i].str(), props);
+ readProperties(xmlPath.str(), props);
} catch (const sg_exception &) {
- SG_LOG(SG_INPUT, SG_ALERT, "Error parsing dialog "
- << xmls[i].str());
- delete props;
- continue;
+ 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;
- }
-}
-
-
-\f
+ _dialog_names[name] = xmlPath;
+ // update cached values
+ if (!cache->isReadOnly()) {
+ cache->stampCacheFile(xmlPath);
+ cache->writeStringProperty(xmlPath.str(), name);
+ }
+ } // of directory children iteration
+
+ txn.commit();
+}\f
////////////////////////////////////////////////////////////////////////
// Style handling.
////////////////////////////////////////////////////////////////////////
void
NewGUI::setupFont (SGPropertyNode *node)
{
- _font = globals->get_fontcache()->get(node);
+ _font = FGFontCache::instance()->get(node);
puSetDefaultFonts(*_font, *_font);
return;
}