diff --git a/configure.ac b/configure.ac index 56c7987be..e5fd840d5 100644 --- a/configure.ac +++ b/configure.ac @@ -71,7 +71,7 @@ AM_CONDITIONAL(ENABLE_NETWORK_OLK, test "x$with_network_olk" != "xno") # Specify if we want to use WeatherCM instead of FGEnvironment. # default to with_weathercm=no -AC_ARG_WITH(new-environment, [ --with-weathercm Use WeatherCM instead of FGEnvironment]) +AC_ARG_WITH(weathercm, [ --with-weathercm Use WeatherCM instead of FGEnvironment]) if test "x$with_weathercm" = "xyes" ; then echo "Building with WeatherCM" AC_DEFINE([FG_WEATHERCM], 1, @@ -81,6 +81,17 @@ else fi AM_CONDITIONAL(ENABLE_WEATHERCM, test "x$with_weathercm" = "xyes") +dnl Specify if we want the new XML menu; default to the old one +AC_ARG_WITH(new-menubar, [ --with-new-menubar Use the new XML menu bar]) +if test "x$with_new_menubar" = "xyes" ; then + echo "Building with new menubar" +else + AC_DEFINE([FG_OLD_MENUBAR], 1, + [Define to build with old menubar]) + echo "Building with old menubar" +fi +AM_CONDITIONAL(ENABLE_WEATHERCM, test "x$with_weathercm" = "xyes") + dnl Thread related checks AC_ARG_WITH(threads, [ --with-threads Include tile loading threads [default=no]]) if test "x$with_threads" = "xyes"; then @@ -610,6 +621,12 @@ else echo "Using FGEnvironment" fi +if test "x$with_new_menubar" != "x"; then + echo "Using new menubar" +else + echo "Defaulting to old menubar" +fi + if test "x$with_threads" = "xyes"; then echo "threads: yes" else diff --git a/src/GUI/Makefile.am b/src/GUI/Makefile.am index 5ca85815f..8cb594c55 100644 --- a/src/GUI/Makefile.am +++ b/src/GUI/Makefile.am @@ -8,6 +8,7 @@ endif libGUI_a_SOURCES = \ new_gui.cxx new_gui.hxx \ + menubar.cxx menubar.hxx \ gui.cxx gui.h gui_funcs.cxx \ gui_local.cxx gui_local.hxx \ mouse.cxx \ diff --git a/src/GUI/gui.cxx b/src/GUI/gui.cxx index a0bc37319..eee417c6c 100644 --- a/src/GUI/gui.cxx +++ b/src/GUI/gui.cxx @@ -63,6 +63,7 @@ extern void ConfirmExitDialogInit(void); puFont guiFnt = 0; fntTexFont *guiFntHandle = 0; +#if defined(FG_OLD_MENUBAR) int gui_menu_on = 0; puMenuBar *mainMenuBar = 0; //static puButton *hideMenuButton = 0; @@ -162,7 +163,7 @@ void destroyMenu(void) { free(Menu[i].submenu[j]); } } - +#endif @@ -238,6 +239,7 @@ void guiInit() mkDialogInit(); +#if defined(FG_OLD_MENUBAR) initMenu(); // Set up menu bar toggle @@ -246,4 +248,5 @@ void guiInit() if (!strcmp(fgGetString("/sim/flight-model"), "ada")) { guiToggleMenu(); // Menu off by default } +#endif } diff --git a/src/GUI/gui.h b/src/GUI/gui.h index b368a9a5c..10a7a0e1f 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -44,7 +44,9 @@ // gui.cxx extern void guiInit(); +#if defined (FG_OLD_MENUBAR) extern void guiToggleMenu(void); +#endif extern void mkDialog(const char *txt); extern void guiErrorMessage(const char *txt); extern void guiErrorMessage(const char *txt, const sg_throwable &throwable); diff --git a/src/GUI/gui_funcs.cxx b/src/GUI/gui_funcs.cxx index d124c0046..6f64d99d6 100644 --- a/src/GUI/gui_funcs.cxx +++ b/src/GUI/gui_funcs.cxx @@ -119,7 +119,9 @@ extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start, GLfloat x_end, GLfloat y_end ); #endif +#if defined(FG_OLD_MENUBAR) extern puMenuBar *mainMenuBar; +#endif puDialogBox *dialogBox = 0; puFrame *dialogFrame = 0; @@ -245,6 +247,7 @@ void guiErrorMessage (const char *txt, const sg_throwable &throwable) mkDialog(msg.c_str()); } +#if defined(FG_OLD_MENUBAR) // Toggle the Menu and Mouse display state void guiToggleMenu(void) { @@ -264,6 +267,7 @@ void guiToggleMenu(void) } gui_menu_on = ~gui_menu_on; } +#endif // FG_OLD_MENUBAR // Intercept the Escape Key void ConfirmExitDialog(void) @@ -423,12 +427,14 @@ void guiTogglePanel(puObject *cb) fgReshape(fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize")); } - + +#if defined(FG_OLD_MENUBAR) //void MenuHideMenuCb(puObject *cb) void hideMenuCb (puObject *cb) { guiToggleMenu(); } +#endif void goodBye(puObject *) { @@ -586,10 +592,12 @@ void fgHiResDump() fgSetBool("/sim/freeze/master", true); } +#if defined(FG_OLD_MENUBAR) if(gui_menu_on) { show_menu = true; guiToggleMenu(); } +#endif if ( !puCursorIsHidden() ) { show_pu_cursor = true; @@ -750,8 +758,10 @@ void fgHiResDump() delete [] filename; +#if defined(FG_OLD_MENUBAR) if( show_menu ) guiToggleMenu(); +#endif if ( show_pu_cursor ) { puShowCursor(); @@ -811,7 +821,9 @@ void printScreen ( puObject *obj ) { puHideCursor(); } // BusyCursor( 0 ); +#if defined(FG_OLD_MENUBAR) mainMenuBar->hide(); +#endif CGlPrinter p( CGlPrinter::PRINT_BITMAP ); int cur_width = fgGetInt("/sim/startup/xsize"); @@ -819,9 +831,11 @@ void printScreen ( puObject *obj ) { p.Begin( "FlightGear", cur_width*3, cur_height*3 ); p.End( hiResScreenCapture(3) ); +#if defined(FG_OLD_MENUBAR) if( gui_menu_on ) { mainMenuBar->reveal(); } +#endif // BusyCursor(1); if ( show_pu_cursor ) { puShowCursor(); @@ -856,7 +870,9 @@ void fgDumpSnapShot () { fgSetBool("/sim/freeze/master", true); } +#if defined(FG_OLD_MENUBAR) mainMenuBar->hide(); +#endif TurnCursorOff(); if ( !puCursorIsHidden() ) { show_pu_cursor = true; @@ -900,9 +916,11 @@ void fgDumpSnapShot () { } TurnCursorOn(); +#if defined(FG_OLD_MENUBAR) if( gui_menu_on ) { mainMenuBar->reveal(); } +#endif if ( !freeze ) { fgSetBool("/sim/freeze/master", false); diff --git a/src/GUI/menubar.cxx b/src/GUI/menubar.cxx new file mode 100644 index 000000000..95981defc --- /dev/null +++ b/src/GUI/menubar.cxx @@ -0,0 +1,146 @@ +#include +#include +#include +#include + +#include
+#include
+ +#include "new_gui.hxx" +#include "menubar.hxx" + + + +//////////////////////////////////////////////////////////////////////// +// Static functions. +//////////////////////////////////////////////////////////////////////// + + +static void +menu_callback (puObject * object) +{ + NewGUI * gui = (NewGUI *)globals->get_subsystem("gui"); + gui->getMenuBar()->fireItem(object); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGMenuBar. +//////////////////////////////////////////////////////////////////////// + + +FGMenuBar::FGMenuBar () + : _visible(false), + _menuBar(0) +{ +} + +FGMenuBar::~FGMenuBar () +{ + hide(); + delete _menuBar; // FIXME: check if PUI owns the pointer + + // Delete all those bindings + map >::iterator it; + it = _bindings.begin(); + while (it != _bindings.end()) { + for (int i = 0; i < it->second.size(); i++) + delete it->second[i]; + } +} + +void +FGMenuBar::init () +{ + if (_menuBar != 0) // FIXME: check if PUI owns the pointer + delete _menuBar; + make_menubar(); +} + +void +FGMenuBar::show () +{ + if (_menuBar != 0) { + _menuBar->reveal(); + _visible = true; + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "No menu bar to show"); + _visible = false; + } +} + +void +FGMenuBar::hide () +{ + if (_menuBar != 0) { + _menuBar->hide(); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "No menu bar to show"); + } + _visible = false; +} + +bool +FGMenuBar::isVisible () const +{ + return _visible; +} + +bool +FGMenuBar::fireItem (puObject * item) +{ + const char * name = item->getLegend(); + vector &bindings = _bindings[name]; + + for (int i = 0; i < bindings.size(); i++) + bindings[i]->fire(); +} + +void +FGMenuBar::make_menu (SGPropertyNode_ptr node) +{ + const char * name = strdup(node->getStringValue("label")); + vector item_nodes = node->getChildren("item"); + + int array_size = item_nodes.size() + 1; + + char ** items = new char*[array_size]; + puCallback * callbacks = new puCallback[array_size]; + + for (int i = 0, j = item_nodes.size() - 1; + i < item_nodes.size(); + i++, j--) { + + // Set up the PUI entries for this item + items[j] = strdup((char *)item_nodes[i]->getStringValue("label")); + callbacks[j] = menu_callback; + + // Load all the bindings for this item + vector binding_nodes = + item_nodes[i]->getChildren("binding"); + for (int k = 0; k < binding_nodes.size(); k++) + _bindings[items[j]].push_back(new FGBinding(binding_nodes[k])); + } + + items[item_nodes.size()] = 0; + callbacks[item_nodes.size()] = 0; + + _menuBar->add_submenu(name, items, callbacks); +} + +void +FGMenuBar::make_menubar () +{ + _menuBar = new puMenuBar; + SGPropertyNode props; + + fgLoadProps("gui/menubar.xml", &props); + vector menu_nodes = props.getChildren("menu"); + for (int i = 0; i < menu_nodes.size(); i++) + make_menu(menu_nodes[i]); + + _menuBar->close(); +} + +// end of menubar.cxx diff --git a/src/GUI/menubar.hxx b/src/GUI/menubar.hxx new file mode 100644 index 000000000..9c3929e69 --- /dev/null +++ b/src/GUI/menubar.hxx @@ -0,0 +1,88 @@ +#ifndef __MENUBAR_HXX +#define __MENUBAR_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include // for SG_USING_STD + +#include + +#include +SG_USING_STD(map); + +#include +SG_USING_STD(vector); + + +class puMenuBar; +class puObject; +class FGBinding; + + +/** + * XML-configured PUI menu bar. + */ +class FGMenuBar +{ +public: + + /** + * Constructor. + */ + FGMenuBar (); + + + /** + * Destructor. + */ + virtual ~FGMenuBar (); + + + /** + * Initialize the menu bar from $FG_ROOT/gui/menubar.xml + */ + virtual void init (); + + + /** + * Make the menu bar visible. + */ + virtual void show (); + + + /** + * Make the menu bar invisible. + */ + virtual void hide (); + + + /** + * Test whether the menu bar is visible. + */ + virtual bool isVisible () const; + + + /** + * IGNORE THIS METHOD!!! + * + * This is necessary only because plib does not provide any easy + * way to attach user data to a menu item. FlightGear should not + * have to know about PUI internals, but this method allows the + * callback to pass the menu item one-shot on to the current menu. + */ + virtual bool fireItem (puObject * item); + + +private: + + void make_menu (SGPropertyNode_ptr node); + void make_menubar (); + + bool _visible; + puMenuBar * _menuBar; + map > _bindings; +}; + +#endif // __MENUBAR_HXX diff --git a/src/GUI/mouse.cxx b/src/GUI/mouse.cxx index f033068e0..d33f8da39 100644 --- a/src/GUI/mouse.cxx +++ b/src/GUI/mouse.cxx @@ -323,7 +323,9 @@ void CenterView( void ) { glutSetCursor(GLUT_CURSOR_INHERIT); // Is this necessary ?? +#if defined(FG_OLD_MENU) if( !gui_menu_on ) TurnCursorOff(); +#endif glutWarpPointer( _savedX, _savedY ); } @@ -368,6 +370,7 @@ void guiMotionFunc ( int x, int y ) wh = MOUSE_YSIZE; if (mouse_mode == MOUSE_POINTER) { +#if defined(FG_OLD_MENU) // TURN MENU ON IF MOUSE AT TOP if( y < 1 ) { if( !gui_menu_on ) @@ -378,6 +381,7 @@ void guiMotionFunc ( int x, int y ) if( gui_menu_on ) guiToggleMenu(); } +#endif puMouse ( x, y ) ; glutPostRedisplay () ; } else { @@ -620,11 +624,13 @@ void guiMouseFunc(int button, int updown, int x, int y) #endif // NO_SMOOTH_MOUSE_VIEW #endif // RESET_VIEW_ON_LEAVING_MOUSE_VIEW glutSetCursor(GLUT_CURSOR_INHERIT); - + +#if defined(FG_OLD_MENU) #if defined(WIN32_CURSOR_TWEAKS_OFF) if(!gui_menu_on) TurnCursorOff(); #endif // WIN32_CURSOR_TWEAKS_OFF +#endif // FG_OLD_MENU break; } // end switch (mouse_mode) glutWarpPointer( x, y ); diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index 90cff403d..e7c6f939f 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -11,6 +11,8 @@ SG_USING_STD(vector); #include #include
+#include "menubar.hxx" + //////////////////////////////////////////////////////////////////////// @@ -257,20 +259,27 @@ GUIWidget::PropertyObject::PropertyObject (const char * n, NewGUI::NewGUI () - : _current_widget(0) + : _menubar(new FGMenuBar), + _current_widget(0) { } NewGUI::~NewGUI () { + delete _menubar; } void NewGUI::init () { - char path[1024]; - ulMakePath(path, getenv("FG_ROOT"), "gui"); - readDir(path); + char path1[1024]; + char path2[1024]; + ulMakePath(path1, getenv("FG_ROOT"), "gui"); + ulMakePath(path2, path1, "dialogs"); + readDir(path2); +#if !defined(FG_OLD_MENUBAR) + _menubar->init(); +#endif } void @@ -300,6 +309,12 @@ NewGUI::getCurrentWidget () return _current_widget; } +FGMenuBar * +NewGUI::getMenuBar () +{ + return _menubar; +} + void NewGUI::readDir (const char * path) { diff --git a/src/GUI/new_gui.hxx b/src/GUI/new_gui.hxx index 91a6aa3df..6b5b0b9e0 100644 --- a/src/GUI/new_gui.hxx +++ b/src/GUI/new_gui.hxx @@ -22,6 +22,7 @@ SG_USING_STD(map); #include
#include +class FGMenuBar; class GUIWidget; @@ -133,11 +134,14 @@ public: virtual void setCurrentWidget (GUIWidget * widget); virtual GUIWidget * getCurrentWidget (); + virtual FGMenuBar * getMenuBar (); + private: void readDir (const char * path); + FGMenuBar * _menubar; GUIWidget * _current_widget; map _widgets; diff --git a/src/Input/input.cxx b/src/Input/input.cxx index 59d874bdb..7a5cbaedc 100644 --- a/src/Input/input.cxx +++ b/src/Input/input.cxx @@ -335,7 +335,9 @@ FGInput::doKey (int k, int modifiers, int x, int y) } case 256+GLUT_KEY_F10: // F10 toggles menu on and off... SG_LOG(SG_INPUT, SG_INFO, "Invoking call back function"); +#if defined(FG_OLD_MENUBAR) guiToggleMenu(); +#endif return; case 256+GLUT_KEY_F11: // F11 Altitude Dialog. SG_LOG(SG_INPUT, SG_INFO, "Invoking Altitude call back function");