Merge PR #788: Support for hover/pressed on SplitPane divider

This commit is contained in:
Karl Tauber
2024-01-10 16:43:28 +01:00
11 changed files with 148 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ FlatLaf Change Log
`libflatlaf-macos-x86_64.dylib`. See also `libflatlaf-macos-x86_64.dylib`. See also
https://www.formdev.com/flatlaf/native-libraries/. https://www.formdev.com/flatlaf/native-libraries/.
- ScrollPane: Support rounded border. (PR #713) - ScrollPane: Support rounded border. (PR #713)
- SplitPane: Support divider hover and pressed background colors. (PR #788)
- TabbedPane: Support vertical tabs. (PR #758, issue #633) - TabbedPane: Support vertical tabs. (PR #758, issue #633)
- TabbedPane: Paint rounded tab area background for rounded cards. (issue #717) - TabbedPane: Paint rounded tab area background for rounded cards. (issue #717)
- ToolBar: Added styling properties `separatorWidth` and `separatorColor`. - ToolBar: Added styling properties `separatorWidth` and `separatorColor`.

View File

@@ -16,7 +16,9 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.Canvas;
import java.awt.Color; import java.awt.Color;
import java.awt.Component;
import java.awt.Container; import java.awt.Container;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Graphics; import java.awt.Graphics;
@@ -67,6 +69,8 @@ import com.formdev.flatlaf.util.UIScale;
* <!-- FlatSplitPaneUI --> * <!-- FlatSplitPaneUI -->
* *
* @uiDefault Component.arrowType String chevron (default) or triangle * @uiDefault Component.arrowType String chevron (default) or triangle
* @uiDefault SplitPaneDivider.hoverColor Color optional
* @uiDefault SplitPaneDivider.pressedColor Color optional
* @uiDefault SplitPaneDivider.oneTouchArrowColor Color * @uiDefault SplitPaneDivider.oneTouchArrowColor Color
* @uiDefault SplitPaneDivider.oneTouchHoverArrowColor Color * @uiDefault SplitPaneDivider.oneTouchHoverArrowColor Color
* @uiDefault SplitPaneDivider.oneTouchPressedArrowColor Color * @uiDefault SplitPaneDivider.oneTouchPressedArrowColor Color
@@ -83,6 +87,7 @@ public class FlatSplitPaneUI
implements StyleableUI implements StyleableUI
{ {
@Styleable protected String arrowType; @Styleable protected String arrowType;
/** @since 3.3 */ @Styleable protected Color draggingColor;
@Styleable protected Color oneTouchArrowColor; @Styleable protected Color oneTouchArrowColor;
@Styleable protected Color oneTouchHoverArrowColor; @Styleable protected Color oneTouchHoverArrowColor;
@Styleable protected Color oneTouchPressedArrowColor; @Styleable protected Color oneTouchPressedArrowColor;
@@ -104,6 +109,8 @@ public class FlatSplitPaneUI
protected void installDefaults() { protected void installDefaults() {
arrowType = UIManager.getString( "Component.arrowType" ); arrowType = UIManager.getString( "Component.arrowType" );
draggingColor = UIManager.getColor( "SplitPaneDivider.draggingColor" );
// get one-touch colors before invoking super.installDefaults() because they are // get one-touch colors before invoking super.installDefaults() because they are
// used in there on LaF switching // used in there on LaF switching
oneTouchArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchArrowColor" ); oneTouchArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchArrowColor" );
@@ -117,6 +124,8 @@ public class FlatSplitPaneUI
protected void uninstallDefaults() { protected void uninstallDefaults() {
super.uninstallDefaults(); super.uninstallDefaults();
draggingColor = null;
oneTouchArrowColor = null; oneTouchArrowColor = null;
oneTouchHoverArrowColor = null; oneTouchHoverArrowColor = null;
oneTouchPressedArrowColor = null; oneTouchPressedArrowColor = null;
@@ -183,12 +192,49 @@ public class FlatSplitPaneUI
return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
} }
@Override
protected Component createDefaultNonContinuousLayoutDivider() {
// only used for non-continuous layout if left or right component is heavy weight
return new Canvas() {
@Override
public void paint( Graphics g ) {
if( !isContinuousLayout() && getLastDragLocation() != -1 )
paintDragDivider( g, 0 );
}
};
}
@Override
public void finishedPaintingChildren( JSplitPane sp, Graphics g ) {
if( sp == splitPane && getLastDragLocation() != -1 && !isContinuousLayout() && !draggingHW )
paintDragDivider( g, getLastDragLocation() );
}
private void paintDragDivider( Graphics g, int dividerLocation ) {
// divider bounds
boolean horizontal = (getOrientation() == JSplitPane.HORIZONTAL_SPLIT);
int x = horizontal ? dividerLocation : 0;
int y = !horizontal ? dividerLocation : 0;
int width = horizontal ? dividerSize : splitPane.getWidth();
int height = !horizontal ? dividerSize : splitPane.getHeight();
// paint background
g.setColor( FlatUIUtils.deriveColor( draggingColor, splitPane.getBackground() ) );
g.fillRect( x, y, width, height );
// paint divider style (e.g. grip)
if( divider instanceof FlatSplitPaneDivider )
((FlatSplitPaneDivider)divider).paintStyle( g, x, y, width, height );
}
//---- class FlatSplitPaneDivider ----------------------------------------- //---- class FlatSplitPaneDivider -----------------------------------------
protected class FlatSplitPaneDivider protected class FlatSplitPaneDivider
extends BasicSplitPaneDivider extends BasicSplitPaneDivider
{ {
@Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" ); @Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" );
/** @since 3.3 */ @Styleable protected Color hoverColor = UIManager.getColor( "SplitPaneDivider.hoverColor" );
/** @since 3.3 */ @Styleable protected Color pressedColor = UIManager.getColor( "SplitPaneDivider.pressedColor" );
@Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" ); @Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
@Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 ); @Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
@Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 ); @Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
@@ -251,15 +297,31 @@ public class FlatSplitPaneUI
@Override @Override
public void paint( Graphics g ) { public void paint( Graphics g ) {
// paint hover or pressed background
Color hoverOrPressedColor = (isContinuousLayout() && dragger != null)
? pressedColor
: (isMouseOver() && dragger == null
? hoverColor
: null);
if( hoverOrPressedColor != null ) {
g.setColor( FlatUIUtils.deriveColor( hoverOrPressedColor, splitPane.getBackground() ) );
g.fillRect( 0, 0, getWidth(), getHeight() );
}
super.paint( g ); super.paint( g );
paintStyle( g, 0, 0, getWidth(), getHeight() );
}
/** @since 3.3 */
protected void paintStyle( Graphics g, int x, int y, int width, int height ) {
if( "plain".equals( style ) ) if( "plain".equals( style ) )
return; return;
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g ); Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
g.setColor( gripColor ); g.setColor( gripColor );
paintGrip( g, 0, 0, getWidth(), getHeight() ); paintGrip( g, x, y, width, height );
FlatUIUtils.resetRenderingHints( g, oldRenderingHints ); FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
} }
@@ -286,6 +348,29 @@ public class FlatSplitPaneUI
: location == (splitPane.getWidth() - getWidth() - insets.right); : location == (splitPane.getWidth() - getWidth() - insets.right);
} }
@Override
protected void setMouseOver( boolean mouseOver ) {
super.setMouseOver( mouseOver );
repaintIfNecessary();
}
@Override
protected void prepareForDragging() {
super.prepareForDragging();
repaintIfNecessary();
}
@Override
protected void finishDraggingTo( int location ) {
super.finishDraggingTo( location );
repaintIfNecessary();
}
private void repaintIfNecessary() {
if( hoverColor != null || pressedColor != null )
repaint();
}
//---- class FlatOneTouchButton --------------------------------------- //---- class FlatOneTouchButton ---------------------------------------
protected class FlatOneTouchButton protected class FlatOneTouchButton

View File

@@ -689,6 +689,9 @@ public class TestFlatStyleableInfo
Map<String, Class<?>> expected = expectedMap( Map<String, Class<?>> expected = expectedMap(
"arrowType", String.class, "arrowType", String.class,
"draggingColor", Color.class,
"hoverColor", Color.class,
"pressedColor", Color.class,
"oneTouchArrowColor", Color.class, "oneTouchArrowColor", Color.class,
"oneTouchHoverArrowColor", Color.class, "oneTouchHoverArrowColor", Color.class,
"oneTouchPressedArrowColor", Color.class, "oneTouchPressedArrowColor", Color.class,

View File

@@ -699,6 +699,9 @@ public class TestFlatStyleableValue
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI(); FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
testString( c, ui, "arrowType", "chevron" ); testString( c, ui, "arrowType", "chevron" );
testColor( c, ui, "draggingColor", 0x123456 );
testColor( c, ui, "hoverColor", 0x123456 );
testColor( c, ui, "pressedColor", 0x123456 );
testColor( c, ui, "oneTouchArrowColor", 0x123456 ); testColor( c, ui, "oneTouchArrowColor", 0x123456 );
testColor( c, ui, "oneTouchHoverArrowColor", 0x123456 ); testColor( c, ui, "oneTouchHoverArrowColor", 0x123456 );
testColor( c, ui, "oneTouchPressedArrowColor", 0x123456 ); testColor( c, ui, "oneTouchPressedArrowColor", 0x123456 );

View File

@@ -870,6 +870,9 @@ public class TestFlatStyling
FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI(); FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI();
ui.applyStyle( "arrowType: chevron" ); ui.applyStyle( "arrowType: chevron" );
ui.applyStyle( "draggingColor: #fff" );
ui.applyStyle( "hoverColor: #fff" );
ui.applyStyle( "pressedColor: #fff" );
ui.applyStyle( "oneTouchArrowColor: #fff" ); ui.applyStyle( "oneTouchArrowColor: #fff" );
ui.applyStyle( "oneTouchHoverArrowColor: #fff" ); ui.applyStyle( "oneTouchHoverArrowColor: #fff" );
ui.applyStyle( "oneTouchPressedArrowColor: #fff" ); ui.applyStyle( "oneTouchPressedArrowColor: #fff" );

View File

@@ -175,6 +175,9 @@ Spinner.buttonPressedArrowColor = Spinner.buttonArrowColor
#---- SplitPaneDivider ---- #---- SplitPaneDivider ----
SplitPaneDivider.draggingColor = SplitPane.background
SplitPaneDivider.hoverColor = SplitPane.background
SplitPaneDivider.pressedColor = SplitPane.background
SplitPaneDivider.oneTouchHoverArrowColor = SplitPaneDivider.oneTouchArrowColor SplitPaneDivider.oneTouchHoverArrowColor = SplitPaneDivider.oneTouchArrowColor
SplitPaneDivider.oneTouchPressedArrowColor = SplitPaneDivider.oneTouchArrowColor SplitPaneDivider.oneTouchPressedArrowColor = SplitPaneDivider.oneTouchArrowColor

View File

@@ -1050,9 +1050,11 @@ SplitPaneDivider.gripColor #afafaf HSL 0 0 69 javax.swing.plaf.Colo
SplitPaneDivider.gripDotCount 3 SplitPaneDivider.gripDotCount 3
SplitPaneDivider.gripDotSize 3 SplitPaneDivider.gripDotSize 3
SplitPaneDivider.gripGap 2 SplitPaneDivider.gripGap 2
SplitPaneDivider.hoverColor #008800 HSL 120 100 27 javax.swing.plaf.ColorUIResource [UI]
SplitPaneDivider.oneTouchArrowColor #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI] SplitPaneDivider.oneTouchArrowColor #00ff00 HSL 120 100 50 javax.swing.plaf.ColorUIResource [UI]
SplitPaneDivider.oneTouchHoverArrowColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] SplitPaneDivider.oneTouchHoverArrowColor #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI]
SplitPaneDivider.oneTouchPressedArrowColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI] SplitPaneDivider.oneTouchPressedArrowColor #0000ff HSL 240 100 50 javax.swing.plaf.ColorUIResource [UI]
SplitPaneDivider.pressedColor #000088 HSL 240 100 27 javax.swing.plaf.ColorUIResource [UI]
SplitPaneDivider.style grip SplitPaneDivider.style grip

View File

@@ -76,6 +76,13 @@ public class FlatContainerTest
tabScrollChanged(); tabScrollChanged();
} }
private void continuousLayoutChanged() {
boolean continuousLayout = continuousLayoutCheckBox.isSelected();
splitPane1.setContinuousLayout( continuousLayout );
splitPane2.setContinuousLayout( continuousLayout );
splitPane3.setContinuousLayout( continuousLayout );
}
private void showOnlyOne() { private void showOnlyOne() {
boolean showOnlyOne = showOnlyOneCheckBox.isSelected(); boolean showOnlyOne = showOnlyOneCheckBox.isSelected();
@@ -519,11 +526,12 @@ public class FlatContainerTest
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JPanel panel9 = new JPanel(); JPanel panel9 = new JPanel();
JLabel splitPaneLabel = new JLabel(); JLabel splitPaneLabel = new JLabel();
JSplitPane splitPane3 = new JSplitPane(); continuousLayoutCheckBox = new JCheckBox();
JSplitPane splitPane1 = new JSplitPane(); splitPane3 = new JSplitPane();
splitPane1 = new JSplitPane();
FlatContainerTest.Panel1 panel15 = new FlatContainerTest.Panel1(); FlatContainerTest.Panel1 panel15 = new FlatContainerTest.Panel1();
FlatContainerTest.Panel2 panel21 = new FlatContainerTest.Panel2(); FlatContainerTest.Panel2 panel21 = new FlatContainerTest.Panel2();
JSplitPane splitPane2 = new JSplitPane(); splitPane2 = new JSplitPane();
JPanel panel12 = new JPanel(); JPanel panel12 = new JPanel();
JLabel label3 = new JLabel(); JLabel label3 = new JLabel();
JPanel panel13 = new JPanel(); JPanel panel13 = new JPanel();
@@ -601,6 +609,12 @@ public class FlatContainerTest
splitPaneLabel.setText("JSplitPane:"); splitPaneLabel.setText("JSplitPane:");
panel9.add(splitPaneLabel, cc.xy(1, 1)); panel9.add(splitPaneLabel, cc.xy(1, 1));
//---- continuousLayoutCheckBox ----
continuousLayoutCheckBox.setText("Continuous Layout");
continuousLayoutCheckBox.setSelected(true);
continuousLayoutCheckBox.addActionListener(e -> continuousLayoutChanged());
panel9.add(continuousLayoutCheckBox, cc.xy(3, 1, CellConstraints.RIGHT, CellConstraints.DEFAULT));
//======== splitPane3 ======== //======== splitPane3 ========
{ {
splitPane3.setResizeWeight(0.5); splitPane3.setResizeWeight(0.5);
@@ -929,6 +943,10 @@ public class FlatContainerTest
} }
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JCheckBox continuousLayoutCheckBox;
private JSplitPane splitPane3;
private JSplitPane splitPane1;
private JSplitPane splitPane2;
private JCheckBox showOnlyOneCheckBox; private JCheckBox showOnlyOneCheckBox;
private FlatTabbedPane tabbedPane1; private FlatTabbedPane tabbedPane1;
private FlatTabbedPane tabbedPane3; private FlatTabbedPane tabbedPane3;

View File

@@ -22,13 +22,32 @@ new FormModel {
name: "splitPaneLabel" name: "splitPaneLabel"
"text": "JSplitPane:" "text": "JSplitPane:"
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) ) }, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "continuousLayoutCheckBox"
"text": "Continuous Layout"
"selected": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "continuousLayoutChanged", false ) )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 3
"gridY": 1
"hAlign": sfield com.jgoodies.forms.layout.CellConstraints RIGHT
} )
add( new FormContainer( "javax.swing.JSplitPane", new FormLayoutManager( class javax.swing.JSplitPane ) ) { add( new FormContainer( "javax.swing.JSplitPane", new FormLayoutManager( class javax.swing.JSplitPane ) ) {
name: "splitPane3" name: "splitPane3"
"resizeWeight": 0.5 "resizeWeight": 0.5
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JSplitPane", new FormLayoutManager( class javax.swing.JSplitPane ) ) { add( new FormContainer( "javax.swing.JSplitPane", new FormLayoutManager( class javax.swing.JSplitPane ) ) {
name: "splitPane1" name: "splitPane1"
"resizeWeight": 0.5 "resizeWeight": 0.5
"oneTouchExpandable": true "oneTouchExpandable": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormComponent( "com.formdev.flatlaf.testing.FlatContainerTest$Panel1" ) { add( new FormComponent( "com.formdev.flatlaf.testing.FlatContainerTest$Panel1" ) {
name: "panel15" name: "panel15"
"background": new java.awt.Color( 217, 163, 67, 255 ) "background": new java.awt.Color( 217, 163, 67, 255 )
@@ -49,6 +68,9 @@ new FormModel {
"orientation": 0 "orientation": 0
"resizeWeight": 0.5 "resizeWeight": 0.5
"oneTouchExpandable": true "oneTouchExpandable": true
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.BorderLayout ) ) {
name: "panel12" name: "panel12"
"background": new java.awt.Color( 242, 101, 34, 255 ) "background": new java.awt.Color( 242, 101, 34, 255 )

View File

@@ -368,6 +368,8 @@ Spinner.focusedBackground = #ff8
#---- SplitPane ---- #---- SplitPane ----
SplitPaneDivider.draggingColor = #800 SplitPaneDivider.draggingColor = #800
SplitPaneDivider.hoverColor = #080
SplitPaneDivider.pressedColor = #008
SplitPaneDivider.oneTouchArrowColor = #0f0 SplitPaneDivider.oneTouchArrowColor = #0f0
SplitPaneDivider.oneTouchHoverArrowColor = #f00 SplitPaneDivider.oneTouchHoverArrowColor = #f00
SplitPaneDivider.oneTouchPressedArrowColor = #00f SplitPaneDivider.oneTouchPressedArrowColor = #00f

View File

@@ -827,9 +827,11 @@ SplitPaneDivider.gripColor
SplitPaneDivider.gripDotCount SplitPaneDivider.gripDotCount
SplitPaneDivider.gripDotSize SplitPaneDivider.gripDotSize
SplitPaneDivider.gripGap SplitPaneDivider.gripGap
SplitPaneDivider.hoverColor
SplitPaneDivider.oneTouchArrowColor SplitPaneDivider.oneTouchArrowColor
SplitPaneDivider.oneTouchHoverArrowColor SplitPaneDivider.oneTouchHoverArrowColor
SplitPaneDivider.oneTouchPressedArrowColor SplitPaneDivider.oneTouchPressedArrowColor
SplitPaneDivider.pressedColor
SplitPaneDivider.style SplitPaneDivider.style
SplitPaneUI SplitPaneUI
TabbedPane.ancestorInputMap TabbedPane.ancestorInputMap