Add a new command, "dialog-new", allowing external code (e.g. Nasal
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).
This commit is contained in:
parent
7ac15db168
commit
0b3159ec0c
4 changed files with 91 additions and 17 deletions
|
@ -79,7 +79,8 @@ NewGUI::showDialog (const string &name)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -87,13 +88,33 @@ NewGUI::showDialog (const string &name)
|
|||
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
|
||||
|
@ -134,10 +155,6 @@ NewGUI::clear ()
|
|||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -154,6 +171,18 @@ test_extension (const char * path, const char * ext)
|
|||
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)
|
||||
{
|
||||
|
@ -189,11 +218,7 @@ 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);
|
||||
|
|
|
@ -80,6 +80,18 @@ public:
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -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 ();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -151,7 +173,8 @@ private:
|
|||
|
||||
FGMenuBar * _menubar;
|
||||
FGDialog * _active_dialog;
|
||||
map<string,SGPropertyNode *> _dialog_props;
|
||||
map<string,FGDialog *> _active_dialogs;
|
||||
map<string,SGPropertyNode_ptr> _dialog_props;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -857,6 +857,28 @@ do_data_logging_commit (const SGPropertyNode * arg)
|
|||
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.
|
||||
|
@ -879,6 +901,8 @@ static bool
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -1066,6 +1090,7 @@ static struct {
|
|||
{ "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 },
|
||||
|
|
|
@ -25,6 +25,7 @@ naGhostType PropNodeGhostType = { propNodeGhostDestroy };
|
|||
|
||||
static naRef propNodeGhostCreate(naContext c, SGPropertyNode* n)
|
||||
{
|
||||
if(!n) return naNil();
|
||||
SGPropertyNode_ptr* ghost = new SGPropertyNode_ptr(n);
|
||||
return naNewGhost(c, &PropNodeGhostType, ghost);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue