]> git.mxchange.org Git - flightgear.git/blobdiff - src/GUI/new_gui.cxx
Launcher: Maintain aircraft selection better
[flightgear.git] / src / GUI / new_gui.cxx
index c13456068ba39ca860d08ff393669c0e021a3b4c..bb8eb52dba624941d88c664b9c1f198935811ff4 100644 (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>
 
 #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;
 
@@ -48,16 +56,10 @@ using std::string;
 NewGUI::NewGUI () :
   _active_dialog(0)
 {
-#if defined(SG_MAC)
-  _menubar.reset(new FGCocoaMenuBar);
-#else
-  _menubar.reset(new FGPUIMenuBar);
-#endif
 }
 
 NewGUI::~NewGUI ()
 {
-    _dialog_props.clear();
     for (_itt_t it = _colors.begin(); it != _colors.end(); ++it)
         delete it->second;
 }
@@ -65,12 +67,38 @@ NewGUI::~NewGUI ()
 void
 NewGUI::init ()
 {
+    createMenuBarImplementation();
+    fgTie("/sim/menubar/visibility", this,
+          &NewGUI::getMenuBarVisible, &NewGUI::setMenuBarVisible);
+    
     setStyle();
     SGPath p(globals->get_fg_root(), "gui/dialogs");
     readDir(p);
+    
+    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 ()
 {
@@ -84,56 +112,72 @@ NewGUI::redraw ()
     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();
@@ -142,14 +186,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
@@ -191,11 +239,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 *
@@ -250,40 +314,62 @@ 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
 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.
 ////////////////////////////////////////////////////////////////////////
@@ -329,7 +415,7 @@ NewGUI::setStyle (void)
 void
 NewGUI::setupFont (SGPropertyNode *node)
 {
-    _font = globals->get_fontcache()->get(node);
+    _font = FGFontCache::instance()->get(node);
     puSetDefaultFonts(*_font, *_font);
     return;
 }