Skip to content

How do I write a JUnit test for a custom SWT-Column-Ratio-Layout?

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.

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