diff --git a/src/GUI/FGCocoaMenuBar.mm b/src/GUI/FGCocoaMenuBar.mm index 9ec02523a..048eb5769 100644 --- a/src/GUI/FGCocoaMenuBar.mm +++ b/src/GUI/FGCocoaMenuBar.mm @@ -24,6 +24,41 @@ typedef std::map MenuItemBindings; @class CocoaMenuDelegate; +namespace { + + class CocoaEnabledListener : public SGPropertyChangeListener + { + public: + CocoaEnabledListener(SGPropertyNode_ptr prop, NSMenuItem* i) : + property(prop->getNode("enabled")), + item(i) + { + if (property.get()) { + property->addChangeListener(this); + } + } + + ~CocoaEnabledListener() + { + if (property.get()) { + property->removeChangeListener(this); + } + } + + + virtual void valueChanged(SGPropertyNode *node) + { + CocoaAutoreleasePool pool; + BOOL b = node->getBoolValue(); + [item setEnabled:b]; + } + + private: + SGPropertyNode_ptr property; + NSMenuItem* item; + }; +} // of anonymous namespace + class FGCocoaMenuBar::CocoaMenuBarPrivate { public: @@ -38,7 +73,7 @@ public: CocoaMenuDelegate* delegate; MenuItemBindings itemBindings; - std::vector listeners; + std::vector listeners; }; // prior to the 10.6 SDK, NSMenuDelegate was an informal protocol @@ -126,35 +161,6 @@ static void setItemShortcutFromString(NSMenuItem* item, const string& s) [item setKeyEquivalentModifierMask:modifiers]; } -namespace { - - class CocoaEnabledListener : public SGPropertyChangeListener - { - public: - CocoaEnabledListener(NSMenuItem* i) : - item(i) - { - - } - - ~CocoaEnabledListener() - { - - } - - - virtual void valueChanged(SGPropertyNode *node) - { - CocoaAutoreleasePool pool; - BOOL b = node->getBoolValue(); - [item setEnabled:b]; - } - - private: - NSMenuItem* item; - }; -} // of anonymous namespace - FGCocoaMenuBar::CocoaMenuBarPrivate::CocoaMenuBarPrivate() { delegate = [[CocoaMenuDelegate alloc] init]; @@ -195,9 +201,9 @@ void FGCocoaMenuBar::CocoaMenuBarPrivate::menuFromProps(NSMenu* menu, SGProperty setItemShortcutFromString(item, shortcut); } - SGPropertyChangeListener* enableListener = new CocoaEnabledListener(item); - listeners.push_back(enableListener); - n->getNode("enabled")->addChangeListener(enableListener); + CocoaEnabledListener* cl = new CocoaEnabledListener(n, item); + listeners.push_back(cl); + [item setTarget:delegate]; [item setAction:@selector(itemAction:)]; } @@ -243,10 +249,18 @@ FGCocoaMenuBar::~FGCocoaMenuBar() [topLevelItem.submenu removeAllItems]; } - std::vector::iterator it; + std::vector::iterator it; for (it = p->listeners.begin(); it != p->listeners.end(); ++it) { delete *it; - } + } + + // owing to the bizarre destructor behaviour of SGBinding, we need + // to explicitly clear these bindings. (PUIMenuBar takes a different + // approach, and copies each binding into /sim/bindings) + MenuItemBindings::iterator j; + for (j = p->itemBindings.begin(); j != p->itemBindings.end(); ++j) { + clearBindingList(j->second); + } } void FGCocoaMenuBar::init() @@ -291,9 +305,8 @@ void FGCocoaMenuBar::init() n->setBoolValue("enabled", true); } - SGPropertyChangeListener* l = new CocoaEnabledListener(item); + CocoaEnabledListener* l = new CocoaEnabledListener( n, item); p->listeners.push_back(l); - n->getNode("enabled")->addChangeListener(l); } } diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index af0738121..d679c44c9 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -63,23 +63,18 @@ NewGUI::~NewGUI () void NewGUI::init () { -#if defined(SG_MAC) - if (fgGetBool("/sim/menubar/native", true)) { - _menubar.reset(new FGCocoaMenuBar); - } -#endif - if (!_menubar.get()) { - _menubar.reset(new FGPUIMenuBar); - } - + 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); @@ -107,6 +102,19 @@ NewGUI::redraw () reset(false); } +void +NewGUI::createMenuBarImplementation() +{ +#if defined(SG_MAC) + if (fgGetBool("/sim/menubar/native", true)) { + _menubar.reset(new FGCocoaMenuBar); + } +#endif + if (!_menubar.get()) { + _menubar.reset(new FGPUIMenuBar); + } +} + void NewGUI::reset (bool reload) { @@ -122,15 +130,13 @@ NewGUI::reset (bool reload) setStyle(); unbind(); -#if !defined(SG_MAC) - _menubar.reset(new FGPUIMenuBar); -#endif if (reload) { _dialog_props.clear(); _dialog_names.clear(); init(); } else { + createMenuBarImplementation(); _menubar->init(); } diff --git a/src/GUI/new_gui.hxx b/src/GUI/new_gui.hxx index d3ee2979e..1ab1361c8 100644 --- a/src/GUI/new_gui.hxx +++ b/src/GUI/new_gui.hxx @@ -201,6 +201,8 @@ protected: virtual void reset (bool reload); private: + void createMenuBarImplementation(); + struct ltstr { bool operator()(const char* s1, const char* s2) const {