close a WebDialog, THEN execute ruby code?

close a WebDialog, THEN execute ruby code?

Postby TomPendergrass » Wed May 07, 2014 12:00 am

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!
0
User avatar
TomPendergrass 
 

Re: close a WebDialog, THEN execute ruby code?

Postby jolran » Wed May 07, 2014 7:30 am

dialog.set_on_close { #do stuff here.. } ?
0
User avatar
jolran 
PluginStore Author
PluginStore Author
 

Re: close a WebDialog, THEN execute ruby code?

Postby Dan Rathbun » Wed May 07, 2014 9:05 am

WebDialog#close()

The set_on_close block was not being run on the Mac. Not sure if this was ever fixed.
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby jolran » Wed May 07, 2014 10:01 am

    Thanks, good to know!
    0
    User avatar
    jolran 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby driven » Wed May 07, 2014 11:59 am

    Dan Rathbun wrote: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
    0
    Last edited by driven on Wed May 07, 2014 2:37 pm, edited 1 time in total.
    learn from the mistakes of others, you may not live long enough to make them all yourself...

    driven 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby slbaumgartner » Wed May 07, 2014 1:53 pm

    driven wrote:
    Dan Rathbun wrote: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;') and dlg.execute_script('window.focus;') do work [from a script]...

    If you are 'finished' with your dlg, just add a dlg.close to your callback, and dlg.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:
    Code: Select all
    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

    Code: Select all
    foo = Foo.new
    foo.add_close_callback() {|val| puts val}



    Steve
    0

    slbaumgartner 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby driven » Wed May 07, 2014 2:33 pm

    @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...
    Code: Select all
    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
    0
    learn from the mistakes of others, you may not live long enough to make them all yourself...

    driven 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby TomPendergrass » Wed May 07, 2014 4:55 pm

    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
    1
    User avatar
    TomPendergrass 
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby slbaumgartner » Wed May 07, 2014 9:19 pm

    TomPendergrass wrote: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
    1

    slbaumgartner 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby Anton_S » Sun Jul 10, 2016 1:52 am

    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 calling dlg.close or clicking on the "x" button, on Mac OS X, hides the dialog rather than actually closing it. Therefore, the the set_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 the dlg.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 calling dlg.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.
    2

    Anton_S 
    PluginStore Author
    PluginStore Author
     

    Re: close a WebDialog, THEN execute ruby code?

    Postby marcosyu26 » Sun Jun 28, 2020 2:24 am

    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.

    Code: Select all
     window.addEventListener("beforeunload", function (e) {
        sketchup.focus_dialog()
      }, false);


    Code: Select all
        @dlg.add_action_callback('focus_dialog') do |ac|
          @dlg.bring_to_front
        end
    0

    marcosyu26 
     

    SketchUcation One-Liner Adverts

    by Ad Machine » 5 minutes ago



    Ad Machine 
    Robot
     



     

    Return to Developers' Forum

    Who is online

    Users browsing this forum: samuelgodjj and 6 guests

    Visit our sponsors: