Merge PR #713: Scrollpane rounded border

This commit is contained in:
Karl Tauber
2023-12-21 17:40:00 +01:00
20 changed files with 1136 additions and 41 deletions

View File

@@ -10,6 +10,7 @@ FlatLaf Change Log
- Native libraries: Added `libflatlaf-macos-arm64.dylib` and
`libflatlaf-macos-x86_64.dylib`. See also
https://www.formdev.com/flatlaf/native-libraries/.
- ScrollPane: Support rounded border. (PR #713)
- ToolBar: Added styling properties `separatorWidth` and `separatorColor`.
#### Fixed bugs
@@ -20,6 +21,8 @@ FlatLaf Change Log
and #750)
- OptionPane: Fixed styling custom panel background in `JOptionPane`. (issue
#761)
- ScrollPane: Styling ScrollPane border properties did not work if view
component is a Table.
- Table: Fixed background of `boolean` columns when using alternating row
colors. (issue #780)
- Fixed broken rendering after resizing window to minimum size and then

View File

@@ -28,7 +28,6 @@ import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicBorders;
import com.formdev.flatlaf.FlatClientProperties;
@@ -195,8 +194,7 @@ public class FlatBorder
protected boolean isEnabled( Component c ) {
if( c instanceof JScrollPane ) {
// check whether view component is disabled
JViewport viewport = ((JScrollPane)c).getViewport();
Component view = (viewport != null) ? viewport.getView() : null;
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
if( view != null && !isEnabled( view ) )
return false;
}

View File

@@ -0,0 +1,118 @@
/*
* 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.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
import com.formdev.flatlaf.util.UIScale;
/**
* Border for {@link javax.swing.JScrollPane}.
*
* @uiDefault ScrollPane.arc int
* @uiDefault ScrollPane.List.arc int
* @uiDefault ScrollPane.Table.arc int
* @uiDefault ScrollPane.TextComponent.arc int
* @uiDefault ScrollPane.Tree.arc int
* @author Karl Tauber
* @since 3.3
*/
public class FlatScrollPaneBorder
extends FlatBorder
{
@Styleable protected int arc = UIManager.getInt( "ScrollPane.arc" );
private boolean isArcStyled;
private final int listArc = FlatUIUtils.getUIInt( "ScrollPane.List.arc", -1 );
private final int tableArc = FlatUIUtils.getUIInt( "ScrollPane.Table.arc", -1 );
private final int textComponentArc = FlatUIUtils.getUIInt( "ScrollPane.TextComponent.arc", -1 );
private final int treeArc = FlatUIUtils.getUIInt( "ScrollPane.Tree.arc", -1 );
@Override
public Object applyStyleProperty( String key, Object value ) {
Object oldValue = super.applyStyleProperty( key, value );
if( "arc".equals( key ) )
isArcStyled = true;
return oldValue;
}
@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 padding = getLeftRightPadding( c );
if( padding > 0 ) {
insets.left += padding;
insets.right += padding;
}
return insets;
}
@Override
protected int getArc( Component c ) {
if( isCellEditor( c ) )
return 0;
if( isArcStyled )
return arc;
if( c instanceof JScrollPane ) {
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
if( listArc >= 0 && view instanceof JList )
return listArc;
if( tableArc >= 0 && view instanceof JTable )
return tableArc;
if( textComponentArc >= 0&& view instanceof JTextComponent )
return textComponentArc;
if( treeArc >= 0 && view instanceof JTree )
return treeArc;
}
return arc;
}
/**
* Returns the scaled left/right padding used when arc is larger than zero.
* <p>
* This is the distance from the inside of the left border to the left side of the view component.
* On the right side, this is the distance between the right side of the view component and
* the vertical scrollbar. Or the inside of the right border if the scrollbar is hidden.
*/
public int getLeftRightPadding( Component c ) {
// Subtract lineWidth from radius because radius is given for the outside
// of the painted line, but insets from super already include lineWidth.
// Reduce padding by 10% to make padding slightly smaller because it is not recognizable
// when the view is minimally painted over the beginning of the border curve.
int arc = getArc( c );
return (arc > 0)
? Math.max( Math.round( UIScale.scale( ((arc / 2f) - getLineWidth( c )) * 0.9f ) ), 0 )
: 0;
}
}

View File

@@ -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 );
@@ -308,6 +330,18 @@ public class FlatScrollPaneUI
scrollpane.revalidate();
scrollpane.repaint();
break;
case "border":
Object newBorder = e.getNewValue();
if( newBorder != null && newBorder == UIManager.getBorder( "Table.scrollPaneBorder" ) ) {
// JTable.configureEnclosingScrollPaneUI() replaces the scrollpane border
// with another one --> re-apply style on new border
borderShared = null;
installStyle();
scrollpane.revalidate();
scrollpane.repaint();
}
break;
}
};
}
@@ -334,9 +368,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 +437,46 @@ 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 );
}
@Override
public void paint( Graphics g, JComponent c ) {
Border viewportBorder = scrollpane.getViewportBorder();
if( viewportBorder != null ) {
Rectangle r = scrollpane.getViewportBorderBounds();
int padding = getBorderLeftRightPadding( scrollpane );
JScrollBar vsb = scrollpane.getVerticalScrollBar();
if( padding > 0 &&
vsb != null && vsb.isVisible() &&
scrollpane.getLayout() instanceof FlatScrollPaneLayout &&
((FlatScrollPaneLayout)scrollpane.getLayout()).canIncreaseViewportWidth( scrollpane ) )
{
boolean ltr = scrollpane.getComponentOrientation().isLeftToRight();
int extraWidth = Math.min( padding, vsb.getWidth() );
viewportBorder.paintBorder( scrollpane, g, r.x - (ltr ? 0 : extraWidth), r.y, r.width + extraWidth, r.height );
} else
viewportBorder.paintBorder( scrollpane, g, r.x, r.y, r.width, r.height );
}
}
/** @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 +496,25 @@ public class FlatScrollPaneUI
return false;
}
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;
}
private static int getBorderLeftRightPadding( JScrollPane scrollPane ) {
Border border = scrollPane.getBorder();
return (border instanceof FlatScrollPaneBorder)
? ((FlatScrollPaneBorder)border).getLeftRightPadding( scrollPane )
: 0;
}
//---- class Handler ------------------------------------------------------
/**
@@ -450,13 +537,71 @@ public class FlatScrollPaneUI
@Override
public void focusGained( FocusEvent e ) {
// necessary to update focus border
if( scrollpane.getBorder() instanceof FlatBorder )
scrollpane.repaint();
}
@Override
public void focusLost( FocusEvent e ) {
// necessary to update focus border
if( scrollpane.getBorder() instanceof FlatBorder )
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;
int padding = getBorderLeftRightPadding( scrollPane );
if( padding > 0 && vsb != null && vsb.isVisible() ) {
// move vertical scrollbar to trailing edge
Insets insets = scrollPane.getInsets();
Rectangle r = vsb.getBounds();
int y = Math.max( r.y, insets.top + padding );
int y2 = Math.min( r.y + r.height, scrollPane.getHeight() - insets.bottom - padding );
boolean ltr = scrollPane.getComponentOrientation().isLeftToRight();
vsb.setBounds( r.x + (ltr ? padding : -padding), y, r.width, y2 - y );
// increase width of viewport, column header and horizontal scrollbar
if( canIncreaseViewportWidth( scrollPane ) ) {
int extraWidth = Math.min( padding, vsb.getWidth() );
resizeViewport( viewport, extraWidth, ltr );
resizeViewport( colHead, extraWidth, ltr );
resizeViewport( hsb, extraWidth, ltr );
}
}
}
boolean canIncreaseViewportWidth( JScrollPane scrollPane ) {
return scrollPane.getComponentOrientation().isLeftToRight()
? !isCornerVisible( upperRight ) && !isCornerVisible( lowerRight )
: !isCornerVisible( upperLeft ) && !isCornerVisible( lowerLeft );
}
private static boolean isCornerVisible( Component corner ) {
return corner != null &&
corner.getWidth() > 0 &&
corner.getHeight() > 0 &&
corner.isVisible();
}
private static void resizeViewport( Component c, int extraWidth, boolean ltr ) {
if( c == null )
return;
Rectangle vr = c.getBounds();
c.setBounds( vr.x - (ltr ? 0 : extraWidth), vr.y, vr.width + extraWidth, vr.height );
}
}
}

View File

@@ -600,10 +600,15 @@ 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
#ScrollPane.List.arc = -1
#ScrollPane.Table.arc = -1
#ScrollPane.TextComponent.arc = -1
#ScrollPane.Tree.arc = -1
#---- SearchField ----
@@ -734,7 +739,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

View File

@@ -601,7 +601,7 @@ public class TestFlatStyleableInfo
);
// border
flatBorder( expected );
flatScrollPaneBorder( expected );
assertMapEquals( expected, ui.getStyleableInfos( c ) );
}
@@ -1008,17 +1008,23 @@ public class TestFlatStyleableInfo
expectedMap( expected,
"arc", int.class,
"roundRect", Boolean.class
);
}
private void flatScrollPaneBorder( Map<String, Class<?>> expected ) {
flatBorder( expected );
expectedMap( expected,
"arc", int.class
);
}
private void flatTextBorder( Map<String, Class<?>> expected ) {
flatBorder( expected );
expectedMap( expected,
"arc", int.class,
"roundRect", Boolean.class
);
}

View File

@@ -625,7 +625,7 @@ public class TestFlatStyleableValue
FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI();
// border
flatBorder( c, ui );
flatScrollPaneBorder( c, ui );
testBoolean( c, ui, "showButtons", true );
}
@@ -968,15 +968,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 );
}
@@ -1037,6 +1041,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 );
}
@@ -1048,6 +1063,7 @@ public class TestFlatStyleableValue
flatBorder( border );
testValue( border, "arc", 6 );
testValue( border, "roundRect", true );
}
@Test

View File

@@ -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" );
@@ -1237,15 +1237,19 @@ public class TestFlatStyling
flatBorder( applyStyle );
applyStyle.accept( "arc: 6" );
applyStyle.accept( "roundRect: true" );
}
private void flatScrollPaneBorder( Consumer<String> applyStyle ) {
flatBorder( applyStyle );
applyStyle.accept( "arc: 6" );
}
private void flatTextBorder( Consumer<String> applyStyle ) {
flatBorder( applyStyle );
applyStyle.accept( "arc: 6" );
applyStyle.accept( "roundRect: true" );
}

View File

@@ -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 ----

View File

@@ -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]

View File

@@ -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 ----

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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,9,1,9 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,9,1,9 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]

View File

@@ -0,0 +1,528 @@
/*
* 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.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.MatteBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.tree.*;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatScrollPaneBorder;
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<String> 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<String>() {
@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 );
Border border = allJScrollPanes[0].getBorder();
paddingField.setText( border instanceof FlatScrollPaneBorder
? Integer.toString( ((FlatScrollPaneBorder)border).getLeftRightPadding( allJScrollPanes[0] ) )
: "?" );
}
private void viewportBorderChanged() {
Border viewportBorder = viewportBorderCheckBox.isSelected()
? new CompoundBorder(
new MatteBorder( 1, 1, 0, 0, Color.red ),
new MatteBorder( 0, 0, 1, 1, Color.blue ) )
: null;
for( JScrollPane scrollPane : allJScrollPanes ) {
scrollPane.setViewportBorder( viewportBorder );
scrollPane.revalidate();
scrollPane.repaint();
}
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
splitPane2 = new JSplitPane();
panel1 = new FlatTestPanel();
listLabel = new JLabel();
paddingLabel = new JLabel();
paddingField = 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();
horizontalScrollBarCheckBox = new JCheckBox();
viewportBorderCheckBox = new JCheckBox();
rowHeaderCheckBox = 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");
//---- paddingLabel ----
paddingLabel.setText("Padding:");
panel1.add(paddingLabel, "cell 0 0,alignx trailing,growx 0");
//---- paddingField ----
paddingField.setText("0");
panel1.add(paddingField, "cell 0 0,alignx trailing,growx 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" +
"[]" +
"[]" +
"[]",
// 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 1 2");
//---- 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");
//---- horizontalScrollBarCheckBox ----
horizontalScrollBarCheckBox.setText("Horizontal ScrollBar");
horizontalScrollBarCheckBox.setSelected(true);
horizontalScrollBarCheckBox.addActionListener(e -> horizontalScrollBarChanged());
panel3.add(horizontalScrollBarCheckBox, "cell 4 0");
//---- viewportBorderCheckBox ----
viewportBorderCheckBox.setText("Viewport border");
viewportBorderCheckBox.addActionListener(e -> viewportBorderChanged());
panel3.add(viewportBorderCheckBox, "cell 2 1");
//---- rowHeaderCheckBox ----
rowHeaderCheckBox.setText("Row Header");
rowHeaderCheckBox.addActionListener(e -> rowHeaderChanged());
panel3.add(rowHeaderCheckBox, "cell 3 1");
//---- verticalScrollBarCheckBox ----
verticalScrollBarCheckBox.setText("Vertical ScrollBar");
verticalScrollBarCheckBox.setSelected(true);
verticalScrollBarCheckBox.addActionListener(e -> verticalScrollBarChanged());
panel3.add(verticalScrollBarCheckBox, "cell 4 1");
}
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 paddingLabel;
private JLabel paddingField;
private JLabel treeLabel;
private JLabel tableLabel;
private JCheckBox autoResizeModeCheckBox;
private JScrollPane listScrollPane;
private JList<String> 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 horizontalScrollBarCheckBox;
private JCheckBox viewportBorderCheckBox;
private JCheckBox rowHeaderCheckBox;
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
}
}
}

View File

@@ -0,0 +1,249 @@
JFDML JFormDesigner: "8.1.1.0.298" 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: "paddingLabel"
"text": "Padding:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,alignx trailing,growx 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "paddingField"
"text": "0"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0,alignx trailing,growx 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[][][]"
"$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 1 2"
} )
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: "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 4 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "viewportBorderCheckBox"
"text": "Viewport border"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "viewportBorderChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1"
} )
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 3 1"
} )
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 4 1"
} )
}, 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 )
} )
}
}

View File

@@ -657,6 +657,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();

View File

@@ -331,6 +331,11 @@ ScrollBar.hoverTrackColor = #0f0
ScrollBar.hoverThumbColor = #f00
#---- ScrollPane ----
ScrollPane.arc = 20
#---- Separator ----
Separator.foreground = #0b0

View File

@@ -720,8 +720,13 @@ ScrollBar.trackHighlight
ScrollBar.trackInsets
ScrollBar.width
ScrollBarUI
ScrollPane.List.arc
ScrollPane.Table.arc
ScrollPane.TextComponent.arc
ScrollPane.Tree.arc
ScrollPane.ancestorInputMap
ScrollPane.ancestorInputMap.RightToLeft
ScrollPane.arc
ScrollPane.background
ScrollPane.border
ScrollPane.fillUpperCorner