简体   繁体   中英

Hide GridLayout column and remaining column spacing

tl;dr Is there a good way to hide a column in a GridLayout and also hide the remaining column spacing on the parent Composite ?


I have a composite with several columns in a GridLayout . One column is a Composite with a StackLayout so that given some action I can hide/show that Composite .

For example: 在此处输入图片说明

To do the hiding/showing I've been setting the exclude attribute on the GridData and the topControl attribute on the StackLayout :

// To hide
stackLayout.topControl = null;
stackComposite.setVisible(false);
((GridData) stackComposite.getLayoutData()).exclude = true;

Now, when I hide the middle Composite , I see extra space appear at the far end of the row.

在此处输入图片说明

This is presumably because the GridLayout on the base Composite still has the same number of columns, so what we see is a column with 0 width, and the specified column spacing on either side.

To fix this I've come up with several (not-ideal) solutions:

  1. Decrement/increment the number of columns when hiding/showing.

  2. Instead of using the exclude attribute, we override the Composite with the StackLayout and change the computeSize(...) functions to either return 0, or compute the real size depending on whether we want it to appear or not. (This is by far my least favorite option and I feel bad even writing it)

  3. Set the horizontalSpacing on the base Composite to 0, and instead using the spacing inside each columns Composite to dictate the spacing. It would look like this when hidden:

在此处输入图片说明

Option 1 has been the most enticing so far, however there's an clear drawback here when trying to keep code modular. For example, if the Composite for each column is setup by some reusable component, decrementing/incrementing a column count depends on that component knowing that its parent Composite has a GridLayout - not a safe assumption!

Option 2 I flat-out do not like.

Option 3 isn't horrible, however it still feels like a misuse of spacing and margins. Plus, back to the point of modularity, the other column components would be responsible spacing which affects the larger view, instead of letting the larger view dictate the spacing.

So my question comes down to: is there another option that's better than these three?


MCVE used to get the images above:

public class MCVE {

    final Display display;
    final Shell shell;

    public MCVE() {
        display = new Display();
        shell = new Shell(display);
        shell.setLayout(new GridLayout());
        shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final Composite baseComposite = new Composite(shell, SWT.NONE);
        baseComposite.setLayout(new GridLayout(3, false));
        baseComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        baseComposite.setBackground(new Color(display, new RGB(125, 125, 255)));

        final Composite contentComposite1 = new Composite(baseComposite, SWT.NONE);
        contentComposite1.setLayout(new GridLayout());
        contentComposite1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        final Label contentLabel1 = new Label(contentComposite1, SWT.NONE);
        contentLabel1.setText("I stretch to fill available space!");

        final Composite stackComposite = new Composite(baseComposite, SWT.NONE);
        final StackLayout stackLayout = new StackLayout();
        stackComposite.setLayout(stackLayout);
        stackComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));

        final Composite stackContentComposite = new Composite(stackComposite, SWT.NONE);
        stackContentComposite.setLayout(new GridLayout());
        stackContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        final Label stackContentLabel = new Label(stackContentComposite, SWT.NONE);
        stackContentLabel.setText("I can disappear and reappear!");

        stackLayout.topControl = stackContentComposite;

        final Composite contentComposite3 = new Composite(baseComposite, SWT.NONE);
        contentComposite3.setLayout(new GridLayout());
        contentComposite3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
        final Label contentLabel3 = new Label(contentComposite3, SWT.NONE);
        contentLabel3.setText("I live on the end :(");

        final Button flipButton = new Button(shell, SWT.PUSH);
        flipButton.setText("Flip");
        flipButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                if (stackLayout.topControl == null) {
                    stackLayout.topControl = stackContentComposite;
                    ((GridData) stackComposite.getLayoutData()).exclude = false;
                    // ((GridLayout) baseComposite.getLayout()).numColumns++;
                    stackComposite.setVisible(true);
                    baseComposite.layout(true, true);
                } else {
                    stackLayout.topControl = null;
                    ((GridData) stackComposite.getLayoutData()).exclude = true;
                    // ((GridLayout) baseComposite.getLayout()).numColumns--;
                    stackComposite.setVisible(false);
                    baseComposite.layout(true, true);
                }
            }
        });
    }

    public void run() {
        shell.setSize(600, 115);
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }

    public static void main(final String... args) {
        new MCVE().run();
    }

}

I can't think of any other way.

Option 1 is definitely what I would use and is used widely by Eclipse code (buttons on the dialog button bar for example).

Since you are already assuming the control layout data is GridData it is safe to assume the parent layout is GridLayout (setting GridData as layout data on some other layout will generally give a run time error).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM