+void
+FGMenuBar::destroy_menubar ()
+{
+ if ( _menuBar == 0 )
+ return;
+
+ hide();
+ puDeleteObject(_menuBar);
+
+ unsigned int i;
+
+ // Delete all the character arrays
+ // we were forced to keep around for
+ // plib.
+ SG_LOG(SG_GENERAL, SG_INFO, "Deleting char arrays");
+ for (i = 0; i < _char_arrays.size(); i++) {
+ for (int j = 0; _char_arrays[i][j] != 0; j++)
+ free(_char_arrays[i][j]); // added with strdup
+ delete[] _char_arrays[i];
+ }
+
+ // Delete all the callback arrays
+ // we were forced to keep around for
+ // plib.
+ SG_LOG(SG_GENERAL, SG_INFO, "Deleting callback arrays");
+ for (i = 0; i < _callback_arrays.size(); i++)
+ delete[] _callback_arrays[i];
+
+ // Delete all those bindings
+ SG_LOG(SG_GENERAL, SG_INFO, "Deleting bindings");
+ map<string,vector<SGBinding *> >::iterator it;
+ for (it = _bindings.begin(); it != _bindings.end(); it++) {
+ SG_LOG(SG_GENERAL, SG_INFO, "Deleting bindings for " << it->first);
+ for ( i = 0; i < it->second.size(); i++ )
+ delete it->second[i];
+ }
+
+ SG_LOG(SG_GENERAL, SG_INFO, "Done.");
+}
+
+void
+FGMenuBar::make_object_map(SGPropertyNode * node)
+{
+ unsigned int menu_index = 0;
+ vector<SGPropertyNode_ptr> menus = node->getChildren("menu");
+ 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;
+
+ if (menu_index >= menus.size()) {
+ SG_LOG(SG_GENERAL, SG_WARN, "'menu' object without node: "
+ << node->getPath() << "/menu[" << menu_index << ']');
+ return;
+ }
+
+ SGPropertyNode *menu = menus.at(menu_index);
+ _objects[menu->getPath()] = obj;
+ add_enabled_listener(menu);
+
+ puGroup *popup = (puGroup *)obj->getUserData();
+ if (!popup)
+ continue;
+
+ // the entries are for some reason reversed (last first), and we
+ // don't know yet how many there will be; so we collect first
+ vector<puObject *> e;
+ for (puObject *me = popup->getFirstChild(); me; me = me->getNextObject())
+ e.push_back(me);
+
+ vector<SGPropertyNode_ptr> items = menu->getChildren("item");
+ for (unsigned int i = 0; i < e.size(); i++) {
+ if (i >= items.size()) {
+ SG_LOG(SG_GENERAL, SG_WARN, "'item' object without node: "
+ << menu->getPath() << "/item[" << i << ']');
+ break;
+ }
+ SGPropertyNode *item = items.at(e.size() - i - 1);
+ _objects[item->getPath()] = e[i];
+ add_enabled_listener(item);
+ }
+ menu_index++;
+ }
+}
+
+struct EnabledListener : SGPropertyChangeListener {
+ void valueChanged(SGPropertyNode *node) {
+ NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+ if (!gui)
+ return;
+ FGMenuBar *menubar = gui->getMenuBar();
+ if (menubar)
+ menubar->enable_item(node->getParent(), node->getBoolValue());
+ }
+};
+
+void
+FGMenuBar::add_enabled_listener(SGPropertyNode * node)
+{
+ if (!node->hasValue("enabled"))
+ node->setBoolValue("enabled", true);
+
+ enable_item(node, node->getBoolValue("enabled"));
+ node->getNode("enabled")->addChangeListener(new EnabledListener());
+}
+
+bool
+FGMenuBar::enable_item(const SGPropertyNode * node, bool state)
+{
+ const char *path = node->getPath();
+ if (_objects.find(path) == _objects.end()) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Trying to enable/disable "
+ "non-existent menu item for node `" << path << '\'');
+ return false;
+ }
+ puObject *object = _objects[path];
+ if (state)
+ object->activate();
+ else
+ object->greyOut();
+
+ return true;
+}
+