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;
}
}
bool
NewGUI::closeActiveDialog ()
{
- if (_active_dialog == 0) {
+ if (_active_dialog == 0)
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 false; // dialog wasn't open...
}
void
{
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();
}
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)
{
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);
*/
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.
*
/**
- * 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 ();
+ /**
+ * 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.
FGMenuBar * _menubar;
FGDialog * _active_dialog;
- map<string,SGPropertyNode *> _dialog_props;
+ map<string,FGDialog *> _active_dialogs;
+ map<string,SGPropertyNode_ptr> _dialog_props;
};
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.
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();
}
{ "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 },
static naRef propNodeGhostCreate(naContext c, SGPropertyNode* n)
{
+ if(!n) return naNil();
SGPropertyNode_ptr* ghost = new SGPropertyNode_ptr(n);
return naNewGhost(c, &PropNodeGhostType, ghost);
}