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.
Advertisement
Answer
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