mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
UIScale introduced
This commit is contained in:
@@ -25,6 +25,7 @@ import java.awt.Insets;
|
||||
import java.awt.Paint;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicBorders;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Border for {@link javax.swing.JButton}.
|
||||
@@ -42,7 +43,7 @@ public class FlatButtonBorder
|
||||
|
||||
float focusWidth = getFocusWidth();
|
||||
float lineWidth = getLineWidth();
|
||||
float arc = 6; //TODO
|
||||
float arc = UIScale.scale( 6f ); //TODO
|
||||
|
||||
g2.setPaint( getBorderColor( c ) );
|
||||
FlatUIUtils.drawRoundRectangle( g2, x, y, width, height, focusWidth, lineWidth, arc );
|
||||
@@ -66,7 +67,7 @@ public class FlatButtonBorder
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
int w = Math.round( getFocusWidth() + getLineWidth() );
|
||||
int w = UIScale.round( getFocusWidth() + getLineWidth() );
|
||||
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
insets.top += w;
|
||||
@@ -78,11 +79,11 @@ public class FlatButtonBorder
|
||||
|
||||
protected float getFocusWidth() {
|
||||
//TODO
|
||||
return 2;
|
||||
return UIScale.scale( 2f );
|
||||
}
|
||||
|
||||
protected float getLineWidth() {
|
||||
//TODO
|
||||
return 1;
|
||||
return UIScale.scale( 1f );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import javax.swing.JComponent;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicButtonUI;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import sun.swing.SwingUtilities2;
|
||||
|
||||
/**
|
||||
@@ -61,8 +62,8 @@ public class FlatButtonUI
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
//TODO
|
||||
float focusWidth = 2;
|
||||
float arc = 6;
|
||||
float focusWidth = UIScale.scale( 2f );
|
||||
float arc = UIScale.scale( 6f );
|
||||
|
||||
g2.setColor( getBackground( c ) );
|
||||
FlatUIUtils.fillRoundRectangle( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Provides information about the current system.
|
||||
@@ -29,11 +30,43 @@ public class SystemInfo
|
||||
public static final boolean IS_MAC;
|
||||
public static final boolean IS_LINUX;
|
||||
|
||||
public static final boolean IS_JAVA_9_OR_LATER;
|
||||
|
||||
public static final boolean IS_JETBRAINS_JVM;
|
||||
|
||||
static {
|
||||
String osName = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH );
|
||||
|
||||
IS_WINDOWS = osName.startsWith( "windows" );
|
||||
IS_MAC = osName.startsWith( "mac" );
|
||||
IS_LINUX = osName.startsWith( "linux" );
|
||||
|
||||
int javaVersion = scanVersion( System.getProperty( "java.version" ) );
|
||||
IS_JAVA_9_OR_LATER = (javaVersion >= toVersion( 9, 0, 0, 0 ));
|
||||
|
||||
IS_JETBRAINS_JVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
||||
.toLowerCase( Locale.ENGLISH ).contains( "jetbrains" );
|
||||
}
|
||||
|
||||
private static int scanVersion( String version ) {
|
||||
int major = 1;
|
||||
int minor = 0;
|
||||
int micro = 0;
|
||||
int patch = 0;
|
||||
try {
|
||||
StringTokenizer st = new StringTokenizer( version, "._-+" );
|
||||
major = Integer.parseInt( st.nextToken() );
|
||||
minor = Integer.parseInt( st.nextToken() );
|
||||
micro = Integer.parseInt( st.nextToken() );
|
||||
patch = Integer.parseInt( st.nextToken() );
|
||||
} catch( Exception ex ) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return toVersion( major, minor, micro, patch );
|
||||
}
|
||||
|
||||
private static int toVersion( int major, int minor, int micro, int patch ) {
|
||||
return (major << 24) + (minor << 16) + (micro << 8) + patch;
|
||||
}
|
||||
}
|
||||
|
||||
188
flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java
Normal file
188
flatlaf-core/src/main/java/com/formdev/flatlaf/util/UIScale.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Two scaling modes are supported for HiDPI displays:
|
||||
*
|
||||
* 1) system scaling mode
|
||||
*
|
||||
* This mode is supported since Java 9 on all platforms and in some Java 8 VMs
|
||||
* (e.g. Apple and JetBrains). The JRE determines the scale factor per-display and
|
||||
* adds a scaling transformation to the graphics object.
|
||||
* E.g. invokes {@code java.awt.Graphics2D.scale( 1.5, 1.5 )} for 150%.
|
||||
* So the JRE does the scaling itself.
|
||||
* E.g. when you draw a 10px line, a 15px line is drawn on screen.
|
||||
* The scale factor may be different for each connected display.
|
||||
*
|
||||
* 2) user scaling mode
|
||||
*
|
||||
* This mode is for Java 8 compatibility and can be removed when changing minimum
|
||||
* required Java version to 9.
|
||||
* The user scale factor is computed based on the used font.
|
||||
* The JRE does not scale anything.
|
||||
* So we have to invoke {@link #scale(float)} where necessary.
|
||||
* There is only one user scale factor for all displays.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class UIScale
|
||||
{
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
//---- system scaling (Java 9) --------------------------------------------
|
||||
|
||||
private static Boolean jreHiDPI;
|
||||
|
||||
private static boolean isJreHiDPIEnabled() {
|
||||
if( jreHiDPI != null )
|
||||
return jreHiDPI;
|
||||
|
||||
jreHiDPI = false;
|
||||
|
||||
if( SystemInfo.IS_JAVA_9_OR_LATER ) {
|
||||
// Java 9 and later supports per-monitor scaling
|
||||
jreHiDPI = true;
|
||||
} else if( SystemInfo.IS_JETBRAINS_JVM ) {
|
||||
// IntelliJ IDEA ships its own JetBrains Java 8 JRE that may supports per-monitor scaling
|
||||
// see com.intellij.ui.JreHiDpiUtil.isJreHiDPIEnabled()
|
||||
try {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
Class<?> sunGeClass = Class.forName( "sun.java2d.SunGraphicsEnvironment" );
|
||||
if( sunGeClass.isInstance( ge ) ) {
|
||||
Method m = sunGeClass.getDeclaredMethod( "isUIScaleOn" );
|
||||
jreHiDPI = (Boolean) m.invoke( ge );
|
||||
}
|
||||
} catch( Throwable ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return jreHiDPI;
|
||||
}
|
||||
|
||||
//---- user scaling (Java 8) ----------------------------------------------
|
||||
|
||||
private static float scaleFactor = 1;
|
||||
|
||||
static {
|
||||
if( isEnabled() ) {
|
||||
// listener to update scale factor if LaF changed or if Label.font changed
|
||||
// (e.g. option "Override default fonts" in IntelliJ IDEA)
|
||||
PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
String propName = e.getPropertyName();
|
||||
if( "lookAndFeel".equals( propName ) ) {
|
||||
// it is not necessary (and possible) to remove listener of old LaF defaults
|
||||
if( e.getNewValue() instanceof LookAndFeel )
|
||||
UIManager.getLookAndFeelDefaults().addPropertyChangeListener( this );
|
||||
updateScaleFactor();
|
||||
} else if( "Label.font".equals( propName ) )
|
||||
updateScaleFactor();
|
||||
}
|
||||
};
|
||||
UIManager.addPropertyChangeListener( listener );
|
||||
UIManager.getLookAndFeelDefaults().addPropertyChangeListener( listener );
|
||||
|
||||
updateScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateScaleFactor() {
|
||||
if( !isEnabled() )
|
||||
return;
|
||||
|
||||
// use font size to calculate scale factor (instead of DPI)
|
||||
// because even if we are on a HiDPI display it is not sure
|
||||
// that a larger font size is set by the current LaF
|
||||
// (e.g. can avoid large icons with small text)
|
||||
Font font = UIManager.getFont( "Label.font" );
|
||||
|
||||
// default font size
|
||||
float fontSizeDivider = 12f;
|
||||
|
||||
if( SystemInfo.IS_WINDOWS ) {
|
||||
// Windows LaF uses Tahoma font rather than the actual Windows system font (Segoe UI),
|
||||
// and its size is always ca. 10% smaller than the actual system font size.
|
||||
// Tahoma 11 is used at 100%
|
||||
if( "Tahoma".equals( font.getFamily() ) )
|
||||
fontSizeDivider = 11f;
|
||||
} else if( SystemInfo.IS_LINUX ) {
|
||||
// default font size for Unity and Gnome is 15
|
||||
fontSizeDivider = 15f;
|
||||
}
|
||||
|
||||
setUserScaleFactor( font.getSize() / fontSizeDivider );
|
||||
}
|
||||
|
||||
private static boolean isEnabled() {
|
||||
if( isJreHiDPIEnabled() )
|
||||
return false; // disable user scaling if JRE scales
|
||||
|
||||
// same as in IntelliJ IDEA
|
||||
String hidpi = System.getProperty( "hidpi" );
|
||||
return (hidpi != null) ? Boolean.parseBoolean( hidpi ) : true;
|
||||
}
|
||||
|
||||
public static float getUserScaleFactor() {
|
||||
return scaleFactor;
|
||||
}
|
||||
|
||||
private static void setUserScaleFactor( float scaleFactor ) {
|
||||
if( scaleFactor <= 1f )
|
||||
scaleFactor = 1f;
|
||||
else // round scale factor to 1/4
|
||||
scaleFactor = Math.round( scaleFactor * 4f ) / 4f;
|
||||
|
||||
UIScale.scaleFactor = scaleFactor;
|
||||
|
||||
if( DEBUG )
|
||||
System.out.println( "HiDPI scale factor " + scaleFactor );
|
||||
}
|
||||
|
||||
public static float scale( float value ) {
|
||||
return (scaleFactor == 1) ? value : (value * scaleFactor);
|
||||
}
|
||||
|
||||
public static int scale( int value ) {
|
||||
return (scaleFactor == 1) ? value : round( value * scaleFactor );
|
||||
}
|
||||
|
||||
public static float unscale( float value ) {
|
||||
return (scaleFactor == 1f) ? value : (value / scaleFactor);
|
||||
}
|
||||
|
||||
public static int unscale( int value ) {
|
||||
return (scaleFactor == 1f) ? value : round( value / scaleFactor );
|
||||
}
|
||||
|
||||
public static int round( float value ) {
|
||||
// subtracting 0.01 gives "better" results in some cases
|
||||
// e.g. 2px * 125% = 2px instead of 3px
|
||||
// or 1px * 150% = 1px instead of 2px
|
||||
return Math.round( value - 0.01f );
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class FlatComponentsTest
|
||||
|
||||
JOptionPane.showMessageDialog( null,
|
||||
new FlatComponentsTest(),
|
||||
"FlatComponentsTest",
|
||||
"FlatComponentsTest (Java " + System.getProperty( "java.version" ) + ")",
|
||||
JOptionPane.PLAIN_MESSAGE );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user