Thumbnail Cache for HtmlDialog with many images?

I’m playing with an HtmlDialog content browser in SketchUp which extracts the thumbnail images from .skm and .style files using RubyZip, then adds them to the dialog to allow users to select them.

What’s the best way to handle the images? Should I try to cache the thumbnails on disk so as not to have to extract them every time the user browses the materials? Or maybe base64 encode the image directly from the UnzipStream and add the encoded string to a data URI in an img tag? Something else?

On Windows, they should already be (after display) in the “Temporary Internet Files” folder if you’ve loaded them into a webpage.


But on Windows I am seeing SKM thumbnails generated by “thumbsup.dll”.

I thought that Windows usually stores the file thumbnails in hidden zip database files, so it doesn’t have to regenerate them ?

I’d say you could do similar beneath your extension folder.
Either zipped folders or not, your choice.


FYI, This works in MSIE WebDialog.

dlg = UI::WebDialog::new("Test")

dlg.set_url('file://C:\Program Files\SketchUp\SketchUp 2016\Materials\Brick, Cladding and Siding')

dlg.show

Then, right click and choose View > Large Icons


Does it in Chromium ?

Hmmm, I guess not, no simplified view of thumbnails on context menu, and no built-in rendering of sortable & filterable columns in details mode. (Maybe a Chrome extension ?)

I extract the images in one of my mac plugin using the builtin unzip as it’s faster…

but I also found the ‘thumbnails’ for textures poor so I dig deeper and save them in my own folders…

@files.each do |file|
                path = File.join( @color, File.basename(file, '.skm'))
                path = File.join( @texture, File.basename(file, '.skm')) if is_texture(file)
                  %x( unzip "#{file}" -d "#{path}")
                  tex = %x(find "#{path}"/ref/*.*[gf]).chomp!
                  img = File.join(path,'doc_thumbnail.png')
                  if  tex == nil
                    img_batch(file, img)
                  else
                    tex = tex.split("\n")[0] if tex.include?("\n")
                    img_batch(file, tex)
              end # if is_texture(file)
              next
            end

for the SU ones I process once and keep the files, but I re-scan the ‘User’ folders looking for updated content only…

seem fast enough in a WebDialog…

with the HtmlDialog being written to a tmp file by SU, I’m not sure Session Storage will help as they seem to be cleared…

john

Thanks to both of you for the feedback.

I was able to test directly encoding the thumbnail to base64 from the Zip InputStream, and it works sufficiently fast enough that performance is not a concern. I load an initial 20 items immediately, then “timer-in” the rest at a rate which keeps the dialog responsive. It works nicely.

Not caching the thumbnails on disk will work out better because otherwise I may have needed to write a cache manager to keep the thumbnails updated and synchronized.

hei @jim_foltz, I stumbled upon your topic and your gif with the material being selected puzzled me a lot. I am trying to do something in a sense of a material selector using an HtmlDialog, but I cannot find a way to translate the click on something inside the dialog (which is an html + js) into selecting one material in particular. I couldn’t find actually a way at all into coding the act of clicking on something being translated into setting the paint bucket tool being set into the mouse. If that is not a problem, could you explain to me how to do that, even if in a high level? Thank you so much in advance!

Your HTML elements can be image buttons or image elements whose onClick is set to fire a javascript function passing it’s name. (You must know it’s name as it was passed into the HTML from the Ruby-side.)

<img src="some/path/to/some_name_thumbnail.jpg" onclick="paint('some_name');">

The javascript function will send the name back to the Rubyside …

function paint(matl_name) {
    sketchup.paint(matl_name);
}

Your Ruby HtmlDialog would already have a callback created named “paint” that expects the name of a material.

@dlg.add_action_callback("paint") {|_unused, matl_name|
  materials = Sketchup.active_model.materials
  if !materials[matl_name]
    materials.load(@matl_path[matl_name])
  end
  materials.current= materials[matl_name]
  Sketchup.send_action("selectPaintTool:")
}

The above callback assumes you’re code has a hash (@matl_path) of material filepaths keyed by their material names.


The real trick is to transfer focus from the web dialog to the main SketchUp application window.
There is no API method to transfer focus, so some hack has to be used. This has been covered in other topic threads. (Try a search of this category.)

UPDATE: With the SketchUp 2021.1 release the API received the Sketchup.focus() method.

1 Like

hei, thank you for the reply! I will have a try at it.

Hi @andre_cb

I don’t really remember but I’m almost sure I used an onclick event as Dan wrote. I was going to post the example code but unfortunately can not find the files on my computer. You can make nearly anything in HTML “clickable” simply by attaching on onclick event.

1 Like