]> git.mxchange.org Git - flightgear.git/blobdiff - src/GUI/dialog.cxx
Moved random ground cover object management code (userdata.[ch]xx) over
[flightgear.git] / src / GUI / dialog.cxx
index 38c77697bac73ae4ca527ebcf633463cf34472cd..a2e2fb8e364064ce0cfefc26dfcd9c1093db3e11 100644 (file)
 // Callbacks.
 ////////////////////////////////////////////////////////////////////////
 
+/**
+ * User data for a GUI object.
+ */
+struct GUIInfo
+{
+    GUIInfo (FGDialog * d);
+    virtual ~GUIInfo ();
+
+    FGDialog * dialog;
+    vector <FGBinding *> bindings;
+};
+
+
 /**
  * Action callback.
  */
@@ -18,13 +31,63 @@ 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++)
+    NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+    gui->setActiveDialog(info->dialog);
+    int nBindings = info->bindings.size();
+    for (int i = 0; i < nBindings; i++) {
         info->bindings[i]->fire();
-    gui->setCurrentWidget(0);
+        if (gui->getActiveDialog() == 0)
+            break;
+    }
+    gui->setActiveDialog(0);
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Static helper functions.
+////////////////////////////////////////////////////////////////////////
+
+/**
+ * Copy a property value to a PUI object.
+ */
+static void
+copy_to_pui (SGPropertyNode * node, puObject * object)
+{
+    switch (node->getType()) {
+    case SGPropertyNode::BOOL:
+    case SGPropertyNode::INT:
+    case SGPropertyNode::LONG:
+        object->setValue(node->getIntValue());
+        break;
+    case SGPropertyNode::FLOAT:
+    case SGPropertyNode::DOUBLE:
+        object->setValue(node->getFloatValue());
+        break;
+    default:
+        object->setValue(node->getStringValue());
+        break;
+    }
+}
+
+
+static void
+copy_from_pui (puObject * object, SGPropertyNode * node)
+{
+    switch (node->getType()) {
+    case SGPropertyNode::BOOL:
+    case SGPropertyNode::INT:
+    case SGPropertyNode::LONG:
+        node->setIntValue(object->getIntegerValue());
+        break;
+    case SGPropertyNode::FLOAT:
+    case SGPropertyNode::DOUBLE:
+        node->setFloatValue(object->getFloatValue());
+        break;
+    default:
+        node->setStringValue(object->getStringValue());
+        break;
+    }
 }
 
 
@@ -33,14 +96,14 @@ action_callback (puObject * object)
 // Implementation of GUIInfo.
 ////////////////////////////////////////////////////////////////////////
 
-GUIInfo::GUIInfo (FGDialog * w)
-    : widget(w)
+GUIInfo::GUIInfo (FGDialog * d)
+    : dialog(d)
 {
 }
 
 GUIInfo::~GUIInfo ()
 {
-    for (int i = 0; i < bindings.size(); i++) {
+    for (unsigned int i = 0; i < bindings.size(); i++) {
         delete bindings[i];
         bindings[i] = 0;
     }
@@ -52,7 +115,7 @@ GUIInfo::~GUIInfo ()
 // Implementation of FGDialog.
 ////////////////////////////////////////////////////////////////////////
 
-FGDialog::FGDialog (SGPropertyNode_ptr props)
+FGDialog::FGDialog (SGPropertyNode * props)
     : _object(0)
 {
     display(props);
@@ -60,14 +123,29 @@ FGDialog::FGDialog (SGPropertyNode_ptr props)
 
 FGDialog::~FGDialog ()
 {
-    delete _object;
+    puDeleteObject(_object);
+
+    unsigned int i;
+
+                                // Delete all the arrays we made
+                                // and were forced to keep around
+                                // because PUI won't do its own
+                                // memory management.
+    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];
+    }
 
-    int i;
+                                // Delete all the info objects we
+                                // were forced to keep around because
+                                // PUI cannot delete its own user data.
     for (i = 0; i < _info.size(); i++) {
-        delete _info[i];
+        delete (GUIInfo *)_info[i];
         _info[i] = 0;
     }
 
+                                // Finally, delete the property links.
     for (i = 0; i < _propertyObjects.size(); i++) {
         delete _propertyObjects[i];
         _propertyObjects[i] = 0;
@@ -77,53 +155,50 @@ FGDialog::~FGDialog ()
 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());
+    for (unsigned int i = 0; i < _propertyObjects.size(); i++) {
+        const string &name = _propertyObjects[i]->name;
+        if (name == objectName)
+            copy_to_pui(_propertyObjects[i]->node,
+                        _propertyObjects[i]->object);
     }
 }
 
 void
 FGDialog::applyValue (const char * objectName)
 {
-    for (int i = 0; i < _propertyObjects.size(); i++) {
+    for (unsigned int i = 0; i < _propertyObjects.size(); i++) {
         if (_propertyObjects[i]->name == objectName)
-            _propertyObjects[i]->node
-                ->setStringValue(_propertyObjects[i]
-                                 ->object->getStringValue());
+            copy_from_pui(_propertyObjects[i]->object,
+                          _propertyObjects[i]->node);
     }
 }
 
 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());
-    }
+    for (unsigned int i = 0; i < _propertyObjects.size(); i++)
+        copy_to_pui(_propertyObjects[i]->node, _propertyObjects[i]->object);
 }
 
 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());
-    }
+    for (unsigned int i = 0; i < _propertyObjects.size(); i++)
+        copy_from_pui(_propertyObjects[i]->object,
+                      _propertyObjects[i]->node);
 }
 
 void
-FGDialog::display (SGPropertyNode_ptr props)
+FGDialog::display (SGPropertyNode * props)
 {
     if (_object != 0) {
         SG_LOG(SG_GENERAL, SG_ALERT, "This widget is already active");
         return;
     }
 
-    _object = makeObject(props, 1024, 768);
+    _object = makeObject(props,
+                      globals->get_props()->getIntValue("/sim/startup/xsize"),
+                      globals->get_props()->getIntValue("/sim/startup/ysize"));
 
     if (_object != 0) {
         _object->reveal();
@@ -145,11 +220,7 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
 
     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;
-    }
+        type = "dialog";
 
     if (type == "dialog") {
         puPopup * dialog;
@@ -171,6 +242,11 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
         puText * text = new puText(x, y);
         setupObject(text, props);
         return text;
+    } else if (type == "checkbox") {
+        puButton * b;
+        b = new puButton(x, y, x + width, y + height, PUBUTTON_CIRCLE);
+        setupObject(b, props);
+        return b;
     } else if (type == "button") {
         puButton * b;
         const char * legend = props->getStringValue("legend", "[none]");
@@ -180,6 +256,49 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
             b = new puButton(x, y, legend);
         setupObject(b, props);
         return b;
+    } else if (type == "combo") {
+        vector<SGPropertyNode_ptr> value_nodes = props->getChildren("value");
+        char ** entries = make_char_array(value_nodes.size());
+        for (unsigned int i = 0, j = value_nodes.size() - 1;
+             i < value_nodes.size();
+             i++, j--)
+            entries[i] = strdup((char *)value_nodes[i]->getStringValue());
+        puComboBox * combo =
+            new puComboBox(x, y, x + width, y + height, entries,
+                           props->getBoolValue("editable", false));
+        setupObject(combo, props);
+        return combo;
+    } else if (type == "slider") {
+        bool vertical = props->getBoolValue("vertical", false);
+        puSlider * slider = new puSlider(x, y, (vertical ? height : width));
+        slider->setMinValue(props->getFloatValue("min", 0.0));
+        slider->setMaxValue(props->getFloatValue("max", 1.0));
+        setupObject(slider, props);
+        return slider;
+    } else if (type == "dial") {
+        puDial * dial = new puDial(x, y, width);
+        dial->setMinValue(props->getFloatValue("min", 0.0));
+        dial->setMaxValue(props->getFloatValue("max", 1.0));
+        dial->setWrap(props->getBoolValue("wrap", true));
+        setupObject(dial, props);
+        return dial;
+    } else if (type == "select") {
+        vector<SGPropertyNode_ptr> value_nodes;
+        SGPropertyNode * selection_node =
+                fgGetNode(props->getChild("selection")->getStringValue(), true);
+
+        for (int q = 0; q < selection_node->nChildren(); q++)
+            value_nodes.push_back(selection_node->getChild(q));
+
+        char ** entries = make_char_array(value_nodes.size());
+        for (unsigned int i = 0, j = value_nodes.size() - 1;
+             i < value_nodes.size();
+             i++, j--)
+            entries[i] = strdup((char *)value_nodes[i]->getName());
+        puSelectBox * select =
+            new puSelectBox(x, y, x + width, y + height, entries);
+        setupObject(select, props);
+        return select;
     } else {
         return 0;
     }
@@ -200,7 +319,7 @@ FGDialog::setupObject (puObject * object, SGPropertyNode * props)
             name = "";
         const char * propname = props->getStringValue("property");
         SGPropertyNode_ptr node = fgGetNode(propname, true);
-        object->setValue(node->getStringValue());
+        copy_to_pui(node, object);
         if (name != 0)
             _propertyObjects.push_back(new PropertyObject(name, object, node));
     }
@@ -209,7 +328,7 @@ FGDialog::setupObject (puObject * object, SGPropertyNode * props)
     if (nodes.size() > 0) {
         GUIInfo * info = new GUIInfo(this);
 
-        for (int i = 0; i < nodes.size(); i++)
+        for (unsigned int i = 0; i < nodes.size(); i++)
             info->bindings.push_back(new FGBinding(nodes[i]));
         object->setCallback(action_callback);
         object->setUserData(info);
@@ -234,6 +353,16 @@ FGDialog::setupGroup (puGroup * group, SGPropertyNode * props,
     group->close();
 }
 
+char **
+FGDialog::make_char_array (int size)
+{
+    char ** list = new char*[size+1];
+    for (int i = 0; i <= size; i++)
+        list[i] = 0;
+    _char_arrays.push_back(list);
+    return list;
+}
+
 
 \f
 ////////////////////////////////////////////////////////////////////////