|
| 1 | +module Trimble |
| 2 | + module InteractiveSketchUpRubyAPI |
| 3 | + |
| 4 | + module DocumentationDialog |
| 5 | + |
| 6 | + path = __dir__ |
| 7 | + path.force_encoding('UTF-8') |
| 8 | + PATH = path.freeze |
| 9 | + |
| 10 | + #This is what gets called when the user clicks the Icon - this is where everything really starts. |
| 11 | + def self.open |
| 12 | + options = { |
| 13 | + :dialog_title => "Interactive SketchUp Ruby API documentation", |
| 14 | + :scrollable => true, |
| 15 | + :resizable => true, |
| 16 | + :width => 1100, |
| 17 | + :height => 700, |
| 18 | + :left => 100, |
| 19 | + :top => 100, |
| 20 | + } |
| 21 | + |
| 22 | + @dialog_to_ruby = UI::HtmlDialog.new(options) |
| 23 | + @dialog_to_ruby.set_url("https://ruby.sketchup.com/") |
| 24 | + |
| 25 | + |
| 26 | + # This block gets called every time a page in the API gets loaded. This |
| 27 | + # block is what kicks off the process to re-write all the sample |
| 28 | + # snippets as code editors. |
| 29 | + # What it does is first injects some special css styles into the page. |
| 30 | + @dialog_to_ruby.add_action_callback("page_loaded") { |action_context| |
| 31 | + inject_css(@dialog_to_ruby) |
| 32 | + inject_ace(@dialog_to_ruby) |
| 33 | + } |
| 34 | + |
| 35 | + # This gets called once the html is modified with the new css, the new |
| 36 | + # Ace editor code is injected and accepted. I had tried combining this |
| 37 | + # functionality with the inject_ace method. However when I tried to load |
| 38 | + # the ace.js script at the same time as running this script, it would |
| 39 | + # not work. I think there was a race condition and this script would not |
| 40 | + # find the ace editor js code. So that is why this has to be called |
| 41 | + # completely separately, after ace is completely loaded. |
| 42 | + @dialog_to_ruby.add_action_callback("inject_ace_editors") { |action_context| |
| 43 | + ace_loader_path = File.join(PATH, "resources", "aceloader.js") |
| 44 | + ace_loader_string = IO.read(ace_loader_path) |
| 45 | + @dialog_to_ruby.execute_script(ace_loader_string) |
| 46 | + } |
| 47 | + |
| 48 | + |
| 49 | + # This is what gets called by the editor when the user clicks the |
| 50 | + # "Execute in Sketchup" button. That button sends the string from the |
| 51 | + # editor to this block, which then evals the string in SketchUp. |
| 52 | + @dialog_to_ruby.add_action_callback("htmlDialog_to_ruby") { |action_context, code| |
| 53 | + SKETCHUP_CONSOLE.show |
| 54 | + result = eval(code) |
| 55 | + p result |
| 56 | + } |
| 57 | + |
| 58 | + @dialog_to_ruby.show |
| 59 | + end |
| 60 | + |
| 61 | + # Inject css to the head of the page to stylize the editor divs. This has |
| 62 | + # to happen before we attempt to inject the code editors because they |
| 63 | + # rely on this css. |
| 64 | + def self.inject_css(dialog) |
| 65 | + ace_css_path = File.join(PATH, "resources", "ace.css") |
| 66 | + ace_css_string = IO.read(ace_css_path) |
| 67 | + ace_css_string.delete!("\n") |
| 68 | + |
| 69 | + # This takes the nicely formatted css string and creates the appropriate |
| 70 | + # style element in the html page. Then injects the css into the page so |
| 71 | + # that the editors have some special css that they need. |
| 72 | + dialog.execute_script(%Q~ |
| 73 | + var thehead = document.head; |
| 74 | + var style_wrap = document.createElement('style'); |
| 75 | + style_wrap.innerHTML="#{ace_css_string}"; |
| 76 | + thehead.appendChild(style_wrap); |
| 77 | + ~) |
| 78 | + end |
| 79 | + |
| 80 | + # This injects a script element into the page. It works like this: Once |
| 81 | + # the page is done loading, this script executes the callback defined in |
| 82 | + # this file called sketchup.inject_ace_editors. Read the comments on that |
| 83 | + # callback block to understand how the code editor swap works. |
| 84 | + # Another point to note. Ideally we could have just put this small js |
| 85 | + # script on every page, and removed the initial page_loaded callback. But |
| 86 | + # that would work to replace the code editors on the first page that loads |
| 87 | + # but it would not work on subsequent pages. So that is why I've added |
| 88 | + # a callback that tells the extension that a pages has loaded, then the |
| 89 | + # extension is aware of every time a new page loads, and the extension |
| 90 | + # starts the process of injecting css and js onto the page and swapping in |
| 91 | + # the code editors. |
| 92 | + def self.inject_ace(dialog) |
| 93 | + # The "A" parameter is a red herring. It does nothing. There is/was a |
| 94 | + # bug that required that I pass in something/anything. So I pass in the |
| 95 | + # A, but it is not used, nor does it mean anything. |
| 96 | + dialog.execute_script(%Q~ |
| 97 | + var script = "https://cdn.jsdelivr.net/ace/1.2.3/min/ace.js"; |
| 98 | + var el = document.createElement('script'); |
| 99 | + var body = document.getElementsByTagName("body")[0] |
| 100 | + body.appendChild(el); |
| 101 | + el.onload = function() { |
| 102 | + sketchup.inject_ace_editors("A"); |
| 103 | + }; |
| 104 | + el.src = script; |
| 105 | + ~) |
| 106 | + end |
| 107 | + |
| 108 | + end |
| 109 | + end |
| 110 | +end |
| 111 | + |
| 112 | + |
0 commit comments