I found a custom SWT-Column-Ratio Layout on the internet which puts the children of a composite/control into a user-defined ratio. Unfortunately I cannot find the source of the implementation of the Column-Ratio Layout, but here's how the code looks like:
public class ColumnRatioLayout extends Layout {
int[] percentages;
public ColumnRatioLayout(int... percentages) {
this.percentages = percentages;
}
@Override
protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
Control[] children = composite.getChildren();
int height = hHint;
int width = wHint;
int consumedPercent = 0;
for (int i = 0; i < children.length; i++) {
int percent = 0;
calculatePercentAndConsumedPercent(percent, consumedPercent, children, i);
Point childSize = children[i].computeSize(wHint == -1 ? -1 : wHint * percent / 100, hHint);
if (wHint == SWT.DEFAULT) {
width = Math.max(width, childSize.x * (100 - percent) / 100);
}
if (hHint == SWT.DEFAULT) {
height = Math.max(height, childSize.y);
}
}
return new Point(width, Math.max(height, 0));
}
protected void calculatePercentAndConsumedPercent(int percent, int consumedPercent, Control[] children, int i) {
if (i >= percentages.length) {
percent = (100 - consumedPercent) / (children.length - percentages.length);
} else {
percent = percentages[i];
consumedPercent += percent;
}
}
@Override
protected void layout(Composite composite, boolean flushCache) {
Control[] children = composite.getChildren();
Rectangle available = composite.getClientArea();
int x = available.x;
int consumedPercent = 0;
for (int i = 0; i < children.length - 1; i++) {
int percent;
if (i >= percentages.length) {
percent = (100 - consumedPercent) / (children.length - percentages.length);
} else {
percent = percentages[i];
consumedPercent += percent;
}
int w = available.width * percent / 100;
children[i].setBounds(x, available.y, w, available.height);
x += w;
}
if (children.length > 0) {
children[children.length - 1].setBounds(x, available.y,
available.width - (x - available.x), available.height);
}
}
}
I want to test this layout. I am writing a JUnit test to test if the ratio is true when using this layot. I have done this, but it gives me no useful output - Point {0, 0}:
public class ColumnRatioLayoutTest {
private static Display _display;
private static Shell _shell;
private static Composite _comp;
@BeforeAll
public static void setUpAll() {
_display = new Display();
_shell = new Shell(_display);
_comp = new Composite(_shell, SWT.NONE);
}
@Test
public void setLayoutTest() {
int[] colRatio = {20, 80};
ColumnRatioLayout colLayout = new ColumnRatioLayout(colRatio);
_comp.setLayout(colLayout);
_comp.setSize(_comp.computeSize(SWT.DEFAULT, SWT.DEFAULT));
Composite comp1 = new Composite(_comp, SWT.NONE);
comp1.setLayout(new FillLayout());
comp1.setSize(comp1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
Composite comp2 = new Composite(_comp, SWT.NONE);
comp2.setLayout(new FillLayout());
comp2.setSize(comp2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
System.out.println("Comp1 size: " + _comp.getSize());
}
}
I basically want to compare the size of the two composites and see that one is 4 times the size of the other. This will fulfill my test. How do I do that? Thanks in advance.
You can test the layout like this:
public class ColumnRatioLayoutTest {
private Display display;
private Shell shell;
@BeforeEach
public void setUp() {
display = new Display();
shell = new Shell(display);
}
@AfterEach
public void tearDown() {
display.dispose();
}
@Test
public void testLayout() {
shell.setSize(shell.computeSize(100, SWT.DEFAULT));
Control control20 = new Label(shell, SWT.NONE);
Control control80 = new Label(shell, SWT.NONE);
shell.setLayout(new ColumnRatioLayout(20, 80));
shell.layout();
assertEquals(100, shell.getSize().x);
assertEquals(20, control20.getSize().x);
assertEquals(80, control80.getSize().x);
}
}
The test creates a shell with a client area width of 100 pixels and then ensures that two controls that should occupy 20% and 80% of the width actually are 20 and 80 pixels wide.
There is no need to declare static Display
and Shell
, re-creating them for each test ensures that tests remain isolated.
BTW, widgets that are managed by a layout must not call setSize
or otherwise modify their bounds, i.e. your code must not call comp1.setSize(...);
And, please, follow the Java Naming conventions, don't prefix variables with underscores