From dfccabc2b980d75203bbc68f7fc3dc5552df72d3 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 8 Jan 2020 14:18:17 +0100 Subject: [PATCH] ToggleButton: support underline toggle button style --- CHANGELOG.md | 2 + .../formdev/flatlaf/FlatClientProperties.java | 9 +++ .../formdev/flatlaf/ui/FlatButtonBorder.java | 2 +- .../com/formdev/flatlaf/ui/FlatButtonUI.java | 71 ++++++++++--------- .../flatlaf/ui/FlatToggleButtonUI.java | 56 +++++++++++++++ .../com/formdev/flatlaf/FlatLaf.properties | 8 +++ .../flatlaf/testing/FlatComponentsTest.java | 15 ++++ .../flatlaf/testing/FlatComponentsTest.jfd | 17 +++++ 8 files changed, 145 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dca90d4..8fdb69bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ FlatLaf Change Log - Label and ToolTip: Fixed font sizes for HTML headings. - Button and ToggleButton: Support square button style (set client property `JButton.buttonType` to `square`). +- ToggleButton: Support underline toggle button style (set client property + `JButton.buttonType` to `underline`). ## 0.23.1 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index 3d0bc85d..8048c6d0 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -42,6 +42,15 @@ public interface FlatClientProperties */ String BUTTON_TYPE_SQUARE = "square"; + /** + * Paint the toggle button in underline style. + *

+ * Components {@link javax.swing.JToggleButton} + * + * @see #TOGGLE_BUTTON_TYPE + */ + String BUTTON_TYPE_UNDERLINE = "underline"; + /** * Paint a help button (circle with question mark). *

diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java index a0341619..70156a6c 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonBorder.java @@ -65,7 +65,7 @@ public class FlatButtonBorder @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { - if( FlatButtonUI.isContentAreaFilled( c ) && !FlatButtonUI.isHelpButton( c ) ) + if( FlatButtonUI.isContentAreaFilled( c ) && !FlatButtonUI.isHelpButton( c ) && !FlatToggleButtonUI.isUnderlineButton( c ) ) super.paintBorder( c, g, x, y, width, height ); } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java index 9eadebee..f1b41324 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java @@ -232,44 +232,47 @@ public class FlatButtonUI return; } - if( isContentAreaFilled( c ) ) { - Color background = getBackground( c ); - if( background != null ) { - Graphics2D g2 = (Graphics2D) g.create(); - try { - FlatUIUtils.setRenderingHints( g2 ); - - Border border = c.getBorder(); - float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0; - float arc = ((border instanceof FlatButtonBorder && !isSquareButton( c )) || isToolBarButton( c )) - ? scale( (float) this.arc ) : 0; - boolean def = isDefaultButton( c ); - - // paint shadow - Color shadowColor = def ? defaultShadowColor : this.shadowColor; - if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && !c.hasFocus() && c.isEnabled() ) { - g2.setColor( shadowColor ); - g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ), - c.getWidth() - focusWidth * 2, c.getHeight() - focusWidth * 2, arc, arc ) ); - } - - // paint background - Color startBg = def ? defaultBackground : startBackground; - Color endBg = def ? defaultEndBackground : endBackground; - if( background == startBg && endBg != null && !startBg.equals( endBg ) ) - g2.setPaint( new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg ) ); - else - FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() ); - FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc ); - } finally { - g2.dispose(); - } - } - } + if( isContentAreaFilled( c ) ) + paintBackground( g, c ); paint( g, c ); } + protected void paintBackground( Graphics g, JComponent c ) { + Color background = getBackground( c ); + if( background != null ) { + Graphics2D g2 = (Graphics2D) g.create(); + try { + FlatUIUtils.setRenderingHints( g2 ); + + Border border = c.getBorder(); + float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0; + float arc = ((border instanceof FlatButtonBorder && !isSquareButton( c )) || isToolBarButton( c )) + ? scale( (float) this.arc ) : 0; + boolean def = isDefaultButton( c ); + + // paint shadow + Color shadowColor = def ? defaultShadowColor : this.shadowColor; + if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && !c.hasFocus() && c.isEnabled() ) { + g2.setColor( shadowColor ); + g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ), + c.getWidth() - focusWidth * 2, c.getHeight() - focusWidth * 2, arc, arc ) ); + } + + // paint background + Color startBg = def ? defaultBackground : startBackground; + Color endBg = def ? defaultEndBackground : endBackground; + if( background == startBg && endBg != null && !startBg.equals( endBg ) ) + g2.setPaint( new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg ) ); + else + FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() ); + FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc ); + } finally { + g2.dispose(); + } + } + } + @Override protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) { if( isHelpButton( b ) ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java index e35a390b..97f390ac 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java @@ -16,12 +16,17 @@ package com.formdev.flatlaf.ui; +import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.JComponent; +import javax.swing.JToggleButton; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import com.formdev.flatlaf.util.UIScale; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JToggleButton}. @@ -55,6 +60,13 @@ import javax.swing.plaf.ComponentUI; * @uiDefault ToggleButton.disabledSelectedBackground Color * @uiDefault ToggleButton.toolbar.selectedBackground Color * + * @uiDefault ToggleButton.underline.underlineHeight int + * @uiDefault ToggleButton.underline.underlineColor Color + * @uiDefault ToggleButton.underline.disabledUnderlineColor Color + * @uiDefault ToggleButton.underline.selectedBackground Color optional + * @uiDefault ToggleButton.underline.hoverBackground Color + * @uiDefault ToggleButton.underline.focusBackground Color + * * * @author Karl Tauber */ @@ -67,6 +79,13 @@ public class FlatToggleButtonUI protected Color toolbarSelectedBackground; + protected int underlineHeight; + protected Color underlineColor; + protected Color disabledUnderlineColor; + protected Color underlineSelectedBackground; + protected Color underlineHoverBackground; + protected Color underlineFocusBackground; + private boolean defaults_initialized = false; private static ComponentUI instance; @@ -93,6 +112,13 @@ public class FlatToggleButtonUI toolbarSelectedBackground = UIManager.getColor( "ToggleButton.toolbar.selectedBackground" ); + underlineHeight = UIManager.getInt( "ToggleButton.underline.underlineHeight" ); + underlineColor = UIManager.getColor( "ToggleButton.underline.underlineColor" ); + disabledUnderlineColor = UIManager.getColor( "ToggleButton.underline.disabledUnderlineColor" ); + underlineSelectedBackground = UIManager.getColor( "ToggleButton.underline.selectedBackground" ); + underlineHoverBackground = UIManager.getColor( "ToggleButton.underline.hoverBackground" ); + underlineFocusBackground = UIManager.getColor( "ToggleButton.underline.focusBackground" ); + defaults_initialized = true; } } @@ -103,6 +129,36 @@ public class FlatToggleButtonUI defaults_initialized = false; } + static boolean isUnderlineButton( Component c ) { + return c instanceof JToggleButton && clientPropertyEquals( (JToggleButton) c, BUTTON_TYPE, BUTTON_TYPE_UNDERLINE ); + } + + @Override + protected void paintBackground( Graphics g, JComponent c ) { + if( isUnderlineButton( c ) ) { + int height = c.getHeight(); + int width = c.getWidth(); + boolean selected = ((AbstractButton)c).isSelected(); + + // paint background + Color background = buttonStateColor( c, + selected ? underlineSelectedBackground : null, + null, underlineFocusBackground, underlineHoverBackground, null ); + if( background != null ) { + g.setColor( background ); + g.fillRect( 0, 0, width, height ); + } + + // paint underline if selected + if( selected ) { + int underlineHeight = UIScale.scale( this.underlineHeight ); + g.setColor( c.isEnabled() ? underlineColor : disabledUnderlineColor ); + g.fillRect( 0, height - underlineHeight, width, underlineHeight ); + } + } else + super.paintBackground( g, c ); + } + @Override protected Color getBackground( JComponent c ) { ButtonModel model = ((AbstractButton)c).getModel(); 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 16426537..0940c8e1 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -435,6 +435,14 @@ ToggleButton.pressedBackground=$Button.pressedBackground ToggleButton.toolbar.hoverBackground=$Button.toolbar.hoverBackground ToggleButton.toolbar.pressedBackground=$Button.toolbar.pressedBackground +# button type "underline" +ToggleButton.underline.underlineHeight=2 +ToggleButton.underline.underlineColor=$TabbedPane.underlineColor +ToggleButton.underline.disabledUnderlineColor=$TabbedPane.disabledUnderlineColor +ToggleButton.underline.selectedBackground=$?TabbedPane.selectedBackground +ToggleButton.underline.hoverBackground=$TabbedPane.hoverColor +ToggleButton.underline.focusBackground=$TabbedPane.focusColor + #---- ToolBar ---- diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java index 07aa13de..0dac7e91 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java @@ -78,6 +78,8 @@ public class FlatComponentsTest JToggleButton toggleButton10 = new JToggleButton(); JToggleButton toggleButton3 = new JToggleButton(); JToggleButton toggleButton4 = new JToggleButton(); + JToggleButton toggleButton5 = new JToggleButton(); + JToggleButton toggleButton8 = new JToggleButton(); JLabel checkBoxLabel = new JLabel(); JCheckBox checkBox1 = new JCheckBox(); JCheckBox checkBox2 = new JCheckBox(); @@ -339,6 +341,19 @@ public class FlatComponentsTest toggleButton4.setSelected(true); add(toggleButton4, "cell 4 2"); + //---- toggleButton5 ---- + toggleButton5.setText("underline"); + toggleButton5.putClientProperty("JButton.buttonType", "underline"); + toggleButton5.setSelected(true); + add(toggleButton5, "cell 5 2"); + + //---- toggleButton8 ---- + toggleButton8.setText("underline"); + toggleButton8.putClientProperty("JButton.buttonType", "underline"); + toggleButton8.setEnabled(false); + toggleButton8.setSelected(true); + add(toggleButton8, "cell 5 2"); + //---- checkBoxLabel ---- checkBoxLabel.setText("JCheckBox"); add(checkBoxLabel, "cell 0 3"); diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd index 2f32943f..9f358bfb 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd @@ -167,6 +167,23 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 2" } ) + add( new FormComponent( "javax.swing.JToggleButton" ) { + name: "toggleButton5" + "text": "underline" + "$client.JButton.buttonType": "underline" + "selected": true + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 5 2" + } ) + add( new FormComponent( "javax.swing.JToggleButton" ) { + name: "toggleButton8" + "text": "underline" + "$client.JButton.buttonType": "underline" + "enabled": false + "selected": true + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 5 2" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "checkBoxLabel" "text": "JCheckBox"