Skip to content

[GTK] Adjacent ToolBars get an uneven item spacer #3536

Description

@vogella

During an update of one of my themes (Neon) I noticed that the toolbar items are not evenly distributed for view menu and min/max.

Image

SWT's theming fixes zero out the top and bottom padding of a GTK toolbar, but leave the left and right padding to the GTK theme. Inside a single toolbar you never notice. As soon as two toolbars sit side by side, each one adds its own padding at the seam.

Every view in the IDE shows this, because the strip in the tab area is actually three toolbars: the view toolbar, the view menu toolbar and the minimize/maximize toolbar.

I reproduced the same structure in a snippet (GTK3, Yaru, deviceZoom 100). Each bar contributes 4 px on the left and 3 px on the right:

pitch 27.0 <- inside the view toolbar
pitch 27.0
pitch 34.0 <- across into the view-menu toolbar

The fix, similar to the rest of the styling.

 toolbar {
      padding-top: 2px;
      padding-bottom: 2px;
+     padding-left: 0px;
+     padding-right: 0px;
 }

I built SWT with that change and every pitch becomes a uniform 27.0, so both seams disappear.

Snippet:

import org.eclipse.swt.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/*
 * Adjacent ToolBars get a larger item pitch than items within one ToolBar,
 * because each bar contributes its own horizontal padding at the seam.
 *
 * Reproduces the layout the Eclipse IDE builds in a view's tab area: the view's
 * own ToolBar and the view menu ToolBar in the CTabFolder's topRight composite,
 * plus CTabFolder's own minimize/maximize ToolBar.
 */
public class ToolBarPitch {

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

		CTabFolder folder = new CTabFolder(shell, SWT.BORDER);
		CTabItem tab = new CTabItem(folder, SWT.NONE);
		tab.setText("Project Explorer");
		tab.setControl(new Composite(folder, SWT.NONE));
		folder.setSelection(tab);

		// same topRight composite StackRenderer builds: no spacing, no margins
		Composite topRight = new Composite(folder, SWT.NONE);
		RowLayout layout = new RowLayout();
		layout.spacing = 0;
		layout.marginTop = layout.marginBottom = layout.marginLeft = layout.marginRight = 0;
		topRight.setLayout(layout);
		folder.setTopRight(topRight, SWT.RIGHT | SWT.WRAP);

		Image icon = new Image(display, 16, 16);
		GC gc = new GC(icon);
		gc.fillRectangle(0, 0, 16, 16);
		gc.dispose();

		ToolBar viewBar = new ToolBar(topRight, SWT.FLAT | SWT.RIGHT);
		for (int i = 0; i < 3; i++) new ToolItem(viewBar, SWT.PUSH).setImage(icon);

		ToolBar menuBar = new ToolBar(topRight, SWT.FLAT | SWT.RIGHT);
		new ToolItem(menuBar, SWT.PUSH).setImage(icon);

		folder.setMinimizeVisible(true);
		folder.setMaximizeVisible(true);

		shell.setSize(700, 220);
		shell.open();

		display.timerExec(800, () -> {
			ToolBar minMaxBar = null;
			for (Control child : folder.getChildren()) {
				if (child instanceof ToolBar bar && bar != viewBar && bar != menuBar) minMaxBar = bar;
			}
			double previousCentre = -1;
			for (ToolBar bar : new ToolBar[] { viewBar, menuBar, minMaxBar }) {
				if (bar == null) continue;
				ToolItem[] items = bar.getItems();
				ToolItem last = items[items.length - 1];
				int barX = bar.getParent().toDisplay(bar.getLocation()).x;
				System.out.printf("ToolBar width %d, %d item(s), lead pad %d, trail pad %d%n",
						bar.getSize().x, items.length, items[0].getBounds().x,
						bar.getSize().x - last.getBounds().x - last.getBounds().width);
				for (ToolItem item : items) {
					Rectangle b = item.getBounds();
					double centre = barX + b.x + b.width / 2.0;
					System.out.printf("   item width %d, centre %.1f%s%n", b.width, centre,
							previousCentre < 0 ? "" : String.format(", pitch %.1f", centre - previousCentre));
					previousCentre = centre;
				}
			}
			shell.dispose();
		});

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions