Closed msasso69 closed 6 years ago
You might be able to get it to work by making sure none of the controls are scaled/expanded as you'd just be fighting with the layout system on which size to actually give the controls. For example, the last column & row of a TableLayout is by default scaled to fit the rest of its container, or any row/column that you have set xscale or yscale to true.
Another option is to use the PixelLayout
so you specify the position and size of each control. For example, your custom tab header.
Thanks for your reply @cwensley,
I'm not sure I'm getting your advice correctly: if the custom control that I'm resizing will be smaller than the Layout in which it is contained I assume that the containing Layout is not resized as well. Is this assumption correct? Or all Layouts (except for PixelLayout) always adapt their sizes in order to perfectly fit the contained controls? Have I understood correctly that PixelLayout never adapts to the content? (Ok this I can easily find out ;) Anyway let me ask you another question: very rarely in the Eto.Test I see you using PixelLayout, and in the Wiki you highly discourage the usage of it in favour of the other Layout types because of their auto size capabilities, so I avoided it as hell and massively used StackLayout and TableLayout. Doing so I ended up in intensive (Table/Stack)Layout nesting and a very slow UI. I hope that the reason of my poor performances is that I'm bouncing from bottom to top and all the way back the resize event as I recently found out, and for sure I'll work on this starting from using PixelLayout for containing my custom tab header as you suggested, but (and here is my question) is the usage of many nested Layout the correct way to design a UI with Eto, or should I limit the nesting to the bare minimum? I never used PixelLayout because looked to me too much old Winforms style, but now I'm starting to think that if I used it I could completely avoid the nested Layout and the UI would be much faster. Is this correct? Which is the faster Layout container?
Thanks
Note: Excuse my "funny" English and sorry if I bother you with so many questions!
if the custom control that I'm resizing will be smaller than the Layout in which it is contained I assume that the containing Layout is not resized as well. Is this assumption correct?
No, that is incorrect. The parent layout (other than Window
, Scrollable
, or Splitter
) will always resize to reflect the size change of a child control, unless the parent has its size set explicitly. For example, this is an invalid case as it is conflicts with the layout:
var myControl = new Drawable { Size = new Size(200, 200) };
var button = new Button { Text = "Click Me" };
var table = new TableLayout {
Rows = {
new TableRow(myControl) { ScaleHeight = true },
button
}
};
var form = new Form { Content = table };
button.Click += (sender, e) => myControl.Size = new Size(100, 100);
The TableLayout will ensure that myControl takes up all space of its cell. If you do want the control to be resized manually, you need to account for the extra space that will be needed. This can be done by using the TableLayout.AutoSized
helper like so:
var table = new TableLayout
{
Rows = {
new TableRow(TableLayout.AutoSized(myControl)) { ScaleHeight = true },
button
}
};
or, perhaps a PixelLayout
:
var pixel = new PixelLayout();
pixel.Add(myControl, 0, 0);
var table = new TableLayout
{
Rows = {
new TableRow(pixel) { ScaleHeight = true },
button
}
};
Have I understood correctly that PixelLayout never adapts to the content?
The PixelLayout
does adapt to the content by autosizing itself based on the controls it contains and their sizes. If you do not want it to do this, set its size explicitly.
is the usage of many nested Layout the correct way to design a UI with Eto, or should I limit the nesting to the bare minimum
Like many UI frameworks, the more you nest the more the UI will have to do to update all those levels of containers. Limiting the nesting to only what you need is the correct way to do it.
I never used PixelLayout because looked to me too much old Winforms style, but now I'm starting to think that if I used it I could completely avoid the nested Layout and the UI would be much faster. Is this correct? Which is the faster Layout container?
Using PixelLayout won't necessarily fix all the performance problems as it does adapt to the content as mentioned.
This all being said, there might be things that can be done to improve performance on one platform or the other. Are you only testing on macOS? The other platforms will definitely have different performance characteristics so if say it's going really fast on WPF but really dog slow on macOS it might be a good idea to see why. A lot of the layout logic on macOS is done manually within Eto so there may be room for improvement.
I can think of at least one thing I've been meaning to do but never saw the need (most UI's I've dealt with don't have performance problems), which is to queue a layout pass instead of updating it each time. This might change the behaviour slightly though as the new sizes wouldn't necessarily be reflected right away.
Note: Excuse my "funny" English and sorry if I bother you with so many questions!
No problem, you're English isn't too hard to follow and questions are always welcome. (;
Thanks Curtis, you definitely gave me some useful hints :) now it's my turn to play with my UI and manage to speed it up.
@msasso69 PR #1020 might help the performance issues as it'll drastically reduce the number of times it needs to layout the controls. There's still a lot of room for improvement, but hopefully that will help.
This is a really good news, I'm looking forward to trying it now! :)
Hey @msasso69, I'm closing this for now as I think this has been greatly improved. If you have more info (e.g. a sample app) that can reproduce any further performance issues, feel free to comment further on this issue.
@msasso69 check out #1112, it might help a ton more to speed up your complex UI on Mac.
Hi,
I'm using Eto and I have now a quite a complex UI, but now I have the need to size some custom controls according to the size of the container. What I do is to register to the SizeChanged event of the parent container and according to the available size I set the size of my child controls accordingly. The problem is that the parent controls are affected as well and once I reach the top level parent all the children are re-sized. On Wpf at the end somehow Eto stops resizing the UI (but takes ages), on Mac it loops forever.
Here is the Mac stack trace and a more detailed description of what happens:
Here Eto fires the SizeChanged event:
Here I size my custom controls according to the size of the parent control:
Here Eto receives the size that I set form my custom control:
If you look at the following stack track you can see that the parent control is affected as well:
and all the chain of parent controls are also affected:
untill I probably reach the top when Eto instruct to resize all children:
untill I reach again my the code in my custom control where I registered for the SizeChanged event:
This loops forever :(
The only thing that I could think of is to set a flag before resizing my custom controls (flag that I reset when my custom controls are resized) and ignore the SizeChanged event while the flag is on.
I'm wondering though whether my approach is correct or if there is a better way to handle the problem, maybe instructing Eto not to relayout the parents.
Any clue?
Specifications