sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    Close a WebDialog, THEN execute ruby code?

    Scheduled Pinned Locked Moved Developers' Forum
    11 Posts 7 Posters 9.9k Views 7 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • TomPendergrassT Offline
      TomPendergrass
      last edited by

      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!

      1 Reply Last reply Reply Quote 0
      • jolranJ Offline
        jolran
        last edited by

        dialog.set_on_close { #do stuff here.. } ?

        1 Reply Last reply Reply Quote 0
        • Dan RathbunD Offline
          Dan Rathbun
          last edited by

          WebDialog#close()

          The set_on_close block was not being run on the Mac. Not sure if this was ever fixed.

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • jolranJ Offline
            jolran
            last edited by

            Thanks, good to know!

            1 Reply Last reply Reply Quote 0
            • S Offline
              slbaumgartner
              last edited by

              @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;') 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:

              
              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

              1 Reply Last reply Reply Quote 0
              • D Offline
                driven
                last edited by

                @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

                learn from the mistakes of others, you may not live long enough to make them all yourself...

                1 Reply Last reply Reply Quote 0
                • D Offline
                  driven
                  last edited by

                  @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

                  learn from the mistakes of others, you may not live long enough to make them all yourself...

                  1 Reply Last reply Reply Quote 0
                  • TomPendergrassT Offline
                    TomPendergrass
                    last edited by

                    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 Reply Last reply Reply Quote 0
                    • S Offline
                      slbaumgartner
                      last edited by

                      @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

                      1 Reply Last reply Reply Quote 0
                      • A Offline
                        Anton_S
                        last edited by

                        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.

                        1 Reply Last reply Reply Quote 0
                        • M Offline
                          marcosyu26
                          last edited by

                          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
                          
                          
                          1 Reply Last reply Reply Quote 0
                          • 1 / 1
                          • First post
                            Last post
                          Buy SketchPlus
                          Buy SUbD
                          Buy WrapR
                          Buy eBook
                          Buy Modelur
                          Buy Vertex Tools
                          Buy SketchCuisine
                          Buy FormFonts

                          Advertisement