More Eto Examples please

To that list i would add a proper csproject setup.

There’s so many ways around setting a proper csproj with eto.
with or without RhinoWindows, with or without original wpf … net7.0-windows or net7.0 etc etc. How to link to existing Windows.Forms to still have grasshopper context menu overrides and Color class… lots of confusion tbh.

I have an eto enabled project atm and trying to add xaml code but can’t get it to work and can’t find any examples. Even InitializeComponent() is non existing. (Edit: that is solved with adding Xaml.Portable to my NuGet)

And you could almost assume that people did their WPF homework from other sources. assume people know MVVM, WPF and XAML.

Give an overview of the existing Rhino helper classes, like the Rhino.UI.ViewModel.

Show styling, binding, - again frame it to an audience who just left their WPF styling and binding tutorials online and would like to apply that to an Eto project.

Also,

A template project for a hybrid Mac/windows build.

How to keep the eto code shared and how to apply platform specific styles in linked projects. That would be awesome.

1 Like

Is there something the latest Rhino templates or Eto templates don’t cover you’d like in particular? You should be able to use them to get going for basically anything without issue.

This guide is essentially cross platform and sets up the csproj ready for Visual Studio or vscode.

I’m just documenting Eto and I don’t have plans to document other UIs really, Eto is already quite a big project.

I’m going to make as few assumptions as possible so that anyone can learn.

I started covering this in the Rhino Specific Eto section here Rhino - Rhino specific Eto but I agree more is needed.

This is on my plate. But it’s tricky.

Is there something specific missing from the below docs about binding I should add?

This is also on my plate as I want to discuss platform specific eccentricities.

Looks like the proper eto overview

Is not displayed at the guides overview

Other things I’d like to see examples of is the drawables David is making for GH2, for instance the gradient mapper or a standard gh component including binding/events. The reason is that Eto.Drawable is the only thing we can customize 100% (afaik), yet its difficult to master and turn into actual interoperable ui components.
See the gradient mapper here
https://developer.rhino3d.com/guides/eto/what-is-eto/

I’m a bit confused here, it’s on the left as far as I can see, can you screenshot what you see?

Yeah Drawable is a little sandbox, it’s aweosme.

This I can do, the SVG Editor workspace is 100% Drawable and it’s got a lot going on. I do want to create a nice juicy Drawable example. A colour picker would be a good idea.

5 Likes

It ain’t that difficult @sonderskovmathias :wink:

Start with a simple custom button to get a hang of it and gradually increase complexity. It’s essentially a canvas with a bunch of events your control can react to. Super powerful.

2 Likes

+1 For more Eto Drawable examples. I’m pretty “deep” in drawables now and I feel like I’m barely scratching the surface… But essentially I’ve realized there’s no point to use Eto without drawables (if you are trying to visually customize things deeply) because the standard Eto components, well very helpful, have very limited visual styling opportunities.

I felt fairly discouraged with Eto being a solution UNTIL I realized that David’s work and @mrhe work he has shared was done with Drawables primarily and now it’s all I use but it’s been a painful trial and error process without many examples to test hands on. Thankfully these forums are full of helpful users willing to share tips along the way!

Eventually I hope to contribute to a user submitted “drawables library” of basic, modern UI elements but ones that allow more robust graphic control. Too busy right now… but that’s where my heart is at haha

5 Likes

I’ve been following a lot of your posts because I’ve always wanted to get into ETO. The more questions you post the more the AI has to draw from haha! The AI is starting to haul ass on ETO forms. Since they can be initiated with the actual code (and in my opinion maintain readability) I’m thinking that this might accelerate the adoption of ETO forms. The drawables part however is not very well explored.

2 Likes

I’m just finishing up some quite thorough docs on Cells, GridViews and TreeViews as they were requested first AND I need to understand them for a UI I’m writing :laughing:.

Drawables will be next up after the Grids segment. The trickiest part of docs, besides finding the time is thinking of a good example that really focuses on the thing being documented.

4 Likes

Thanks for the effort @CallumSykes!
+1 for Eto Drawables :wink:.
I am watching this topic closely :eyes:

I’ll likely post updates to the docs here New Eto Documentation - #12 by michaelvollrath

3 Likes

This is great! Also one of the pieces of Eto I find most confusing as anytime tables and grids are involved my brain wants to check out on me… sorry Excel.

Anyways, looking forward to the docs on this!!

1 Like

It would be cool to see a recreation of one of the Grasshopper 2 input components.
Maybe David would agree to reveal a little bit of the secret.

I have another Eto Example request please!

  1. An example of taking the control of one form and dragging it to a droppable zone on the same form such as a reordering operation.



  2. Dragging a control from one form onto a droppable zone of another form (sort of a cut/paste or copy/paste where either the control gets duplicated or removed from one form and added to the other):



  3. Dragging an external file / file icon from an external source onto a droppable zone of a modal dialog or non modal would be fine as well (in this example “browse” would open the Rhino file explorer or import):


That’s my wish list for now :smiling_face_with_three_hearts:

Some relevant code snippets I found but haven’t yet synthesized into a working sample:

Cheers!

3 Likes

Great suggestion! I’ll try and get that done this year :laughing:

3 Likes

:laughing:

I’ll try and help haha

1 Like

@michaelvollrath,

this is relatively simple to do. Derive your custom control from Drawable, override its OnDragOver, OnDragDrop, and OnDragLeave events.

Then, in the receiving control, use the e.Source from DragEventArgs e to get the source control of the drag operation to do your magic.

2 Likes

Hi @mrhe,

Got something hooked up to this effect this afternoon with Python 3 (need to tighten up the code but it’s a start):

Drag a control from one form to the droppable area of another:

#! python3
import Eto.Forms as forms
import Eto.Drawing as drawing
import Rhino

# Global variable to track the label being dragged
drag_source = None


class DragDropForm(forms.Form):
    def __init__(self, title, form_id):
        super().__init__()
        try:
            self.Title = title
            self.form_id = form_id
            self.ClientSize = drawing.Size(300, 230)
            self.Padding = drawing.Padding(10)

            # Set up main layout
            self.layout = forms.DynamicLayout()
            self.layout.Spacing = drawing.Size(10, 10)
            self.layout.Padding = drawing.Padding(10)

            # Create draggable label
            self.drag_label = forms.Label()
            self.drag_label.Text = f"Drag me from {title}!"
            self.drag_label.BackgroundColor = drawing.Colors.LightGrey
            self.drag_label.Size = drawing.Size(150, 30)
            self.drag_label.TextAlignment = forms.TextAlignment.Center

            # Add mouse events
            self.drag_label.MouseDown += self.on_label_mouse_down

            # Add label to layout
            self.layout.Add(self.drag_label)

            self.bg_color = drawing.Colors.LightGrey
            self.bg_enter_color = drawing.Colors.LightGreen

            # Add drop area
            self.drop_area = forms.Panel()
            self.drop_area.Size = drawing.Size(200, 100)
            self.drop_area.BackgroundColor = self.bg_color
            self.drop_area.AllowDrop = True
            self.drop_area.DragEnter += self.on_drag_enter
            self.drop_area.DragLeave += self.on_drag_leave
            self.drop_area.DragDrop += self.on_drag_drop

            # Add a label for the drop area
            drop_indicator = forms.Label()
            drop_indicator.Text = "Drop Zone"
            drop_indicator.TextAlignment = forms.TextAlignment.Center

            # Create layout for drop area
            drop_layout = forms.DynamicLayout()
            drop_layout.Add(drop_indicator)
            self.drop_area.Content = drop_layout

            # Add drop area to main layout
            self.layout.Add(self.drop_area)

            # Set form content
            self.Content = self.layout

            # Add a status label
            self.status_label = forms.Label()
            self.status_label.Text = "Status: Ready"
            self.layout.Add(self.status_label)

        except Exception as e:
            print(f"DragDropFrom Exception: {e}")

    def on_label_mouse_down(self, sender, e):
        try:
            global drag_source

            if e.Buttons == forms.MouseButtons.Primary:
                Rhino.RhinoApp.WriteLine(">>>ONLABELMOUSEDOWN primary")
                # Update status
                self.status_label.Text = "Status: Starting drag..."

                # Record drag source
                drag_source = {
                    "form": self,
                    "text": sender.Text,
                    "control": sender
                }

                # Create data object
                data = forms.DataObject()
                data.SetString(f"label-{self.form_id}", "text/plain")

                if data:
                    print(f">>>data: {data}")
                else:
                    print("no data!")

                # Start drag operation
                self.status_label.Text = "Status: DoDragDrop called"
                result = sender.DoDragDrop(data, forms.DragEffects.Copy)
                # result = forms.DragDrop.DoDragDrop(data, forms.DragEffects.Copy)
                self.status_label.Text = f"Status: Drag completed with result {result}"
                e.Handled = True

        except Exception as e:
            self.status_label.Text = f"Error: {str(e)}"
            print(f"on_label_mouse_down Exception: {e}")

    def on_drag_enter(self, sender, e):
        try:
            global drag_source

            if drag_source is not None and drag_source["form"] != self:
                e.Effects = forms.DragEffects.Copy
                self.drop_area.BackgroundColor = self.bg_enter_color
                self.status_label.Text = "Status: Drag entered from another form"
            else:
                e.Effects = forms.DragEffects.NONE
                self.status_label.Text = "Status: Invalid drag source"

            e.Handled = True

        except Exception as e:
            self.status_label.Text = f"Error: {str(e)}"
            print(f"on_drag_enter Exception: {e}")

    def on_drag_leave(self, sender, e):
        try:
            global drag_source

            if drag_source is not None and drag_source["form"] != self:
                self.drop_area.BackgroundColor = self.bg_color

        except Exception as e:
            self.status_label.Text = f"Error: {str(e)}"
            print(f"on_drag_enter Exception: {e}")

    def on_drag_drop(self, sender, e):
        try:
            global drag_source

            if drag_source is not None and drag_source["form"] != self:
                # Create a new label in this form's drop area
                new_label = forms.Label()
                new_label.Text = drag_source["text"]
                new_label.BackgroundColor = drawing.Colors.LightGreen
                new_label.Size = drawing.Size(150, 30)
                new_label.TextAlignment = forms.TextAlignment.Center

                # Get the drop area's layout
                drop_layout = self.drop_area.Content
                drop_layout.Add(new_label)

                # Refresh UI
                self.drop_area.Invalidate()
                self.status_label.Text = "Status: Drop successful"
                e.Handled = True
            else:
                self.status_label.Text = "Status: Invalid drop"

        except Exception as e:
            self.status_label.Text = f"Error: {str(e)}"
            print(f"on_drag_drop Exception: {e}")


if __name__ == "__main__":
    """Create and show forms"""
    form1 = DragDropForm("Form 1", 1)
    form2 = DragDropForm("Form 2", 2)

    form1.Show()
    form2.Show()
6 Likes

The docs are open source and accepting PRs :wink: !

6 Likes

That’s interesting :slightly_smiling_face:

More examples and more pictures please. :face_holding_back_tears: :beers:

Maybe something for windows, cause that looks like mac stuff. Even though maybe linux would be better idk :sweat_smile: