* Melchior FRANZ -- Tuesday 06 December 2005 15:57:
> This should better be hooked into the property tree, so that one can
> directly set /sim/menubar/default/menu[2]/item[3]/enabled to false and
> get the menu disabled. 

Done. Attached is a better patch. No more fgCommand, and no Nasal-wrapper.
Just set the "enabled" property. This can also be done in gui/menubar.xml.
"Fuel & Payload" would be globally disabled there, and only FDMs which
support this feature turn it on. (Or rather: gui.nas enables it for YASim.)

m.
Index: menubar.cxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/GUI/menubar.cxx,v
retrieving revision 1.25
diff -u -p -r1.25 menubar.cxx
--- menubar.cxx	9 Nov 2005 10:48:45 -0000	1.25
+++ menubar.cxx	6 Dec 2005 15:53:42 -0000
@@ -4,6 +4,7 @@
 
 #include <string.h>
 #include <iostream>
+#include <sstream>
 #include <plib/pu.h>
 #include <simgear/debug/logstream.hxx>
 
@@ -302,6 +303,8 @@ FGMenuBar::make_menubar(const SGProperty
         make_menu(menu_nodes[i]);
 
     _menuBar->close();
+    make_map(props);
+
     if (_visible)
         _menuBar->reveal();
     else
@@ -349,6 +352,106 @@ FGMenuBar::destroy_menubar ()
     SG_LOG(SG_GENERAL, SG_INFO, "Done.");
 }
 
+struct MenuListener : SGPropertyChangeListener {
+    MenuListener() : menubar(0) {
+        NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+        if (gui)
+            menubar = gui->getMenuBar();
+    }
+    FGMenuBar *menubar;
+    void valueChanged(SGPropertyNode* node) {
+        menubar->enable_item(node->getParent(), node->getBoolValue());
+    }
+};
+
+void
+FGMenuBar::make_map(const SGPropertyNode * node)
+{
+    string base = node->getPath();
+    const char *legend;
+
+    int menu_index = 0;
+    for (puObject *obj = ((puGroup *)_menuBar)->getFirstChild();
+            obj; obj = obj->getNextObject()) {
+
+        // skip puPopupMenus. They are also children of _menuBar,
+        // but we access them via getUserData()  (see below)
+        if (!(obj->getType() & PUCLASS_ONESHOT))
+            continue;
+
+        legend = obj->getLegend();
+        if (!legend)
+            continue;
+
+        std::ostringstream menu;
+        menu << base << '/' << "menu[" << menu_index << "]";
+        SGPropertyNode *prop = fgGetNode(menu.str().c_str());
+        if (!prop) {
+            SG_LOG(SG_GENERAL, SG_WARN, "menu without node: " << menu.str());
+            continue;
+        }
+
+        // push "menu" entry
+        _entries[prop->getPath()] = obj;
+        if (!prop->hasValue("enabled"))
+            prop->setBoolValue("enabled", true);
+
+        enable_item(prop, prop->getBoolValue("enabled"));
+        prop->getNode("enabled")->addChangeListener(new MenuListener());
+
+        // push "item" entries
+        puPopupMenu *popup = (puPopupMenu *)obj->getUserData();
+        if (!popup)
+            continue;
+
+        vector<puObject *> e;
+
+        for (puObject *me = ((puGroup *)popup)->getFirstChild();
+                me; me = me->getNextObject()) {
+
+            legend = me->getLegend();
+            if (!legend)
+                continue;
+
+            e.push_back(me);
+        }
+
+        for (unsigned int i = 0; i < e.size(); i++) {
+
+            std::ostringstream item;
+            item << menu.str() << '/' << "item[" << (e.size() - i - 1) << "]";
+            prop = fgGetNode(item.str().c_str());
+            if (!prop) {
+                SG_LOG(SG_GENERAL, SG_WARN, "item without node: " << item.str());
+                continue;
+            }
+            _entries[prop->getPath()] = e[i];
+            if (!prop->hasValue("enabled"))
+                prop->setBoolValue("enabled", true);
+
+            enable_item(prop, prop->getBoolValue("enabled"));
+            prop->getNode("enabled")->addChangeListener(new MenuListener());
+        }
+        menu_index++;
+    }
+}
+
+bool
+FGMenuBar::enable_item(const SGPropertyNode * node, bool state)
+{
+    if (!node || _entries.find(node->getPath()) == _entries.end()) {
+        SG_LOG(SG_GENERAL, SG_WARN, "Trying to enable/disable "
+            "non-existent menu item");
+        return false;
+    }
+    puObject *object = _entries[node->getPath()];
+    if (state)
+        object->activate();
+    else
+        object->greyOut();
+
+    return true;
+}
 
 char **
 FGMenuBar::make_char_array (int size)
Index: menubar.hxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/GUI/menubar.hxx,v
retrieving revision 1.7
diff -u -p -r1.7 menubar.hxx
--- menubar.hxx	22 Oct 2004 09:26:51 -0000	1.7
+++ menubar.hxx	6 Dec 2005 15:53:42 -0000
@@ -96,6 +96,12 @@ public:
     void destroy_menubar ();
 
 
+    /**
+     * disable/enable menu titles and entries
+     */
+    bool enable_item (const SGPropertyNode * item, bool state);
+
+
 private:
 
     // Make a single menu.
@@ -104,6 +110,9 @@ private:
     // Make the top-level menubar.
     void make_menubar ();
 
+    // Create a property-path -> puObject map for menu node
+    void make_map(const SGPropertyNode * node);
+
     // Is the menu visible?
     bool _visible;
 
@@ -121,6 +130,8 @@ private:
     puCallback * make_callback_array (int size);
     vector<char **> _char_arrays;
     vector<puCallback *> _callback_arrays;
+
+    map<string, puObject *> _entries;
 };
 
 #endif // __MENUBAR_HXX
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@flightgear.org
http://mail.flightgear.org/mailman/listinfo/flightgear-devel
2f585eeea02e2c79d7b1d8c4963bae2d

Reply via email to