• Login
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
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.
  • T Offline
    TomPendergrass
    last edited by 6 May 2014, 23:00

    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
    • J Offline
      jolran
      last edited by 7 May 2014, 06:30

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

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 7 May 2014, 08:05

        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
        • J Offline
          jolran
          last edited by 7 May 2014, 09:01

          Thanks, good to know!

          1 Reply Last reply Reply Quote 0
          • S Offline
            slbaumgartner
            last edited by 7 May 2014, 12:53

            @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 7 May 2014, 13:33

              @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 7 May 2014, 13:37

                @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
                • T Offline
                  TomPendergrass
                  last edited by 7 May 2014, 15:55

                  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 7 May 2014, 20:19

                    @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 10 Jul 2016, 00:52

                      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 28 Jun 2020, 01:24

                        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