This works great, thank you so much @Gijs !
EDIT:
Actually this is even better because now I can use drawable code within the CustomTooltip as well to add things like “icons” or “shortcut symbols”.
Cheers!
EDIT 2:
I noticed the tooltip spawns instantly OnMouseEnter so I added an Eto UI Timer to add a variable delay. Here’s the code:
import Eto.Forms
import Eto.Drawing
import Rhino
class CustomToolTip(Eto.Forms.FloatingForm):
def __init__(self, text):
super().__init__()
self.WindowStyle = Eto.Forms.WindowStyle.NONE
Rhino.UI.EtoExtensions.UseRhinoStyle(self)
self.Resizable = False
label = Eto.Forms.Label()
label.Text = text
self.Padding = Eto.Drawing.Padding(10)
layout = Eto.Forms.DynamicLayout()
layout.AddRow(label)
self.Content = layout
class FloatingForm(Eto.Forms.FloatingForm):
def __init__(self):
super().__init__()
self.Title = "Floating Form with Custom Tooltip"
self.Size = Eto.Drawing.Size(300, 100)
self.Topmost = True
Rhino.UI.EtoExtensions.UseRhinoStyle(self)
# Create a button that will show the tooltip when hovered over
button = Eto.Forms.Button()
button.Text = "Hover over me"
button.MouseEnter += self.ToggleTooltip
button.MouseLeave += self.ToggleTooltip
# Layout setup
layout = Eto.Forms.DynamicLayout()
layout.Padding = Eto.Drawing.Padding(5)
layout.AddRow(button)
self.Content = layout
# Tooltip and timer attributes
self.tooltip = None
self.enabled = False
self.hover_timer = Eto.Forms.UITimer()
self.hover_timer.Interval = 0.75 # add a delay
self.hover_timer.Elapsed += self.ShowTooltip
def ToggleTooltip(self, sender, e):
self.enabled = not self.enabled
if self.enabled:
# Start the UITimer to show the tooltip after delay
self.hover_timer.Start()
else:
# Stop the timer and hide the tooltip if the mouse leaves before the delay
self.hover_timer.Stop()
self.HideTooltip()
def ShowTooltip(self, sender=None, e=None):
# Stop the timer to avoid repeated execution
self.hover_timer.Stop()
# Check if tooltip should be shown and display it
if self.tooltip is None or not self.tooltip.Visible:
self.tooltip = CustomToolTip("This is a Rhino style tooltip")
mouse_position = Eto.Forms.Mouse.Position
self.tooltip.Location = Eto.Drawing.Point(mouse_position.X + 10, mouse_position.Y + 10)
self.tooltip.Show()
def HideTooltip(self):
# Hide the tooltip if it's visible
if self.tooltip and self.tooltip.Visible:
self.tooltip.Close()
self.tooltip = None # clear the tooltip
form = FloatingForm()
form.Show()
EDIT 3:
Unfortunately it seems that Eto.Forms.FloatingForm does not support transparent window styling like so?
It works when using Eto.Forms.Form but not with Eto.Forms.Floating.Form.
@clement is this something you have come across before?
class CustomTooltip(Eto.Forms.Form):
def __init__(self, text, shortcut=None, toolbar=None):
super().__init__()
try:
self.has_shortcut = True if shortcut is not None else False
self.WindowStyle = Eto.Forms.WindowStyle.NONE
# Rhino.UI.EtoExtensions.UseRhinoStyle(self)
# Add transparent style
self.Styles.Add[Eto.Forms.Panel]("transparent", UI.TransparentFormStyler)
self.Style = "transparent"
self.Resizable = False
self.TopMost = True
self.MovableByWindowBackground = False
TransparentStyler:
class UI():
@staticmethod
def TransparentFormStyler(control): # Set the form background to transparent
control.BackgroundColor = Eto.Drawing.Colors.Transparent
window = control.ControlObject
if hasattr(window, "AllowsTransparency"):
window.AllowsTransparency = True
if hasattr(window, "Background"):
brush = window.Background.Clone()
brush.Opacity = 0 # Adjust opacity as needed
window.Background = brush
else:
color = window.BackgroundColor
window.BackgroundColor = color.FromRgba(0, 0, 0, 0)
Thank you all!
EDIT 4:
My current workaround is (instead of drawing the tooltip, background shape, and border path on a form with a transparent background via drawable onpaint code) I actually draw the text only on a FloatingForm with the background color I want and WindowStyle set to None:
This has the advantage of still allowing me to add icons, text, and other graphics while allowing the tooltip to be on top of any other eto.form but is severely limiting in how I can “style” the border/shape itself. I happen to like the current Rhino windows implementation but am I bit uneasy of how it will translate to Mac.
Anyways, thanks for reading if you’ve made it this far