]> git.mxchange.org Git - flightgear.git/commitdiff
Add a new command, "dialog-new", allowing external code (e.g. Nasal
authorandy <andy>
Mon, 8 Dec 2003 02:05:10 +0000 (02:05 +0000)
committerandy <andy>
Mon, 8 Dec 2003 02:05:10 +0000 (02:05 +0000)
scripts) to create dialogs at runtime.  Augment "dialog-close" to take
a name argument, allowing code other than PUI callbacks to close
dialogs.

The changes to the GUI directory to enable this are actually minor,
basically amounting to using SGPropertyNode_ptr reference counting
(the GUI subsystem no longer "controls" the dialog property trees, so
it can't delete them).

src/GUI/new_gui.cxx
src/GUI/new_gui.hxx
src/Main/fg_commands.cxx
src/Scripting/nasal-props.cxx

index f6e087ca91a1ad602d9ee7c8ac60cc103561a9db..8a3a12f3c9bd120f683ef1ac72c66d0844853578 100644 (file)
@@ -79,7 +79,8 @@ NewGUI::showDialog (const string &name)
         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
         return false;
     } else {
         SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
         return false;
     } else {
-        new FGDialog(_dialog_props[name]); // it will be deleted by a callback
+        if(!_active_dialogs[name])
+            _active_dialogs[name] = new FGDialog(_dialog_props[name]);
         return true;
     }
 }
         return true;
     }
 }
@@ -87,13 +88,33 @@ NewGUI::showDialog (const string &name)
 bool
 NewGUI::closeActiveDialog ()
 {
 bool
 NewGUI::closeActiveDialog ()
 {
-    if (_active_dialog == 0) {
+    if (_active_dialog == 0)
         return false;
         return false;
-    } else {
-        delete _active_dialog;
-        _active_dialog = 0;
+
+    // Kill any entries in _active_dialogs...  Is there an STL
+    // algorithm to do (delete map entries by value, not key)?  I hate
+    // the STL :) -Andy
+    map<string,FGDialog *>::iterator iter = _active_dialogs.begin();
+    for(/**/; iter != _active_dialogs.end(); iter++)
+        if(iter->second == _active_dialog)
+            _active_dialogs.erase(iter);
+
+    delete _active_dialog;
+    _active_dialog = 0;
+    return true;
+}
+
+bool
+NewGUI::closeDialog (const string& name)
+{
+    if(_active_dialogs.find(name) != _active_dialogs.end()) {
+        if(_active_dialog == _active_dialogs[name])
+            _active_dialog = 0;
+        delete _active_dialogs[name];
+        _active_dialogs.erase(name);
         return true;
     }
         return true;
     }
+    return false; // dialog wasn't open...
 }
 
 void
 }
 
 void
@@ -134,10 +155,6 @@ NewGUI::clear ()
 {
     delete _menubar;
     _menubar = 0;
 {
     delete _menubar;
     _menubar = 0;
-
-    map<string,SGPropertyNode *>::iterator it;
-    for (it = _dialog_props.begin(); it != _dialog_props.end(); it++)
-        delete it->second;
     _dialog_props.clear();
 }
 
     _dialog_props.clear();
 }
 
@@ -154,6 +171,18 @@ test_extension (const char * path, const char * ext)
     return true;
 }
 
     return true;
 }
 
+void
+NewGUI::newDialog (SGPropertyNode* props)
+{
+    const char* cname = props->getStringValue("name");
+    if(!cname) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "New dialog has no <name> property");
+        return;
+    }
+    string name = props->getStringValue("name");
+    _dialog_props[name] = props;
+}
+
 void
 NewGUI::readDir (const char * path)
 {
 void
 NewGUI::readDir (const char * path)
 {
@@ -189,11 +218,7 @@ NewGUI::readDir (const char * path)
                 delete props;
                 continue;
             }
                 delete props;
                 continue;
             }
-            string name = props->getStringValue("name");
-            SG_LOG(SG_INPUT, SG_BULK, "Saving dialog " << name);
-            if (_dialog_props[name] != 0)
-                delete _dialog_props[name];
-            _dialog_props[name] = props;
+            newDialog(props);
         }
     }
     ulCloseDir(dir);
         }
     }
     ulCloseDir(dir);
index c0cda22b31f27a4d30bb51f89d8cd253366aebae..5aec7c5388ba976a046a05457da62e6690e76b7d 100644 (file)
@@ -80,6 +80,18 @@ public:
      */
     virtual void update (double delta_time_sec);
 
      */
     virtual void update (double delta_time_sec);
 
+    /**
+     * Creates a new dialog box, using the same property format as the
+     * gui/dialogs configuration files.  Does not display the
+     * resulting dialog.  If a pre-existing dialog of the same name
+     * exists, it will be deleted.  The node argument will be stored
+     * in the GUI subsystem using SGPropertNode_ptr reference counting.
+     * It should not be deleted by user code.
+     *
+     * @param node A property node containing the dialog definition
+     */
+    virtual void newDialog (SGPropertyNode* node);
+
     /**
      * Display a dialog box.
      *
     /**
      * Display a dialog box.
      *
@@ -96,12 +108,22 @@ public:
 
 
     /**
 
 
     /**
-     * Close the currently-active dialog, if any.
+     * Close the currenty active dialog.  This function is intended to
+     * be called from code (pui callbacks, for instance) that registers
+     * its dialog object as active via setActiveDialog().  Other
+     * user-level code should use the closeDialog(name) API.
      *
      *
-     * @return true if a dialog was active, false otherwise.
+     * @return true if a dialog was active, false otherwise
      */
     virtual bool closeActiveDialog ();
 
      */
     virtual bool closeActiveDialog ();
 
+    /**
+     * Close a named dialog, if it is open.
+     *
+     * @param name The name of the dialog box.
+     * @return true if the dialog was active, false otherwise.
+     */
+    virtual bool closeDialog (const string &name);
 
     /**
      * Return a pointer to the current menubar.
 
     /**
      * Return a pointer to the current menubar.
@@ -151,7 +173,8 @@ private:
 
     FGMenuBar * _menubar;
     FGDialog * _active_dialog;
 
     FGMenuBar * _menubar;
     FGDialog * _active_dialog;
-    map<string,SGPropertyNode *> _dialog_props;
+    map<string,FGDialog *> _active_dialogs;
+    map<string,SGPropertyNode_ptr> _dialog_props;
 
 };
 
 
 };
 
index 9663ad8922752a5eaf130a22278da4385eae61b6..69edb7d0cc3d55f651006806d68d967b285ace92 100644 (file)
@@ -857,6 +857,28 @@ do_data_logging_commit (const SGPropertyNode * arg)
     return true;
 }
 
     return true;
 }
 
+/**
+ * Built-in command: Add a dialog to the GUI system.  Does *not*
+ * display the dialog.  The property node should have the same format
+ * as a dialog XML configuration.  It must include:
+ *
+ * name: the name of the GUI dialog for future reference.
+ */
+static bool
+do_dialog_new (const SGPropertyNode * arg)
+{
+    NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+
+    // Note the casting away of const: this is *real*.  Doing a
+    // "dialog-apply" command later on will mutate this property node.
+    // I'm not convinced that this isn't the Right Thing though; it
+    // allows client to create a node, pass it to dialog-new, and get
+    // the values back from the dialog by reading the same node.
+    // Perhaps command arguments are not as "const" as they would
+    // seem?
+    gui->newDialog((SGPropertyNode*)arg);
+    return true;
+}
 
 /**
  * Built-in command: Show an XML-configured dialog.
 
 /**
  * Built-in command: Show an XML-configured dialog.
@@ -879,6 +901,8 @@ static bool
 do_dialog_close (const SGPropertyNode * arg)
 {
     NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
 do_dialog_close (const SGPropertyNode * arg)
 {
     NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
+    if(arg->hasValue("dialog-name"))
+        return gui->closeDialog(arg->getStringValue("dialog-name"));
     return gui->closeActiveDialog();
 }
 
     return gui->closeActiveDialog();
 }
 
@@ -1066,6 +1090,7 @@ static struct {
     { "property-cycle", do_property_cycle },
     { "property-randomize", do_property_randomize },
     { "data-logging-commit", do_data_logging_commit },
     { "property-cycle", do_property_cycle },
     { "property-randomize", do_property_randomize },
     { "data-logging-commit", do_data_logging_commit },
+    { "dialog-new", do_dialog_new },
     { "dialog-show", do_dialog_show },
     { "dialog-close", do_dialog_close },
     { "dialog-show", do_dialog_show },
     { "dialog-show", do_dialog_show },
     { "dialog-close", do_dialog_close },
     { "dialog-show", do_dialog_show },
index de0efca33fac241c29c8835dcc481b41663fb243..78401e1f9cebaff2b74aecb5f78a0c61642650b4 100644 (file)
@@ -25,6 +25,7 @@ naGhostType PropNodeGhostType = { propNodeGhostDestroy };
 
 static naRef propNodeGhostCreate(naContext c, SGPropertyNode* n)
 {
 
 static naRef propNodeGhostCreate(naContext c, SGPropertyNode* n)
 {
+    if(!n) return naNil();
     SGPropertyNode_ptr* ghost = new SGPropertyNode_ptr(n);
     return naNewGhost(c, &PropNodeGhostType, ghost);
 }
     SGPropertyNode_ptr* ghost = new SGPropertyNode_ptr(n);
     return naNewGhost(c, &PropNodeGhostType, ghost);
 }