I'd like to have a ScrolledComposite
which has a parent with GridLayout
but the scrollbar doesn't show up, unless I use FillLayout
. My problem with FillLayout
is that its children takes equal parts of the available space.
In my case there are two widgets, the one on top should take not more than 1/4 of the window and the ScrolledComposite
should take the remainder space. However, both of them take half of it.
Is there a way to use a GridLayout
with ScrolledComposite
or is it possible to modify the behaviour of FillLayout
?
Here's my code:
private void initContent() {
//GridLayout shellLayout = new GridLayout();
//shellLayout.numColumns = 1;
//shellLayout.verticalSpacing = 10;
//shell.setLayout(shellLayout);
shell.setLayout(new FillLayout(SWT.VERTICAL));
searchComposite = new SearchComposite(shell, SWT.NONE);
searchComposite.getSearchButton().addListener(SWT.Selection, this);
ScrolledComposite scroll = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
scroll.setLayout(new GridLayout(1, true));
Composite scrollContent = new Composite(scroll, SWT.NONE);
scrollContent.setLayout(new GridLayout(1, true));
for (ChangeDescription description : getChanges(false)) {
ChangesComposite cc = new ChangesComposite(scrollContent, description);
}
scroll.setMinSize(scrollContent.computeSize(SWT.DEFAULT, SWT.DEFAULT));
scroll.setContent(scrollContent);
scroll.setExpandVertical(true);
scroll.setExpandHorizontal(true);
scroll.setAlwaysShowScrollBars(true);
}
In addition to setLayout(), it is necessary to call setLayoutData(). In the following code example, take a look at how the GridData
objects are constructed and passed to each of the two setLayoutData() calls.
private void initContent(Shell shell)
{
// Configure shell
shell.setLayout(new GridLayout());
// Configure standard composite
Composite standardComposite = new Composite(shell, SWT.NONE);
standardComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
// Configure scrolled composite
ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
scrolledComposite.setLayout(new GridLayout());
scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
scrolledComposite.setExpandVertical(true);
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setAlwaysShowScrollBars(true);
// Add content to scrolled composite
Composite scrolledContent = new Composite(scrolledComposite, SWT.NONE);
scrolledContent.setLayout(new GridLayout());
scrolledComposite.setContent(scrolledContent);
}
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:
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.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With