mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 06:57:13 -06: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:
@@ -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