From 74909da110f81ee4eb6a67a5504f9daa8e5ca529 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 14 Jan 2020 18:42:06 +0100 Subject: [PATCH] Button and ToggleButton: - support per component minimum height (issue #44) - do not apply minimum width if button border was changed (is no longer an instance of `FlatButtonBorder`) - ToggleButton: no longer use focus width for underline style toggle buttons to compute component size, which reduces/fixes component size in "Flat IntelliJ" and "Flat Darcula" themes - revalidate/repaint client properties minimum width/height or buttonType change --- CHANGELOG.md | 7 ++++ .../formdev/flatlaf/FlatClientProperties.java | 19 +++++++++- .../com/formdev/flatlaf/ui/FlatBorder.java | 12 +++---- .../formdev/flatlaf/ui/FlatButtonBorder.java | 5 +++ .../com/formdev/flatlaf/ui/FlatButtonUI.java | 35 +++++++++++++++++-- .../flatlaf/ui/FlatToggleButtonUI.java | 23 ++++++++++++ .../com/formdev/flatlaf/ui/FlatUIUtils.java | 7 ++-- 7 files changed, 96 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8722cf0..17a60019 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ FlatLaf Change Log - TabbedPane: In scroll-tab-layout, the cropped line is now hidden. (issue #40) - Tree: UI default value `Tree.textBackground` now has a valid color and is no longer `null`. +- Button and ToggleButton: Support per component minimum height (set client + property `JComponent.minimumHeight` to an integer). (issue #44) +- Button and ToggleButton: Do not apply minimum width if button border was + changed (is no longer an instance of `FlatButtonBorder`). +- ToggleButton: No longer use focus width for underline style toggle buttons to + compute component size, which reduces/fixes component size in "Flat IntelliJ" + and "Flat Darcula" themes. ## 0.24 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 d6952d0e..45081cae 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -79,11 +79,19 @@ public interface FlatClientProperties /** * Specifies minimum width of a component. *

- * Component {@link javax.swing.JButton} and {@link javax.swing.text.JTextComponent}
+ * Component {@link javax.swing.JButton}, {@link javax.swing.JToggleButton} and {@link javax.swing.text.JTextComponent}
* Value type {@link java.lang.Integer}
*/ String MINIMUM_WIDTH = "JComponent.minimumWidth"; + /** + * Specifies minimum height of a component. + *

+ * Component {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}
+ * Value type {@link java.lang.Integer}
+ */ + String MINIMUM_HEIGHT = "JComponent.minimumHeight"; + /** * Specifies whether the decrease/increase arrow buttons of a scrollbar are shown. *

@@ -131,4 +139,13 @@ public interface FlatClientProperties Object value = c.getClientProperty( key ); return (value instanceof Boolean) ? (boolean) value : defaultValue; } + + /** + * Checks whether a client property of a component is an integer and returns its value. + * If the client property is not set, or not an integer, defaultValue is returned. + */ + static int clientPropertyInt( JComponent c, String key, int defaultValue ) { + Object value = c.getClientProperty( key ); + return (value instanceof Integer) ? (int) value : defaultValue; + } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java index 8da2517b..0cf2b7ea 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java @@ -73,7 +73,7 @@ public class FlatBorder FlatUIUtils.setRenderingHints( g2 ); boolean isCellEditor = isTableCellEditor( c ); - float focusWidth = isCellEditor ? 0 : getFocusWidth(); + float focusWidth = isCellEditor ? 0 : getFocusWidth( c ); float borderWidth = getBorderWidth( c ); float arc = isCellEditor ? 0 : getArc( c ); @@ -82,7 +82,7 @@ public class FlatBorder g2.setColor( getFocusColor( c ) ); FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height, focusWidth, - getLineWidth() + scale( innerFocusWidth ), arc ); + getLineWidth( c ) + scale( innerFocusWidth ), arc ); } g2.setPaint( getBorderColor( c ) ); @@ -153,7 +153,7 @@ public class FlatBorder @Override public Insets getBorderInsets( Component c, Insets insets ) { boolean isCellEditor = isTableCellEditor( c ); - float ow = (isCellEditor ? 0 : getFocusWidth()) + getLineWidth(); + float ow = (isCellEditor ? 0 : getFocusWidth( c )) + getLineWidth( c ); insets = super.getBorderInsets( c, insets ); insets.top = Math.round( scale( (float) insets.top ) + ow ); @@ -163,16 +163,16 @@ public class FlatBorder return insets; } - protected float getFocusWidth() { + protected float getFocusWidth( Component c ) { return scale( (float) focusWidth ); } - protected float getLineWidth() { + protected float getLineWidth( Component c ) { return scale( 1f ); } protected float getBorderWidth( Component c ) { - return getLineWidth(); + return getLineWidth( c ); } protected float getArc( Component c ) { 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 70156a6c..4fd505b3 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 @@ -104,6 +104,11 @@ public class FlatButtonBorder return insets; } + @Override + protected float getFocusWidth( Component c ) { + return FlatToggleButtonUI.isUnderlineButton( c ) ? 0 : super.getFocusWidth(c ); + } + @Override protected float getBorderWidth( Component c ) { return FlatButtonUI.isDefaultButton( c ) ? scale( (float) defaultBorderWidth ) : super.getBorderWidth( c ); 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 dd9cd90b..c8d0b2a9 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 @@ -28,6 +28,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.RoundRectangle2D; +import java.beans.PropertyChangeEvent; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.Icon; @@ -39,6 +40,7 @@ import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicButtonListener; import javax.swing.plaf.basic.BasicButtonUI; import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.util.UIScale; @@ -180,7 +182,7 @@ public class FlatButtonUI LookAndFeel.installProperty( b, "opaque", false ); LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) ); - MigLayoutVisualPadding.install( b, focusWidth ); + MigLayoutVisualPadding.install( b, getFocusWidth( b ) ); } @Override @@ -191,6 +193,26 @@ public class FlatButtonUI defaults_initialized = false; } + @Override + protected BasicButtonListener createButtonListener( AbstractButton b ) { + return new BasicButtonListener( b ) { + @Override + public void propertyChange( PropertyChangeEvent e ) { + super.propertyChange( e ); + FlatButtonUI.this.propertyChange( b, e ); + } + }; + } + + protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) { + switch( e.getPropertyName() ) { + case MINIMUM_WIDTH: + case MINIMUM_HEIGHT: + b.revalidate(); + break; + } + } + static boolean isContentAreaFilled( Component c ) { return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled(); } @@ -246,7 +268,7 @@ public class FlatButtonUI FlatUIUtils.setRenderingHints( g2 ); Border border = c.getBorder(); - float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0; + float focusWidth = (border instanceof FlatBorder) ? scale( (float) getFocusWidth( c ) ) : 0; float arc = ((border instanceof FlatButtonBorder && !isSquareButton( c )) || isToolBarButton( c )) ? scale( (float) this.arc ) : 0; boolean def = isDefaultButton( c ); @@ -362,9 +384,16 @@ public class FlatButtonUI // or apply minimum width, if not in toolbar and not a icon-only button if( isIconOnlyButton( c ) ) prefSize.width = Math.max( prefSize.width, prefSize.height ); - else if( !isToolBarButton( c ) ) + else if( !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) { + int focusWidth = getFocusWidth( c ); prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) + (focusWidth * 2) ) ); + prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) + (focusWidth * 2) ) ); + } return prefSize; } + + protected int getFocusWidth( JComponent c ) { + return focusWidth; + } } 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 97f390ac..f313b64e 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 @@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; +import java.beans.PropertyChangeEvent; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.JComponent; @@ -129,6 +130,23 @@ public class FlatToggleButtonUI defaults_initialized = false; } + @Override + protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) { + super.propertyChange( b, e ); + + switch( e.getPropertyName() ) { + case BUTTON_TYPE: + if( BUTTON_TYPE_UNDERLINE.equals( e.getOldValue() ) || BUTTON_TYPE_UNDERLINE.equals( e.getNewValue() ) ) { + MigLayoutVisualPadding.uninstall( b ); + MigLayoutVisualPadding.install( b, getFocusWidth( b ) ); + b.revalidate(); + } + + b.repaint(); + break; + } + } + static boolean isUnderlineButton( Component c ) { return c instanceof JToggleButton && clientPropertyEquals( (JToggleButton) c, BUTTON_TYPE, BUTTON_TYPE_UNDERLINE ); } @@ -186,4 +204,9 @@ public class FlatToggleButtonUI return super.getForeground( c ); } + + @Override + protected int getFocusWidth( JComponent c ) { + return isUnderlineButton( c ) ? 0 : super.getFocusWidth( c ); + } } 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 b12af8e1..e8e1dec1 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 @@ -113,8 +113,11 @@ public class FlatUIUtils } public static int minimumWidth( JComponent c, int minimumWidth ) { - Object p = c.getClientProperty( FlatClientProperties.MINIMUM_WIDTH ); - return (p instanceof Integer) ? ((Integer)p).intValue() : minimumWidth; + return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_WIDTH, minimumWidth ); + } + + public static int minimumHeight( JComponent c, int minimumHeight ) { + return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_HEIGHT, minimumHeight ); } public static boolean isTableCellEditor( Component c ) {