NB! This answer is based on Eclipse RAP which might behave differently then regular SWT.
I was struggling with the exact same issue a couple of days ago. I had two ScrolledComposite
s on the same page and i needed that the left one would not take more space then needed (even if the space would be available).
While trying out different solutions i noticed that the behavior of a ScrolledComposite
depends on its LayoutData
as follows:
- If the
layoutData
is set to new GridData(SWT.LEFT, SWT.TOP, false, true)
, then the ScrolledComposite
will keep it's intended size regardless of parent Composite
size changes.
- If the
layoutData
is set to new GridData(SWT.LEFT, SWT.TOP, true, true)
, then the ScrolledComposite
will shrink/expand according to the size changes of the parent Composite
. This also includes expanding to greater width that was desired (meaning that the columns are kept equal).
Based on this behavior i was able to solve the problem by adding a resize listener to the parent Composite
that changes the layoutData
of the left ScrolledComposite
based on the parent Composite size
.
This approach is illustrated the following example:
public class LayoutingScrolledComposites extends AbstractEntryPoint {
public void createContents( Composite parent ) {
parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
parent.setLayout(new GridLayout(2, false));
ScrolledComposite sc1 = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
Composite c1 = new Composite(sc1, SWT.BORDER);
sc1.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
c1.setLayout(new GridLayout(3, false));
sc1.setContent(c1);
Label l1 = new Label (c1, SWT.BORDER);
l1.setText("Some text");
l1 = new Label (c1, SWT.BORDER);
l1.setText("Some text");
l1 = new Label (c1, SWT.BORDER);
l1.setText("Some text");
c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
ScrolledComposite sc2 = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
sc2.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
Composite c2 = new Composite(sc1, SWT.BORDER);
c2.setLayout(new GridLayout(3, false));
sc2.setContent(c2);
Label l2 = new Label (c2, SWT.BORDER);
l2.setText("Some text");
l2 = new Label (c2, SWT.BORDER);
l2.setText("Some text");
l2 = new Label (c2, SWT.BORDER);
l2.setText("Some text");
c2.setSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
parent.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event e) {
int sc1_x = sc1.getContent().getSize().x;
int sc2_x = sc2.getContent().getSize().x;
//Enable/Disable grabExcessHorizontalSpace based on whether both sc's would fit in the shell
if (LayoutingScrolledComposites.this.getShell().getSize().x > sc1_x+sc2_x) {
if (((GridData)sc1.getLayoutData()).grabExcessHorizontalSpace) {
//sc1 does not change width in this mode
((GridData)sc1.getLayoutData()).grabExcessHorizontalSpace=false;
}
} else {
if (!((GridData)sc1.getLayoutData()).grabExcessHorizontalSpace) {
//sc1 changes width in this mode
((GridData)sc1.getLayoutData()).grabExcessHorizontalSpace=true;
}
}
parent.layout(); //Needed so that the layout change would take effect during the same event
}
});
}
}
However this approach does seem to me a bit too "hackish" solution. Therefore i would love to see a better approach.