eclipse-platform / eclipse.platform.swt

Eclipse SWT
https://www.eclipse.org/swt/
Eclipse Public License 2.0
105 stars 125 forks source link

[macOS] GridLayout: misaligned label radio button or checkbox #937

Open tmssngr opened 7 months ago

tmssngr commented 7 months ago

Describe the bug Try to align the base line of a label and a radio button or checkbox. On macOS this won't work by using the GridLayout and vertically centered alignment, because labels have an add default height while radio buttons or checkboxes have an even default height.

To Reproduce Please run this snippet

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class LabelRadioButtonAlignment {

    public static void main(String[] args) {
        final Display display = new Display();

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

        createLabel(shell, "Label:");
        createButton(shell, 1, SWT.RADIO);
        createButton(shell, 2, SWT.RADIO);

        createLabel(shell, "Label:");
        createButton(shell, 1, SWT.CHECK);

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

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

        display.dispose();
    }

    private static void createLabel(Shell shell, String text) {
        final Label label = new Label(shell, SWT.NONE);
        label.setText(text);
        System.out.println(text + " " + label.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
    }

    private static void createButton(Shell shell, int index, int style) {
        final Button radio = new Button(shell, style);
        final String text = "Option " + index;
        radio.setText(text);
        System.out.println(text + ": " + radio.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        radio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
    }
}

Expected behavior The base line of the label, radio buttons and checkbox are at the same y coordinate.

Screenshots Screenshot 2023-12-14 at 09 50 42

Environment:

  1. Select the platform(s) on which the behavior is seen:

      • [ ] All OS
      • [ ] Windows
      • [ ] Linux
      • [x] macOS
  2. Additional OS info (e.g. OS version, Linux Desktop, etc) Screenshot was taken on macOS 14.2.

Workaround (or) Additional context Use an own layout manager.

tmssngr commented 7 months ago

Here is the same image shown with a baseline and zoomed 8 times: zoomed

tmssngr commented 7 months ago

I could not reproduce this problem on Windows and Linux, because on these platforms the labels, radiobuttons and checkboxes have the same default vertical height.

tmssngr commented 7 months ago

Even worse it is for comboboxes: Screenshot 2023-12-14 at 12 25 13


import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;

public class LabelRadioButtonAlignment {

    public static void main(String[] args) {
        final Display display = new Display();

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

        createLabel(shell);
        createButton(shell, 1, SWT.RADIO);
        createButton(shell, 2, SWT.RADIO);

        createLabel(shell);
        final Button radio = new Button(shell, SWT.CHECK);
        radio.setText("Option " + 1);
        System.out.println("Checkbox: " + radio.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        radio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));

        createLabel(shell);
        final Combo combo = new Combo(shell, SWT.BORDER | SWT.READ_ONLY);
        combo.setItems("Option 1", "Option 2");
        combo.select(0);
        System.out.println("Combo: " + combo.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        combo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));

        createLabel(shell);
        final Combo editableCombo = new Combo(shell, SWT.BORDER);
        editableCombo.setItems("Option 1", "Option 2");
        editableCombo.select(0);
        System.out.println("Editable Combo: " + editableCombo.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        editableCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

        createLabel(shell);
        final Text text = new Text(shell, SWT.BORDER);
        text.setText("Text field");
        System.out.println("Text field: " + text.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));

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

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

        display.dispose();
    }

    private static void createLabel(Shell shell) {
        final Label label = new Label(shell, SWT.NONE);
        final String text = "Label:";
        label.setText(text);
        System.out.println(text + " " + label.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
    }

    private static void createButton(Shell shell, int index, int style) {
        final Button radio = new Button(shell, style);
        final String text = "Option " + index;
        radio.setText(text);
        System.out.println(text + ": " + radio.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
        radio.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
    }
}```