mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-13 07:17:13 -06:00
fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is zero (default in "Flat Light" and "Flat Dark" themes)
This commit is contained in:
@@ -6,6 +6,8 @@ FlatLaf Change Log
|
|||||||
- TabbedPane: Support background color for selected tabs.
|
- TabbedPane: Support background color for selected tabs.
|
||||||
- CheckBox: changed `CheckBox.arc` from radius to diameter to be consistent with
|
- CheckBox: changed `CheckBox.arc` from radius to diameter to be consistent with
|
||||||
`Button.arc` and `Component.arc`
|
`Button.arc` and `Component.arc`
|
||||||
|
- Fixed clipped borders at 125%, 150% and 175% scaling when outer focus width is
|
||||||
|
zero (default in "Flat Light" and "Flat Dark" themes).
|
||||||
|
|
||||||
|
|
||||||
## 0.21
|
## 0.21
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ public class FlatComboBoxUI
|
|||||||
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
||||||
float lw = scale( 1f );
|
float lw = scale( 1f );
|
||||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||||
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
|
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
paint( g, c );
|
paint( g, c );
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ public class FlatSpinnerUI
|
|||||||
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
||||||
float lw = scale( 1f );
|
float lw = scale( 1f );
|
||||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||||
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
|
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
|
||||||
|
|
||||||
paint( g, c );
|
paint( g, c );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import javax.swing.LookAndFeel;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ColorUIResource;
|
import javax.swing.plaf.ColorUIResource;
|
||||||
import com.formdev.flatlaf.util.DerivedColor;
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.JavaCompatibility;
|
import com.formdev.flatlaf.util.JavaCompatibility;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -136,6 +137,23 @@ public class FlatUIUtils
|
|||||||
*/
|
*/
|
||||||
public static void paintComponentOuterBorder( Graphics2D g, int x, int y, int width, int height,
|
public static void paintComponentOuterBorder( Graphics2D g, int x, int y, int width, int height,
|
||||||
float focusWidth, float lineWidth, float arc )
|
float focusWidth, float lineWidth, float arc )
|
||||||
|
{
|
||||||
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
|
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||||
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||||
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
|
paintComponentOuterBorderImpl( g2d, x2, y2, width2, height2,
|
||||||
|
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paintComponentOuterBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void paintComponentOuterBorderImpl( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
float focusWidth, float lineWidth, float arc )
|
||||||
{
|
{
|
||||||
float outerRadius = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
|
float outerRadius = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
|
||||||
float ow = focusWidth + lineWidth;
|
float ow = focusWidth + lineWidth;
|
||||||
@@ -159,6 +177,23 @@ public class FlatUIUtils
|
|||||||
*/
|
*/
|
||||||
public static void paintComponentBorder( Graphics2D g, int x, int y, int width, int height,
|
public static void paintComponentBorder( Graphics2D g, int x, int y, int width, int height,
|
||||||
float focusWidth, float lineWidth, float arc )
|
float focusWidth, float lineWidth, float arc )
|
||||||
|
{
|
||||||
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
|
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||||
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||||
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
|
paintComponentBorderImpl( g2d, x2, y2, width2, height2,
|
||||||
|
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paintComponentBorderImpl( g, x, y, width, height, focusWidth, lineWidth, arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void paintComponentBorderImpl( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
float focusWidth, float lineWidth, float arc )
|
||||||
{
|
{
|
||||||
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
|
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
|
||||||
|
|
||||||
@@ -187,6 +222,23 @@ public class FlatUIUtils
|
|||||||
*/
|
*/
|
||||||
public static void paintComponentBackground( Graphics2D g, int x, int y, int width, int height,
|
public static void paintComponentBackground( Graphics2D g, int x, int y, int width, int height,
|
||||||
float focusWidth, float arc )
|
float focusWidth, float arc )
|
||||||
|
{
|
||||||
|
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||||
|
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||||
|
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||||
|
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||||
|
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||||
|
paintComponentBackgroundImpl( g2d, x2, y2, width2, height2,
|
||||||
|
(float) (focusWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paintComponentBackgroundImpl( g, x, y, width, height, focusWidth, arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void paintComponentBackgroundImpl( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
float focusWidth, float arc )
|
||||||
{
|
{
|
||||||
g.fill( new RoundRectangle2D.Float(
|
g.fill( new RoundRectangle2D.Float(
|
||||||
x + focusWidth, y + focusWidth,
|
x + focusWidth, y + focusWidth,
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* 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.Graphics2D;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class HiDPIUtils
|
||||||
|
{
|
||||||
|
public interface Painter {
|
||||||
|
public void paint( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void paintAtScale1x( Graphics2D g, JComponent c, Painter painter ) {
|
||||||
|
paintAtScale1x( g, 0, 0, c.getWidth(), c.getHeight(), painter );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) {
|
||||||
|
paintAtScale1x( g, x, y, width, height, UIScale.getSystemScaleFactor( g ), painter );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint at system scale factor 1x to avoid rounding issues at 125%, 150% and 175% scaling.
|
||||||
|
* <p>
|
||||||
|
* Scales the given Graphics2D down to 100% and invokes the
|
||||||
|
* given painter passing scaled x, y, width and height.
|
||||||
|
* <p>
|
||||||
|
* Uses the same scaling calculation as the JRE uses.
|
||||||
|
*/
|
||||||
|
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height,
|
||||||
|
double scaleFactor, Painter painter )
|
||||||
|
{
|
||||||
|
if( scaleFactor == 1 ) {
|
||||||
|
painter.paint( g, x, y, width, height, 1 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save original transform
|
||||||
|
AffineTransform transform = g.getTransform();
|
||||||
|
|
||||||
|
// scale rectangle
|
||||||
|
Rectangle2D.Double scaledRect = scale( transform, x, y, width, height );
|
||||||
|
|
||||||
|
try {
|
||||||
|
// unscale to factor 1.0
|
||||||
|
double scale = 1.0 / scaleFactor;
|
||||||
|
g.scale( scale, scale );
|
||||||
|
|
||||||
|
// compute origin delta x/y
|
||||||
|
double dx = Math.floor( scaledRect.x ) - transform.getTranslateX();
|
||||||
|
double dy = Math.floor( scaledRect.y ) - transform.getTranslateY();
|
||||||
|
|
||||||
|
// move origin to make sure that origin x/y are at whole numbers
|
||||||
|
if( dx != 0 || dy != 0 )
|
||||||
|
g.translate( dx, dy );
|
||||||
|
|
||||||
|
int swidth = (int) scaledRect.width;
|
||||||
|
int sheight = (int) scaledRect.height;
|
||||||
|
|
||||||
|
// paint
|
||||||
|
painter.paint( g, 0, 0, swidth, sheight, scaleFactor );
|
||||||
|
} finally {
|
||||||
|
// restore original transform
|
||||||
|
g.setTransform( transform );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales a rectangle in the same way as the JRE does in
|
||||||
|
* sun.java2d.pipe.PixelToParallelogramConverter.fillRectangle(),
|
||||||
|
* which is used by Graphics.fillRect().
|
||||||
|
*/
|
||||||
|
private static Rectangle2D.Double scale( AffineTransform transform, int x, int y, int width, int height ) {
|
||||||
|
double dx1 = transform.getScaleX();
|
||||||
|
double dy2 = transform.getScaleY();
|
||||||
|
double px = x * dx1 + transform.getTranslateX();
|
||||||
|
double py = y * dy2 + transform.getTranslateY();
|
||||||
|
dx1 *= width;
|
||||||
|
dy2 *= height;
|
||||||
|
|
||||||
|
double newx = normalize( px );
|
||||||
|
double newy = normalize( py );
|
||||||
|
dx1 = normalize( px + dx1 ) - newx;
|
||||||
|
dy2 = normalize( py + dy2 ) - newy;
|
||||||
|
|
||||||
|
return new Rectangle2D.Double( newx, newy, dx1, dy2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double normalize( double value ) {
|
||||||
|
return Math.floor( value + 0.25 ) + 0.25;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -255,7 +255,7 @@ public class FlatDatePickerUI
|
|||||||
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
g2.setColor( enabled ? borderColor : disabledBorderColor );
|
||||||
float lw = scale( 1f );
|
float lw = scale( 1f );
|
||||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||||
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - (focusWidth * 2) ) );
|
g2.fill( new Rectangle2D.Float( lx, focusWidth, lw, height - 1 - (focusWidth * 2) ) );
|
||||||
|
|
||||||
paint( g, c );
|
paint( g, c );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user