Dims
Dims

Reputation: 51239

How to make SWT button, text and label of the same height on Windows?

I am trying to make a GUI for chatting and I placed three SWT controls in a row.

Unfortunately I can't find beautiful alignment for them.

The following code

    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new GridLayout(3, false));

    Label firstLabel = new Label(shell, SWT.NONE);
    firstLabel.setText("PROMPT:");
    firstLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));

    Text firstText = new Text(shell, SWT.NONE);
    firstText.setText("hello");
    firstText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

    Button firstButton = new Button(shell, SWT.PUSH);
    firstButton.setText("Say");
    firstButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));

    shell.pack();
    shell.open();
    shell.setSize(400, 300);

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

gives

enter image description here

i.e. text field is as tall as a button but text is not centered vertically inside it.

If code the text following way

    Text firstText = new Text(shell, SWT.NONE);
    firstText.setText("hello");
    firstText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

I will get

enter image description here

The most beautiful result will be given by

    Text firstText = new Text(shell, SWT.BORDER);
    firstText.setText("hello");
    firstText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

which is

enter image description here

but a button is again slightly taller than a text.

UPDATE

People say they have good result on non-windows platforms, but the question is probably how to control padding/margins of SWT controls.

UPDATE 2

Even in best case text field height is smaller that button's on Windows and the result is platform-dependent.

enter image description here

Upvotes: 6

Views: 4842

Answers (2)

Stefan
Stefan

Reputation: 12370

I use a custom label that wraps the actual label in a composite.

package org.treez.core.swt;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.widgets.FormToolkit;

/**
 * A label composite that vertically aligns with Text
 * 
 */
public class CustomLabel extends Composite {

    // #region ATTRIBUTES

    /**
     * The wrapped label
     */
    Label label;

    // #end region

    // #region CONSTRUCTORS

    /**
     * Constructor
     * @param toolkit 
     * 
     * @param parent
     * @param text
     */
    public CustomLabel(FormToolkit toolkit, Composite parent, String text) {
        super(parent, SWT.NONE);        
        setGridLayoutWithoutMargins(this);  
        Composite verticalAlignmentContainer = createContainer(parent, toolkit);
        label = toolkit.createLabel(verticalAlignmentContainer, text);      
    }

    // #end region

    // #region METHODS

    /**
     * Creates a wrapping container
     * 
     * @param parent
     * @param toolkit
     * @return
     */
    private static Composite createContainer(Composite parent,
            FormToolkit toolkit) {
        Composite container = toolkit.createComposite(parent,SWT.NONE);     
        setGridLayoutWithoutMargins(container);         
        return container;
    }

    /**
     * Sets the grid layout 
     * 
     * @param container
     */
    private static void setGridLayoutWithoutMargins(Composite container) {
        org.eclipse.swt.layout.GridLayout gridLayout = new org.eclipse.swt.layout.GridLayout(1,false);
        gridLayout.horizontalSpacing = 0;       
        gridLayout.verticalSpacing = 0;
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;     
        container.setLayout(gridLayout);

        GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
        container.setLayoutData(gridData);
    }

    /**
     * Sets a preferred width for short labels
     * 
     * @param preferredWidth
     */
    public void setPrefferedWidth(int preferredWidth) {

        int labelWidth = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
        if (labelWidth < preferredWidth) {
            GridDataFactory.fillDefaults().hint(preferredWidth, SWT.DEFAULT)
                    .applyTo(label);            
        }               
    }

    // #end region

    // #region ACCESSORS

    /**
     * Sets the text
     * 
     * @param text
     */
    public void setText(String text) {
        label.setText(text);
    }

    /**
     * Returns the text
     * 
     * @return
     */
    public String getText() {
        return label.getText();
    }

    /**
     * Sets the background color
     */
    @Override
    public void setBackground(Color color) {
        super.setBackground(color);
        label.setBackground(color);
    }

    /**
     * Return the size
     */
    @Override
    public Point getSize(){
        return label.getSize();
    }

    /**
     * Return the bounds
     */
    @Override
    public Rectangle getBounds(){
        return label.getBounds();
    }

    // #end region

}

Upvotes: 0

Baz
Baz

Reputation: 36904

Here is a code example that should give you an idea how to solve your problem:

public static void main(String[] args)
{
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new GridLayout(3, false));

    Label firstLabel = new Label(shell, SWT.NONE);
    firstLabel.setText("PROMPT:");
    firstLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));

    Text firstText = new Text(shell, SWT.BORDER);
    firstText.setText("hello");
    firstText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

    Button firstButton = new Button(shell, SWT.PUSH);
    firstButton.setText("Say");
    firstButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));

    Label secondLabel = new Label(shell, SWT.NONE);
    secondLabel.setText("PROMPT:");
    secondLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));

    Text secondText = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.WRAP);
    secondText.setText("hello");
    secondText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    Button secondButton = new Button(shell, SWT.PUSH);
    secondButton.setText("Say");
    secondButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, true));

    shell.pack();
    shell.open();
    shell.setSize(400, 300);

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

Looks like this:

enter image description here

Without SWT.BORDER:

enter image description here

Upvotes: 4

Related Questions