How to create a line divider using Eto.Forms?

rhino
rhinocommon
eto
styles

(Ibrahim Mahmoud) #1

I’m just getting introduced to Eto.Forms, and as a crash course I am trying to make a window similar to the one that appears during the “Loft” command.

Capture2

I’m actually really confused on how this is set up. Here are my questions, in order of importance to what I can’t figure out on my own:

  1. How do I create line dividers, like what’s after “Style” and “Cross-section curve options”?

  2. As far as I know, the easiest way to organize stuff in a window is by using a TableLayout using rows and columns. Is this what is happening here? If so, it seems like the second part has 3 columns (the bullet, the text box, and the text after it), while the first part only has 1 - but it seems to take up the same amount of space as the 3 columns below it, and as far as what I learned I don’t know how to do that. If not, how is this organized so I can mimic it?

  3. Every time I click on the Rhino window outside of the Eto window, the Eto window disappears behind the Rhino window and the only way to make it appear again is by minimizing the Rhino window. If I don’t minimize the Rhino window, even if I click on the Eto window on the Windows taskbar it will automatically jump behind the Rhino window. How do I stop this from happening?

Thank you for your help!


#2

I’m not at all familiar with Eto, so can’t answer your questions, but I thought I would remind you that Rhino has been around since the 1990’s and much, if not all, of it was developed using the Windows SDK of various vintages and then updated. Later some stuff was implemented using .Net API’s. My point is that Eto may not be capable of implementing everything you see in Rhino exactly as you see it.

I’ll leave it to the Rhino and Eto experts here to expand on this and answer your specific questions.


(Ibrahim Mahmoud) #3

Thank you for the reminder, it didn’t even cross my mind that Eto might not even be a part of the Loft command at all. I don’t think Eto was around since the1990s so I’ll just have to cross my fingers and hope a solution exists!


#4

as far as I know…

  1. The closest to that is probably a GroupBox. I’m not aware of a pure divider you seek in Eto

  2. Check out StackLayout. Or in TableLayout you can probably change column and row sizes. Some controls also have an attribute boolean that tells it to whether fill the entire container space or not.

  3. See this attribute of Window


(Dale Fugier) #5

Here is how Rhino does it:

  /// <summary> label with a line separator </summary>
  class LabelSeparator : Panel
  {
    readonly Label m_label;
    readonly Divider m_divider;
    public string Text
    {
      get { return m_label.Text; }
      set { m_label.Text = value; }
    }

    public Color Color
    {
      get { return m_divider.Color; }
      set { m_divider.Color = value; }
    }
    public LabelSeparator()
    {
      m_label = new Label();
      m_divider = new Divider();
      if (Rhino.Runtime.HostUtils.RunningOnOSX)
        m_divider.Color = Colors.DarkGray;
      Content = new StackLayout
      {
        Orientation = Orientation.Horizontal,
        VerticalContentAlignment = VerticalAlignment.Stretch,
        Spacing = 2,
        Items =
        {
          m_label,
          new StackLayoutItem(m_divider, true)
        }
      };
    }
  }

– Dale


#6

I can’t find Divider class on Eto API docs


(Dale Fugier) #7

Hi @Will_Wang

Use Rhino.UI.Controls.Divider.

Also, I’ve added the above code as a new Rhino.UI.Controls.LabelSeparator class that will appear in a future SR of Rhino.

– Dale


(Ibrahim Mahmoud) #8

Hello @dale,

Will this work in Rhino 5? I’m trying to make a plugin compatible with both Rhino 5 and Rhino 6, but Visual Studio says that “Rhino.UI.Controls” doesn’t exist.


(Dale Fugier) #9

Well, no, Eto is not included with Rhino 5 (for Windows).

– Dale


(Ibrahim Mahmoud) #10

I embedded Eto into my Rhino 5 plugin, and as far as I know with my limited knowledge everything seems to be working fine. Will that be an obstacle in getting a Divider working?


(Dale Fugier) #11

Well, the Divider class mentioned above is not included with Rhino 5. It’s embedded in Rhino 6.

– Dale


(Dale Fugier) #12

Hi @eebs99,

This class should get you close. You’ll need to figure out the correct color.

public class MyDivider : Eto.Forms.Drawable
{
  private Eto.Drawing.Color m_color;

  public Eto.Drawing.Color Color
  {
    get { return m_color; }
    set
    {
      if (m_color == value)
        return;
      m_color = value;
      Invalidate();
    }
  }

  public Eto.Forms.Orientation Orientation => Width < Height 
    ? Eto.Forms.Orientation.Vertical 
    : Eto.Forms.Orientation.Horizontal;

  public MyDivider()
  {
    m_color = Eto.Drawing.Colors.LightGrey;
    Size = new Eto.Drawing.Size(3, 3);
  }

  protected override void OnSizeChanged(System.EventArgs e)
  {
    base.OnSizeChanged(e);
    Invalidate();
  }

  protected override void OnLoadComplete(System.EventArgs e)
  {
    base.OnLoadComplete(e);
    Invalidate();
  }

  protected override void OnPaint(Eto.Forms.PaintEventArgs e)
  {
    base.OnPaint(e);
    var middle = new Eto.Drawing.PointF(Size / 2);
    e.Graphics.FillRectangle(
      Color,
      Orientation == Eto.Forms.Orientation.Horizontal
        ? new Eto.Drawing.RectangleF(0f, middle.Y, ClientSize.Width, 1)
        : new Eto.Drawing.RectangleF(middle.Y, 0f, 1, ClientSize.Height));
  }
}

– Dale


(Ibrahim Mahmoud) #13

Hello @dale,

Thank you for this code snippet, it’s been really helpful with my understanding! I have a few questions about how this works:

  1. In the OnPaint method, why do you use middle for the height positioning of the divider? It isn’t exactly in the middle, as 3 / 2 equals 1 not 1.5, yet if you replace it with 1.5 the divider looks like the color is lighter. In fact, the more the number approaches 3, the divider fades and goes away. Why does this happen?

    new Eto.Drawing.RectangleF(0f, X, ClientSize.Width, 1)

    X = 1f, X = 1.5f, X = 2.7f, X = 3f

    image image image image

  2. I looked into StackLayout, and I want to learn how to use that., However, the Eto docs are not very informative in this regard, and unfortunately MyDivider does not work well with StackLayouts. What I’m wanting is that the divider will extend to the width of the window, but when I use a StackLayout (I used TableLayout in the example above) the divider only works if it’s by itself and if nothing else is with it on the same row (there should be a divider after the white box), and it only extends 3 pixels I think.

    image

    That little blue blip is the divider. I think the issue is with ClientSize, because in the OnPaint method ClientSize is not the same as the window size, but it is the same as Size (which has a width of 3 - it should be 96 pixels I think, as the white box under it is 96 pixels wide). Are there are easy fixes to this?

Thanks for your help with these problems! I’ve been making a lot of progress.


(Dale Fugier) #14

Hi @eebs99,

The Size parameter passed to OnPaint is the size of the drawable, not the size of the rectangle to be drawn. If you’re curious, put a breakpoint in the method and look at the size.

Also, a StackLayout is designed to have horizontal or vertical list of controls, which is how a lot of simple dialog boxes have their controls organized. It isn’t the best layout in many cases, I tend to use a TableLayout frequently. I’ve attached a StackLayout sample, which uses the divider code from above, for you to review.

TestIbrahim.cs (4.6 KB)

– Dale