Thanks @CallumSykes ,
Good to know, and that does make sense!
I still am trying to figure out if there’s a viable way to have a floating viewport with the main eto UI there so in other words…
screen 1 could have vanilla/default Rhino with it’s typical UI
screen 2 (or floating viewport not maximized) would just be a single monolithic viewport with UI on top of it as needed.
In testing the screen 2 version the floating viewport seems to show the Window.Style.Utility (single red X close button)
I can add Eto on top of this and handle close/minimize/maximize in a custom way but I’m curious if one can just set the Window.Style to be .Default on a floating viewport so that you could see the minimize/maximize/and title bar? OR set Window.Style to Window.Style.NONE and then again… have the eto UI handle the min, max, close, and titlebar graphics/functions.
Here’s a VERY silly “sketch” of a test attempt to have Eto on top of a floating viewport (obviously the viewport titlebar/close button would be hidden if possible)
This code has the Eto.Form driving the viewport size/position maybe i’m thinking about it the exact opposite of how I should be
:
import Rhino
import Eto.Forms as forms
import Eto.Drawing as drawing
import System.Drawing as sdrawing
class MyEtoForm(forms.Form):
def __init__(self):
super().__init__()
self.Title = " Standard Viewport in Eto Form"
self.Size = drawing.Size(800, 600)
self.Location = drawing.Point(0, 0)
self.MovableByWindowBackground = True
self.WindowStyle = forms.WindowStyle.NONE
self.window_button_size = drawing.Size(32, 32)
self.window_button_bg_color = drawing.Color(180, 180, 180)
self.viewport = None
self.AddViewport()
self.CreateWindowButtons()
# Add Transparent Style To The Form Background Panel
self.Styles.Add[forms.Panel]("transparent", self.MyFormStyler)
self.Style = "transparent"
# Subscribe to Eto form events
self.LocationChanged += self.OnFormMove
self.SizeChanged += self.OnFormResize
def OnMinimizeButtonClick(self, sender, e):
try:
self.Minimize() # Minimize Eto Form
except Exception as ex:
Rhino.RhinoApp.WriteLine(f"Minimize Button Exception: {ex}")
def OnMaximizeButtonClick(self, sender, e):
try:
self.Maximize() # Maximize Eto Form
except Exception as ex:
Rhino.RhinoApp.WriteLine(f"Maximize Button Exception: {ex}")
def OnFormClose(self, sender, e):
try:
if self.viewport:
self.viewport.Close() # Close "Embedded" Viewport
self.Close() # Close Eto Form
except Exception as ex:
Rhino.RhinoApp.WriteLine(f"Close Button Exception: {ex}")
def CreateWindowButtons(self):
self.header_label = forms.Label()
self.header_label.Size = drawing.Size(300, self.window_button_size.Height)
self.header_label.Text = self.Title
self.header_label.BackgroundColor = self.window_button_bg_color
self.MinimizeButton = forms.Button()
self.MinimizeButton.Size = self.window_button_size
self.MinimizeButton.Text = "-"
self.MinimizeButton.BackgroundColor = self.window_button_bg_color
self.MaximizeButton = forms.Button()
self.MaximizeButton.Size = self.window_button_size
self.MaximizeButton.Text = "[ ]"
self.MaximizeButton.BackgroundColor = self.window_button_bg_color
self.CloseButton = forms.Button()
self.CloseButton.Size = self.window_button_size
self.CloseButton.Text = "X"
self.CloseButton.BackgroundColor = self.window_button_bg_color
self.MinimizeButton.Click += self.OnMinimizeButtonClick
self.MaximizeButton.Click += self.OnMaximizeButtonClick
self.CloseButton.Click += self.OnFormClose
self.layout = forms.DynamicLayout()
self.layout.Height = self.window_button_size.Height
self.layout.AddRow(self.header_label, self.MinimizeButton, self.MaximizeButton, self.CloseButton)
self.layout.AddRow(None)
self.Content = self.layout
def AddViewport(self):
if self.viewport:
self.viewport.Close()
self.display_mode = Rhino.Display.DisplayModeDescription.FindByName("Rendered")
# Create a Rhino viewport (floating)
view_rectangle = sdrawing.Rectangle(self.Location.X, (self.Location.Y + self.window_button_size.Height), self.Size.Width, (self.Size.Height - self.window_button_size.Height))
self.viewport = Rhino.RhinoDoc.ActiveDoc.Views.Add("embedded_viewport", Rhino.Display.DefinedViewportProjection.Perspective, view_rectangle, True)
self.viewport.TitleVisible = False
# handle = self.viewport.Handle
# Rhino.RhinoApp.WriteLine(f"viewport handle: {handle}")
# self.viewport.Topmost = True
# self.SendToBack = False
def OnFormMove(self, sender, e):
self.UpdateViewportPosition()
def OnFormResize(self, sender, e):
self.UpdateViewportPosition()
def UpdateViewportPosition(self):
if self.viewport:
self.AddViewport()
# Rhino.RhinoApp.WriteLine("Update Viewport Location On Form Move")
# Get the form's screen position and size
form_rect = self.Bounds
# Convert form position to screen coordinates
screen_position = forms.Screen.PrimaryScreen.Bounds.Location
new_position = sdrawing.Point(form_rect.X + screen_position.X, form_rect.Y + screen_position.Y)
new_size = sdrawing.Size(form_rect.Width - 16, form_rect.Height - 36)
# Update viewport position and size
self.viewport.Position = new_position
Rhino.RhinoApp.WriteLine(f"New Pos: {new_position}")
self.viewport.Size = new_size
self.viewport.DisplayMode = self.display_mode
# UI STYLE CODE -------------------------------------------------------
# Handle Overall Background Transparency
def MyFormStyler(self, control):
self.BackgroundColor = drawing.Colors.Transparent
window = control.ControlObject
if hasattr(window, "AllowsTransparency"):
window.AllowsTransparency = True
if hasattr(window, "Background"):
brush = window.Background.Clone()
brush.Opacity = 0
window.Background = brush
else:
color = window.BackgroundColor
window.BackgroundColor = color.FromRgba(0, 0, 0, 0)
# Create and show the Eto form
def EstablishForm():
main_toolbar = MyEtoForm()
main_toolbar.Owner = Rhino.UI.RhinoEtoApp.MainWindow
main_toolbar.Show()
if __name__ == "__main__":
EstablishForm()
EDIT:
In looking at this again, I think having the ability to set the floating viewport Window.Style and Titlebar text is actually what I am after.
I can’t seem to find methods exposed to do that though?