How to set a button expands to a whole the space or shrink to minimal width in a tablelayout? - codenameone

I don't know how to set a button(or textfield) to expand to the whole space or shrink to minimal width of the button in a table-layout.
For example:
TableLayout tl = new TableLayout(1,2);
Container Cnt = new Container(tl);
add(Cnt);
Button searchBtn = new Button("Expand or Shrink");
Cnt.add(tl.createConstraint().widthPercentage(80),searchBtn);
Sometimes searchBtn would expand to the whole space(80 percent of container's width), but others would shrink to the minimum width of searchBtn in a table-layout.
How do I expand or shrink a button in a table-layout as I wish?
And the expanding and shrinking rules of a button for in a BoxLayout.

The default behavior of a table layout is fill. If you add the button directly it will take up the 80 percent:
Cnt.add(tl.cc().wp(80), searchBtn);
If you need it to be in a container make sure not to use something like FlowLayout which grants it preferred size. Use something like the center of a border layout which grants the available size.
To make the button take the preferred size you can use a couple of other approaches. There are other constraints available as explained in the javadocs. There's also the common trick of nesting as you mentioned in the comment. E.g. for nesting:
Cnt.add(tl.cc().wp(80), FlowLayout.center(searchBtn));
Notice you can use other constraints in the flow layout to impact the alignment.
The second approach is to use the layout constraints:
Cnt.add(tl.cc().wp(80).ha(CENTER), searchBtn);
See: https://www.codenameone.com/javadoc/com/codename1/ui/table/TableLayout.Constraint.html#setHorizontalAlign-int-

Related

Codename one SpanLabel text does not occupying full width

I'm using the SpanLabel Component, but on the screen the text content does not occupying the full width when text size is lower
Someone can help please?
This can happen if the width isn't deterministic. The SpanLabel won't be able to reflow and at best will cause only its own Container to resize. There are two solutions:
Deterministic hierarchy - this is generally best but not always possible
Use TextArea - sometimes this works around the issue by reducing the hierarchy depth.
Deterministic layout means that the size of the elements is determined in a clear way by the hierarchy. E.g. BoxLayout.Y is deterministic on the X axis as it gives the components on the X axis all available space. FlowLayout isn't deterministic as it gives components their preferred size.
Some layouts can go back and forth and vary in determinism based on their axis.
This is important because when we layout the components we go from top down. So we go through the Form to its children asking each for their preferred size. If at this point the SpanLabel doesn't know its size it can give the wrong value and we can't really fix that later as we don't reflow the UI. Reflow would create a potential infinite loop and a performance problem at best.
We try to workaround some of this behavior by making a revalidate() call within TextArea but that has its limits. If the hierarchy is too deep the preferred size is already set and won't adapt. SpanLabel is just a Container with a TextArea and a Label (for the icon). So by only using a TextArea you'd slightly simplify the hierarchy and it sometimes might be enough. E.g.
TextArea t = new TextArea(myText);
t.setEditable(false);
t.setFocusable(false);
t.setUIID("Label");

Automatically resize form and move controls when new ones are added or a text in a label grows

Beginner in Visual Studio here.
I'm trying to create an C# Windows Form application that simply displays a form to show some information about the local system.
I have created this form with the help of the VS designer:
As you can see, it consists of a simple panel with a PictureBox at the top, a label below it (both centered), three table layouts next to each other, and a button at the bottom. Never mind the label texts.
The rows of all the table layouts are set to absolute, this is because I want to programatically add rows to the end middle and right table layout if there are more than one local IP address in the computer and setting the rows to auto size or percentage would make alignment difficult if more rows are added.
Now, my problem is that I can't figure out how to make the form resize and move the controls (specifically move the 'OK' button down) when more rows are added.
I have tried anchoring the button to the bottom edge of the form as well as the bottom of the middle table, both produce the same result: the button stays where it is and the new rows overlap it, like this
I would also like to know how to have the form resize to fit the contents of the labels. For example, if the text in one of the labels inside the layout is bigger than the column width, I'd like to have the form grow to accommodate it. Likewise, I'd like the form to shrink to fit the largest text.
I realize that this may not be the most efficient or easiest way to create this particular form, but it is what I've come up with, I of course welcome any suggestions in that regard. It is important to maintain alignment between the rows of all table layouts.
Thanks in advance.
Use a data grid and add controls to it if an add button is pressed. You can scroll through the rows so you won't need to adjust the height of the form

Setting control height explicitly

I have a XamDataGrid in one of my user controls, inside of a stackpanel. I want the grid to maintain the same height regardless of how many rows are present in the grid. To do that, I set the grid's Height property to an explicit value.
Is that how things are done in WPF? Every time I do explicit sizing I feel like I am doing WinForms and not using WPF properly. Is setting the Height directly the only/correct solution?
There's nothing wrong with setting an explicit Height in situations where you want an element to always stay the same height. Where it's less appropriate is in situations where sizing is better handled by the parent layout Panel or the element's child content which can use the available space dynamically.
WPF uses a relative measurement system which at first glance is not intuitive. I have never found an example when I was forced to use explicit sizes ( once when I paint something on Canvas). I use styles in 90% cases where I define Padding, Margin, Aligment etc. Sometimes I use MinHeight and MinWidth for simple things.
About that Grid you can put it in the ScrollViewer or ViewBox to have dynamic sizing, yet If it won't be trouble set the explicit Height.

Spreading controls to fill space as a dialog resizes

I have a dialog with column down the right side filled with buttons. The dialog is built with Windows Forms. I have a mockup at the following link:original dialog
(I would have included it but apparently i'm not allowed to use image tags)
I would like for the buttons in the right column to resize themselves to fill the remaining vertical space when the dialog resizes. It doesn't particularly matter to me whether or not buttons simply increase in size or whether the buttons remain the same size while the gaps between them increase. I'm simply want the buttons to go from the top to the bottom. (I have a mockup for this as well but apparenlty i can only include one link)
I've tried hosting the buttons in a FlowLayoutPanel but they do not increase as the dialog stretches, I only get whitespace at the bottom after I run out of buttons. I also tried a TableLayoutPanel and had the same result but I may have misused it. Does anyone have any ideas how I could accomplish this?
Thanks in advance,
Jeremy
To get you started. Use the TableLayoutPanel, set its Anchor property to top, bottom, left, and right. Set the rows and columns to percentages as needed. I suggest each control have it own cell. Note that each control in a "cell" can have its Dock and Anchor property set as needed.
You can do this with a TableLayoutPanel. Create a column for the buttons, with each button having it's own row / cell in the column. Set each row to be an even percentage for height (if there are 10 buttons, each row would be 10%), and dock the TableLayoutPanel to the right side of the screen. Then, put the buttons into their rows and set them to full docking. Then, when the dialog expands, the TableLayoutPanel will expand to fill the entire right side of the screen, each row will adjust proportionally, and each button would expand to fit the new row size.
You may have to adjust this a bit to fit your needs, especially in how it relates to the other content in the window.

How to get controls in WPF to fill available space?

Some WPF controls (like the Button) seem to happily consume all the available space in its' container if you don't specify the height it is to have.
And some, like the ones I need to use right now, the (multiline) TextBox and the ListBox seem more worried about just taking the space necessary to fit their contents, and no more.
If you put these guys in a cell in a UniformGrid, they will expand to fit the available space. However, UniformGrid instances are not right for all situations. What if you have a grid with some rows set to a * height to divide the height between itself and other * rows? What if you have a StackPanel and you have a Label, a List and a Button, how can you get the list to take up all the space not eaten by the label and the button?
I would think this would really be a basic layout requirement, but I can't figure out how to get them to fill the space that they could (putting them in a DockPanel and setting it to fill also doesn't work, it seems, since the DockPanel only takes up the space needed by its' subcontrols).
A resizable GUI would be quite horrible if you had to play with Height, Width, MinHeight, MinWidth etc.
Can you bind your Height and Width properties to the grid cell you occupy? Or is there another way to do this?
There are also some properties you can set to force a control to fill its available space when it would otherwise not do so. For example, you can say:
HorizontalContentAlignment="Stretch"
... to force the contents of a control to stretch horizontally. Or you can say:
HorizontalAlignment="Stretch"
... to force the control itself to stretch horizontally to fill its parent.
Each control deriving from Panel implements distinct layout logic performed in Measure() and Arrange():
Measure() determines the size of the panel and each of its children
Arrange() determines the rectangle where each control renders
The last child of the DockPanel fills the remaining space. You can disable this behavior by setting the LastChild property to false.
The StackPanel asks each child for its desired size and then stacks them. The stack panel calls Measure() on each child, with an available size of Infinity and then uses the child's desired size.
A Grid occupies all available space, however, it will set each child to their desired size and then center them in the cell.
You can implement your own layout logic by deriving from Panel and then overriding MeasureOverride() and ArrangeOverride().
See this article for a simple example.
Well, I figured it out myself, right after posting, which is the most embarassing way. :)
It seems every member of a StackPanel will simply fill its minimum requested size.
In the DockPanel, I had docked things in the wrong order. If the TextBox or ListBox is the only docked item without an alignment, or if they are the last added, they WILL fill the remaining space as wanted.
I would love to see a more elegant method of handling this, but it will do.
Use the HorizontalAlignment and VerticalAlignment layout properties. They control how an element uses the space it has inside its parent when more room is available than it required by the element.
The width of a StackPanel, for example, will be as wide as the widest element it contains. So, all narrower elements have a bit of excess space. The alignment properties control what the child element does with the extra space.
The default value for both properties is Stretch, so the child element is stretched to fill all available space. Additional options include Left, Center and Right for HorizontalAlignment and Top, Center and Bottom for VerticalAlignment.
Use SizeChanged="OnSizeChanged" in your xaml and the set the sizes you want in the code behind.
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
TheScrollViewer.Height = MainWin.Height - 100;
}
Long term it will be better for you.
When your manager comes along and asks "make that a bit bigger" you won't to spend the afternoon messing about with layout controls trying to get it to work. Also you won't have to explain WHY you spent the afternoon trying to make it work.

Resources