[ETO] Resize form when controls are added or removed

When you first run a dialog class with DynamicLayout, if you don’t specify the form’s height, its height will be set perfectly to contain the controls.

I would like to have the user press a Next button, basically loading in a “second page” and I would like to have the form recalculate its height based on the controls on the second page.

Is that possible? (I can specify the heights for each page, I was just hoping to let it be auto-calculated)

perhaps you can re-instantiate the “first” page dialog as the “second” page.
or instantiate a new dialog as the second and show it when appropriate.

1 Like

Thanks for the suggestion. I decided to just go ahead and specify a height that will work for all pages.

@Will_Wang and anyone else who might be interested in the future…

I accidentally stumbled on a hint to the answer somewhere in the forum, but I don’t remember where. After some experimenting, it seems the process is…

  1. Set the form or dialog’s AutoSize property to True. This only works in Rhino 7 and above. In Rhino 6, you will need to set the form or dialog’s Height property, which may require experimentation. I prefer to let AutoSize handle it, so I put the Rhino6 stuff in an if-clause.
  2. Put the layout in a separate function that can be called when you need to add or remove controls.
  3. Start the layout function by calling the layout object’s Clear() method. Store the layout object in a variable so that you can call its clear method the next time you call the layout function.
  4. In the layout function, right before setting the form’s Content property, call the layout object’s Create() method.

Below is a working example, but note that I only deal with changing the height. If the width is affected, in Rhino 6, you would also need to recalculate the form’s Width property each time the layout function is called.

#! python 2

import Eto
import rhinoscriptsyntax as rs

class MyDialog(Eto.Forms.Dialog):
    def __init__(self):
        # call the super function in a way that works in python2
        super(MyDialog, self).__init__()

        # variables
        self.AutoSize = True
        self.Layout = None
        self.Padding = Eto.Drawing.Padding(10)
        self.BaseHeight = 80
        self.IncrementalHeight = 20

        if rs.ExeVersion() == 6:
            self.Height = self.BaseHeight

        # controls
        self.AddLabelButton = Eto.Forms.Button()
        self.AddLabelButton.Text = 'Add Label'
        self.AddLabelButton.Click += self.OnAddLabelButtonClick        

        # set the DefaultButton property and cross your fingers and hope
        # that this will be enough to make it compatible with Macs
        self.DefaultButton = self.AddLabelButton

        lbl = Eto.Forms.Label()
        lbl = 'A Label'
        self.Labels = [lbl]

        self.LayoutForm()

    def LayoutForm(self):
        if self.Layout:
            self.Layout.Clear()

        self.Layout = Eto.Forms.DynamicLayout()
        self.Layout.DefaultSpacing = Eto.Drawing.Size(5, 5)
        self.Layout.AddRow(self.AddLabelButton)

        for lbl in self.Labels:
            self.Layout.AddRow(lbl)
            
        if rs.ExeVersion() == 6:
            base_height = self.BaseHeight
            extra_height = len(self.Labels) * self.IncrementalHeight
            self.Height = base_height + extra_height

        self.Layout.Create()
        self.Content = self.Layout

    def OnAddLabelButtonClick(self, sender, e):
        lbl = Eto.Forms.Label()
        lbl.Text = 'Another Label'
        self.Labels.append(lbl)
        self.LayoutForm()


if __name__ == "__main__":        
    dialog = MyDialog()
    dialog.ShowModal()







1 Like