From 144f79f0f94c0736a8b6947076f89c3893784506 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 2 Oct 2019 19:13:47 +0200 Subject: [PATCH] chevron arrows implemented (closes #7) use chevron arrows in "Flat Light" and "Flat Dark" themes, but keep triangle arrows in "Flat IntelliJ" and "Flat Darcula" themes --- CHANGELOG.md | 2 ++ .../flatlaf/icons/FlatMenuArrowIcon.java | 16 +++++++++-- .../flatlaf/icons/FlatTreeCollapsedIcon.java | 25 +++++++++++++++-- .../flatlaf/icons/FlatTreeExpandedIcon.java | 9 +++--- .../formdev/flatlaf/ui/FlatArrowButton.java | 28 +++++++++++++------ .../formdev/flatlaf/ui/FlatComboBoxUI.java | 5 +++- .../com/formdev/flatlaf/ui/FlatSpinnerUI.java | 5 +++- .../formdev/flatlaf/ui/FlatSplitPaneUI.java | 6 +++- .../formdev/flatlaf/ui/FlatTabbedPaneUI.java | 4 ++- .../com/formdev/flatlaf/ui/FlatUIUtils.java | 7 ++++- .../formdev/flatlaf/FlatDarculaLaf.properties | 1 + .../flatlaf/FlatIntelliJLaf.properties | 1 + .../com/formdev/flatlaf/FlatLaf.properties | 1 + 13 files changed, 86 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b82e7d0c..dbee2884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ FlatLaf Change Log ## Unreleased +- Use new chevron arrows in "Flat Light" and "Flat Dark" themes, but keep + triangle arrows in "Flat IntelliJ" and "Flat Darcula" themes. (issue #7) - Added Java 9 module descriptor `module-info.class` to `flatlaf.jar` (in `META-INF/versions/9`). But FlatLaf remains Java 8 compatible. (issue #1) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java index ac1473ea..b42a19fe 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java @@ -16,9 +16,11 @@ package com.formdev.flatlaf.icons; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; import java.awt.Graphics2D; +import java.awt.geom.Path2D; import javax.swing.JMenu; import javax.swing.UIManager; import com.formdev.flatlaf.ui.FlatUIUtils; @@ -26,6 +28,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils; /** * "arrow" icon for {@link javax.swing.JMenu}. * + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault Menu.icon.arrowColor Color * @uiDefault Menu.icon.disabledArrowColor Color * @uiDefault Menu.selectionForeground Color @@ -35,12 +38,13 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatMenuArrowIcon extends FlatAbstractIcon { + protected final boolean chevron = "chevron".equals( UIManager.getString( "Component.arrowType" ) ); protected final Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" ); protected final Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" ); protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" ); public FlatMenuArrowIcon() { - super( 5, 10, null ); + super( 6, 10, null ); } @Override @@ -49,7 +53,15 @@ public class FlatMenuArrowIcon g.rotate( Math.toRadians( 180 ), width / 2., height / 2. ); g.setColor( getArrowColor( c ) ); - g.fill( FlatUIUtils.createPath( 0,0.5, 0,9.5, 5,5 ) ); + if( chevron ) { + // chevron arrow + Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 ); + g.setStroke( new BasicStroke( 1f ) ); + g.draw( path ); + } else { + // triangle arrow + g.fill( FlatUIUtils.createPath( 0,0.5, 0,9.5, 5,5 ) ); + } } private Color getArrowColor( Component c ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java index c8e34259..2f2c9cb2 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java @@ -16,6 +16,7 @@ package com.formdev.flatlaf.icons; +import java.awt.Color; import java.awt.Component; import java.awt.Graphics2D; import javax.swing.UIManager; @@ -24,6 +25,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils; /** * "collapsed" icon for {@link javax.swing.JTree}. * + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault Tree.icon.collapsedColor Color * * @author Karl Tauber @@ -31,15 +33,32 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatTreeCollapsedIcon extends FlatAbstractIcon { + private final boolean chevron; + public FlatTreeCollapsedIcon() { - super( 11, 11, UIManager.getColor( "Tree.icon.collapsedColor" ) ); + this( UIManager.getColor( "Tree.icon.collapsedColor" ) ); + } + + FlatTreeCollapsedIcon( Color color ) { + super( 11, 11, color ); + chevron = "chevron".equals( UIManager.getString( "Component.arrowType" ) ); } @Override protected void paintIcon( Component c, Graphics2D g ) { + rotate( c, g ); + + if( chevron ) { + // chevron arrow + g.fill( FlatUIUtils.createPath( 3,1, 3,2.5, 6,5.5, 3,8.5, 3,10, 4.5,10, 9,5.5, 4.5,1 ) ); + } else { + // triangle arrow + g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) ); + } + } + + void rotate( Component c, Graphics2D g ) { if( !c.getComponentOrientation().isLeftToRight() ) g.rotate( Math.toRadians( 180 ), width / 2., height / 2. ); - - g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeExpandedIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeExpandedIcon.java index 489aabb1..113139e9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeExpandedIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeExpandedIcon.java @@ -19,7 +19,6 @@ package com.formdev.flatlaf.icons; import java.awt.Component; import java.awt.Graphics2D; import javax.swing.UIManager; -import com.formdev.flatlaf.ui.FlatUIUtils; /** * "expanded" icon for {@link javax.swing.JTree}. @@ -29,14 +28,14 @@ import com.formdev.flatlaf.ui.FlatUIUtils; * @author Karl Tauber */ public class FlatTreeExpandedIcon - extends FlatAbstractIcon + extends FlatTreeCollapsedIcon { public FlatTreeExpandedIcon() { - super( 11, 11, UIManager.getColor( "Tree.icon.expandedColor" ) ); + super( UIManager.getColor( "Tree.icon.expandedColor" ) ); } @Override - protected void paintIcon( Component c, Graphics2D g ) { - g.fill( FlatUIUtils.createPath( 1,2, 10,2, 5.5,10 ) ); + void rotate( Component c, Graphics2D g ) { + g.rotate( Math.toRadians( 90 ), width / 2., height / 2. ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java index 1cc56c3d..6a9c7fbc 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatArrowButton.java @@ -17,6 +17,7 @@ package com.formdev.flatlaf.ui; import static com.formdev.flatlaf.util.UIScale.scale; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; @@ -37,6 +38,7 @@ public class FlatArrowButton extends BasicArrowButton implements UIResource { + private final boolean chevron; private final Color foreground; private final Color disabledForeground; private final Color hoverForeground; @@ -47,11 +49,12 @@ public class FlatArrowButton private boolean hover; - public FlatArrowButton( int direction, Color foreground, Color disabledForeground, + public FlatArrowButton( int direction, String type, Color foreground, Color disabledForeground, Color hoverForeground, Color hoverBackground ) { super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE ); + this.chevron = "chevron".equals( type ); this.foreground = foreground; this.disabledForeground = disabledForeground; this.hoverForeground = hoverForeground; @@ -121,8 +124,8 @@ public class FlatArrowButton int direction = getDirection(); boolean vert = (direction == NORTH || direction == SOUTH); - int w = scale( 9 ); - int h = scale( 5 ); + int w = scale( chevron ? 8 : 9 ); + int h = scale( chevron ? 4 : 5 ); int x = Math.round( (width - (vert ? w : h)) / 2f + scale( (float) xOffset ) ); int y = Math.round( (height - (vert ? h : w)) / 2f + scale( (float) yOffset ) ); @@ -131,16 +134,23 @@ public class FlatArrowButton ? (hover && hoverForeground != null ? hoverForeground : foreground) : disabledForeground ); g.translate( x, y ); - g2.fill( createArrowShape( direction, w, h ) ); + Shape arrowShape = createArrowShape( direction, chevron, w, h ); + if( chevron ) { + g2.setStroke( new BasicStroke( scale( 1f ) ) ); + g2.draw( arrowShape ); + } else { + // triangle + g2.fill( arrowShape ); + } g.translate( -x, -y ); } - public static Shape createArrowShape( int direction, int w, int h ) { + public static Shape createArrowShape( int direction, boolean chevron, int w, int h ) { switch( direction ) { - case NORTH: return FlatUIUtils.createPath( 0,h, w,h, (w / 2f),0 ); - case SOUTH: return FlatUIUtils.createPath( 0,0, w,0, (w / 2f),h ); - case WEST: return FlatUIUtils.createPath( h,0, h,w, 0,(w / 2f) ); - case EAST: return FlatUIUtils.createPath( 0,0, 0,w, h,(w / 2f) ); + case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h ); + case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 ); + case WEST: return FlatUIUtils.createPath( !chevron, h,0, 0,(w / 2f), h,w ); + case EAST: return FlatUIUtils.createPath( !chevron, 0,0, h,(w / 2f), 0,w ); default: return new Path2D.Float(); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java index e55cab77..8b95f8e5 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java @@ -57,6 +57,7 @@ import com.formdev.flatlaf.util.UIScale; * * @uiDefault Component.focusWidth int * @uiDefault Component.arc int + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault Component.borderColor Color * @uiDefault Component.disabledBorderColor Color * @uiDefault ComboBox.disabledBackground Color @@ -74,6 +75,7 @@ public class FlatComboBoxUI { protected int focusWidth; protected int arc; + protected String arrowType; protected Color borderColor; protected Color disabledBorderColor; @@ -96,6 +98,7 @@ public class FlatComboBoxUI focusWidth = UIManager.getInt( "Component.focusWidth" ); arc = UIManager.getInt( "Component.arc" ); + arrowType = UIManager.getString( "Component.arrowType" ); borderColor = UIManager.getColor( "Component.borderColor" ); disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" ); @@ -224,7 +227,7 @@ public class FlatComboBoxUI @Override protected JButton createArrowButton() { - return new FlatArrowButton( SwingConstants.SOUTH, buttonArrowColor, + return new FlatArrowButton( SwingConstants.SOUTH, arrowType, buttonArrowColor, buttonDisabledArrowColor, buttonHoverArrowColor, null ); } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java index 2eebca06..53710d7c 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java @@ -48,6 +48,7 @@ import javax.swing.plaf.basic.BasicSpinnerUI; * @uiDefault Component.focusWidth int * @uiDefault Component.arc int * @uiDefault Component.minimumWidth int + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault Component.borderColor Color * @uiDefault Component.disabledBorderColor Color * @uiDefault Spinner.disabledBackground Color @@ -68,6 +69,7 @@ public class FlatSpinnerUI protected int focusWidth; protected int arc; protected int minimumWidth; + protected String arrowType; protected Color borderColor; protected Color disabledBorderColor; protected Color disabledBackground; @@ -89,6 +91,7 @@ public class FlatSpinnerUI focusWidth = UIManager.getInt( "Component.focusWidth" ); arc = UIManager.getInt( "Component.arc" ); minimumWidth = UIManager.getInt( "Component.minimumWidth" ); + arrowType = UIManager.getString( "Component.arrowType" ); borderColor = UIManager.getColor( "Component.borderColor" ); disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" ); disabledBackground = UIManager.getColor( "Spinner.disabledBackground" ); @@ -209,7 +212,7 @@ public class FlatSpinnerUI } private Component createArrowButton( int direction, String name ) { - FlatArrowButton button = new FlatArrowButton( direction, buttonArrowColor, + FlatArrowButton button = new FlatArrowButton( direction, arrowType, buttonArrowColor, buttonDisabledArrowColor, buttonHoverArrowColor, null ); button.setName( name ); button.setYOffset( (direction == SwingConstants.NORTH) ? 1 : -1 ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java index e854505d..d2217fd6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java @@ -31,6 +31,7 @@ import com.formdev.flatlaf.util.UIScale; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JSplitPane}. * + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault SplitPane.background Color * @uiDefault SplitPane.foreground Color unused * @uiDefault SplitPane.dividerSize int @@ -46,6 +47,7 @@ import com.formdev.flatlaf.util.UIScale; public class FlatSplitPaneUI extends BasicSplitPaneUI { + protected String arrowType; private Boolean continuousLayout; private Color oneTouchArrowColor; private Color oneTouchHoverArrowColor; @@ -56,6 +58,8 @@ public class FlatSplitPaneUI @Override protected void installDefaults() { + arrowType = UIManager.getString( "Component.arrowType" ); + // get one-touch colors before invoking super.installDefaults() because they are // used in there on LaF switching oneTouchArrowColor = UIManager.getColor( "SplitPaneDivider.oneTouchArrowColor" ); @@ -108,7 +112,7 @@ public class FlatSplitPaneUI private final boolean left; public FlatOneTouchButton( boolean left ) { - super( SwingConstants.NORTH, oneTouchArrowColor, null, oneTouchHoverArrowColor, null ); + super( SwingConstants.NORTH, arrowType, oneTouchArrowColor, null, oneTouchHoverArrowColor, null ); setCursor( Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR ) ); this.left = left; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java index 6f06c13c..5da172e7 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java @@ -39,6 +39,7 @@ import javax.swing.text.View; * * @clientProperty JTabbedPane.hasFullBorder boolean * + * @uiDefault Component.arrowType String triangle (default) or chevron * @uiDefault TabbedPane.font Font * @uiDefault TabbedPane.background Color * @uiDefault TabbedPane.foreground Color @@ -144,7 +145,8 @@ public class FlatTabbedPaneUI @Override protected JButton createScrollButton( int direction ) { // this method is invoked before installDefaults(), so we can not use color fields here - return new FlatArrowButton( direction, UIManager.getColor("TabbedPane.shadow"), + return new FlatArrowButton( direction, UIManager.getString( "Component.arrowType" ), + UIManager.getColor( "TabbedPane.shadow" ), UIManager.getColor( "TabbedPane.disabledForeground" ), null, UIManager.getColor( "TabbedPane.hoverColor" ) ); } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java index 7edee9ef..d44aaa99 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java @@ -181,11 +181,16 @@ public class FlatUIUtils } public static Path2D createPath( double... points ) { + return createPath( true, points ); + } + + public static Path2D createPath( boolean close, double... points ) { Path2D path = new Path2D.Float(); path.moveTo( points[0], points[1] ); for( int i = 2; i < points.length; i += 2 ) path.lineTo( points[i], points[i + 1] ); - path.closePath(); + if( close ) + path.closePath(); return path; } diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties index 0d2ce1fe..fb4ac334 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties @@ -21,6 +21,7 @@ #---- Component ---- Component.focusWidth=2 +Component.arrowType=triangle #---- RadioButton ---- diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatIntelliJLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatIntelliJLaf.properties index 10b930af..14f1dfbe 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatIntelliJLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatIntelliJLaf.properties @@ -37,6 +37,7 @@ CheckBox.icon.selectedPressedBackground=72A1D4 #---- Component ---- Component.focusWidth=2 +Component.arrowType=triangle #---- RadioButton ---- 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 bb96e010..df29e424 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -105,6 +105,7 @@ ComboBox.padding=2,6,2,6 Component.focusWidth=0 Component.arc=5 Component.minimumWidth=64 +Component.arrowType=chevron #---- EditorPane ----