1
0
Fork 0

GUI: add explicit close hook to FGDialog

Allow triggering close of dialogs explicitly, rather than relying on
ref-count drop to delete them. Compat dialogs have a Nasal peer and
we can't rely on GC to cause a timely close of the dialog.
This commit is contained in:
James Turner 2023-01-20 16:08:41 +00:00
parent 437ebfd272
commit 98958af2a3
6 changed files with 34 additions and 1 deletions

View file

@ -47,6 +47,8 @@ public:
}
private:
// the Nasal peer does not hold an owning reference to the
// main dialog object (dialogs are owned by the NewGUI subsystem)
SGWeakPtr<FGPUICompatDialog> _dialog;
};
@ -107,9 +109,14 @@ FGPUICompatDialog::FGPUICompatDialog(SGPropertyNode* props) : FGDialog(props),
}
FGPUICompatDialog::~FGPUICompatDialog()
{
// nothing to do, all work was done in close()
}
void FGPUICompatDialog::close()
{
if (_peer) {
_peer->callMethod<void>("doClose");
_peer->callMethod<void>("onClose");
}
_props->setIntValue("lastx", getX());
@ -124,6 +131,8 @@ FGPUICompatDialog::~FGPUICompatDialog()
}
nas->deleteModule(_module.c_str());
}
_peer.clear();
}
bool FGPUICompatDialog::init()

View file

@ -112,6 +112,8 @@ public:
double width() const;
double height() const;
void close() override;
private:
friend naRef f_makeDialogPeer(const nasal::CallContext& ctx);
friend naRef f_dialogRootObject(FGPUICompatDialog& dialog, naContext c);

View file

@ -1464,6 +1464,11 @@ void FGPUIDialog::applySize(puObject* object)
object->setSize(w, h);
}
void FGPUIDialog::close()
{
// no-op for PUI version
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGDialog::PropertyObject.
////////////////////////////////////////////////////////////////////////

View file

@ -102,6 +102,8 @@ public:
*/
virtual void update();
void close() override;
/**
* Recompute the dialog's layout
*/

View file

@ -63,6 +63,14 @@ public:
virtual const char *getName() { return ""; }
virtual void bringToFront() {}
/**
* @brief Close the dialog. This should actually close the GUI
* assets associated, if you want an 'are you sure?' interaction, it
* needs to be handled in advance of this interaction.
*/
virtual void close() = 0;
protected:
/**
* Construct a new GUI widget configured by a property tree.

View file

@ -331,12 +331,19 @@ NewGUI::closeActiveDialog ()
if (_active_dialog == 0)
return false;
// TODO support a request-close callback here, optionally
// many places in code assume this code-path does an
// immediate close, but for some UI paths it would be nice to
// allow some dialogs the chance to inervene
// 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
auto iter = _active_dialogs.begin();
for(/**/; iter != _active_dialogs.end(); iter++) {
if(iter->second == _active_dialog) {
_active_dialog->close();
_active_dialogs.erase(iter);
// iter is no longer valid
break;