diff --git a/src/GUI/Makefile.am b/src/GUI/Makefile.am index 8cb594c55..7d6d59b82 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 \ + dialog.cxx dialog.hxx \ menubar.cxx menubar.hxx \ gui.cxx gui.h gui_funcs.cxx \ gui_local.cxx gui_local.hxx \ diff --git a/src/GUI/dialog.cxx b/src/GUI/dialog.cxx new file mode 100644 index 000000000..38c77697b --- /dev/null +++ b/src/GUI/dialog.cxx @@ -0,0 +1,253 @@ +// dialog.cxx: implementation of an XML-configurable dialog box. + +#include + +#include "dialog.hxx" +#include "new_gui.hxx" + + + +//////////////////////////////////////////////////////////////////////// +// Callbacks. +//////////////////////////////////////////////////////////////////////// + +/** + * Action callback. + */ +static void +action_callback (puObject * object) +{ + GUIInfo * info = (GUIInfo *)object->getUserData(); + NewGUI * gui = + (NewGUI *)globals->get_subsystem_mgr() + ->get_group(FGSubsystemMgr::INIT)->get_subsystem("gui"); + gui->setCurrentWidget(info->widget); + for (int i = 0; i < info->bindings.size(); i++) + info->bindings[i]->fire(); + gui->setCurrentWidget(0); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of GUIInfo. +//////////////////////////////////////////////////////////////////////// + +GUIInfo::GUIInfo (FGDialog * w) + : widget(w) +{ +} + +GUIInfo::~GUIInfo () +{ + for (int i = 0; i < bindings.size(); i++) { + delete bindings[i]; + bindings[i] = 0; + } +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGDialog. +//////////////////////////////////////////////////////////////////////// + +FGDialog::FGDialog (SGPropertyNode_ptr props) + : _object(0) +{ + display(props); +} + +FGDialog::~FGDialog () +{ + delete _object; + + int i; + for (i = 0; i < _info.size(); i++) { + delete _info[i]; + _info[i] = 0; + } + + for (i = 0; i < _propertyObjects.size(); i++) { + delete _propertyObjects[i]; + _propertyObjects[i] = 0; + } +} + +void +FGDialog::updateValue (const char * objectName) +{ + for (int i = 0; i < _propertyObjects.size(); i++) { + if (_propertyObjects[i]->name == objectName) + _propertyObjects[i]->object + ->setValue(_propertyObjects[i]->node->getStringValue()); + } +} + +void +FGDialog::applyValue (const char * objectName) +{ + for (int i = 0; i < _propertyObjects.size(); i++) { + if (_propertyObjects[i]->name == objectName) + _propertyObjects[i]->node + ->setStringValue(_propertyObjects[i] + ->object->getStringValue()); + } +} + +void +FGDialog::updateValues () +{ + for (int i = 0; i < _propertyObjects.size(); i++) { + puObject * object = _propertyObjects[i]->object; + SGPropertyNode_ptr node = _propertyObjects[i]->node; + object->setValue(node->getStringValue()); + } +} + +void +FGDialog::applyValues () +{ + for (int i = 0; i < _propertyObjects.size(); i++) { + puObject * object = _propertyObjects[i]->object; + SGPropertyNode_ptr node = _propertyObjects[i]->node; + node->setStringValue(object->getStringValue()); + } +} + +void +FGDialog::display (SGPropertyNode_ptr props) +{ + if (_object != 0) { + SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active"); + return; + } + + _object = makeObject(props, 1024, 768); + + if (_object != 0) { + _object->reveal(); + } else { + SG_LOG(SG_GENERAL, SG_ALERT, "Widget " + << props->getStringValue("name", "[unnamed]") + << " does not contain a proper GUI definition"); + } +} + +puObject * +FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight) +{ + int width = props->getIntValue("width", parentWidth); + int height = props->getIntValue("height", parentHeight); + + int x = props->getIntValue("x", (parentWidth - width) / 2); + int y = props->getIntValue("y", (parentHeight - height) / 2); + + string type = props->getName(); + if (type == "") + type = props->getStringValue("type"); + if (type == "") { + SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object"); + return 0; + } + + if (type == "dialog") { + puPopup * dialog; + if (props->getBoolValue("modal", false)) + dialog = new puDialogBox(x, y); + else + dialog = new puPopup(x, y); + setupGroup(dialog, props, width, height, true); + return dialog; + } else if (type == "group") { + puGroup * group = new puGroup(x, y); + setupGroup(group, props, width, height, false); + return group; + } else if (type == "input") { + puInput * input = new puInput(x, y, x + width, y + height); + setupObject(input, props); + return input; + } else if (type == "text") { + puText * text = new puText(x, y); + setupObject(text, props); + return text; + } else if (type == "button") { + puButton * b; + const char * legend = props->getStringValue("legend", "[none]"); + if (props->getBoolValue("one-shot", true)) + b = new puOneShot(x, y, legend); + else + b = new puButton(x, y, legend); + setupObject(b, props); + return b; + } else { + return 0; + } +} + +void +FGDialog::setupObject (puObject * object, SGPropertyNode * props) +{ + if (props->hasValue("legend")) + object->setLegend(props->getStringValue("legend")); + + if (props->hasValue("label")) + object->setLabel(props->getStringValue("label")); + + if (props->hasValue("property")) { + const char * name = props->getStringValue("name"); + if (name == 0) + name = ""; + const char * propname = props->getStringValue("property"); + SGPropertyNode_ptr node = fgGetNode(propname, true); + object->setValue(node->getStringValue()); + if (name != 0) + _propertyObjects.push_back(new PropertyObject(name, object, node)); + } + + vector nodes = props->getChildren("binding"); + if (nodes.size() > 0) { + GUIInfo * info = new GUIInfo(this); + + for (int i = 0; i < nodes.size(); i++) + info->bindings.push_back(new FGBinding(nodes[i])); + object->setCallback(action_callback); + object->setUserData(info); + _info.push_back(info); + } + + object->makeReturnDefault(props->getBoolValue("default")); +} + +void +FGDialog::setupGroup (puGroup * group, SGPropertyNode * props, + int width, int height, bool makeFrame) +{ + setupObject(group, props); + + if (makeFrame) + new puFrame(0, 0, width, height); + + int nChildren = props->nChildren(); + for (int i = 0; i < nChildren; i++) + makeObject(props->getChild(i), width, height); + group->close(); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGDialog::PropertyObject. +//////////////////////////////////////////////////////////////////////// + +FGDialog::PropertyObject::PropertyObject (const char * n, + puObject * o, + SGPropertyNode_ptr p) + : name(n), + object(o), + node(p) +{ +} + + +// end of dialog.cxx diff --git a/src/GUI/dialog.hxx b/src/GUI/dialog.hxx new file mode 100644 index 000000000..de2e900a9 --- /dev/null +++ b/src/GUI/dialog.hxx @@ -0,0 +1,116 @@ +// dialog.hxx - XML-configurable dialog box. + +#ifndef __DIALOG_HXX +#define __DIALOG_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include + +#include // for SG_USING_STD +#include + +#include +SG_USING_STD(vector); + +class FGDialog; +class FGBinding; + + +/** + * PUI userdata describing a GUI object. + */ +struct GUIInfo +{ + GUIInfo (FGDialog * w); + virtual ~GUIInfo (); + + FGDialog * widget; + vector bindings; +}; + + +/** + * Top-level GUI widget. + */ +class FGDialog +{ +public: + + + /** + * Construct a new GUI widget configured by a property tree. + */ + FGDialog (SGPropertyNode_ptr props); + + + /** + * Destructor. + */ + virtual ~FGDialog (); + + + /** + * Update the values of all GUI objects with a specific name. + * + * This method copies from the property to the GUI object. + * + * @param objectName The name of the GUI object(s) to update. + * Use the empty name for all unnamed objects. + */ + virtual void updateValue (const char * objectName); + + + /** + * Apply the values of all GUI objects with a specific name. + * + * This method copies from the GUI object to the property. + * + * @param objectName The name of the GUI object(s) to update. + * Use the empty name for all unnamed objects. + */ + virtual void applyValue (const char * objectName); + + + /** + * Update the values of all GUI objects. + * + * This method copies from the properties to the GUI objects. + */ + virtual void updateValues (); + + + /** + * Apply the values of all GUI objects. + * + * This method copies from the GUI objects to the properties. + */ + virtual void applyValues (); + + +private: + FGDialog (const FGDialog &); // just for safety + + void display (SGPropertyNode_ptr props); + puObject * makeObject (SGPropertyNode * props, + int parentWidth, int parentHeight); + void setupObject (puObject * object, SGPropertyNode * props); + void setupGroup (puGroup * group, SGPropertyNode * props, + int width, int height, bool makeFrame = false); + + puObject * _object; + vector _info; + struct PropertyObject { + PropertyObject (const char * name, + puObject * object, + SGPropertyNode_ptr node); + string name; + puObject * object; + SGPropertyNode_ptr node; + }; + vector _propertyObjects; +}; + +#endif // __DIALOG_HXX diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx index e7c6f939f..6be566c65 100644 --- a/src/GUI/new_gui.cxx +++ b/src/GUI/new_gui.cxx @@ -5,251 +5,11 @@ #include #include -#include -SG_USING_STD(vector); - #include #include
#include "menubar.hxx" - - - -//////////////////////////////////////////////////////////////////////// -// Callbacks. -//////////////////////////////////////////////////////////////////////// - -/** - * Action callback. - */ -static void -action_callback (puObject * object) -{ - GUIInfo * info = (GUIInfo *)object->getUserData(); - NewGUI * gui = - (NewGUI *)globals->get_subsystem_mgr() - ->get_group(FGSubsystemMgr::INIT)->get_subsystem("gui"); - gui->setCurrentWidget(info->widget); - for (int i = 0; i < info->bindings.size(); i++) - info->bindings[i]->fire(); - gui->setCurrentWidget(0); -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of GUIInfo. -//////////////////////////////////////////////////////////////////////// - -GUIInfo::GUIInfo (GUIWidget * w) - : widget(w) -{ -} - -GUIInfo::~GUIInfo () -{ - for (int i = 0; i < bindings.size(); i++) { - delete bindings[i]; - bindings[i] = 0; - } -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of GUIWidget. -//////////////////////////////////////////////////////////////////////// - -GUIWidget::GUIWidget (SGPropertyNode_ptr props) - : _object(0) -{ - display(props); -} - -GUIWidget::~GUIWidget () -{ - delete _object; - - int i; - for (i = 0; i < _info.size(); i++) { - delete _info[i]; - _info[i] = 0; - } - - for (i = 0; i < _propertyObjects.size(); i++) { - delete _propertyObjects[i]; - _propertyObjects[i] = 0; - } -} - -void -GUIWidget::updateValue (const char * objectName) -{ - for (int i = 0; i < _propertyObjects.size(); i++) { - if (_propertyObjects[i]->name == objectName) - _propertyObjects[i]->object - ->setValue(_propertyObjects[i]->node->getStringValue()); - } -} - -void -GUIWidget::applyValue (const char * objectName) -{ - for (int i = 0; i < _propertyObjects.size(); i++) { - if (_propertyObjects[i]->name == objectName) - _propertyObjects[i]->node - ->setStringValue(_propertyObjects[i] - ->object->getStringValue()); - } -} - -void -GUIWidget::updateValues () -{ - for (int i = 0; i < _propertyObjects.size(); i++) { - puObject * object = _propertyObjects[i]->object; - SGPropertyNode_ptr node = _propertyObjects[i]->node; - object->setValue(node->getStringValue()); - } -} - -void -GUIWidget::applyValues () -{ - for (int i = 0; i < _propertyObjects.size(); i++) { - puObject * object = _propertyObjects[i]->object; - SGPropertyNode_ptr node = _propertyObjects[i]->node; - node->setStringValue(object->getStringValue()); - } -} - -void -GUIWidget::display (SGPropertyNode_ptr props) -{ - if (_object != 0) { - SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active"); - return; - } - - _object = makeObject(props, 1024, 768); - - if (_object != 0) { - _object->reveal(); - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "Widget " - << props->getStringValue("name", "[unnamed]") - << " does not contain a proper GUI definition"); - } -} - -puObject * -GUIWidget::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight) -{ - int width = props->getIntValue("width", parentWidth); - int height = props->getIntValue("height", parentHeight); - - int x = props->getIntValue("x", (parentWidth - width) / 2); - int y = props->getIntValue("y", (parentHeight - height) / 2); - - string type = props->getName(); - if (type == "") - type = props->getStringValue("type"); - if (type == "") { - SG_LOG(SG_GENERAL, SG_ALERT, "No type specified for GUI object"); - return 0; - } - - if (type == "dialog") { - puPopup * dialog; - if (props->getBoolValue("modal", false)) - dialog = new puDialogBox(x, y); - else - dialog = new puPopup(x, y); - setupGroup(dialog, props, width, height, true); - return dialog; - } else if (type == "group") { - puGroup * group = new puGroup(x, y); - setupGroup(group, props, width, height, false); - return group; - } else if (type == "input") { - puInput * input = new puInput(x, y, x + width, y + height); - setupObject(input, props); - return input; - } else if (type == "text") { - puText * text = new puText(x, y); - setupObject(text, props); - return text; - } else if (type == "button") { - puButton * b; - const char * legend = props->getStringValue("legend", "[none]"); - if (props->getBoolValue("one-shot", true)) - b = new puOneShot(x, y, legend); - else - b = new puButton(x, y, legend); - setupObject(b, props); - return b; - } else { - return 0; - } -} - -void -GUIWidget::setupObject (puObject * object, SGPropertyNode * props) -{ - if (props->hasValue("legend")) - object->setLegend(props->getStringValue("legend")); - - if (props->hasValue("label")) - object->setLabel(props->getStringValue("label")); - - if (props->hasValue("property")) { - const char * name = props->getStringValue("name"); - if (name == 0) - name = ""; - const char * propname = props->getStringValue("property"); - SGPropertyNode_ptr node = fgGetNode(propname, true); - object->setValue(node->getStringValue()); - if (name != 0) - _propertyObjects.push_back(new PropertyObject(name, object, node)); - } - - vector nodes = props->getChildren("binding"); - if (nodes.size() > 0) { - GUIInfo * info = new GUIInfo(this); - - for (int i = 0; i < nodes.size(); i++) - info->bindings.push_back(new FGBinding(nodes[i])); - object->setCallback(action_callback); - object->setUserData(info); - _info.push_back(info); - } - - object->makeReturnDefault(props->getBoolValue("default")); -} - -void -GUIWidget::setupGroup (puGroup * group, SGPropertyNode * props, - int width, int height, bool makeFrame) -{ - setupObject(group, props); - - if (makeFrame) - new puFrame(0, 0, width, height); - - int nChildren = props->nChildren(); - for (int i = 0; i < nChildren; i++) - makeObject(props->getChild(i), width, height); - group->close(); -} - -GUIWidget::PropertyObject::PropertyObject (const char * n, - puObject * o, - SGPropertyNode_ptr p) - : name(n), - object(o), - node(p) -{ -} +#include "dialog.hxx" @@ -294,16 +54,16 @@ NewGUI::display (const string &name) if (_widgets.find(name) == _widgets.end()) SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined"); else - new GUIWidget(_widgets[name]); + new FGDialog(_widgets[name]); } void -NewGUI::setCurrentWidget (GUIWidget * widget) +NewGUI::setCurrentWidget (FGDialog * widget) { _current_widget = widget; } -GUIWidget * +FGDialog * NewGUI::getCurrentWidget () { return _current_widget; diff --git a/src/GUI/new_gui.hxx b/src/GUI/new_gui.hxx index 6b5b0b9e0..4a7f425ce 100644 --- a/src/GUI/new_gui.hxx +++ b/src/GUI/new_gui.hxx @@ -20,105 +20,10 @@ SG_USING_STD(map); #include
#include
-#include class FGMenuBar; -class GUIWidget; - - -/** - * Information about a GUI widget. - */ -struct GUIInfo -{ - GUIInfo (GUIWidget * w); - virtual ~GUIInfo (); - - GUIWidget * widget; - vector bindings; -}; - - -/** - * Top-level GUI widget. - */ -class GUIWidget -{ -public: - - - /** - * Construct a new GUI widget configured by a property tree. - */ - GUIWidget (SGPropertyNode_ptr props); - - - /** - * Destructor. - */ - virtual ~GUIWidget (); - - - /** - * Update the values of all GUI objects with a specific name. - * - * This method copies from the property to the GUI object. - * - * @param objectName The name of the GUI object(s) to update. - * Use the empty name for all unnamed objects. - */ - virtual void updateValue (const char * objectName); - - - /** - * Apply the values of all GUI objects with a specific name. - * - * This method copies from the GUI object to the property. - * - * @param objectName The name of the GUI object(s) to update. - * Use the empty name for all unnamed objects. - */ - virtual void applyValue (const char * objectName); - - - /** - * Update the values of all GUI objects. - * - * This method copies from the properties to the GUI objects. - */ - virtual void updateValues (); - - - /** - * Apply the values of all GUI objects. - * - * This method copies from the GUI objects to the properties. - */ - virtual void applyValues (); - - -private: - GUIWidget (const GUIWidget &); // just for safety - - void display (SGPropertyNode_ptr props); - puObject * makeObject (SGPropertyNode * props, - int parentWidth, int parentHeight); - void setupObject (puObject * object, SGPropertyNode * props); - void setupGroup (puGroup * group, SGPropertyNode * props, - int width, int height, bool makeFrame = false); - - puObject * _object; - vector _info; - struct PropertyObject { - PropertyObject (const char * name, - puObject * object, - SGPropertyNode_ptr node); - string name; - puObject * object; - SGPropertyNode_ptr node; - }; - vector _propertyObjects; -}; +class FGDialog; +class FGBinding; class NewGUI : public FGSubsystem @@ -131,8 +36,8 @@ public: virtual void update (double delta_time_sec); virtual void display (const string &name); - virtual void setCurrentWidget (GUIWidget * widget); - virtual GUIWidget * getCurrentWidget (); + virtual void setCurrentWidget (FGDialog * widget); + virtual FGDialog * getCurrentWidget (); virtual FGMenuBar * getMenuBar (); @@ -142,7 +47,7 @@ private: void readDir (const char * path); FGMenuBar * _menubar; - GUIWidget * _current_widget; + FGDialog * _current_widget; map _widgets; };