Update components border/insets on user scale change

Viewed 73

I'm currently using FlatLaf UI as look&feel for my Swing application.
FlatLaf offers a user scale mechanism based on the font size, e.g.:

12pt: 1.0 | 100%
16pt: 1.3 | 130%

This means all the borders and insets are calculated considering this factor:

BorderFactory.createEmptyBorder(UIScale.scale(10), ... // Which means 10 * 1.3, for example

The problem arises when the user scale is changed and components are shown on screen.
Given I add and customize components on class constructors...

public class ProtocolSearchBar extends Box {
  public ProtocolSearchBar() {
    ...
    add(protocolLabel);
    add(Box.createHorizontalStrut(UIScale.scale(10)));
    add(protocol);
    add(Box.createHorizontalStrut(UIScale.scale(10)));
    add(fetchButton);
  }
  ...

...how can I efficiently update their insets each time the UI scale is changed by the user?

FlatLaf offers a callback to be notified.

UIScale.addPropertyChangeListener(event -> {
  if ("userScaleFactor".equals(event.getPropertyName())) {
    ...
  }
});
1 Answers

A neat solution is extending the standard Swing components, e.g.

public class ScaledFiller extends Filler {
  public enum Axis {
    X_AXIS,
    Y_AXIS
  }

  public ScaledFiller(final int size, final Axis axis) {
    super(
        new Dimension(axis == X_AXIS ? size : 0, axis == Y_AXIS ? size : 0),
        new Dimension(axis == X_AXIS ? size : 0, axis == Y_AXIS ? size : 0),
        new Dimension(axis == X_AXIS ? size : Short.MAX_VALUE, axis == Y_AXIS ? size : Short.MAX_VALUE)
    );
  }

  public ScaledFiller(final Dimension min, final Dimension pref, final Dimension max) {
    super(min, pref, max);
  }

  @Override
  public Dimension getMinimumSize() {
    return new ScaledDimension(super.getMinimumSize());
  }

  @Override
  public Dimension getPreferredSize() {
    return new ScaledDimension(super.getPreferredSize());
  }

  @Override
  public Dimension getMaximumSize() {
    return new ScaledDimension(super.getMaximumSize());
  }
}

And used as

@NotNull
public static Filler horizontalStrut(final int size) {
  return new ScaledFiller(size, ScaledFiller.Axis.X_AXIS);
}

@NotNull
public static Filler verticalStrut(final int size) {
  return new ScaledFiller(size, ScaledFiller.Axis.Y_AXIS);
}
Related