Lesson Learned: How to Create Layout - Center Aligned Box with Left Aligned Content
Hi, after quite long playing with achieving layout[1] I decide to write down what I found. Short Version ------------- To get nice box centered at middle of screen, but content in box left aligned use HBox( HStretch, VBox( VStretch, Left(<content>), VStretch ), HStretch ) Long Version ------------ It start with feature to adapt theme and our designed team found some strange alignment that they want to change in dialog layout. So I start with trivial idea to have something like `Center(VBox(Left(*content)))` This sadly does not work as it in the end create box over whole place and everything is ugly on left side. which looks strange ( see screenshots in [1]). So next attempt with a bit of help is MarginBox. It looks fine and is shrinkable, so even on very small screen in ncurses looks fine, but in qt it is hard to pick good sizes as with different resolutions it is never on center for all resolutions. So good to make some spacing, but not to align box. The proper solution is to use that stretches around that create spacing around box that is proportional and content in Box then can left alignment with proper position. Pro tip: If you do not want center but e.g. in one third, it is possible to use Weight to stretch. See documentation at [2] Josef [1] https://github.com/yast/yast-registration/pull/519 [2] https://yast-ui-bindings.surge.sh/classYWeight.html
On 2020-12-17 22:49, josef Reidinger wrote:
To get nice box centered at middle of screen, but content in box left aligned use HBox( HStretch, VBox( VStretch, Left(<content>), VStretch ), HStretch )
This is really just an overly complex way of writing HVCenter( Left( content ) ) because HBox( HStretch(), content, HStretch() ) is the same as HCenter( content ) and it's the same in the other dimension, i.e. VBox( VStretch(), content, VStretch() ) I feel it's time to repeat that very basic presentation I once gave at a YaST workshop in Prague back in 2005 or 2006 (unfortunately, I don't seem to have those slides anymore). Our layouts have become mind-bogglingly complex; layout widgets are always added, sometimes counteracting each other, sometimes just doing nothing. Often enough it's very hard to find out why it behaves like it does simply because of the sheer number of layers upon layers. Back many years ago I had added the YDialogSpy (Ctrl-Shift-Alt-Y) mostly to visualize what level of layout elements correspond to what screen area. I found that it helps a lot to just invoke it; very often it's surprising to see how large or how small any of those layout boxes really are. Please use it! I believe that most of the insecurity that our developers have about layouts comes from not really understanding a widget's stretchability in both dimensions and how this changes when you put it into an alignment widget (Left, Right, Top, Bottom, HCenter, VCenter, HVCenter) and how layout stretch items (HStretch, VStretch) and spacings interact with the layout algorithm. In general, if there are several ways to achieve the same layout, use the simpler one. If a part of a layout is blown up too large, put it into a squash widget (HSquash, VSquash, HVSquash) to "let out air". If it then becomes too small, put a MinSize (or MinWidth or MinHeight) inside it. And normally it's a good idea to add a margin (MarginBox) around it if it's the outermost layout level in a dialog: MarginBox( 3, 1, # add some border around it HVSquash( # squeeze out excess space MinSize( 42, 7, # enforce minimum size content ) ) ) That's a lot simpler and a lot less error-prone than cascading tons of extra VBox, HBox, VStretch, HStretch, VSpacing, HSpacing as we see so often in our dialogs. And the layout engine will give you much more predictable results, too. Kind regards + Merry Christmas, everyone! -- Stefan Hundhammer <shundhammer@suse.de> YaST Developer SUSE Linux GmbH GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg)
On 12/18/20 9:27 PM, Stefan Hundhammer wrote:
On 2020-12-17 22:49, josef Reidinger wrote:
To get nice box centered at middle of screen, but content in box left aligned use HBox( HStretch, VBox( VStretch, Left(<content>), VStretch ), HStretch )
This is really just an overly complex way of writing
HVCenter( Left( content ) )
because
HBox( HStretch(), content, HStretch() )
is the same as
HCenter( content )
and it's the same in the other dimension, i.e. VBox( VStretch(), content, VStretch() )
I feel it's time to repeat that very basic presentation I once gave at a YaST workshop in Prague back in 2005 or 2006 (unfortunately, I don't seem to have those slides anymore).
+1 for repeating it. Having some slides with "visual" examples would be great for a better understanding. Thanks!
Our layouts have become mind-bogglingly complex; layout widgets are always added, sometimes counteracting each other, sometimes just doing nothing. Often enough it's very hard to find out why it behaves like it does simply because of the sheer number of layers upon layers.
Back many years ago I had added the YDialogSpy (Ctrl-Shift-Alt-Y) mostly to visualize what level of layout elements correspond to what screen area. I found that it helps a lot to just invoke it; very often it's surprising to see how large or how small any of those layout boxes really are. Please use it!
I believe that most of the insecurity that our developers have about layouts comes from not really understanding a widget's stretchability in both dimensions and how this changes when you put it into an alignment widget (Left, Right, Top, Bottom, HCenter, VCenter, HVCenter) and how layout stretch items (HStretch, VStretch) and spacings interact with the layout algorithm.
Yes, at least for me, sometimes I am lost when combining different layout items. Basically, I tend to use a "try-error" approach.
In general, if there are several ways to achieve the same layout, use the simpler one. If a part of a layout is blown up too large, put it into a squash widget (HSquash, VSquash, HVSquash) to "let out air". If it then becomes too small, put a MinSize (or MinWidth or MinHeight) inside it. And normally it's a good idea to add a margin (MarginBox) around it if it's the outermost layout level in a dialog:
MarginBox( 3, 1, # add some border around it HVSquash( # squeeze out excess space MinSize( 42, 7, # enforce minimum size content ) ) )
That's a lot simpler and a lot less error-prone than cascading tons of extra VBox, HBox, VStretch, HStretch, VSpacing, HSpacing as we see so often in our dialogs. And the layout engine will give you much more predictable results, too.
Kind regards + Merry Christmas, everyone!
-- José Iván López González YaST Team at SUSE LINUX GmbH IRC: jilopez
On Fri, 18 Dec 2020 22:27:27 +0100 Stefan Hundhammer <shundhammer@suse.de> wrote:
On 2020-12-17 22:49, josef Reidinger wrote:
To get nice box centered at middle of screen, but content in box left aligned use HBox( HStretch, VBox( VStretch, Left(<content>), VStretch ), HStretch )
This is really just an overly complex way of writing
HVCenter( Left( content ) )
because
HBox( HStretch(), content, HStretch() )
is the same as
HCenter( content )
and it's the same in the other dimension, i.e. VBox( VStretch(), content, VStretch() )
Hi, thanks for hint. I try it now as I have another change in installation proposal where I need same layout and found that HVCenter does not work at all. see [1]. Also I found another cave-eat. Each element has to have own Left as Left(VBox()) does not work as expected. See mentioned PR for final solution that produce layout I want. Josef [1] https://github.com/yast/yast-firewall/pull/144#issuecomment-778116640
<snip>
Kind regards + Merry Christmas, everyone!
participants (3)
-
josef Reidinger
-
José Iván López González
-
Stefan Hundhammer