Anna W.
Anna W.

Reputation: 37

Nested SWT Composites with conflicting GridLayout

I'm new to SWT and am trying to create a page with several nested Composites. I'm running into problems with using a GridLayout nested within Composites of other layout types.

This is some simplified mock code that illustrates what it is I'm trying to accomplish, and the error I'm running into:

package layouts_test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Composite;

public class LayoutsTest {

  public static void main(String[] args) {

    Display display = new Display();
    Shell shell = new Shell(display);

    // Composite that contains all nested Composites
    Composite pageComposite = new Composite(shell, SWT.NONE);
    final StackLayout stackLayout = new StackLayout();
    pageComposite.setLayout(stackLayout);

    // Construct some Composites to stack on the pageComposite
    Composite stackComposite1 = new Composite(pageComposite, SWT.NONE);
    stackComposite1.setLayout(new RowLayout(SWT.VERTICAL));
    Composite stackComposite2 = new Composite(pageComposite, SWT.NONE);
    stackComposite2.setLayout(new FillLayout());

    // Construct a grid composite to go into stackComposite1
    Composite gridComposite = new Composite(stackComposite1, SWT.NONE);
    gridComposite.setLayout(new GridLayout(3, true));
    gridComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    gridComposite.layout();

    // Arbitrarily set stackComposite1 on top
    stackLayout.topControl = stackComposite1;
    stackComposite1.layout();

    shell.pack();
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }

    display.dispose();
    return;
  }

}

When I run this code, I get the following exception complaining that stackComposite1 apparently is using GridData when it should be using RowData to lay out:

Exception in thread "main" java.lang.ClassCastException: org.eclipse.swt.layout.GridData cannot be cast to org.eclipse.swt.layout.RowData
at org.eclipse.swt.layout.RowLayout.layoutVertical(RowLayout.java:367)
at org.eclipse.swt.layout.RowLayout.layout(RowLayout.java:239)
at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1291)
at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1277)
at org.eclipse.swt.widgets.Composite.layout(Composite.java:666)
at org.eclipse.swt.widgets.Composite.layout(Composite.java:624)
at org.eclipse.swt.widgets.Composite.layout(Composite.java:587)
at layouts_test.LayoutsTest.main(LayoutsTest.java:39)

If I change the layout type of stackComposite1 to FillLayout, I receive a similar error, complaining about using GridData instead of FillData. However, when I remove the gridComposite altogether from the code, it works fine.

I feel like I'm missing something very crucial here. As far as I understood, layouts only affect the way a Composite arranges UI elements contained within itself. Why is the nested gridComposite forcing its parent stackComposite1 to also use GridData when I clearly am setting it up with another layout type altogether?

Upvotes: 1

Views: 3194

Answers (1)

greg-449
greg-449

Reputation: 111162

You have:

Composite stackComposite1 = new Composite(pageComposite, SWT.NONE);
stackComposite1.setLayout(new RowLayout(SWT.VERTICAL));

so stackComposite1 is using RowLayout.

Then you have:

Composite gridComposite = new Composite(stackComposite1, SWT.NONE);
gridComposite.setLayout(new GridLayout(3, true));
gridComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

the problem line here is:

gridComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

The layout data set by setLayoutData is used by the parent Composite layout - the parent here is stackComposite1 which is using row layout not grid layout. You should use RowData here.

Upvotes: 6

Related Questions