mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-09 16:25:10 +03:00
fixed/improved vertical position of text when scaled on HiDPI screens on Windows when running on Java 9 or later
This commit is contained in:
@@ -18,6 +18,8 @@ FlatLaf Change Log
|
|||||||
`Spinner.buttonStyle` to `button` (default) or `none`).
|
`Spinner.buttonStyle` to `button` (default) or `none`).
|
||||||
- TableHeader: Support top/bottom/left positioned sort arrow when using
|
- TableHeader: Support top/bottom/left positioned sort arrow when using
|
||||||
[Glazed Lists](https://github.com/glazedlists/glazedlists). (issue #113)
|
[Glazed Lists](https://github.com/glazedlists/glazedlists). (issue #113)
|
||||||
|
- Fixed/improved vertical position of text when scaled on HiDPI screens on
|
||||||
|
Windows when running on Java 9 or later.
|
||||||
|
|
||||||
|
|
||||||
## 0.36
|
## 0.36
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
@@ -28,6 +29,7 @@ import javax.swing.plaf.UIResource;
|
|||||||
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
||||||
@@ -119,6 +121,11 @@ public class FlatEditorPaneUI
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintSafely( Graphics g ) {
|
||||||
|
super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
@@ -29,7 +30,9 @@ import javax.swing.UIManager;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.plaf.basic.BasicLabelUI;
|
import javax.swing.plaf.basic.BasicLabelUI;
|
||||||
|
import javax.swing.text.View;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,6 +127,12 @@ public class FlatLabelUI
|
|||||||
BasicHTML.updateRenderer( c, text );
|
BasicHTML.updateRenderer( c, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint( Graphics g, JComponent c ) {
|
||||||
|
View v = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
super.paint( (v != null) ? HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) : g, c );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintEnabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
|
protected void paintEnabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
|
||||||
int mnemIndex = FlatLaf.isShowMnemonics() ? l.getDisplayedMnemonicIndex() : -1;
|
int mnemIndex = FlatLaf.isShowMnemonics() ? l.getDisplayedMnemonicIndex() : -1;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.event.FocusListener;
|
import java.awt.event.FocusListener;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
@@ -33,6 +34,7 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
import javax.swing.plaf.basic.BasicPasswordFieldUI;
|
import javax.swing.plaf.basic.BasicPasswordFieldUI;
|
||||||
import javax.swing.text.Caret;
|
import javax.swing.text.Caret;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}.
|
||||||
@@ -153,7 +155,8 @@ public class FlatPasswordFieldUI
|
|||||||
FlatTextFieldUI.paintBackground( g, getComponent(), isIntelliJTheme );
|
FlatTextFieldUI.paintBackground( g, getComponent(), isIntelliJTheme );
|
||||||
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
|
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||||
paintCapsLock( g );
|
paintCapsLock( g );
|
||||||
super.paintSafely( g );
|
|
||||||
|
super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCapsLock( Graphics g ) {
|
protected void paintCapsLock( Graphics g ) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
@@ -27,6 +28,7 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicTextAreaUI;
|
import javax.swing.plaf.basic.BasicTextAreaUI;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextArea}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextArea}.
|
||||||
@@ -89,6 +91,11 @@ public class FlatTextAreaUI
|
|||||||
FlatEditorPaneUI.propertyChange( getComponent(), e );
|
FlatEditorPaneUI.propertyChange( getComponent(), e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintSafely( Graphics g ) {
|
||||||
|
super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import javax.swing.plaf.basic.BasicTextFieldUI;
|
|||||||
import javax.swing.text.Caret;
|
import javax.swing.text.Caret;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
|
||||||
@@ -146,7 +147,8 @@ public class FlatTextFieldUI
|
|||||||
protected void paintSafely( Graphics g ) {
|
protected void paintSafely( Graphics g ) {
|
||||||
paintBackground( g, getComponent(), isIntelliJTheme );
|
paintBackground( g, getComponent(), isIntelliJTheme );
|
||||||
paintPlaceholder( g, getComponent(), placeholderForeground );
|
paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||||
super.paintSafely( g );
|
|
||||||
|
super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
@@ -26,6 +27,7 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicTextPaneUI;
|
import javax.swing.plaf.basic.BasicTextPaneUI;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextPane}.
|
||||||
@@ -99,6 +101,11 @@ public class FlatTextPaneUI
|
|||||||
return FlatEditorPaneUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
return FlatEditorPaneUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintSafely( Graphics g ) {
|
||||||
|
super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicHTML;
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
import javax.swing.plaf.basic.BasicToolTipUI;
|
import javax.swing.plaf.basic.BasicToolTipUI;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,7 +131,7 @@ public class FlatToolTipUI
|
|||||||
FlatUIUtils.drawString( c, g, line, leftToRight ? x : x2 - SwingUtilities.computeStringWidth( fm, line ), y );
|
FlatUIUtils.drawString( c, g, line, leftToRight ? x : x2 - SwingUtilities.computeStringWidth( fm, line ), y );
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
super.paint( g, c );
|
super.paint( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ), c );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMultiLine( JComponent c ) {
|
private boolean isMultiLine( JComponent c ) {
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
|||||||
import com.formdev.flatlaf.util.DerivedColor;
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.JavaCompatibility;
|
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,23 +448,24 @@ public class FlatUIUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given string at the specified location using text properties
|
* Draws the given string at the specified location.
|
||||||
* and anti-aliasing hints from the provided component.
|
* The provided component is used to query text properties and anti-aliasing hints.
|
||||||
*
|
* <p>
|
||||||
* Use this method instead of Graphics.drawString() for correct anti-aliasing.
|
* Use this method instead of {@link Graphics#drawString(String, int, int)} for correct anti-aliasing.
|
||||||
*
|
* <p>
|
||||||
* Replacement for SwingUtilities2.drawString()
|
* Replacement for {@code SwingUtilities2.drawString()}.
|
||||||
|
* Uses {@link HiDPIUtils#drawStringWithYCorrection(JComponent, Graphics2D, String, int, int)}.
|
||||||
*/
|
*/
|
||||||
public static void drawString( JComponent c, Graphics g, String text, int x, int y ) {
|
public static void drawString( JComponent c, Graphics g, String text, int x, int y ) {
|
||||||
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, -1, x, y );
|
HiDPIUtils.drawStringWithYCorrection( c, (Graphics2D) g, text, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given string at the specified location underlining the specified
|
* Draws the given string at the specified location underlining the specified character.
|
||||||
* character. The provided component is used to query text properties and
|
* The provided component is used to query text properties and anti-aliasing hints.
|
||||||
* anti-aliasing hints.
|
* <p>
|
||||||
*
|
* Replacement for {@code SwingUtilities2.drawStringUnderlineCharAt()}.
|
||||||
* Replacement for SwingUtilities2.drawStringUnderlineCharAt()
|
* Uses {@link HiDPIUtils#drawStringUnderlineCharAtWithYCorrection(JComponent, Graphics2D, String, int, int, int)}.
|
||||||
*/
|
*/
|
||||||
public static void drawStringUnderlineCharAt( JComponent c, Graphics g,
|
public static void drawStringUnderlineCharAt( JComponent c, Graphics g,
|
||||||
String text, int underlinedIndex, int x, int y )
|
String text, int underlinedIndex, int x, int y )
|
||||||
@@ -487,7 +487,7 @@ public class FlatUIUtils
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
|
HiDPIUtils.drawStringUnderlineCharAtWithYCorrection( c, (Graphics2D) g, text, underlinedIndex, x, y );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasOpaqueBeenExplicitlySet( JComponent c ) {
|
public static boolean hasOpaqueBeenExplicitlySet( JComponent c ) {
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.util;
|
package com.formdev.flatlaf.util;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.text.AttributedCharacterIterator;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,4 +97,116 @@ public class HiDPIUtils
|
|||||||
private static double normalize( double value ) {
|
private static double normalize( double value ) {
|
||||||
return Math.floor( value + 0.25 ) + 0.25;
|
return Math.floor( value + 0.25 ) + 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Boolean useTextYCorrection;
|
||||||
|
|
||||||
|
private static boolean useTextYCorrection() {
|
||||||
|
if( useTextYCorrection == null )
|
||||||
|
useTextYCorrection = Boolean.valueOf( System.getProperty( "flatlaf.useTextYCorrection", "true" ) );
|
||||||
|
return useTextYCorrection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When painting text on HiDPI screens and the JRE scales, then the text is
|
||||||
|
* painted too far down on some operating systems.
|
||||||
|
* The higher the system scale factor is, the more.
|
||||||
|
* <p>
|
||||||
|
* This methods computes a correction value for the Y position.
|
||||||
|
*/
|
||||||
|
public static float computeTextYCorrection( Graphics2D g ) {
|
||||||
|
if( !useTextYCorrection() || !SystemInfo.IS_WINDOWS || !SystemInfo.IS_JAVA_9_OR_LATER )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
AffineTransform t = g.getTransform();
|
||||||
|
double scaleY = t.getScaleY();
|
||||||
|
if( scaleY < 1.25 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Text is painted at slightly different Y positions depending on scale factor
|
||||||
|
// and Y position of component.
|
||||||
|
// The exact reason is not yet known (to me), but there are several factors:
|
||||||
|
// - fractional scale factors result in fractional component Y device coordinates
|
||||||
|
// - fractional text Y device coordinates are rounded for horizontal lines of characters
|
||||||
|
// - maybe different rounding methods for drawing primitives (e.g. rectangle) and text
|
||||||
|
// - Java adds 0.5 to X/Y positions in before drawing string in BufferedTextPipe.enqueueGlyphList()
|
||||||
|
|
||||||
|
// this is not the optimal solution, but works very good in most cases
|
||||||
|
// (tested with class FlatPaintingStringTest on Windows 10 with font "Segoe UI")
|
||||||
|
if( scaleY <= 1.25 )
|
||||||
|
return -0.875f;
|
||||||
|
if( scaleY <= 1.5 )
|
||||||
|
return -0.625f;
|
||||||
|
if( scaleY <= 1.75 )
|
||||||
|
return -0.875f;
|
||||||
|
if( scaleY <= 2.0 )
|
||||||
|
return -0.75f;
|
||||||
|
if( scaleY <= 2.25 )
|
||||||
|
return -0.875f;
|
||||||
|
if( scaleY <= 3.5 )
|
||||||
|
return -0.75f;
|
||||||
|
return -0.875f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies Y correction and draws the given string at the specified location.
|
||||||
|
* The provided component is used to query text properties and anti-aliasing hints.
|
||||||
|
* <p>
|
||||||
|
* Use this method instead of {@link Graphics#drawString(String, int, int)} for correct anti-aliasing.
|
||||||
|
* <p>
|
||||||
|
* Replacement for {@code SwingUtilities2.drawString()}.
|
||||||
|
*/
|
||||||
|
public static void drawStringWithYCorrection( JComponent c, Graphics2D g, String text, int x, int y ) {
|
||||||
|
drawStringUnderlineCharAtWithYCorrection( c, g, text, -1, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies Y correction and draws the given string at the specified location underlining the specified character.
|
||||||
|
* The provided component is used to query text properties and anti-aliasing hints.
|
||||||
|
* <p>
|
||||||
|
* Replacement for {@code SwingUtilities2.drawStringUnderlineCharAt()}.
|
||||||
|
*/
|
||||||
|
public static void drawStringUnderlineCharAtWithYCorrection( JComponent c,
|
||||||
|
Graphics2D g, String text, int underlinedIndex, int x, int y )
|
||||||
|
{
|
||||||
|
float yCorrection = computeTextYCorrection( g );
|
||||||
|
if( yCorrection != 0 ) {
|
||||||
|
g.translate( 0, yCorrection );
|
||||||
|
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
|
||||||
|
g.translate( 0, -yCorrection );
|
||||||
|
} else
|
||||||
|
JavaCompatibility.drawStringUnderlineCharAt( c, g, text, underlinedIndex, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a graphics object and applies Y correction to string drawing methods.
|
||||||
|
* If no Y correction is necessary, the passed in graphics object is returned.
|
||||||
|
*/
|
||||||
|
public static Graphics2D createGraphicsTextYCorrection( Graphics2D g ) {
|
||||||
|
float yCorrection = computeTextYCorrection( g );
|
||||||
|
if( yCorrection == 0 )
|
||||||
|
return g;
|
||||||
|
|
||||||
|
return new Graphics2DProxy( g ) {
|
||||||
|
@Override
|
||||||
|
public void drawString( String str, int x, int y ) {
|
||||||
|
super.drawString( str, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawString( String str, float x, float y ) {
|
||||||
|
super.drawString( str, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawString( AttributedCharacterIterator iterator, int x, int y ) {
|
||||||
|
super.drawString( iterator, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawString( AttributedCharacterIterator iterator, float x, float y ) {
|
||||||
|
super.drawString( iterator, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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
|
||||||
|
*
|
||||||
|
* https://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.testing;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.JavaCompatibility;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatPaintingStringTest
|
||||||
|
extends JPanel
|
||||||
|
{
|
||||||
|
public static void main( String[] args ) {
|
||||||
|
System.setProperty( "sun.java2d.uiScale", "1x" );
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
FlatTestFrame frame = FlatTestFrame.create( args, "FlatPaintingStringTest" );
|
||||||
|
|
||||||
|
ToolTipManager.sharedInstance().setInitialDelay( 0 );
|
||||||
|
ToolTipManager.sharedInstance().setDismissDelay( 10000 );
|
||||||
|
|
||||||
|
frame.showFrame( FlatPaintingStringTest::new );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatPaintingStringTest() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
if( !SystemInfo.IS_JAVA_9_OR_LATER ) {
|
||||||
|
add( new JLabel( "requires Java 9 or later" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add( new JLabel() );
|
||||||
|
add( new JLabel( "none" ) );
|
||||||
|
add( new JLabel( "flatlaf" ) );
|
||||||
|
add( new JLabel( "0.25*scale" ) );
|
||||||
|
add( new JLabel( "0.5*scale" ) );
|
||||||
|
add( new JLabel( "0.25" ) );
|
||||||
|
add( new JLabel( "0.5" ) );
|
||||||
|
add( new JLabel( "0.625" ) );
|
||||||
|
add( new JLabel( "0.75" ) );
|
||||||
|
add( new JLabel( "0.875" ) );
|
||||||
|
|
||||||
|
YCorrectionFunction none = (g, scaleFactor) -> 0;
|
||||||
|
YCorrectionFunction flatlaf = (g, scaleFactor) -> HiDPIUtils.computeTextYCorrection( g );
|
||||||
|
YCorrectionFunction oneQSysScale = (g, scaleFactor) -> -(0.25f * scaleFactor);
|
||||||
|
YCorrectionFunction halfSysScale = (g, scaleFactor) -> -(0.5f * scaleFactor);
|
||||||
|
YCorrectionFunction oneQ = (g, scaleFactor) -> -0.25f;
|
||||||
|
YCorrectionFunction half = (g, scaleFactor) -> -0.5f;
|
||||||
|
YCorrectionFunction fiveEights = (g, scaleFactor) -> -0.625f;
|
||||||
|
YCorrectionFunction threeQ = (g, scaleFactor) -> -0.75f;
|
||||||
|
YCorrectionFunction sevenEights = (g, scaleFactor) -> -0.875f;
|
||||||
|
|
||||||
|
float[] scaleFactors = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 3f, 3.5f, 4f };
|
||||||
|
|
||||||
|
for( float scaleFactor : scaleFactors ) {
|
||||||
|
add( new JLabel( String.valueOf( scaleFactor ) ), "newLine" );
|
||||||
|
|
||||||
|
add( scaleFactor, none );
|
||||||
|
add( scaleFactor, flatlaf );
|
||||||
|
add( scaleFactor, oneQSysScale );
|
||||||
|
add( scaleFactor, halfSysScale );
|
||||||
|
add( scaleFactor, oneQ );
|
||||||
|
add( scaleFactor, half );
|
||||||
|
add( scaleFactor, fiveEights );
|
||||||
|
add( scaleFactor, threeQ );
|
||||||
|
add( scaleFactor, sevenEights );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add( float scaleFactor, YCorrectionFunction correctionFunction ) {
|
||||||
|
add( new Painter( scaleFactor, correctionFunction, 0 ), "split 4, gapx 0 0" );
|
||||||
|
add( new Painter( scaleFactor, correctionFunction, 0.25f ), "gapx 0 0" );
|
||||||
|
add( new Painter( scaleFactor, correctionFunction, 0.5f ), "gapx 0 0" );
|
||||||
|
add( new Painter( scaleFactor, correctionFunction, 0.75f ), "gapx 0 0" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
|
|
||||||
|
//======== this ========
|
||||||
|
setBorder(null);
|
||||||
|
setLayout(new MigLayout(
|
||||||
|
"insets dialog,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[fill]",
|
||||||
|
// rows
|
||||||
|
"[fill]"));
|
||||||
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
|
||||||
|
private interface YCorrectionFunction {
|
||||||
|
float computeTextYCorrection( Graphics2D g, float scaleFactor );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class Painter ------------------------------------------------------
|
||||||
|
|
||||||
|
public static class Painter
|
||||||
|
extends JLabel
|
||||||
|
{
|
||||||
|
private final float scaleFactor;
|
||||||
|
private final YCorrectionFunction correctionFunction;
|
||||||
|
private final float yOffset;
|
||||||
|
|
||||||
|
public Painter( float scaleFactor, YCorrectionFunction correctionFunction, float yOffset ) {
|
||||||
|
super( "E" );
|
||||||
|
this.scaleFactor = scaleFactor;
|
||||||
|
this.correctionFunction = correctionFunction;
|
||||||
|
this.yOffset = yOffset;
|
||||||
|
setBorder( new EmptyBorder( 2, 4, 2, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredSize() {
|
||||||
|
Dimension size = super.getPreferredSize();
|
||||||
|
Insets insets = getInsets();
|
||||||
|
int leftRight = insets.left + insets.right;
|
||||||
|
return new Dimension(
|
||||||
|
scale( size.width -leftRight ) + leftRight,
|
||||||
|
scale( size.height ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent( Graphics g ) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g;
|
||||||
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
|
// simulate component y position at a fraction
|
||||||
|
if( scaleFactor > 1 )
|
||||||
|
g2.translate( 0, yOffset );
|
||||||
|
|
||||||
|
int width = getWidth();
|
||||||
|
int height = getHeight();
|
||||||
|
Insets insets = getInsets();
|
||||||
|
FontMetrics fm = getFontMetrics( getFont() );
|
||||||
|
|
||||||
|
// paint lines at 1x
|
||||||
|
HiDPIUtils.paintAtScale1x( g2, 0, 0, width, height,
|
||||||
|
(g2d, x2, y2, width2, height2, scaleFactor2) -> {
|
||||||
|
// g.setColor( Color.blue );
|
||||||
|
// g.drawLine( 0, 0, width2, 0 );
|
||||||
|
// g.drawLine( 0, height2 - 1, width2, height2 - 1 );
|
||||||
|
|
||||||
|
int baseline = (int) Math.round( (insets.top + fm.getAscent()) * scaleFactor2 * scaleFactor ) - 1;
|
||||||
|
int topline = height2 - baseline - 1;
|
||||||
|
|
||||||
|
g.setColor( Color.red );
|
||||||
|
g.drawLine( 0, baseline, width2, baseline );
|
||||||
|
g.drawLine( 0, topline, width2, topline );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// move x before scaling to have same left inset at all scale factors
|
||||||
|
g.translate( insets.left, 0 );
|
||||||
|
|
||||||
|
// scale
|
||||||
|
((Graphics2D)g).scale( scaleFactor, scaleFactor );
|
||||||
|
|
||||||
|
// compute Y correction
|
||||||
|
float yCorrection = correctionFunction.computeTextYCorrection( g2, scaleFactor );
|
||||||
|
|
||||||
|
// create graphics that applies Y correction
|
||||||
|
Graphics2D cg = new Graphics2DProxy( g2 ) {
|
||||||
|
@Override
|
||||||
|
public void drawString( String str, int x, int y ) {
|
||||||
|
super.drawString( str, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawString( String str, float x, float y ) {
|
||||||
|
super.drawString( str, x, y + yCorrection );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// draw string
|
||||||
|
g.setColor( getForeground() );
|
||||||
|
int y = insets.top + fm.getAscent();
|
||||||
|
JavaCompatibility.drawStringUnderlineCharAt( this, cg, "E", -1, 0, y );
|
||||||
|
|
||||||
|
// set tooltip text
|
||||||
|
if( getToolTipText() == null ) {
|
||||||
|
AffineTransform t = g2.getTransform();
|
||||||
|
double textY = t.getTranslateY() + (y * t.getScaleY());
|
||||||
|
setToolTipText( textY + " + " + yCorrection + " = " + (textY + yCorrection) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int scale( int value ) {
|
||||||
|
return Math.round( value * scaleFactor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
JFDML JFormDesigner: "7.0.2.0.298" Java: "14" encoding: "UTF-8"
|
||||||
|
|
||||||
|
new FormModel {
|
||||||
|
contentType: "form/swing"
|
||||||
|
root: new FormRoot {
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.defaultVariableLocal": true
|
||||||
|
}
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[fill]"
|
||||||
|
"$rowConstraints": "[fill]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
"border": sfield com.jformdesigner.model.FormObject NULL_VALUE
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 450, 300 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user