From 3802c64be3fd47b66dc7d3bd8d7c0a78ec0b08dd Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 3 Jun 2022 09:33:19 +0200 Subject: [PATCH] Tree: better support for non-wide rounded selection --- .../flatlaf/ui/FlatMenuItemRenderer.java | 4 +- .../com/formdev/flatlaf/ui/FlatTreeUI.java | 54 +++++++++++++------ .../com/formdev/flatlaf/ui/FlatUIUtils.java | 27 ++-------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java index 60f0e1b2..7d4707ec 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java @@ -353,9 +353,11 @@ debug*/ /** @since 3 */ protected void paintSelection( Graphics g, Color selectionBackground, Insets selectionInsets, int selectionArc ) { + float arc = scale( selectionArc / 2f ); + g.setColor( deriveBackground( selectionBackground ) ); FlatUIUtils.paintSelection( (Graphics2D) g, 0, 0, menuItem.getWidth(), menuItem.getHeight(), - scale( selectionInsets ), scale( (float) selectionArc ), 0 ); + scale( selectionInsets ), arc, arc, arc, arc, 0 ); } /** @since 3 */ diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java index 20b6bc89..30f6ebd8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java @@ -17,7 +17,6 @@ package com.formdev.flatlaf.ui; import static com.formdev.flatlaf.FlatClientProperties.*; - import java.awt.Color; import java.awt.Component; import java.awt.Graphics; @@ -377,7 +376,7 @@ public class FlatTreeUI } /** - * Same as super.paintRow(), but supports wide selection and uses + * Similar to super.paintRow(), but supports wide selection and uses * inactive selection background/foreground if tree is not focused. */ @Override @@ -458,7 +457,7 @@ public class FlatTreeUI paintWideSelection( g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf ); } else { // non-wide selection - paintCellBackground( g, rendererComponent, bounds ); + paintCellBackground( g, rendererComponent, bounds, row, true ); } // this is actually not necessary because renderer should always set color @@ -472,7 +471,7 @@ public class FlatTreeUI if( bg != null && !bg.equals( defaultCellNonSelectionBackground ) ) { Color oldColor = g.getColor(); g.setColor( bg ); - paintCellBackground( g, rendererComponent, bounds ); + paintCellBackground( g, rendererComponent, bounds, row, false ); g.setColor( oldColor ); } } @@ -527,16 +526,18 @@ public class FlatTreeUI private void paintWideSelection( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds, TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf ) { - int flags = 0; + float arcTop, arcBottom; + arcTop = arcBottom = UIScale.scale( selectionArc / 2f ); + if( useUnitedRoundedSelection() ) { if( row > 0 && tree.isRowSelected( row - 1 ) ) - flags |= FlatUIUtils.FLAG_TOP_NOT_ROUNDED; + arcTop = 0; if( row < tree.getRowCount() - 1 && tree.isRowSelected( row + 1 ) ) - flags |= FlatUIUtils.FLAG_BOTTOM_NOT_ROUNDED; + arcBottom = 0; } FlatUIUtils.paintSelection( (Graphics2D) g, 0, bounds.y, tree.getWidth(), bounds.height, - UIScale.scale( selectionInsets ), UIScale.scale( (float) selectionArc ), flags ); + UIScale.scale( selectionInsets ), arcTop, arcTop, arcBottom, arcBottom, 0 ); // paint expand/collapse icon // (was already painted before, but painted over with wide selection) @@ -546,12 +547,9 @@ public class FlatTreeUI } } - private boolean useUnitedRoundedSelection() { - return selectionArc > 0 && - (selectionInsets == null || (selectionInsets.top == 0 && selectionInsets.bottom == 0)); - } - - private void paintCellBackground( Graphics g, Component rendererComponent, Rectangle bounds ) { + private void paintCellBackground( Graphics g, Component rendererComponent, Rectangle bounds, + int row, boolean paintSelection ) + { int xOffset = 0; int imageOffset = 0; @@ -564,8 +562,32 @@ public class FlatTreeUI xOffset = label.getComponentOrientation().isLeftToRight() ? imageOffset : 0; } - FlatUIUtils.paintSelection( (Graphics2D) g, bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height, - UIScale.scale( selectionInsets ), UIScale.scale( (float) selectionArc ), 0 ); + if( paintSelection ) { + float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight; + arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f ); + + if( useUnitedRoundedSelection() ) { + if( row > 0 && tree.isRowSelected( row - 1 ) ) { + Rectangle r = getPathBounds( tree, tree.getPathForRow( row - 1 ) ); + arcTopLeft = Math.min( arcTopLeft, r.x - bounds.x ); + arcTopRight = Math.min( arcTopRight, (bounds.x + bounds.width) - (r.x + r.width) ); + } + if( row < tree.getRowCount() - 1 && tree.isRowSelected( row + 1 ) ) { + Rectangle r = getPathBounds( tree, tree.getPathForRow( row + 1 ) ); + arcBottomLeft = Math.min( arcBottomLeft, r.x - bounds.x ); + arcBottomRight = Math.min( arcBottomRight, (bounds.x + bounds.width) - (r.x + r.width) ); + } + } + + FlatUIUtils.paintSelection( (Graphics2D) g, bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height, + UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 ); + } else + g.fillRect( bounds.x + xOffset, bounds.y, bounds.width - imageOffset, bounds.height ); + } + + private boolean useUnitedRoundedSelection() { + return selectionArc > 0 && + (selectionInsets == null || (selectionInsets.top == 0 && selectionInsets.bottom == 0)); } /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java index fa4abe0c..200cb7fd 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java @@ -624,26 +624,17 @@ public class FlatUIUtils } } - // flags for paintSelection() - public static final int - FLAG_TOP_LEFT_NOT_ROUNDED = (1 << 0), - FLAG_TOP_RIGHT_NOT_ROUNDED = (1 << 1), - FLAG_BOTTOM_LEFT_NOT_ROUNDED = (1 << 2), - FLAG_BOTTOM_RIGHT_NOT_ROUNDED = (1 << 3), - FLAG_TOP_NOT_ROUNDED = FLAG_TOP_LEFT_NOT_ROUNDED | FLAG_TOP_RIGHT_NOT_ROUNDED, - FLAG_BOTTOM_NOT_ROUNDED = FLAG_BOTTOM_LEFT_NOT_ROUNDED | FLAG_BOTTOM_RIGHT_NOT_ROUNDED; - /** * Paints a selection. *

* The bounds of the painted selection (rounded) rectangle are * {@code x + insets.left, y + insets.top, width - insets.left - insets.right, height - insets.top - insets.bottom}. - * The given arc diameter refers to the painted rectangle (and not to {@code x,y,width,height}). + * The given arc radius refers to the painted rectangle (and not to {@code x,y,width,height}). * * @since 3 */ - public static void paintSelection( Graphics2D g, int x, int y, int width, int height, - Insets insets, float arc, int flags ) + public static void paintSelection( Graphics2D g, int x, int y, int width, int height, Insets insets, + float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight, int flags ) { if( insets != null ) { x += insets.left; @@ -652,15 +643,7 @@ public class FlatUIUtils height -= insets.top + insets.bottom; } - if( arc > 0 ) { - // because createRoundRectanglePath() expects a radius - float arcRadius = arc / 2; - - float arcTopLeft = ((flags & FLAG_TOP_LEFT_NOT_ROUNDED) != 0) ? 0 : arcRadius; - float arcTopRight = ((flags & FLAG_TOP_RIGHT_NOT_ROUNDED) != 0) ? 0 : arcRadius; - float arcBottomLeft = ((flags & FLAG_BOTTOM_LEFT_NOT_ROUNDED) != 0) ? 0 : arcRadius; - float arcBottomRight = ((flags & FLAG_BOTTOM_RIGHT_NOT_ROUNDED) != 0) ? 0 : arcRadius; - + if( arcTopLeft > 0 || arcTopRight > 0 || arcBottomLeft > 0 || arcBottomRight > 0 ) { 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% @@ -765,7 +748,7 @@ public class FlatUIUtils } /** - * Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner. + * Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius of each corner. */ public static Path2D createRoundRectangle( float x, float y, float width, float height, float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )