Passing information into Rhino.UI.Panel

I want to create an Eto.Forms.Panel whose component are multiple EtoCollapsibleSection.
The problem is, the values displayed in these EtoCollapsibleSection are calculated at run time (after several RhinoCommands have been ran).

Is there anyway to do this ? As according to the documentation, the whole panel must have zero-parameters. Does this meant it is not possible to pass information into Rhino.UI.Panel ?

MVVM pattern is a solution to bind your View - in this case panel - controls to VieModel properties. ViewModel should communicate with logic in Model to get those values.

With this solution you are separating UI code from your plugin logic.

Search more for MVVM.

Thank for your input, but it’s not really what i’m looking for.

I’m aware of the Model-View-ViewModel design pattern, I can create a View using the Eto.Form.Panel class, and pass data from my model (multiple Rhino Commands) into it just fine.

I’m asking about the specific API call needed to pass initialized value into Rhino.UI.Panel, as the API call only pass the GUID - not specific value.

Check out this example rhino-developer-samples/rhinocommon/cs/SampleCsCollapsibleSectionETO_UI at 7 · mcneel/rhino-developer-samples · GitHub

The panel registering you should actually do in the plug-in OnLoad implementation instead of in the command RunCommand implementation, but otherwise this example should be fine.

Yeah, this was my original example that I followed.
For my case, specifically, at line 49 of CollapsibleSectionUIPanel.cs

      SectionOne section1 = new SectionOne();

I need to pass some information obtained from some algorithm (my plugin have multiple commands).
Ideally, It would look something like this

      SectionOne section1 = new SectionOne(Dictionary <double, Color> colorDict);

The colorDict variable is not available OnLoad.
Ofc I can register the Panel (as shown in line 37 of CollapsibleSectionUICommand.cs).
However, I’m pretty sure i cannot pass colorDict into this API call.
As such, I’m asking is there any work around ?

You should abstract the need for color dictionary out such that you don’t need to know that at startup. But once you everything is running and you do get a (valid) dictionary with colors you’d gave it to you data handling part of your code.

If you’re not doing that you’ll end up with conundrums like this.

You should follow the advice of @mlukasz87 . You should be able to set up your GUI without the need for direct access to your data.

Ah okay, can you show me an example of the ‘data handling’ part as you said ?

Not directly sections in a separate panel, but still here are the collapsible sections as implemented by RhinoCycles, the Cycles integration plug-in for Rhino:

Happy new year!
I’ve looked through SessionSection.cs. Afaik, the code initialized m_throttlems_lb, which are updated in the UI when value changes through an event.

Are you saying I should initialized an empty colorDict, then set up an event that update the UI when colorDict is changed ?
If so, how do I set up a connection from the model’s colorDict (which I calculated) and the UI’s colorDict ?

Also, the folder is while big, so i’m not even sure that was what you meant.

m_throttlems_lb is just a label with non-changing text.

You can see that n_throttlems is set in the handler for InitialisationCompleted event the RhinoCycles plug-in core itself has published RhinoCycles/SessionSection.cs at rhino-8.x · mcneel/RhinoCycles · GitHub . And there is a second handler for a different event that will set the m_throttlems.Value: RhinoCycles/SessionSection.cs at rhino-8.x · mcneel/RhinoCycles · GitHub .

The ThrottleMs for RhinoCycles is saved as part of its plug-in settings: RhinoCycles/ApplicationAndDocumentSettings.cs at f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3 · mcneel/RhinoCycles · GitHub . The very first time on a brand-new install of Rhino the first value will be set at RhinoCycles/ApplicationAndDocumentSettings.cs at f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3 · mcneel/RhinoCycles · GitHub .

Plug-in initialisation will trigger here RhinoCycles/Plugin.cs at f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3 · mcneel/RhinoCycles · GitHub its InitialisationCompleted event. This in itself will not yet set the value, since empty event is passed on.

Typically the value will be set via the DisplayData RhinoCycles/SessionSection.cs at f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3 · mcneel/RhinoCycles · GitHub call.

1 Like

Thanks you for the details, it helps me a lot, Currently, I understand the code as followed:

  • You have a class storing the all settings
  • When a settings is changed, you change the value in that settings class
  • Inside your UI, you setup an event - observing the settings class
  • When settings changes, you detach control event, copy the value from the settings class to your UI, then re-attach control event.

But i’m still confused at this line, mainly Settings variable. Where did you initialized it, is it a global variable (in-your plugin scope) ?

I set up an event handler. The event is in the core and triggered where it needs to be triggered so that the UI can react to changes in the data. Small, but important difference where the event is published.

Regarding the Settings property that is provided by the base class ApplicationSection: https://github.com/mcneel/RhinoCycles/blob/f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3/Settings/ApplicationSection.cs#L45 . It is an accessor to the private variable vps that is initialised here: https://github.com/mcneel/RhinoCycles/blob/f07ebf2ea7036e2c9afe9afd629d20040c2aa6a3/Settings/ApplicationSection.cs#L37.

I suggest you clone the repository and open up the code in Visual Studio or Visual Studio Code. You should be able to navigate the code a bit better and utilize intellisense capabilities to gain better understanding.

Okay, i’ve spent sometime looking through the repo you shown me, and I still have no idea what this has to do with my problem.

Let just say, I have a Rhino.UI.Panel - which contain a EtoCollapsibleSection.
This EtoCollapsibleSection need data from the model.
Then, how do I bind this data to the EtoCollapsibleSection ? Especially the case where EtoCollapsibleSection ‘live’ inside Rhino.UI.Panel - and has zero ideas that the model existed.

The model you do give to your collapsible section. Just make sure you have a way to update the model and trigger refreshing of your collapsible section implementation via events and handlers.

Thanks, It worked now, although it is kinda ‘hacky’. Can you give me any suggestion on my current approach:

  • algorithm calculate colorDict
  • colorDict is passed into a Singleton(basically a list of calculated number) called session
  • create a custom Eto.Forms.Panel class, whose contain a private variable pointing to session.
  • In the init function, pass session into an EtoCollapsibleSection class, as shown below.
        public ColorScalePanel()
        {
            EtoCollapsibleSectionHolder holder = new EtoCollapsibleSectionHolder();
            ColorScaleSection section1 = new ColorScaleSection(session.depthColorDict);
            holder.Add(section1);
            TableLayout tableLayout = new TableLayout()
            {
                Rows =
                {
                    holder
                }
            };
            Content = tableLayout;
        }

Afaik, this is basically pointing straight from the “view” Eto.Forms.Panel to the “model” session, meaning, there isn’t any “viewModel”’ as all.
Further down the line, If I wanna include the “viewModel”, are the event logics be coded in here ?

Also, I have another problem regarding Eto.Forms.Label, as shown here.