1
0
Fork 0

PUI: window (FgPopup) handling changes

- I think I've fixed a long standing problem with clicks traveling through windows and bringing the dialog window underneath to the foreground.

- Added /sim/gui/dialogs/current-dialog that contains the name of the currently active (in front) dialog window.

- Changed dialog-open to bring a dialog to the front if it is already open.
This commit is contained in:
Richard Harrison 2018-08-07 18:33:57 +02:00
parent 6513dc1137
commit c13bfe2722
4 changed files with 40 additions and 12 deletions

View file

@ -101,8 +101,8 @@ validate_format(const char *f)
//
class fgPopup : public puPopup {
public:
fgPopup(int x, int y, bool r = true, bool d = true) :
puPopup(x, y), _draggable(d), _resizable(r), _dragging(false)
fgPopup(FGPUIDialog *parent_dialog, int x, int y, bool r = true, bool d = true) :
puPopup(x, y), _draggable(d), _resizable(r), _dragging(false), parentDialog(parent_dialog)
{}
int checkHit(int b, int up, int x, int y);
int checkKey(int key, int updown);
@ -114,6 +114,7 @@ public:
private:
enum { LEFT = 1, RIGHT = 2, TOP = 4, BOTTOM = 8 };
bool _draggable;
FGPUIDialog *parentDialog;
bool _resizable;
bool _dragging;
int _resizing;
@ -310,9 +311,15 @@ puObject *fgPopup::getActiveInputField(puObject *object)
int fgPopup::checkHit(int button, int updown, int x, int y)
{
int result = 0;
if (updown != PU_DRAG && !_dragging)
// still need to ensure that the hit is within this window. The code used to check _dragging
// as well, however that had the unfortunate side effect of allowing clicks to pass through to
// the underlying window. RJH-07-08-18.
if (updown == PU_UP || updown == PU_DOWN){
result = puPopup::checkHit(button, updown, x, y);
if (result && parentDialog) {
fgSetString("/sim/gui/dialogs/current-dialog", parentDialog->getName());
}
}
if (!_draggable)
return result;
@ -567,7 +574,6 @@ action_callback (puObject *object)
gui->setActiveDialog(0);
}
////////////////////////////////////////////////////////////////////////
// Static helper functions.
////////////////////////////////////////////////////////////////////////
@ -662,7 +668,7 @@ FGPUIDialog::FGPUIDialog (SGPropertyNode *props) :
_needsRelayout(false)
{
_module = string("__dlg:") + props->getStringValue("name", "[unnamed]");
_name = props->getStringValue("name", "[unnamed]");
SGPropertyNode *nasal = props->getNode("nasal");
if (nasal) {
_nasal_close = nasal->getNode("close");
@ -710,6 +716,14 @@ FGPUIDialog::~FGPUIDialog ()
}
}
void FGPUIDialog::bringToFront() {
puMoveToLast(_object);
}
std::string FGPUIDialog::getName()
{
return _name;
}
void
FGPUIDialog::updateValues(const std::string& objectName)
{
@ -833,6 +847,9 @@ FGPUIDialog::display (SGPropertyNode *props)
// configuration file or from the layout widget.
_object = makeObject(props, screenw, screenh);
//if (_object->getParent())
// _object->getParent()-> //setActiveCallback(FGPUIDialog_active_callback);
// Remove automatically generated properties, so the layout looks
// the same next time around, or restore x and y to preserve negative coords.
if (userx)
@ -880,7 +897,7 @@ FGPUIDialog::makeObject (SGPropertyNode *props, int parentWidth, int parentHeigh
if (props->getBoolValue("modal", false))
obj = new puDialogBox(x, y);
else
obj = new fgPopup(x, y, resizable, draggable);
obj = new fgPopup(this, x, y, resizable, draggable);
setupGroup(obj, props, width, height, true);
setColor(obj, props);
return obj;
@ -1084,7 +1101,6 @@ FGPUIDialog::setupObject (puObject *object, SGPropertyNode *props)
object->setLabelPlace(PUPLACE_CENTERED_RIGHT);
object->makeReturnDefault(props->getBoolValue("default"));
info->node = props;
if (props->hasValue("legend")) {
info->legend = props->getStringValue("legend");
object->setLegend(info->legend.c_str());

View file

@ -100,7 +100,9 @@ public:
void setNeedsLayout() {
_needsRelayout = true;
}
virtual std::string getName();
virtual void bringToFront();
class ActiveWidget
{
public:
@ -164,6 +166,7 @@ private:
std::string _module;
SGPropertyNode_ptr _nasal_close;
std::string _name;
// PUI provides no way for userdata to be deleted automatically
// with a GUI object, so we have to keep track of all the special
// data we allocated and then free it manually when the dialog

View file

@ -59,6 +59,8 @@ public:
*/
virtual void update () = 0;
virtual std::string getName() { return std::string(); }
virtual void bringToFront() {}
protected:
/**
* Construct a new GUI widget configured by a property tree.

View file

@ -201,16 +201,20 @@ bool
NewGUI::showDialog (const string &name)
{
// first, check if it's already shown
if (_active_dialogs.find(name) != _active_dialogs.end())
return true;
if (_active_dialogs.find(name) != _active_dialogs.end()){
_active_dialogs[name]->bringToFront();
return true;
}
// check we know about the dialog by name
if (_dialog_names.find(name) == _dialog_names.end()) {
SG_LOG(SG_GENERAL, SG_ALERT, "Dialog " << name << " not defined");
return false;
}
_active_dialogs[name] = new FGPUIDialog(getDialogProperties(name));
fgSetString("/sim/gui/dialogs/current-dialog", name);
// setActiveDialog(new FGPUIDialog(getDialogProperties(name)));
return true;
}
@ -289,6 +293,9 @@ NewGUI::getDialog (const string &name)
void
NewGUI::setActiveDialog (FGDialog * dialog)
{
if (dialog){
fgSetString("/sim/gui/dialogs/current-dialog", dialog->getName());
}
_active_dialog = dialog;
}