Close a WebDialog, THEN execute ruby code?
-
Greetings users! I have quite a specific conundrum that I could use help solving.
I'm writing a ruby script that deals with importing ESRI shapefiles and related imagery. long story short, I need file paths to several different folders (Input_Dir, Output_Dir, Texture.jpg, etc) Instead of bombarding the user with four+ UI.openpanel calls, I've created a WebDialog which uses several <input type='file'>.
after the user presses Ok I gather all the file paths from the inputs through dialog.get_element_value('element_id') and call the rest of my code. This is where my issue occurs:
I am unable to load the texture file. no error is passed but the texture is blank. Through experimentation I realized that if the texture is 'opened' in the WebDialog and I try to that texture to a material through sketchup normally (not through ruby) Sketchup states that it is unable to load the file. After I close the dialog I am able to import the texture image. Is there a way I can close the webdialog, and afterwards execute the rest of my code? I didn't notice any Observers related to webdialogs.
Thank you ahead of time for considering my predicament!
-
dialog.set_on_close { #do stuff here.. } ?
-
The
set_on_close
block was not being run on the Mac. Not sure if this was ever fixed. -
Thanks, good to know!
-
@driven said:
@dan rathbun said:
The
set_on_close
block was not being run on the Mac. Not sure if this was ever fixed.totally pointless, but not technically broken...
It has always run, but you rarely see it's actions as it fires when you close SU, not the dlg, which is possibly a little late...
To see it running you need to interrupt SU's closing with unsaved changes and have an set_on_close alert that will fire...
on a mac both
dlg.execute_script('window.blur;')
anddlg.execute_script('window.focus;')
do work [from a script]...If you are 'finished' with your dlg, just add a
dlg.close
to your callback, anddlg.bring_to_front
to get it back later...john
Are you guys certain about that? I used set_on_close successfully to detect a WebDialog closing under SU8 on Mac and Windows - the dialog, not the whole SU app. Haven't tested this under 2014 as the plugin that used it is no longer necessary, but...
Like this:
within the definition of the class that owns the WebDialog:
class Foo # code that creates WebDialog @dlg, populates it, and gives it other callbacks # and assigns something to @value def add_close_callback() @dlg.set_on_close() { begin yield(@value) rescue Exception => e puts "On close error;\n #{e.class} -> #{e.message} end } end end
Then elsewhere in the code, something like
foo = Foo.new foo.add_close_callback() {|val| puts val}
Steve
-
your right [again]
I was sure I had re-tested this recently so didn't...
There was a problem with it in the past, but...
dlg = UI;;WebDialog.new('TB', false,'tlbs', 36, 600, 2, 2, false) dlg.show_modal dlg.set_on_close { puts "Set on close fired." } # => true # => Set on close fired. # from close button dlg.bring_to_front # => #<UI;;WebDialog;0x59d7100> dlg.close # => Set on close fired. # =>nil
I'll edit my post above...
john
-
@dan rathbun said:
The
set_on_close
block was not being run on the Mac. Not sure if this was ever fixed.EDIT: removed what was erroneous content, as Steve points out below, it does indeed now work on a mac...
I was sure it was still wrong...
john
-
I attempted the set_on_close method, and it kept the dialog box open until the method within the set_on_close call had finished. it seems to run it's code block and then close the dialog box, instead of vice versa.
After a long drive I've decided to replace the type=file input with a button that calls UI.openpanel from ruby, and then returns the path that sketchup provides back into a text field in the webDialog. I just tested it and it solves the problem! Thank you all for your timely responses.
Thomas
-
@tompendergrass said:
I attempted the set_on_close method, and it kept the dialog box open until the method within the set_on_close call had finished. it seems to run it's code block and then close the dialog box, instead of vice versa.
After a long drive I've decided to replace the type=file input with a button that calls UI.openpanel from ruby, and then returns the path that sketchup provides back into a text field in the webDialog. I just tested it and it solves the problem! Thank you all for your timely responses.
Thomas
You are correct. This behavior is consistent with the paradigm of "on close" events in many other frameworks, but is not mentioned in the SU API docs. The callback is really "about to close" rather than "was closed". I suppose this is so that the callback can access window attributes before they are destroyed, or maybe release other resources held by Ruby.
In the case of a SketchUp WebDialog, the anticipation isn't really needed because the WebDialog object actually persists until the last Ruby reference to it is cleared and the Ruby garbage collector runs (which can be some time later unless you explicitly invoke it). In other words, WebDialog#close really means "hide" not "destroy". John's example code illustrates this point: he is able to bring_to_front the dialog after it was previously closed! You can continue to access the WebDialog from Ruby after it is closed so long as you hold a reference to it.
In any case, as you found, this means that the set_on_close Ruby code block needs to finish its work quickly and return, else SU will stall with the WebDialog still visible. The most common use is as an abort/cancel for your tool that activates the selection tool in SU (which makes sense because the user might have closed the dialog by clicking on the frame close button!). Don't invoke #close from within the set_on_close block in an attempt to clear the screen - this will create an endless loop that will block SU until it exhausts the stack and BugSplats!
In particular, this isn't the way to return control to Ruby permanently when the WebDialog closes. Instead, invoke a javascript callback to an skp: handler in which you close the WebDialog and continue with Ruby. On a PC this will leave javascript waiting for return because it is synchronous, but if you are done with the WebDialog you really don't care.
Steve
-
I would like to resume this old thread. I have the same issue with Mac OS X Mavericks and SU2015; the
set_on_close
callback is never triggered until the whole SketchUp application is closed. It seems that callingdlg.close
or clicking on the "x" button, on Mac OS X, hides the dialog rather than actually closing it. Therefore, the theset_on_close
callback is never triggered until SketchUp application is closed, because when SketchUp is closed all associated WebDialogs close as well).Furthermore, when the WebDialog is closed, on Mac OS X, it seems that all the JavaScript still keeps running (until SketchUp application is closed). As an example, an interval timer still keeps running after the webdialog is closed.
The JS window.unload event never gets called either (until SketchUp application is closed).
I wonder if there is a way to actually close a WebDialog on Mac OS X rather than "hiding" it.
Edit: The
set_on_close
callback is triggered if the dialog was originally opened using thedlg.show
method. Still though all interval timers keep running and the window.unload event doesn't gets called.Edit 2: I noticed that assigning
set_on_close
event after callingdlg.show
/dlg.show_modal
rather than prior to, does make it work on Mac OS X. That's what probably slbaumgartner and driven meant in the prior posts. -
I did some workaround on this behavior by adding an event listener on the dialog box via JS. This way the callback will be triggered.
window.addEventListener("beforeunload", function (e) { sketchup.focus_dialog() }, false);
@dlg.add_action_callback('focus_dialog') do |ac| @dlg.bring_to_front end
Advertisement