I was almost getting it, then found out theres 2 problems:
I can’t rlly trigger the docking time since “onLButtonUp” observer doesn’t seem to work while above an htmldialog.
I could try “onMouseMove” but may flood the API buffer or something?
I can’t get htmldialog position coords:
#<NoMethodError: undefined method `get_position’ for #UI::HtmlDialog:0x00023f47e31d08>
(“.get_position” works on SU2021.1 above, I need SU17 above)
feels like:
Suggestions?
Code:
module Taxsola
module Tax_Engineering
class Dock_Observer
def onLButtonUp(flags, x, y, view)
puts ("LButton Up at [#{x},#{y}]") #Debug
Tax_Engineering.update_html_dock()
end
end
def self.dockable_html
#Default HTML dialog size
@@Default_Html_Width = 200
@@Default_Html_Height = 200
@@Dock_Dialog = UI::HtmlDialog.new({
:dialog_title => "Dockable html dialog",
:preferences_key => "com.sample.plugin",
:resizable => false,
:style => UI::HtmlDialog::STYLE_DIALOG
})
(html = "
<!DOCTYPE html>
<html>
<head></head>
<body>
<h4>
A<br>
dockable<br>
html<br>
dialog<br>
</h4>
</body>
</html>")
@@Dock_Dialog.set_html(html)
@@Dock_Dialog.set_position(100, 50)
@@Dock_Dialog.set_size(@@Default_Html_Width, @@Default_Html_Height)
@@Dock_Dialog.show
model = Sketchup.active_model
view = model.active_view
#ADD OBSERVER
@Dock = model.select_tool Dock_Observer.new
view.add_observer (@Dock)
@@Dock_Dialog.set_on_closed { view.remove_observer(@Dock) } #REMOVE OBSERVER
end
def self.update_html_dock
model = Sketchup.active_model
view = model.active_view
@ViewPort_Coord = view.corner(0) #Get coords of viewport corner #0: top left, 1: top right, 2: bottom left, 3: bottom right.
puts("Viewport at:" + @ViewPort_Coord.to_s) #Debug
@ViewPort_height = view.vpheight #Get viewport height
puts(@@Dock_Dialog.get_position) #Debug (error: '.get_position' method works on SU2021.1 above)
@Html_L_pos, @Html_T_pos = @@Dock_Dialog.get_position
@X_dist = (@Html_L_pos - @ViewPort_Coord)
@Y_dist = (@Html_T_pos - @ViewPort_Coord)
@html_dist = Math.sqrt((@X_dist*@X_dist) + (@Y_dist*@Y_dist))
if (@html_dist < 100)
@@Dock_Dialog.set_position(@ViewPort_Coord)
@@Dock_Dialog.set_size(@@Default_Html_Width, @ViewPort_height)
else
@@Dock_Dialog.set_size( @@Default_Html_Width, @@Default_Html_Height)
end
end
self.dockable_html
end
end
To get dialog coord, I used “window.screenLeft” on js instead of “get_position” on ruby. (should work SU17 above)
Cons:
Used “onMouseMove” observer on ruby and “onmousemove” on html/css
So now its flooding buffer twice, I guess :l
As you said, doesn’t work outside viewport;
The titlebars keeps flickering since its always updating (think I can disable it with a status variable, gonna try);
Dialog doesn’t fit perfectly, so doesn’t look like a well finished UI
It may have some issues when multiple dialogs are open (not tested)
But even so I think it can be useful since user can still use as a side pannel while tweaking the model or something.
The main problem now is that “view.corner(0)” (top left) always return [0,0] local coords so I can’t use it as reference for positioning the dialog on screen.
I used a fixed value that fit my toolbar setup.
Is there a way to get the viewport’s global coords? (up left)
Code:
module Taxsola
module Tax_Engineering
class Dock_Observer
def onMouseMove(flags, x, y, view) #old onLButtonUp
Tax_Engineering.update_html_dock()
end
end
def self.dockable_html
model = Sketchup.active_model
view = model.active_view
@Viewport_X = 0
@Viewport_PlusX = -6
@Viewport_Y = 285 #User relative value. It must be the viewport global screen coord
@Viewport_PlusY = 8
#Default HTML dialog size
@@Default_Html_Width = 200
@@Default_Html_Height = 200
@Titlebar_Offset = 31
@@Dock_Dialog = UI::HtmlDialog.new({
:dialog_title => "Dockable html dialog",
:preferences_key => "com.sample.plugin",
:resizable => false,
:style => UI::HtmlDialog::STYLE_DIALOG
})
(html = "
<!DOCTYPE html>
<html onmousemove='get_coords()'>
<head>
<script>function get_coords() { sketchup.SendCoords(window.screenLeft, window.screenTop); }</script>
</head>
<body>
<h4>
AAA<br>
dockable<br>
html<br>
dialog<br>
</h4>
</body>
</html>")
@@Dock_Dialog.set_html(html)
@@Dock_Dialog.set_size(@@Default_Html_Width, @@Default_Html_Height)
@@Dock_Dialog.set_position( (@Viewport_X + @Viewport_PlusX), (@Viewport_Y-@Titlebar_Offset))
@@Dock_Dialog.show
#OBSERVER SET UP
@Dock = model.select_tool Dock_Observer.new
@@Dock_Dialog.set_on_closed { view.remove_observer(@Dock) } #REMOVE OBSERVER
@@Dock_Dialog.add_action_callback("SendCoords"){|action_context, htmlL, htmlT|
model = Sketchup.active_model
view = model.active_view
@Html_L_pos = htmlL
@Html_T_pos = htmlT
@X_dist = (@Html_L_pos - @Viewport_X)
@Y_dist = ((@Html_T_pos) - @Viewport_Y)
@html_dist = Math.sqrt((@X_dist*@X_dist) + (@Y_dist*@Y_dist))
if (@html_dist < 100)
@@Dock_Dialog.set_position( (@Viewport_X + @Viewport_PlusX), (@Viewport_Y-@Titlebar_Offset))
@ViewPort_height = view.vpheight
@@Dock_Dialog.set_size(@@Default_Html_Width, (@ViewPort_height + @Viewport_PlusY))
else
@@Dock_Dialog.set_size( @@Default_Html_Width, @@Default_Html_Height)
end
}
end
def self.update_html_dock
@@Dock_Dialog.execute_script("get_coords()")
end
self.dockable_html
end
end
Nevermind, better to wait for that built in class/property to make it properly.
Its too glitchy, uses more space and compromises performance.
User can still put it mannually there if he wants to.
I’ve been asking for docking dialogs continuously for 5 years. I think that until that feature is implemented extensions will always seem like a tacked on feature. I’ve been pestering @eneroth3 and @thomthom. They both understand the need, but apparently it’s something that is not trivial to implement.
You can see some of my attempts and discussion in this thread.
It’s something we really want. But it’s deeply tangled into the UI framework and logic of SketchUp itself. And we’re currently looking at some significant overhaul so there’s a lot of moving pieces right now.