Eclipse RCP Layout: SWT GridLayout

If you develop an RCP rich client application, sooner or later you will have to know some layout to organize the widgets in your view. This code example requires that you have an RCP application with a view. Here is how to make an RCP app with a view.

This tutorial is about the most powerful and flexible layout - GridLayout.

GridLayout

GridLayout is a frequently used layout for eclipse RCP apps, it can layout your widgets in a well-formed grid. As it's name, the GridLayout separate the view to a grid and put each component to a grid.

The goal of this code example looks like the following:

This is a typical embedded composite layout. The bottom composite("top") is use a GridLayout. Of course, you can directly add to parent composite, or even add more layers of composite.

	public void createPartControl(Composite parent) {
		Composite top = new Composite(parent, SWT.NONE);
 
		top.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL,
				GridData.VERTICAL_ALIGN_BEGINNING, true, false));
		GridLayout layout = new GridLayout();
		layout.marginHeight = 5;
		layout.marginWidth = 5;
		// the number of pixels of vertical margin that will be placed along
		// the top and bottom edges of the layout.
 
		layout.makeColumnsEqualWidth = true;// make each column have same width
		layout.numColumns = 4; // number of columns
		layout.verticalSpacing = 10;
		top.setLayout(layout);
 
		new Button(top, SWT.PUSH).setText("B1");
		new Button(top, SWT.PUSH).setText("B 2");
		new Button(top, SWT.PUSH).setText("Button 3");
		new Button(top, SWT.PUSH).setText("B4");
 
		new Button(top, SWT.PUSH).setText("Button 5");
		new Button(top, SWT.PUSH).setText("Button 6");
		new Button(top, SWT.PUSH).setText("B7");
		new Button(top, SWT.PUSH).setText("Wide Button 8");
		new Button(top, SWT.PUSH).setText("Button 9");
		new Button(top, SWT.PUSH).setText("B10");
 
		final Text text = new Text(top, SWT.MULTI | SWT.WRAP);
		text.setText("a text area");
 
		GridData gridData = new GridData();
 
		// here like the banner, text is added to "top".
		text.setText("a text area");
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 4;
		gridData.grabExcessVerticalSpace = true;
		gridData.grabExcessHorizontalSpace = true;
		text.setLayoutData(gridData);
	}

You can check out the reference to see more available field from GridLayout that you can assign different values.

It is trivial to just add those component/widget to your view, but what if I want to skip some cell(s) and leave them empty?

To skip a cell in a grid, you can simple add an empty label to the grid to skip, such as the following:

new Label(banner, SWT.SINGLE);

Apparently, this is not the correct way to skip a cell, even though it works very well. To do it correctly, we need another class called GridData.

GridData

GridData is the layout data object that are used within a GridLayout. The rule for GridData is that every component/widget in a GridLayout must have a unique GridData object. That is, the GridData object is not sharable among different widget even though they are exactly the same. To set a widget's GridData object, we can use the setLayoutData method.

In the following exam, the button "B10" is set to span 2 cells horizontally. If you let this button align to the left then the next cell is skiped/empty.

GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
button.setLayoutData(gridData);

horizontalAlignment could also be GridData.BEGINNING, GridData.CENTER, and GridData.END.
horizontalSpan spans the cell to 2 cells from the current cell horizontally.

This is the same for vertical alignment and verticalSpan, which use the following fields.

gridData.verticalAlignment = GridData.FILL;
gridData.verticalSpan = 2;

Note: verticalSpan span cells from the first row to the second row, vice does not work.

We can also let widget's size change or not if window size is dragged to be enlarged. For example, you may want the text area's size to change according to the window size. This can be achieved by simple using the following two fields.

gridData.grabExcessVerticalSpace = true;
gridData.grabExcessHorizontalSpace = true;

The example below let "Button 6" grew horizontally and vertically, but "B10" grew only horizontally. By comparing the code below, the reason can be easily figured out. The other buttons stayed with their original sizes, since we do not add anything related with grabbing space.

GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
gridData.grabExcessVerticalSpace = true;	
gridData.grabExcessHorizontalSpace = true;
button.setLayoutData(gridData);
 
gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalAlignment = GridData.FILL;
gridData.verticalSpan = 2;
gridData.grabExcessVerticalSpace = true;	
gridData.grabExcessHorizontalSpace = true;
b6.setLayoutData(gridData);

Many other fancy layouts are just various combination of different values of the above fields. The good way to figure it out is to start with a project and optimize the layout again and again. This is exactly the same way of how we optimized CSS layout for webpage.

You may curious about how to change the windows size, this is out of layout's control.

Reference:

1. GridLayout doc from eclipse

2. GridData doc from eclipse

Category >> Rich Client Platform(RCP)  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • ryanlr

    If the code generated by WindowBuilder is easy to adjust and change, then I would like to use it. Otherwise, I would create my own to have a better control.

  • would u recommend to rather code those ui stuff by hand instead using the WindowBuilder?

  • ryanlr

    I don’t use WindowBuilder. From the error message, GridData and FillData are not in an inheritance relation, so the exception is thrown.

  • try to load the view above in WindowBuilder design mode will cause it to crash:

    WindowBuilder encountered unexpected internal error.

    This could be caused by a WindowBuilder bug or by a misconfiguration issue,
    conflict, partial update, etc.

    java.lang.ClassCastException: org.eclipse.swt.layout.GridData cannot be cast
    to org.eclipse.swt.layout.FillData

    Any ideas?