Web/Html Dialog "Message box like"

Hi all,

I have a simple problem that I cannot solve. In one of my plug-in, I had a message box displaying a quite simple content: the version of my plug-in and some other textual information. It was perfect except that now I have to include the logo of my company and I cannot do that in a message box (or I missed something in the doc).

So I thought of creating a Web or Html Dialog but I am lost. My main problem is that I can’t find a way to create a button, displaying “OK” and just closing the dialog. I tried to create a button and using the javascript method to close the window but… it does not close the dialog.

I tried to work from an example I thought I had understood but… not at all (and I read some doc too). Could someone help me creating a dialog that just displays an image, some text and closes itself when I click on the “OK” button ?

Thanks a lot and have a good day :slight_smile:

This suffices for a simple dialog. If your requirements grow, you would save the html string into a file and load it with set_file, then move the JavaScript call from inline into a <script> block or a separate file (same for styles), etc.
See here for the documentation.

def show_my_messagebox(message, title)
  properties = {
    :dialog_title => title,
    :scrollable => false,
    :width => 300,
    :height => 350
  }
  html = <<-HTML
  <html>
    <body>
      <img src="https://www.sketchup.com/themes/sketchup_www_terra/images/SU_FullColor.png" width="100%" />
      <h1>#{title}</h1>
      <p>#{message}</p>
      <div style="text-align: center">
        <button onclick="window.sketchup.close()">Close</button>
      </div>
    </body>
  </html>
  HTML
  dialog = UI::HtmlDialog.new(properties)
  dialog.set_html(html)
  dialog.add_action_callback('close') { |action_context|
    dialog.close
  }
  dialog.center
  dialog.show_modal
end

show_my_messagebox("You are using SketchUp #{Sketchup.version} with Ruby #{RUBY_VERSION}", "Hello SketchUpper!")
1 Like

the basics…

dialog = UI::HtmlDialog.new(
{
  :dialog_title => "Dialog Example",
  :preferences_key => "com.sample.plugin",

 # :scrollable => true,
 # :resizable => true,
  :width => 60,
  :height => 40,
 # :left => 100,
 # :top => 100,
 # :min_width => 50,
 # :min_height => 50,
 # :max_width =>1000,
 # :max_height => 1000,
  :style => UI::HtmlDialog::STYLE_DIALOG
})
dialog.add_action_callback('close_dialog'){dialog.close}
dialog.set_html("<input type='button' value='OK' onclick='sketchup.close_dialog();'>")
dialog.center
dialog.show
1 Like

Gosh, how could I miss something so simple ? I guess I was puzzled by the whole HTML/Java thing and the link with the Sketchup callbacks (I don’t know anything about it). As you said John, the basics :wink:

But now I understood some things and I should be able to do Web/Html Dialogs.

So thanks a lot to you boths for your clear examples and for taking some time to help me :slight_smile:

Have a good day :slight_smile:

And you even don’t need to install a Java virtual machine (JRE or JDK) because HtmlDialogs use simple JavaScript (unrelated to Java).
And SketchUp comes with everything included (right-click in an HtmlDialog and choose “Developer Tools”).

Thanks :slight_smile:

Hi again,

Well thanks to your help, I could finish my HtmlDialog and it now looks fine. But the plug-ins I maintain must work for all versions of SketchUp, including versions prior to 2017. So I also needed to create a WebDialog for older versions. So I read the documentation, saw that there were differences and tried to do a WebDialog from the HtmlDialog you showed me. And I almost succeeded… except that my callback function is never called…

My function now looks like this:

def self.about
@OSE_SKP_WB_VERSION = ENV[“OSE_SKP_WB_VERSION”]
# you never know…
if @OSE_SKP_WB_VERSION.nil? then
@OSE_SKP_WB_VERSION = 2019
end
directory = Sketchup.get_resource_path “Styles.strings”
@iconPath=“"#{directory[0,(directory.length-15)]}/…/…/Tools/SE-FFT-2SKP/hd_converter.ico"”
versionNumber = Sketchup.version_number
if versionNumber < 1700000000 then
@cbCall = “"skp:close"”
else
@cbCall = “"window.sketchup.close()"”
end

	html = <<-HTML
	<html>
		<body>
			
			<table>
				<col width="100">
				<col width="300">
				<tr>
					<td>
						<img src=#{@iconPath} width="70%" />
					</td>
					<td>
						<h1 style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">SE-FFT SketchUp plug-ins</br></h1>
						<p style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">Version #{@OSE_SKP_WB_VERSION}</p>
						<p style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">OKTAL Synthetic Environment - www.oktal-se.fr</p>
					</td>
				</tr>
			</table>
			
			<div style="text-align: center;margin-top: 10px;">
			<button onclick=#{@cbCall}>Close</button>
			</div>
			
		</body>
	</html>
	HTML

	@dlg_height = 160
	@dlg_width = 400
	if versionNumber < 1700000000 then
		model = Sketchup.active_model
		view = model.active_view
		height = view.vpheight
		width = view.vpwidth
		@top = ((height - @dlg_height)/2).to_i
		@left = ((width - @dlg_width)/2).to_i
		@aboutDialog = UI::WebDialog.new("About OKTAL-SE SDM plug-ins", false, "AboutOKTALSESDMplugins", @dlg_width, @dlg_height, @left, @top, false)
		@aboutDialog.set_html(html)
		@aboutDialog.add_action_callback('close') { |dialog, params|
			UI.messagebox("callback")
			@aboutDialog.close
		}
	else
		properties = {
			:dialog_title => "About OKTAL-SE SDM plug-ins",
			:scrollable => false,
			:width => @dlg_width,
			:height => @dlg_height
		}	
		@aboutDialog = UI::HtmlDialog.new(properties)
		@aboutDialog.set_html(html)
		@aboutDialog.add_action_callback('close') { |action_context|
			@aboutDialog.close
		}
		@aboutDialog.center
	end
	@aboutDialog.show_modal
end

What do I do wrong in the callback call/function?

Thanks a lot for your help and have a good day :slight_smile:

You should seriously think about whether you need to support versions before 2017:

  • WebDialog is broken and by making your plugin also work with webdialogs, you won’t ever get rid of them. Moreover, HtmlDialog makes developers’ lifes easier, and if that’s a reason for your users to upgrade then it is a very good reason!
  • Statistics say that the majority of Pro users are on recent versions and that the vast majority of plugin users are Pro users.
  • Even hobbiests can install SketchUp Make 2017, which will remain free for non-commercial use and supports HtmlDialog.

If you format code with the </> button (or wrap it into triple backticks ```), it becomes easier to read and the forum software does not apply typography that does not work when copied into the Ruby console.


  • You should avoid using instance variables (@cbCall) at all, unless you use them for persistent state of the class. But then be careful because unpredictable application state is the most common source of bugs that are hard to test and reproduce. In almost all cases it is better to initialize instance variables within the class constructor (except for setter methods).
    Variables that you only use within a certain method should be local variables without @.
  • I’m not sure what you were trying to do (and what was modified by the forum’s typography), but this definitely looks not right, directory parent should be two points, and you seem to have a lot of risky assumptions how the directory path looks like (how can you know you need to slice 15 characters?).
    Look into Ruby’s File.join() and File.dirname() and File.realpath() methods. To get a file path from your plugin’s directory, you can use:
    File.join(__dir__, "hd_converter.ico")
    
    (assuming the Ruby script is in the directory “SE-FFT-2SKP”, as well as the image file.)
  • Quotes around a string are not part of the string (not characters within the string). To escape a string that is embedded into another string with string interpolation, I use String#inspect:
    onclick=#{cbCall} would become onclick=window.sketchup.close()
    onclick=#{cbCall.inspect} becomes onclick="window.sketchup.close()"
  • The .ico file-format is a proprietary image format that is not standardized for use in browsers (although Chromium can render it). Consider using a standard image format like .png or .jpg.
  • Prefer feature-checking instead version-checking: if defined?(UI::HtmlDialog)
  • Style-wise, Ruby programmers use snake_case, not pascalCase for variables and methods.

class MyClass
  def initialize
    @OSE_SKP_WB_VERSION = ENV["OSE_SKP_WB_VERSION"]
    # you never know… …but it's better you can ensure this never happens
    if @OSE_SKP_WB_VERSION.nil? then
      @OSE_SKP_WB_VERSION = 2019
    end
  end

  def about
    icon_path = File.join(__dir__, "hd_converter.ico")
    if defined?(UI::HtmlDialog)
      cb_call = "window.sketchup.close()"
    else
      cb_call = "window.location.href = 'skp:close'"
    end
    html = <<-HTML
    <html>
      <body>
        
        <table>
          <col width="100">
          <col width="300">
          <tr>
            <td>
              <img src=#{icon_path} width="70%" />
            </td>
            <td>
              <h1 style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">SE-FFT SketchUp plug-ins</br></h1>
              <p style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">Version #{@OSE_SKP_WB_VERSION}</p>
              <p style="font-family: Tahoma, Geneva, sans-serif;font-size: 12px;">OKTAL Synthetic Environment - www.oktal-se.fr</p>
            </td>
          </tr>
        </table>
        
        <div style="text-align: center;margin-top: 10px;">
        <button onclick=#{cb_call}>Close</button>
        </div>
        
      </body>
    </html>
    HTML

    dlg_height = 160
    dlg_width = 400
    if defined?(UI::HtmlDialog)
      properties = {
        :dialog_title => "About OKTAL-SE SDM plug-ins",
        :scrollable => false,
        :width => dlg_width,
        :height => dlg_height
      }	
      about_dialog = UI::HtmlDialog.new(properties)
      about_dialog.set_html(html)
      about_dialog.add_action_callback("close") { |action_context|
        about_dialog.close
      }
      about_dialog.center
    else # UI::WebDialog
      model = Sketchup.active_model
      view = model.active_view
      height = view.vpheight
      width = view.vpwidth
      top = ((height - dlg_height)/2).to_i
      left = ((width - dlg_width)/2).to_i
      about_dialog = UI::WebDialog.new("About OKTAL-SE SDM plug-ins", false, "AboutOKTALSESDMplugins", dlg_width, dlg_height, left, top, false)
      about_dialog.set_html(html)
      about_dialog.add_action_callback("close") { |dialog, params|
        UI.messagebox("callback")
        about_dialog.close
      }
    end
    about_dialog.show_modal
  end

end
1 Like

Ruby also has the __dir__ global method for Ruby versions 2.0.0 and later.

Versions of SketchUp (prior to 2014) using Ruby 1.8.x can use File.dirname(__FILE__).

1 Like

To my knowledge this method is heavily discouraged as it requires the extension to run specifically from the Plugins folder. While this often is the case there are valid reasons to have it elsewhere, e.g. in a development folder if you are a developer.

I’m so far using FILE but as Dan says dir is also an option. I’m not sure if any of them has any benefits over the other.

Hi all,

Thanks a lot, especially Aerilius, for your answers ! I feel like my code is very dirty but that with your help I am going to clean it a lot and learn a lot :slight_smile:

It is going to take me a little time to understand all this and clean my code but I sure will do it :slight_smile:

And as for version prior to 2017 : we should be able to drop them one day but we have defense clients who, for safety reasons, always work with last year version of our products or older, while they validate the new vesrion with their own tests, that can take several months. So, for them, we have to maintain old stuff for a while :slight_smile: But fundamentally you’re right :slight_smile:

Thanks again to all of you and have a good day :slight_smile:

help me…how i can change dialog_title by callback ???

hai DanRathbun !!! can i change dialog title by action callback???

No. Once HtmlDialog created, there is no documented method to change it’s title. You must create a new one with a different Option hash with new, desired dialog_title key in it.

BTW: You cannot run an extension or Ruby script in your ‘SketchUp for Schools (web)’ version at all.

1 Like

So…how it work with multiple html page.

If you are asking how to manage multiple HtmlDialogs open at the same time, you can give each a unique title when you create it. What’s missing is ability to change the title later if you load different HTML content into a HtmlDialog. You’d have to show a distinct heading or similar via the HTML content itself.

…and You can #close the dialog if become obsolete if you want.

I also suggest you leave the ‘dialog title’ alone and prefer to enter a title inside the html window that is much easier to change, by Ruby or javascript…
‘Dirty’ example:

dialog = UI::HtmlDialog.new(
{
  :dialog_title => "Dialog Example",
  :scrollable => true,
  :resizable => true,
  :width => 300,
  :height => 200,
  :left => 100,
  :top => 100,
  :min_width => 50,
  :min_height => 50,
  :max_width =>1000,
  :max_height => 1000,
  :style => UI::HtmlDialog::STYLE_DIALOG
})
html_title = '<b>Hello world!</b>'
html = '<br><br>Please tell us what do you want to achieve?'
dialog.set_html(html_title+html)
dialog.show
new_html_title = '<b>Hello SketchUp!</b>'
id = UI.start_timer(5, false) { dialog.set_html(new_html_title+html) }

thank you