From 51a90d32f847cef9add23e4cc051b98d42a7a33f Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 12 Oct 2021 11:13:40 +0200 Subject: [PATCH] support defining "defaultFont" in FlatLaf properties files (issue #384) --- .../java/com/formdev/flatlaf/FlatLaf.java | 69 ++++++++++++------- .../com/formdev/flatlaf/util/UIScale.java | 60 +++++++++------- 2 files changed, 81 insertions(+), 48 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index cf36cf5e..f5311895 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -44,6 +44,7 @@ import java.util.ResourceBundle; import java.util.ServiceLoader; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.IntUnaryOperator; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; @@ -429,6 +430,10 @@ public abstract class FlatLaf else UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults ); + // setup default font after loading defaults from properties + // to allow defining "defaultFont" in properties + initDefaultFont( defaults ); + // use Aqua MenuBarUI if Mac screen menubar is enabled if( SystemInfo.isMacOS && Boolean.getBoolean( "apple.laf.useScreenMenuBar" ) ) { defaults.put( "MenuBarUI", "com.apple.laf.AquaMenuBarUI" ); @@ -519,8 +524,22 @@ public abstract class FlatLaf } private void initFonts( UIDefaults defaults ) { + // use active value for all fonts to allow changing fonts in all components with: + // UIManager.put( "defaultFont", myFont ); + // (this is similar as in Nimbus L&F) + Object activeFont = new ActiveFont( null, -1, 0, 0, 0, 0 ); + + // override fonts + for( Object key : defaults.keySet() ) { + if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) ) + defaults.put( key, activeFont ); + } + } + + private void initDefaultFont( UIDefaults defaults ) { FontUIResource uiFont = null; + // determine UI font based on operating system if( SystemInfo.isWindows ) { Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" ); if( winFont != null ) { @@ -563,20 +582,21 @@ public abstract class FlatLaf if( uiFont == null ) uiFont = createCompositeFont( Font.SANS_SERIF, Font.PLAIN, 12 ); + // get/remove "defaultFont" from defaults if set in properties files + // (use remove() to avoid that ActiveFont.createValue() gets invoked) + Object defaultFont = defaults.remove( "defaultFont" ); + + // use font from OS as base font and derive the UI font from it + if( defaultFont instanceof ActiveFont ) { + Font baseFont = uiFont; + uiFont = ((ActiveFont)defaultFont).derive( baseFont, fontSize -> { + return Math.round( fontSize * UIScale.computeFontScaleFactor( baseFont ) ); + } ); + }; + // increase font size if system property "flatlaf.uiScale" is set uiFont = UIScale.applyCustomScaleFactor( uiFont ); - // use active value for all fonts to allow changing fonts in all components - // (similar as in Nimbus L&F) with: - // UIManager.put( "defaultFont", myFont ); - Object activeFont = new ActiveFont( null, -1, 0, 0, 0, 0 ); - - // override fonts - for( Object key : defaults.keySet() ) { - if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) ) - defaults.put( key, activeFont ); - } - // set default font defaults.put( "defaultFont", uiFont ); } @@ -1170,7 +1190,7 @@ public abstract class FlatLaf private final float scaleSize; // cache (scaled/derived) font - private Font font; + private FontUIResource font; private Font lastDefaultFont; /** @@ -1204,17 +1224,13 @@ public abstract class FlatLaf if( lastDefaultFont != defaultFont ) { lastDefaultFont = defaultFont; - font = derive( defaultFont ); - - // make sure that font is a UIResource for LaF switching - if( !(font instanceof UIResource) ) - font = new FontUIResource( font ); + font = derive( defaultFont, fontSize -> UIScale.scale( fontSize ) ); } return font; } - private Font derive( Font baseFont ) { + FontUIResource derive( Font baseFont, IntUnaryOperator scale ) { int baseStyle = baseFont.getStyle(); int baseSize = baseFont.getSize(); @@ -1227,9 +1243,9 @@ public abstract class FlatLaf // new size int newSize = (absoluteSize > 0) - ? UIScale.scale( absoluteSize ) + ? scale.applyAsInt( absoluteSize ) : (relativeSize != 0) - ? (baseSize + UIScale.scale( relativeSize )) + ? (baseSize + scale.applyAsInt( relativeSize )) : (scaleSize > 0) ? Math.round( baseSize * scaleSize ) : baseSize; @@ -1241,15 +1257,22 @@ public abstract class FlatLaf for( String family : families ) { Font font = createCompositeFont( family, newStyle, newSize ); if( !isFallbackFont( font ) || family.equalsIgnoreCase( Font.DIALOG ) ) - return font; + return toUIResource( font ); } } // derive font if( newStyle != baseStyle || newSize != baseSize ) - return baseFont.deriveFont( newStyle, newSize ); + return toUIResource( baseFont.deriveFont( newStyle, newSize ) ); else - return baseFont; + return toUIResource( baseFont ); + } + + private FontUIResource toUIResource( Font font ) { + // make sure that font is a UIResource for LaF switching + return (font instanceof FontUIResource) + ? (FontUIResource) font + : new FontUIResource( font ); } private boolean isFallbackFont( Font font ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java index 41f8d35c..c511b846 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java @@ -192,7 +192,15 @@ public class UIScale if( font == null ) font = UIManager.getFont( "Label.font" ); - float newScaleFactor; + setUserScaleFactor( computeFontScaleFactor( font ), true ); + } + + /** + * For internal use only. + * + * @since 2 + */ + public static float computeFontScaleFactor( Font font ) { if( SystemInfo.isWindows ) { // Special handling for Windows to be compatible with OS scaling, // which distinguish between "screen scaling" and "text scaling". @@ -204,33 +212,35 @@ public class UIScale // - Settings > Display > Scale and layout // - Settings > Ease of Access > Display > Make text bigger (100% - 225%) if( font instanceof UIResource ) { - if( isSystemScalingEnabled() ) { - // Do not apply own scaling if the JRE scales using Windows screen scale factor. - // If user increases font size in Windows 10 settings, desktop property - // "win.messagebox.font" is changed and FlatLaf uses the larger font. - newScaleFactor = 1; - } else { - // If the JRE does not scale (Java 8), the size of the UI font - // (usually from desktop property "win.messagebox.font") - // combines the Windows screen and text scale factors. - // But the font in desktop property "win.defaultGUI.font" is only - // scaled with the Windows screen scale factor. So use it to compute - // our scale factor that is equal to Windows screen scale factor. - Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.defaultGUI.font" ); - newScaleFactor = computeScaleFactor( (winFont != null) ? winFont : font ); + Font uiFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" ); + if( uiFont == null || uiFont.getSize() == font.getSize() ) { + if( isSystemScalingEnabled() ) { + // Do not apply own scaling if the JRE scales using Windows screen scale factor. + // If user increases font size in Windows 10 settings, desktop property + // "win.messagebox.font" is changed and FlatLaf uses the larger font. + return 1; + } else { + // If the JRE does not scale (Java 8), the size of the UI font + // (usually from desktop property "win.messagebox.font") + // combines the Windows screen and text scale factors. + // But the font in desktop property "win.defaultGUI.font" is only + // scaled with the Windows screen scale factor. So use it to compute + // our scale factor that is equal to Windows screen scale factor. + Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.defaultGUI.font" ); + return computeScaleFactor( (winFont != null) ? winFont : font ); + } } - } else { - // If font was explicitly set from outside (is not a UIResource) - // use it to compute scale factor. This allows applications to - // use custom fonts (e.g. that the user can change in UI) and - // get scaling if a larger font size is used. - // E.g. FlatLaf Demo supports increasing font size in "Font" menu and UI scales. - newScaleFactor = computeScaleFactor( font ); } - } else - newScaleFactor = computeScaleFactor( font ); - setUserScaleFactor( newScaleFactor, true ); + // If font was explicitly set from outside (is not a UIResource), + // or was set in FlatLaf properties files (is a UIResource), + // use it to compute scale factor. This allows applications to + // use custom fonts (e.g. that the user can change in UI) and + // get scaling if a larger font size is used. + // E.g. FlatLaf Demo supports increasing font size in "Font" menu and UI scales. + } + + return computeScaleFactor( font ); } private static float computeScaleFactor( Font font ) {