How to hide or dock HtmlDialog? Is c extension only the solution?

I have been creating a plugin for a few months that is a Htmldialog application. There are 2 features important to it, but seem not available yet in Htmldialog api:

  1. Hide the Htmldialog. The Htmldialog window can be closed or brought to front, but not hidden. It is not convenient, because the page has to be loaded when it is re-opened every time.

  2. Dock the Htmldialog. I read the add-abilitity-to-dock-htmldialogs. The feature has not been implemented yet.

I would like to turn to c/c# extension for the 2 features above. But I do not know where to start with? Thanks for any suggestions.

1 Like

If you have already the two problems above, don’t you think moving to C/C# without experience will rather create more problems than less?

That depends on how you close it. As far as I’m aware, close hides the dialog so that it can be reshown any number of times as long as you keep a reference to it (instead of creating a new dialog every time, which needs to reload the page). However if you don’t keep a reference, the dialog will be garbage collected and removed from memory.

How to keep the reference? I create the Htmldialog:

dialog = UI::HtmlDialog.new({...})

And close it with:

dialog.close

Use Instance Variables:

@dialog = UI::HtmlDialog.new({...})
@dialog.show
@dialog.close

# code
# code....

@dialog.show
1 Like

Just in case if you have not seen yet:

" The #visible? method is useful to tell if the dialog is shown and still alive, if the dialog is minimized or not visible on the screen this will still return true ."

I believe that 1 of the window styles allows the dialog to go behind the application window.

:wink: proof:

UI::HtmlDialog::STYLE_DIALOG
HtmlDialog stays at the top of SketchUp.

UI::HtmlDialog::STYLE_WINDOW
HtmlDialog can go behind SketchUp and doesn’t disappear when SketchUp looses focus.

UI::HtmlDialog::STYLE_UTILITY
HtmlDialog is shown with small titlebar and stays on top of SketchUp.

1 Like

Here’s quick test module:

module Testing

  extend self

  @dialog = nil if !defined?(@dialog)

  def go
    if @dialog.nil?
      create_dialog()
    elsif !@dialog.visible?
      attach_callbacks()
      @dialog.show
    else
      front()
    end
  end

  def behind
    Sketchup.focus
  end

  def front
    @dialog.bring_to_front
  end

  private

  def attach_callbacks
    @dialog.add_action_callback("Dummy") {|_, params|
      puts "Dummny callback"
    }
    # ... more callbacks ...
  end

  def create_dialog
    @dialog = UI::HtmlDialog.new(
      dialog_title: "Dialog Example",
      preferences_key: "Dialog Testing",
      scrollable: true,
      resizable: true,
      width:  600,
      height: 400,
      left:   100,
      top:    100,
      min_width:  50,
      min_height: 50,
      max_width:  1000,
      max_height: 1000,
      style: UI::HtmlDialog::STYLE_WINDOW
    )
    @dialog.set_url("http://www.sketchup.com")
    attach_callbacks()

    @dialog.show
  end

end

(… scroll to see all code …)

It is likely dangerous to attempt to dock any custom windows in SketchUp’s tray by any means, as SketchUp’s shutdown cycle is not expecting any other inspector panels but it’s own when saving the window metrics.
Ie, the entries in the registry where SketchUp saves the tray setups might become corrupted, and the subsequent startups may fail. (Ie, SketchUp crashes when loading.)

If you look at the GUI interface for manipulating the trays and panels, you’ll see that the list of inspectors is hardcoded and is a set of checkboxes, not a scrollable list that is enumerated and displayed. (Meaning there is no current expectation for custom inspector panels to exist.)

It is best to work within what the API allows. Going “outside the bounds” can get your extension rejected from the Extension Warehouse.

For info, this does not work so simply.

Before you call @dialog.show the second time, you have to set again its HTML content and its callbacks (and as a consequence reprocess the whole logic of creation). So it’s pretty much equivalent as to recreate the dialog.

Here is a piece of code showing it

def test_close
	#HTML content
	html_text = ''
	html_text += %q(<!DOCTYPE HTML>)
	html_text += %q(<META http-equiv='Content-Script-Type' content='text/javascript'>)
	html_text += %q(<META http-equiv='Content-Type' Content='text/html; charset=UTF-8'>)
	html_text += "<button onclick='sketchup.onclick()'>Click to Close the dialog</button>"
	
	#Creating the HtmlDialog
	hsh = { :dialog_title => 'Test close HtmlDialog', :preferences_key => 'close' }
	wdlg = UI::HtmlDialog.new hsh
	wdlg.add_action_callback("onclick") do |action_context, p1, p2| 
		wdlg.close
		UI.start_timer(1) { wdlg.show }
	end	
	wdlg.set_html html_text
	wdlg.show
end	

If you run it, the dialog appears empty the second time it is ‘shown’.

2 Likes

I agree on it!

However I have a simple example where it works as simple as it is… :wink:

simlehtmlexample

:beers:

1 Like

There must be a different treatment for set_url.

The fact is that the dialog does not retain its HTML content and callbacks when it closes.

In the Ruby Console:

wdlg = UI::HtmlDialog.new
wdlg.set_html "Hello World"
wdlg.show

image

Then close the dialog and execute

wdlg.show

The dialog box is empty.

image

2 Likes

And again, it is true! :+1:

BUT: :innocent:

Oh…hoo. Interesting. Yes. As well as for set_file… it will still “keep the reference” similar as the set_url :thinking:

Try with this simple test.html:

<!DOCTYPE html>
<html>
Hello
</html>
@wdlg = UI::HtmlDialog.new
@wdlg.set_file("c:/test.html")
@wdlg.show

@wdlg.close

@wdlg.show

It will still open the dialog containing the test.html. Does not matter if you close it manually or with .close (I just tried with instance variable if it is matter in this regards… but not)

1 Like

Funny thing is that set_html does somehow work on Mac, except there is a glitch on the redisplay (the body is shifted down).

Anyway, the API has a problem because

  • if method close means hide, then we must make sure that there is no reference left to the dialog so that it is garbaged.
  • a method hide should be more explicit, in addition to a method close that would do a true discard of the dialog.
2 Likes

When Sketchup focus, the window will go behind. That is not my intention. I want to manipulate models on Sketchup and keep the plugin window on top of Sketchup.

I tried @dialog.close and @dialog.show. But the second @dialog.show still loads html page again, instead of simply restores the window. So @dialog.close is not hiding the window, it is not keeping the html content of the page.

Then you have to use one of the other two mentioned in my post. ( UI::HtmlDialog::STYLE_UTILITY or UI::HtmlDialog::STYLE_DIALOG)

1 Like

Yes we discussed this above.

You can use the “combination” of
UI::HtmlDialog::STYLE_WINDOW opttion
Sketchup.focus
.bring_to_front
instead. Dan prepared a very nice example for you in the post#8

Docked HtmlDialogs/custom panels have been requested by numerous developers and it is something we have on our radar. It’s not as trivial to implement though as it may seem, as it needs to be coordinated with the UI/UX work in SketchUp both today and for years to come in the future.

For the time being, maybe it’s possible to move the window outside of the screen, or change its size like Open Cutlist is doing (I’d recommend to change the size vertically though and keep the title bar wide enough for the window to be moved also when collapsed).

2021-08-10_10h36_32

1 Like

In both cases the dialog object “knows” the reference to a resource that it can reload automatically.

The dialog object should also “know” what the html text property is so it can be reloaded (same as for the other 2 content setter methods.) If this does not work the same on Windows then please file a bug report for #set_html (and also mention the body shift for Mac.)

@dialog.set_on_closed {
  save_state()
  @dialog = nil
}

I had this in my above example, but removed it as I thought it would confuse the issues discussed.

Not quite sure, but I think I agree here that if close is already destructive why not garbage collect the object ? Maybe the method cannot be changed now… if this is the case, then perhaps a new destructive #destroy method ?

On the Windows GUI, “hide” a window means minimize (to the task bar.)
Yes, it would be nice to have a method to minimize the window (and restore) a dialog window.

(Hint, hint … feature request in the tracker.)

1 Like