From 7bec5ec6dc81d10f0d82ff5774c7e60d51006f18 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sun, 13 Aug 2023 14:01:09 +0200 Subject: [PATCH] ScrollPane: support rounded border --- .../flatlaf/ui/FlatScrollPaneBorder.java | 63 +++ .../formdev/flatlaf/ui/FlatScrollPaneUI.java | 93 +++- .../com/formdev/flatlaf/FlatLaf.properties | 5 +- .../flatlaf/ui/TestFlatStyleableInfo.java | 12 +- .../flatlaf/ui/TestFlatStyleableValue.java | 22 +- .../formdev/flatlaf/ui/TestFlatStyling.java | 10 +- .../dumps/uidefaults/FlatDarculaLaf_1.8.0.txt | 8 +- .../dumps/uidefaults/FlatDarkLaf_1.8.0.txt | 5 +- .../uidefaults/FlatIntelliJLaf_1.8.0.txt | 8 +- .../dumps/uidefaults/FlatLightLaf_1.8.0.txt | 5 +- .../dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt | 5 +- .../uidefaults/FlatMacLightLaf_1.8.0.txt | 5 +- .../dumps/uidefaults/FlatTestLaf_1.8.0.txt | 5 +- .../testing/FlatRoundedScrollPaneTest.java | 488 ++++++++++++++++++ .../testing/FlatRoundedScrollPaneTest.jfd | 230 +++++++++ .../flatlaf/testing/FlatTestFrame.java | 8 + .../flatlaf/testing/FlatTestLaf.properties | 5 + .../flatlaf/themeeditor/FlatLafUIKeys.txt | 1 + 18 files changed, 942 insertions(+), 36 deletions(-) create mode 100644 flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneBorder.java create mode 100644 flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.java create mode 100644 flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.jfd diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneBorder.java new file mode 100644 index 00000000..845ea12f --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneBorder.java @@ -0,0 +1,63 @@ +/* + * Copyright 2023 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.ui; + +import java.awt.Component; +import java.awt.Insets; +import javax.swing.UIManager; +import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; +import com.formdev.flatlaf.util.UIScale; + +/** + * Border for {@link javax.swing.JScrollPane}. + * + * @uiDefault ScrollPane.arc int + + * @author Karl Tauber + * @since 3.3 + */ +public class FlatScrollPaneBorder + extends FlatBorder +{ + @Styleable protected int arc = UIManager.getInt( "ScrollPane.arc" ); + + @Override + public Insets getBorderInsets( Component c, Insets insets ) { + insets = super.getBorderInsets( c, insets ); + + // if view is rounded, increase left and right insets to avoid that the viewport + // is painted over the rounded border on the corners + int arc = getArc( c ); + if( arc > 0 ) { + // increase insets by radius minus lineWidth because radius is measured + // from the outside of the line, but insets from super include lineWidth + int padding = UIScale.scale( (arc / 2) - getLineWidth( c ) ); + insets.left += padding; + insets.right += padding; + } + + return insets; + } + + @Override + protected int getArc( Component c ) { + if( isCellEditor( c ) ) + return 0; + + return arc; + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java index a62e8369..bb65fac8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java @@ -17,9 +17,12 @@ package com.formdev.flatlaf.ui; import java.awt.Component; +import java.awt.Container; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Insets; import java.awt.KeyboardFocusManager; +import java.awt.LayoutManager; import java.awt.Rectangle; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; @@ -41,16 +44,19 @@ import javax.swing.JTree; import javax.swing.JViewport; import javax.swing.LookAndFeel; import javax.swing.ScrollPaneConstants; +import javax.swing.ScrollPaneLayout; import javax.swing.Scrollable; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollPaneUI; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.util.LoggingFacade; +import com.formdev.flatlaf.util.UIScale; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JScrollPane}. @@ -97,7 +103,13 @@ public class FlatScrollPaneUI super.installUI( c ); int focusWidth = UIManager.getInt( "Component.focusWidth" ); - LookAndFeel.installProperty( c, "opaque", focusWidth == 0 ); + int arc = UIManager.getInt( "ScrollPane.arc" ); + LookAndFeel.installProperty( c, "opaque", focusWidth == 0 && arc == 0 ); + + // install layout manager + LayoutManager layout = c.getLayout(); + if( layout != null && layout.getClass() == ScrollPaneLayout.UIResource.class ) + c.setLayout( createScrollPaneLayout() ); installStyle(); @@ -108,6 +120,10 @@ public class FlatScrollPaneUI public void uninstallUI( JComponent c ) { MigLayoutVisualPadding.uninstall( scrollpane ); + // uninstall layout manager + if( c.getLayout() instanceof FlatScrollPaneLayout ) + c.setLayout( new ScrollPaneLayout.UIResource() ); + super.uninstallUI( c ); oldStyleValues = null; @@ -130,6 +146,13 @@ public class FlatScrollPaneUI handler = null; } + /** + * @since 3.3 + */ + protected FlatScrollPaneLayout createScrollPaneLayout() { + return new FlatScrollPaneLayout(); + } + @Override protected MouseWheelListener createMouseWheelListener() { MouseWheelListener superListener = super.createMouseWheelListener(); @@ -290,8 +313,7 @@ public class FlatScrollPaneUI Object corner = e.getNewValue(); if( corner instanceof JButton && ((JButton)corner).getBorder() instanceof FlatButtonBorder && - scrollpane.getViewport() != null && - scrollpane.getViewport().getView() instanceof JTable ) + getView( scrollpane ) instanceof JTable ) { ((JButton)corner).setBorder( BorderFactory.createEmptyBorder() ); ((JButton)corner).setFocusable( false ); @@ -334,9 +356,10 @@ public class FlatScrollPaneUI /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { - if( key.equals( "focusWidth" ) ) { + if( key.equals( "focusWidth" ) || key.equals( "arc" ) ) { int focusWidth = (value instanceof Integer) ? (int) value : UIManager.getInt( "Component.focusWidth" ); - LookAndFeel.installProperty( scrollpane, "opaque", focusWidth == 0 ); + int arc = (value instanceof Integer) ? (int) value : UIManager.getInt( "ScrollPane.arc" ); + LookAndFeel.installProperty( scrollpane, "opaque", focusWidth == 0 && arc == 0 ); } if( borderShared == null ) @@ -402,13 +425,26 @@ public class FlatScrollPaneUI c.getHeight() - insets.top - insets.bottom ); } + // if view is rounded, paint rounded background with view background color + // to ensure that free areas at left and right have same color as view + Component view; + float arc = getBorderArc( scrollpane ); + if( arc > 0 && (view = getView( scrollpane )) != null ) { + float focusWidth = FlatUIUtils.getBorderFocusWidth( c ); + + g.setColor( view.getBackground() ); + + Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g ); + FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc ); + FlatUIUtils.resetRenderingHints( g, oldRenderingHints ); + } + paint( g, c ); } /** @since 1.3 */ public static boolean isPermanentFocusOwner( JScrollPane scrollPane ) { - JViewport viewport = scrollPane.getViewport(); - Component view = (viewport != null) ? viewport.getView() : null; + Component view = getView( scrollPane ); if( view == null ) return false; @@ -428,6 +464,18 @@ public class FlatScrollPaneUI return false; } + private static Component getView( JScrollPane scrollPane ) { + JViewport viewport = scrollPane.getViewport(); + return (viewport != null) ? viewport.getView() : null; + } + + private static float getBorderArc( JScrollPane scrollPane ) { + Border border = scrollPane.getBorder(); + return (border instanceof FlatScrollPaneBorder) + ? UIScale.scale( (float) ((FlatScrollPaneBorder)border).getArc( scrollPane ) ) + : 0; + } + //---- class Handler ------------------------------------------------------ /** @@ -459,4 +507,35 @@ public class FlatScrollPaneUI scrollpane.repaint(); } } + + //---- class FlatScrollPaneLayout ----------------------------------------- + + /** + * @since 3.3 + */ + protected static class FlatScrollPaneLayout + extends ScrollPaneLayout.UIResource + { + @Override + public void layoutContainer( Container parent ) { + super.layoutContainer( parent ); + + JScrollPane scrollPane = (JScrollPane) parent; + float arc = getBorderArc( scrollPane ); + if( arc > 0 ) { + JScrollBar vsb = getVerticalScrollBar(); + if( vsb != null && vsb.isVisible() ) { + // move vertical scrollbar to trailing edge + int padding = Math.round( (arc / 2) - FlatUIUtils.getBorderLineWidth( scrollPane ) ); + Insets insets = parent.getInsets(); + Rectangle r = vsb.getBounds(); + int y = Math.max( r.y, insets.top + padding ); + int y2 = Math.min( r.y + r.height, parent.getHeight() - insets.bottom - padding ); + boolean ltr = parent.getComponentOrientation().isLeftToRight(); + + vsb.setBounds( r.x + (ltr ? padding : -padding), y, r.width, y2 - y ); + } + } + } + } } diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 36763714..a620989f 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -597,10 +597,11 @@ ScrollBar.allowsAbsolutePositioning = true #---- ScrollPane ---- -ScrollPane.border = com.formdev.flatlaf.ui.FlatBorder +ScrollPane.border = com.formdev.flatlaf.ui.FlatScrollPaneBorder ScrollPane.background = $ScrollBar.track ScrollPane.fillUpperCorner = true ScrollPane.smoothScrolling = true +ScrollPane.arc = 0 #---- SearchField ---- @@ -731,7 +732,7 @@ Table.showVerticalLines = false Table.showTrailingVerticalLine = false Table.consistentHomeEndKeyBehavior = true Table.intercellSpacing = 0,0 -Table.scrollPaneBorder = com.formdev.flatlaf.ui.FlatBorder +Table.scrollPaneBorder = com.formdev.flatlaf.ui.FlatScrollPaneBorder Table.ascendingSortIcon = com.formdev.flatlaf.icons.FlatAscendingSortIcon Table.descendingSortIcon = com.formdev.flatlaf.icons.FlatDescendingSortIcon Table.sortIconColor = @icon diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java index 028030d8..948fb771 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java @@ -601,7 +601,7 @@ public class TestFlatStyleableInfo ); // border - flatBorder( expected ); + flatScrollPaneBorder( expected ); assertMapEquals( expected, ui.getStyleableInfos( c ) ); } @@ -1005,17 +1005,23 @@ public class TestFlatStyleableInfo expectedMap( expected, "arc", int.class, - "roundRect", Boolean.class ); } + private void flatScrollPaneBorder( Map> expected ) { + flatBorder( expected ); + + expectedMap( expected, + "arc", int.class + ); + } + private void flatTextBorder( Map> expected ) { flatBorder( expected ); expectedMap( expected, "arc", int.class, - "roundRect", Boolean.class ); } diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java index 7e5b1127..58636694 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java @@ -625,7 +625,7 @@ public class TestFlatStyleableValue FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI(); // border - flatBorder( c, ui ); + flatScrollPaneBorder( c, ui ); testBoolean( c, ui, "showButtons", true ); } @@ -965,15 +965,19 @@ public class TestFlatStyleableValue flatBorder( c, ui ); testInteger( c, ui, "arc", 123 ); - testBoolean( c, ui, "roundRect", true ); } + private void flatScrollPaneBorder( JComponent c, StyleableUI ui ) { + flatBorder( c, ui ); + + testInteger( c, ui, "arc", 123 ); + } + private void flatTextBorder( JComponent c, StyleableUI ui ) { flatBorder( c, ui ); testInteger( c, ui, "arc", 123 ); - testBoolean( c, ui, "roundRect", true ); } @@ -1034,6 +1038,17 @@ public class TestFlatStyleableValue // FlatRoundBorder extends FlatBorder flatBorder( border ); + testValue( border, "arc", 6 ); + testValue( border, "roundRect", true ); + } + + @Test + void flatScrollPaneBorder() { + FlatScrollPaneBorder border = new FlatScrollPaneBorder(); + + // FlatScrollPaneBorder extends FlatBorder + flatBorder( border ); + testValue( border, "arc", 6 ); } @@ -1045,6 +1060,7 @@ public class TestFlatStyleableValue flatBorder( border ); testValue( border, "arc", 6 ); + testValue( border, "roundRect", true ); } @Test diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java index a336b380..116376f0 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java @@ -760,7 +760,7 @@ public class TestFlatStyling FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI(); // border - flatBorder( style -> ui.applyStyle( style ) ); + flatScrollPaneBorder( style -> ui.applyStyle( style ) ); ui.applyStyle( "showButtons: true" ); @@ -1234,15 +1234,19 @@ public class TestFlatStyling flatBorder( applyStyle ); applyStyle.accept( "arc: 6" ); - applyStyle.accept( "roundRect: true" ); } + private void flatScrollPaneBorder( Consumer applyStyle ) { + flatBorder( applyStyle ); + + applyStyle.accept( "arc: 6" ); + } + private void flatTextBorder( Consumer applyStyle ) { flatBorder( applyStyle ); applyStyle.accept( "arc: 6" ); - applyStyle.accept( "roundRect: true" ); } diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt index 8291260a..cba7171f 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt @@ -87,8 +87,8 @@ #---- ScrollPane ---- -- ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] -+ ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +- ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ++ ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] #---- Spinner ---- @@ -99,8 +99,8 @@ #---- Table ---- -- Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] -+ Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +- Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ++ Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] #---- TextField ---- diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index d2dcd9c6..2aa1aa49 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -906,8 +906,9 @@ ScrollBarUI com.formdev.flatlaf.ui.FlatScrollBarUI #---- ScrollPane ---- +ScrollPane.arc 0 ScrollPane.background #3e4244 HSL 200 5 25 com.formdev.flatlaf.util.DerivedColor [UI] lighten(1%) -ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ScrollPane.fillUpperCorner true ScrollPane.font [active] $defaultFont [UI] ScrollPane.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] @@ -1118,7 +1119,7 @@ Table.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.Colo Table.gridColor #5a5e60 HSL 200 3 36 javax.swing.plaf.ColorUIResource [UI] Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI] Table.rowHeight 20 -Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] Table.selectionBackground #4b6eaf HSL 219 40 49 javax.swing.plaf.ColorUIResource [UI] Table.selectionForeground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] Table.selectionInactiveBackground #0f2a3d HSL 205 61 15 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatIntelliJLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatIntelliJLaf_1.8.0.txt index f579ab89..7b2d2fd2 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatIntelliJLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatIntelliJLaf_1.8.0.txt @@ -107,8 +107,8 @@ #---- ScrollPane ---- -- ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] -+ ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +- ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ++ ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] #---- Spinner ---- @@ -119,8 +119,8 @@ #---- Table ---- -- Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] -+ Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +- Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ++ Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] #---- TextField ---- diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt index 7871f3ee..33980206 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -911,8 +911,9 @@ ScrollBarUI com.formdev.flatlaf.ui.FlatScrollBarUI #---- ScrollPane ---- +ScrollPane.arc 0 ScrollPane.background #f5f5f5 HSL 0 0 96 com.formdev.flatlaf.util.DerivedColor [UI] lighten(1%) -ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ScrollPane.fillUpperCorner true ScrollPane.font [active] $defaultFont [UI] ScrollPane.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI] @@ -1123,7 +1124,7 @@ Table.foreground #000000 HSL 0 0 0 javax.swing.plaf.Colo Table.gridColor #ebebeb HSL 0 0 92 javax.swing.plaf.ColorUIResource [UI] Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI] Table.rowHeight 20 -Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] Table.selectionBackground #2675bf HSL 209 67 45 javax.swing.plaf.ColorUIResource [UI] Table.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] Table.selectionInactiveBackground #d3d3d3 HSL 0 0 83 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt index 41e289f9..3f7fd9b9 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatMacDarkLaf_1.8.0.txt @@ -915,8 +915,9 @@ ScrollBarUI com.formdev.flatlaf.ui.FlatScrollBarUI #---- ScrollPane ---- +ScrollPane.arc 0 ScrollPane.background #282828 HSL 0 0 16 javax.swing.plaf.ColorUIResource [UI] -ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ScrollPane.fillUpperCorner true ScrollPane.font [active] $defaultFont [UI] ScrollPane.foreground #dddddd HSL 0 0 87 javax.swing.plaf.ColorUIResource [UI] @@ -1128,7 +1129,7 @@ Table.foreground #dddddd HSL 0 0 87 javax.swing.plaf.Colo Table.gridColor #3c3c3c HSL 0 0 24 javax.swing.plaf.ColorUIResource [UI] Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI] Table.rowHeight 20 -Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] Table.selectionBackground #0054cc HSL 215 100 40 javax.swing.plaf.ColorUIResource [UI] Table.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] Table.selectionInactiveBackground #464646 HSL 0 0 27 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatMacLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatMacLightLaf_1.8.0.txt index e735c091..be81c656 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatMacLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatMacLightLaf_1.8.0.txt @@ -919,8 +919,9 @@ ScrollBarUI com.formdev.flatlaf.ui.FlatScrollBarUI #---- ScrollPane ---- +ScrollPane.arc 0 ScrollPane.background #fafafa HSL 0 0 98 javax.swing.plaf.ColorUIResource [UI] -ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +ScrollPane.border [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ScrollPane.fillUpperCorner true ScrollPane.font [active] $defaultFont [UI] ScrollPane.foreground #262626 HSL 0 0 15 javax.swing.plaf.ColorUIResource [UI] @@ -1132,7 +1133,7 @@ Table.foreground #262626 HSL 0 0 15 javax.swing.plaf.Colo Table.gridColor #ebebeb HSL 0 0 92 javax.swing.plaf.ColorUIResource [UI] Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI] Table.rowHeight 20 -Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatBorder [UI] +Table.scrollPaneBorder [lazy] 3,3,3,3 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] Table.selectionBackground #005fe6 HSL 215 100 45 javax.swing.plaf.ColorUIResource [UI] Table.selectionForeground #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI] Table.selectionInactiveBackground #dcdcdc HSL 0 0 86 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt index 3ff67dd1..d15bd88d 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -932,8 +932,9 @@ ScrollBarUI com.formdev.flatlaf.ui.FlatScrollBarUI #---- ScrollPane ---- +ScrollPane.arc 20 ScrollPane.background #88ff88 HSL 120 100 77 javax.swing.plaf.ColorUIResource [UI] -ScrollPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +ScrollPane.border [lazy] 1,10,1,10 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] ScrollPane.fillUpperCorner true ScrollPane.font [active] $defaultFont [UI] ScrollPane.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] @@ -1154,7 +1155,7 @@ Table.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.Colo Table.gridColor #00ffff HSL 180 100 50 javax.swing.plaf.ColorUIResource [UI] Table.intercellSpacing 0,0 javax.swing.plaf.DimensionUIResource [UI] Table.rowHeight 25 -Table.scrollPaneBorder [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatBorder [UI] +Table.scrollPaneBorder [lazy] 1,10,1,10 false com.formdev.flatlaf.ui.FlatScrollPaneBorder [UI] Table.selectionBackground #00aa00 HSL 120 100 33 javax.swing.plaf.ColorUIResource [UI] Table.selectionForeground #ffff00 HSL 60 100 50 javax.swing.plaf.ColorUIResource [UI] Table.selectionInactiveBackground #888888 HSL 0 0 53 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.java new file mode 100644 index 00000000..967b1358 --- /dev/null +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.java @@ -0,0 +1,488 @@ +/* + * Copyright 2023 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.EventQueue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import javax.swing.tree.*; +import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.util.UIScale; +import net.miginfocom.swing.*; + +/** + * @author Karl Tauber + */ +public class FlatRoundedScrollPaneTest + extends FlatTestPanel +{ + private JScrollPane[] allJScrollPanes; + + public static void main( String[] args ) { + SwingUtilities.invokeLater( () -> { + FlatTestFrame frame = FlatTestFrame.create( args, "FlatRoundedScrollPaneTest" ); + frame.useApplyComponentOrientation = true; + frame.showFrame( FlatRoundedScrollPaneTest::new ); + } ); + } + + FlatRoundedScrollPaneTest() { + initComponents(); + + allJScrollPanes = new JScrollPane[] { + listScrollPane, treeScrollPane, tableScrollPane, + textAreaScrollPane, textPaneScrollPane, editorPaneScrollPane, customScrollPane + }; + + ArrayList items = new ArrayList<>(); + for( char ch = '0'; ch < 'z'; ch++ ) { + if( (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a') ) + continue; + + char[] chars = new char[ch - '0' + 1]; + Arrays.fill( chars, ch ); + items.add( new String( chars ) ); + } + + // list model + list.setModel( new AbstractListModel() { + @Override + public int getSize() { + return items.size(); + } + @Override + public String getElementAt( int index ) { + return items.get( index ); + } + } ); + + // tree model + DefaultMutableTreeNode root = new DefaultMutableTreeNode( items.get( 0 ) ); + DefaultMutableTreeNode last = null; + for( int i = 1; i < items.size(); i++ ) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode( items.get( i ) ); + if( i % 5 == 1 ) { + root.add( node ); + last = node; + } else + last.add( node ); + } + tree.setModel( new DefaultTreeModel( root ) ); + for( int row = tree.getRowCount() - 1; row >= 0; row-- ) + tree.expandRow( row ); + + // table model + table.setModel( new AbstractTableModel() { + @Override + public int getRowCount() { + return items.size(); + } + @Override + public int getColumnCount() { + return 4; + } + @Override + public Object getValueAt( int rowIndex, int columnIndex ) { + if( columnIndex > 0 ) + rowIndex = (items.size() + rowIndex - ((items.size() / 4) * columnIndex)) % items.size(); + return items.get( rowIndex ); + } + } ); + + // select some rows to better see smooth scrolling issues + for( int i = 5; i < items.size(); i += 10 ) { + list.addSelectionInterval( i, i ); + tree.addSelectionInterval( i, i ); + table.addRowSelectionInterval( i, i ); + } + + // text components + String longText = items.stream().collect( Collectors.joining( " " ) ) + ' ' + + items.stream().limit( 20 ).collect( Collectors.joining( " " ) ); + String text = items.stream().collect( Collectors.joining( "\n" ) ) + '\n'; + textArea.setText( longText + '\n' + text ); + textPane.setText( text ); + editorPane.setText( text ); + + textArea.select( 0, 0 ); + textPane.select( 0, 0 ); + editorPane.select( 0, 0 ); + + arcSliderChanged(); + + EventQueue.invokeLater( () -> { + EventQueue.invokeLater( () -> { + list.requestFocusInWindow(); + } ); + } ); + } + + private void autoResizeModeChanged() { + table.setAutoResizeMode( autoResizeModeCheckBox.isSelected() ? JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS : JTable.AUTO_RESIZE_OFF ); + } + + private void cornersChanged() { + boolean sel = cornersCheckBox.isSelected(); + for( JScrollPane scrollPane : allJScrollPanes ) { + scrollPane.setCorner( JScrollPane.UPPER_LEADING_CORNER, sel ? new Corner( Color.magenta ) : null ); + scrollPane.setCorner( JScrollPane.UPPER_TRAILING_CORNER, sel ? new Corner( Color.red ) : null ); + scrollPane.setCorner( JScrollPane.LOWER_LEADING_CORNER, sel ? new Corner( Color.cyan ) : null ); + scrollPane.setCorner( JScrollPane.LOWER_TRAILING_CORNER, sel ? new Corner( Color.pink ) : null ); + } + } + + private void columnHeaderChanged() { + boolean sel = columnHeaderCheckBox.isSelected(); + for( JScrollPane scrollPane : allJScrollPanes ) { + if( scrollPane == tableScrollPane ) + continue; + + JViewport header = null; + if( sel ) { + header = new JViewport(); + Corner view = new Corner( Color.cyan ); + view.setPreferredSize( new Dimension( 0, UIScale.scale( 20 ) ) ); + header.setView( view ); + } + scrollPane.setColumnHeader( header ); + } + } + + private void rowHeaderChanged() { + boolean sel = rowHeaderCheckBox.isSelected(); + for( JScrollPane scrollPane : allJScrollPanes ) { + JViewport header = null; + if( sel ) { + header = new JViewport(); + Corner view = new Corner( Color.yellow ); + view.setPreferredSize( new Dimension( UIScale.scale( 20 ), 0 ) ); + header.setView( view ); + } + scrollPane.setRowHeader( header ); + } + } + + private void horizontalScrollBarChanged() { + int policy = horizontalScrollBarCheckBox.isSelected() + ? JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED + : JScrollPane.HORIZONTAL_SCROLLBAR_NEVER; + + for( JScrollPane scrollPane : allJScrollPanes ) + scrollPane.setHorizontalScrollBarPolicy( policy ); + } + + private void verticalScrollBarChanged() { + int policy = verticalScrollBarCheckBox.isSelected() + ? JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED + : JScrollPane.VERTICAL_SCROLLBAR_NEVER; + + for( JScrollPane scrollPane : allJScrollPanes ) + scrollPane.setVerticalScrollBarPolicy( policy ); + } + + private void arcSliderChanged() { + int arc = arcSlider.getValue(); + for( JScrollPane scrollPane : allJScrollPanes ) + scrollPane.putClientProperty( FlatClientProperties.STYLE, "arc: " + arc ); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + splitPane2 = new JSplitPane(); + panel1 = new FlatTestPanel(); + listLabel = new JLabel(); + treeLabel = new JLabel(); + tableLabel = new JLabel(); + autoResizeModeCheckBox = new JCheckBox(); + listScrollPane = new JScrollPane(); + list = new JList<>(); + treeScrollPane = new JScrollPane(); + tree = new JTree(); + tableScrollPane = new JScrollPane(); + table = new JTable(); + panel2 = new FlatTestPanel(); + textAreaLabel = new JLabel(); + textPaneLabel = new JLabel(); + editorPaneLabel = new JLabel(); + customLabel = new JLabel(); + textAreaScrollPane = new JScrollPane(); + textArea = new JTextArea(); + textPaneScrollPane = new JScrollPane(); + textPane = new JTextPane(); + editorPaneScrollPane = new JScrollPane(); + editorPane = new JEditorPane(); + customScrollPane = new JScrollPane(); + button1 = new JButton(); + panel3 = new JPanel(); + JLabel arcLabel = new JLabel(); + arcSlider = new JSlider(); + cornersCheckBox = new JCheckBox(); + columnHeaderCheckBox = new JCheckBox(); + rowHeaderCheckBox = new JCheckBox(); + horizontalScrollBarCheckBox = new JCheckBox(); + verticalScrollBarCheckBox = new JCheckBox(); + + //======== this ======== + setLayout(new MigLayout( + "ltr,insets dialog,hidemode 3", + // columns + "[200,grow,fill]", + // rows + "[grow,fill]" + + "[]")); + + //======== splitPane2 ======== + { + splitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT); + splitPane2.setResizeWeight(0.5); + + //======== panel1 ======== + { + panel1.setLayout(new MigLayout( + "ltr,insets 3,hidemode 3", + // columns + "[200,grow,fill]" + + "[200,grow,fill]" + + "[200,grow,fill]" + + "[200,grow,fill]", + // rows + "[]0" + + "[200,grow,fill]")); + + //---- listLabel ---- + listLabel.setText("JList:"); + listLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel1.add(listLabel, "cell 0 0,aligny top,growy 0"); + + //---- treeLabel ---- + treeLabel.setText("JTree:"); + treeLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel1.add(treeLabel, "cell 1 0"); + + //---- tableLabel ---- + tableLabel.setText("JTable:"); + tableLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel1.add(tableLabel, "cell 2 0 2 1"); + + //---- autoResizeModeCheckBox ---- + autoResizeModeCheckBox.setText("Auto-resize mode"); + autoResizeModeCheckBox.setSelected(true); + autoResizeModeCheckBox.addActionListener(e -> autoResizeModeChanged()); + panel1.add(autoResizeModeCheckBox, "cell 2 0 2 1,alignx right,growx 0"); + + //======== listScrollPane ======== + { + listScrollPane.setViewportView(list); + } + panel1.add(listScrollPane, "cell 0 1,growx"); + + //======== treeScrollPane ======== + { + treeScrollPane.setViewportView(tree); + } + panel1.add(treeScrollPane, "cell 1 1"); + + //======== tableScrollPane ======== + { + tableScrollPane.setViewportView(table); + } + panel1.add(tableScrollPane, "cell 2 1 2 1,width 100,height 100"); + } + splitPane2.setTopComponent(panel1); + + //======== panel2 ======== + { + panel2.setLayout(new MigLayout( + "ltr,insets 3,hidemode 3", + // columns + "[200,grow,fill]" + + "[200,grow,fill]" + + "[200,grow,fill]" + + "[200,grow,fill]", + // rows + "[]0" + + "[200,grow,fill]")); + + //---- textAreaLabel ---- + textAreaLabel.setText("JTextArea:"); + textAreaLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel2.add(textAreaLabel, "cell 0 0"); + + //---- textPaneLabel ---- + textPaneLabel.setText("JTextPane:"); + textPaneLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel2.add(textPaneLabel, "cell 1 0"); + + //---- editorPaneLabel ---- + editorPaneLabel.setText("JEditorPane:"); + editorPaneLabel.setHorizontalTextPosition(SwingConstants.LEADING); + panel2.add(editorPaneLabel, "cell 2 0"); + + //---- customLabel ---- + customLabel.setText("Custom:"); + panel2.add(customLabel, "cell 3 0"); + + //======== textAreaScrollPane ======== + { + textAreaScrollPane.setViewportView(textArea); + } + panel2.add(textAreaScrollPane, "cell 0 1"); + + //======== textPaneScrollPane ======== + { + textPaneScrollPane.setViewportView(textPane); + } + panel2.add(textPaneScrollPane, "cell 1 1"); + + //======== editorPaneScrollPane ======== + { + editorPaneScrollPane.setViewportView(editorPane); + } + panel2.add(editorPaneScrollPane, "cell 2 1"); + + //======== customScrollPane ======== + { + + //---- button1 ---- + button1.setText("I'm a large button, but do not implement Scrollable interface"); + button1.setPreferredSize(new Dimension(800, 800)); + button1.setHorizontalAlignment(SwingConstants.LEADING); + button1.setVerticalAlignment(SwingConstants.TOP); + customScrollPane.setViewportView(button1); + } + panel2.add(customScrollPane, "cell 3 1"); + } + splitPane2.setBottomComponent(panel2); + } + add(splitPane2, "cell 0 0"); + + //======== panel3 ======== + { + panel3.setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[grow,fill]para" + + "[fill]" + + "[fill]" + + "[fill]" + + "[fill]" + + "[fill]", + // rows + "[]")); + + //---- arcLabel ---- + arcLabel.setText("Arc:"); + panel3.add(arcLabel, "cell 0 0"); + + //---- arcSlider ---- + arcSlider.setMaximum(40); + arcSlider.setValue(20); + arcSlider.setSnapToTicks(true); + arcSlider.setMajorTickSpacing(10); + arcSlider.setMinorTickSpacing(1); + arcSlider.setPaintTicks(true); + arcSlider.setPaintLabels(true); + arcSlider.addChangeListener(e -> arcSliderChanged()); + panel3.add(arcSlider, "cell 1 0"); + + //---- cornersCheckBox ---- + cornersCheckBox.setText("Corners"); + cornersCheckBox.addActionListener(e -> cornersChanged()); + panel3.add(cornersCheckBox, "cell 2 0"); + + //---- columnHeaderCheckBox ---- + columnHeaderCheckBox.setText("Column Header"); + columnHeaderCheckBox.addActionListener(e -> columnHeaderChanged()); + panel3.add(columnHeaderCheckBox, "cell 3 0"); + + //---- rowHeaderCheckBox ---- + rowHeaderCheckBox.setText("Row Header"); + rowHeaderCheckBox.addActionListener(e -> rowHeaderChanged()); + panel3.add(rowHeaderCheckBox, "cell 4 0"); + + //---- horizontalScrollBarCheckBox ---- + horizontalScrollBarCheckBox.setText("Horizontal ScrollBar"); + horizontalScrollBarCheckBox.setSelected(true); + horizontalScrollBarCheckBox.addActionListener(e -> horizontalScrollBarChanged()); + panel3.add(horizontalScrollBarCheckBox, "cell 5 0"); + + //---- verticalScrollBarCheckBox ---- + verticalScrollBarCheckBox.setText("Vertical ScrollBar"); + verticalScrollBarCheckBox.setSelected(true); + verticalScrollBarCheckBox.addActionListener(e -> verticalScrollBarChanged()); + panel3.add(verticalScrollBarCheckBox, "cell 6 0"); + } + add(panel3, "cell 0 1"); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JSplitPane splitPane2; + private FlatTestPanel panel1; + private JLabel listLabel; + private JLabel treeLabel; + private JLabel tableLabel; + private JCheckBox autoResizeModeCheckBox; + private JScrollPane listScrollPane; + private JList list; + private JScrollPane treeScrollPane; + private JTree tree; + private JScrollPane tableScrollPane; + private JTable table; + private FlatTestPanel panel2; + private JLabel textAreaLabel; + private JLabel textPaneLabel; + private JLabel editorPaneLabel; + private JLabel customLabel; + private JScrollPane textAreaScrollPane; + private JTextArea textArea; + private JScrollPane textPaneScrollPane; + private JTextPane textPane; + private JScrollPane editorPaneScrollPane; + private JEditorPane editorPane; + private JScrollPane customScrollPane; + private JButton button1; + private JPanel panel3; + private JSlider arcSlider; + private JCheckBox cornersCheckBox; + private JCheckBox columnHeaderCheckBox; + private JCheckBox rowHeaderCheckBox; + private JCheckBox horizontalScrollBarCheckBox; + private JCheckBox verticalScrollBarCheckBox; + // JFormDesigner - End of variables declaration //GEN-END:variables + + //---- class Corner ------------------------------------------------------- + + private static class Corner + extends JPanel + { + Corner( Color color ) { + super.setBackground( color ); + } + + @Override + public void setBackground( Color bg ) { + // do not change background when checkbox "explicit colors" is selected + } + } +} diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.jfd new file mode 100644 index 00000000..bb602b71 --- /dev/null +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatRoundedScrollPaneTest.jfd @@ -0,0 +1,230 @@ +JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8" + +new FormModel { + contentType: "form/swing" + root: new FormRoot { + add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "ltr,insets dialog,hidemode 3" + "$columnConstraints": "[200,grow,fill]" + "$rowConstraints": "[grow,fill][]" + } ) { + name: "this" + add( new FormContainer( "javax.swing.JSplitPane", new FormLayoutManager( class javax.swing.JSplitPane ) ) { + name: "splitPane2" + "orientation": 0 + "resizeWeight": 0.5 + add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$columnConstraints": "[200,grow,fill][200,grow,fill][200,grow,fill][200,grow,fill]" + "$rowConstraints": "[]0[200,grow,fill]" + "$layoutConstraints": "ltr,insets 3,hidemode 3" + } ) { + name: "panel1" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "listLabel" + "text": "JList:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0,aligny top,growy 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "treeLabel" + "text": "JTree:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "tableLabel" + "text": "JTable:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0 2 1" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "autoResizeModeCheckBox" + "text": "Auto-resize mode" + "selected": true + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "autoResizeModeChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0 2 1,alignx right,growx 0" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "listScrollPane" + add( new FormComponent( "javax.swing.JList" ) { + name: "list" + auxiliary() { + "JavaCodeGenerator.typeParameters": "String" + "JavaCodeGenerator.variableLocal": false + } + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1,growx" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "treeScrollPane" + add( new FormComponent( "javax.swing.JTree" ) { + name: "tree" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "tableScrollPane" + add( new FormComponent( "javax.swing.JTable" ) { + name: "table" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 1 2 1,width 100,height 100" + } ) + }, new FormLayoutConstraints( class java.lang.String ) { + "value": "left" + } ) + add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$columnConstraints": "[200,grow,fill][200,grow,fill][200,grow,fill][200,grow,fill]" + "$rowConstraints": "[]0[200,grow,fill]" + "$layoutConstraints": "ltr,insets 3,hidemode 3" + } ) { + name: "panel2" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "textAreaLabel" + "text": "JTextArea:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "textPaneLabel" + "text": "JTextPane:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "editorPaneLabel" + "text": "JEditorPane:" + "horizontalTextPosition": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "customLabel" + "text": "Custom:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 0" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "textAreaScrollPane" + add( new FormComponent( "javax.swing.JTextArea" ) { + name: "textArea" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "textPaneScrollPane" + add( new FormComponent( "javax.swing.JTextPane" ) { + name: "textPane" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "editorPaneScrollPane" + add( new FormComponent( "javax.swing.JEditorPane" ) { + name: "editorPane" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 1" + } ) + add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { + name: "customScrollPane" + add( new FormComponent( "javax.swing.JButton" ) { + name: "button1" + "text": "I'm a large button, but do not implement Scrollable interface" + "preferredSize": new java.awt.Dimension( 800, 800 ) + "horizontalAlignment": 10 + "verticalAlignment": 1 + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 1" + } ) + }, new FormLayoutConstraints( class java.lang.String ) { + "value": "right" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3" + "$columnConstraints": "[fill][grow,fill]para[fill][fill][fill][fill][fill]" + "$rowConstraints": "[]" + } ) { + name: "panel3" + add( new FormComponent( "javax.swing.JLabel" ) { + name: "arcLabel" + "text": "Arc:" + auxiliary() { + "JavaCodeGenerator.variableLocal": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JSlider" ) { + name: "arcSlider" + "maximum": 40 + "value": 20 + "snapToTicks": true + "majorTickSpacing": 10 + "minorTickSpacing": 1 + "paintTicks": true + "paintLabels": true + addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "arcSliderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "cornersCheckBox" + "text": "Corners" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "cornersChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 2 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "columnHeaderCheckBox" + "text": "Column Header" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "columnHeaderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "rowHeaderCheckBox" + "text": "Row Header" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "rowHeaderChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "horizontalScrollBarCheckBox" + "text": "Horizontal ScrollBar" + "selected": true + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "horizontalScrollBarChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 5 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "verticalScrollBarCheckBox" + "text": "Vertical ScrollBar" + "selected": true + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "verticalScrollBarChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 6 0" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + }, new FormLayoutConstraints( null ) { + "location": new java.awt.Point( 0, 0 ) + "size": new java.awt.Dimension( 875, 715 ) + } ) + } +} diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java index 84e79473..ecd968f1 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java @@ -651,6 +651,14 @@ public class FlatTestFrame JViewport columnHeader = ((JScrollPane)c).getColumnHeader(); if( columnHeader != null ) action.accept( columnHeader.getView(), "columnHeader" ); + } else if( c instanceof JSplitPane ) { + JSplitPane splitPane = (JSplitPane) c; + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + if( left instanceof Container ) + updateComponentsRecur( (Container) left, action ); + if( right instanceof Container ) + updateComponentsRecur( (Container) right, action ); } else if( c instanceof JTabbedPane ) { JTabbedPane tabPane = (JTabbedPane)c; int tabCount = tabPane.getTabCount(); diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties index d8c6d942..6a60b729 100644 --- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties @@ -331,6 +331,11 @@ ScrollBar.hoverTrackColor = #0f0 ScrollBar.hoverThumbColor = #f00 +#---- ScrollPane ---- + +ScrollPane.arc = 20 + + #---- Separator ---- Separator.foreground = #0b0 diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 6545b7d2..b067ba31 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -719,6 +719,7 @@ ScrollBar.width ScrollBarUI ScrollPane.ancestorInputMap ScrollPane.ancestorInputMap.RightToLeft +ScrollPane.arc ScrollPane.background ScrollPane.border ScrollPane.fillUpperCorner