Eto.Forms Styling

Hi All,

Is there documentation/tutorials somewhere that would show me how to go from the standard Eto.Forms to something like the attached image? Credits to @agi.andre

http://andreagi.se/work_etos_forms.html

4 Likes

Hi Jordan
This is all done with the WebView Class: http://pages.picoe.ca/docs/api/html/T_Eto_Forms_WebView.htm
It allows you to style the form with HTML, CSS.

The you can invoke python functions through javascript

4 Likes

Very cool! Thanks for answering. I’ll look to it. This should be fun. I’m more familiar with JS, html and css than c# so that’s a relief.

Jordan

Hi @agi.andre,

This is a beautiful styling for a custom interface: congratulations!
What would be the best approach to implement an interface based on WebView for Rhino and Grasshopper plugins?

Is there any tutorial that we can follow or a template available that we can study?

Thanks

1 Like

You would need to embed a WebView in your panel:

string html =  "<head><meta http-equiv='X-UA-Compatible' content='IE=edge' /><title>Rhino UI</title></head>
<body><p>Runoff limit<input type='range' min='0' max='100' value='50' class='slider' id='runoffLimit'></p></body>";

        WebView webView = new WebView { Height = 1000 };

        public GreenScenarioPanel()
        {

            var layout = new DynamicLayout { DefaultSpacing = new Size(5, 5), Padding = new Padding(0) };

            webView.LoadHtml(html);
            webView.DocumentLoading += (sender, e) =>
            {
                if (e.Uri.Scheme == "greenscenario") //search for markers in html
                {
                    e.Cancel = true; // prevent navigation
                    CommunicateWithWebView(e.Uri.PathAndQuery);
                }
            };

            layout.AddSeparateRow(webView);
            layout.Add(null);
            Content = layout;
        }

In your html add some javascript listeners to tell Rhino, that certain fields were updated by user input:

document.getElementById(‘runoffLimit’).onchange = function() {window.location = ‘greenscenario:runofflimit’;};

In the C# part create a method returning data from the html-based UI to Rhino. In my case:

    private void CommunicateWithWebView(string path)
        {
        switch (path)
        {
            case "runofflimit":
                string text = webView.ExecuteScript("return document.getElementById('runoffLimit').value;");
                Rhino.RhinoApp.WriteLine($"Runoff limit: {text}");
                break;
        }

Here is a quick demo of how it looks like in action:

16 Likes

Here is a progress update on the upcoming Rhino Terrain plugin. The UI is 100% custom Eto.Forms mostly based on Drawables. If you dig deep enough into the framework a lot can be done in terms of interactivity and visual quality.

The majority of work on the UI was done by @Wiley:

@sonderskovmathias @kitjmv @D-W

16 Likes

@mrhe that looks beautiful! Looks to me that Rhino Terrain functionality would be great to have for shaping SubD’s :slight_smile:

Thanks @Gijs!

It took a lot of iterations to get to that stage :slight_smile:
We aim to release the alpha version before Christmas - it should cover the free-form sculpting functionality and some curve-based operations as well.

Terrain works on native Rhino meshes, which can easily be converted to SubD.

No way that looks awesome! You can sell UIs for other plugins also :sunglasses:

ons. 9. nov. 2022 16.21 skrev Mariusz Hermansdorfer via McNeel Forum <notifications@mcneel.discoursemail.com>:

Thanks Mathias!
Rather than monetizing it, I’d prefer to lobby with @curtisw and @dale to transition the official Rhino UI in this direction.

8 Likes

Very nice! This UI looks very promising and reading through the options which are shown here it looks like there’s a juicy piece of software in the oven :cook: Keep up good work!

2 Likes

Keep it up! It’s looking great!

2 Likes

Thanks for sharing.
I’m getting an error with your code using Rhino 8.2:

A breakpoint instruction (__debugbreak() statement or a similar call) was executed in Rhino.exe.

at string text = webView.ExecuteScript("return document.getElementById('runoffLimit').value;"); on CommunicateWithWebView().

Do you have some idea how to avoid this? had you tried this on RH 8?

EDIT: I compile it for RH7 and it works fine, but not for RH8.

2 Likes

Interesting! I haven’t touched this approach for a while. Maybe Rhino’s interop with WebView has changed with the switch to .NET 7?

Can @stevebaer or @curtisw shade more light?

In Rhino 8, Eto’s WebView controls uses Edge WebView2 on Windows, WKWebView on Mac.

In Rhino 7, it used the System.Windows.Forms.WebBrowser control on Windows, which uses the old IE engine.

1 Like

I just posted about a similar problem. I can’t get ExecuteScript to work inside of Rhino 8.

@David_Moreau Do you have an example that shows what you’re trying to do?

Do note that you can’t call ExecuteScript until the DocumentLoaded event has been fired.

Another huge difference with the Edge WebView control is that it does not have a non-async version of ExecuteScript so we pump the message loop while we wait for it to complete. This approach works most of the time but can have issues. Ideally if you change all of your code to use WebView.ExecuteScriptAsync() instead, it might get you further.