How to pass information from the popups?

Hi all
I am replacing system.gui.messagebox() and system.gui.confirm() calls which are bad because they are blocking the thread in which they are working. This is not acceptable in most cases.

To replace system.gui.messagebox() is not a problem because i created custom popup to display title and message -VERY EASY

To replace system.gui.confirm() i created a function which opens custom popup. Now i have some mental block as i am not sure how to pass the value from 2 buttons - yes or no passing 1 or 0 to the calling function. Do I need to create custom property in my custom popup and read the value from the function which displays the custom popup?

Could you please help me ?

I didn’t make this but there is something like this on my project. The way it was made -

Feed the Main Window path to the popup as a parameter.

In the popup, if something is confirmed, then you can do a system.gui.getWindow(mainWindowPath), get the root container from there, and change a custom property indicating something was confirmed (or denied).

Then you would need a root container property change to catch this and do something with the response.

It’s kind of ugly tbh but it works.

1 Like

Thanks for reply.
I am using a function which when called displays the popup with 2 buttons. Can your solution me modified to return the value from the popup to return the value to the calling function?

I don’t think so unfortunately.

Alternatively, you might be better off with a message handler. If I as making this from scratch I would probably go with a message handler route tbh.

You’re MainWindow opens up the popup and the script ends there. Then the response from the popup yes or no, is sent to a client message handler which then does things on your main window. You could make a generic message handler that then calls a certain function depending on the mainWindow parameter of the popup (which of course must be provided to the message handler as well).

But if you want to be able to do something like this in your submit button

# some stuff

# custom.confirmation opens some popup window
if custom.confirmation("someMainWindow", "some question to get an answer to"):
     # then do other stuff

with your custom popup - I think the answer is no. I think you necessarily need to block the thread to be able to write it like that.

I’m also very biased though and hate having any business logic on any gui components and I would encourage you to do the same as it is an AntiPattern of the Magic Pushbutton variety. I would put all the logic for this window into a project scripting library. Then when a button is clicked to trigger your popup (or whatever triggers it) - this would be my first function in the library that opens your popup. My second function would be the message handler response from that popup. This way I don’t need to go to a window (or multiple windows), and then message handlers to get a full picture of what is going on - I just need to go to my scripting library for that main window and read downwards. Makes debugging much easier imo.

1 Like

thanks a lot for your time but i am using vision only area so message handlers are not availabe. Do you have any guidance for that please?

My advice applies to vision. You should see Client message handlers - that’s what you would want to use.

ok i will double check thanks

In Vision, you can use .putClientProperty() on the popup window to stash a callable for the OK button to use. That callable can be a custom method on a component in the calling window, or a runtime defined function with suitable closures/default arguments.

2 Likes

Thanks for reply but i am bit lost.
Did you mean to create custom property on the root container of the popup “.putClientProperty()” or is this something else. Please provide bit more steps if you can

Not a custom property in Ignition. .putClientProperty() is provided by Java Swing for all JComponents, which includes Vision Windows. This action is runtime transient–nothing serializes these, and the value can be any java/jython object.

So, in the caller (a button’s actionPerformed event, perhaps):

def onThisOK(ev=event):
	# do something with caller's event as 'ev', then
	ev.source.enable = True
w = system.nav.openWindow("path/to/popup")
w.putClientProperty('onOK', onThisOK)
event.source.enable = False

In the popup window’s OK button actionPerformed:

w = system.gui.getParentWindow(event)
callable = w.getClientProperty('onOK')
if callable:
	callable()
system.nav.closeWindow(w)

If you need it, you can make your Cancel button accept a callable, too. If the caller doesn’t set it, the button will do nothing. You might want it to re-enable the caller’s button.

Note that the caller can use system.nav.openWindowInstance() instead of openWindow, and the window instances will be connected to the correct operations.

4 Likes

your example is very educational for me and i did try it out. Thank you for that.
However i am wondering if for my simple case of YES/NO popup which needs passing 1 or 0 to the external code maybe using int client tag be good enough ? or would it be a bad practice to create another tags and should be avoided…?

Using a client tag is fine. But most cases you then need a change script that runs when the client tag is updated. So you don’t escape the need for a separate script to run when the popup closes.

1 Like

I am still struggling with this simple popup …
i am trying to replace system.gui.confirm which according to my understanding should not be used because if several clients are used at the same time then one can block the operation of the others without any feedback what is going on.

Existing code behind the button would use “if system.gui.confirm” and based on the answer continued to the IF or ELSE section of the code.
I am trying to use WHILE loop in the modified code instead of IF but the new popup has to provide the condition to break the WHILE loop so the plan is to use YES or NO buttons to change client tag to the value of 1 or 0 which SHOULD brake the WHILE loop.

The problem i am struggling now is how to break the WHILE loop - reading the tag value in the loop freezes the client so i guess there must be a smarter way to do it :slight_smile:

Any chance for some pointers about how to update the break condition in WHILE loop so the rest of the code can continue?

You simply cannot continue with the answer in the same script. It MUST be a separate script that handles the answer. The original script must end. The fundamental reason for the lockup is the script not ending. There is no 1-for-1 replacement for those system.gui.* functions.

3 Likes

i hit my head with rubber hammer and things finally clicked in :slight_smile:
I understand now i was trying to do the impossible thing using just one script - you understood my problem very precisely
I implemented your solution and it works beautifully
Thanks again for your help - i wish forum had some function to send you a tip :slight_smile:

1 Like

@pturmel would be a rich man if this was a feature

1 Like

Ooooo! I should go put a PayPal tip button on my website...

6 Likes