diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java new file mode 100644 index 00000000..c59e5bd1 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -0,0 +1,36 @@ +/* + * Copyright 2019 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; + +import java.util.Objects; +import javax.swing.JComponent; + +/** + * @author Karl Tauber + */ +public interface FlatClientProperties +{ + String BUTTON_TYPE = "JButton.buttonType"; + String BUTTON_TYPE_HELP = "help"; + + /** + * Checks whether a client property of a component has the given value. + */ + static boolean clientPropertyEquals( JComponent c, String key, Object value ) { + return Objects.equals( c.getClientProperty( key ), value ); + } +} diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java new file mode 100644 index 00000000..f53a5e25 --- /dev/null +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java @@ -0,0 +1,123 @@ +/* + * Copyright 2019 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.icons; + +import static com.formdev.flatlaf.util.UIScale.*; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import javax.swing.UIManager; + +/** + * Help button icon for {@link javax.swing.JButton}. + * + * @uiDefault Component.focusWidth int + * @uiDefault Component.focusColor Color + * @uiDefault HelpButton.borderColor Color + * @uiDefault HelpButton.disabledBorderColor Color + * @uiDefault HelpButton.focusedBorderColor Color + * @uiDefault HelpButton.background Color + * @uiDefault HelpButton.disabledBackground Color + * @uiDefault HelpButton.questionMarkColor Color + * @uiDefault HelpButton.disabledQuestionMarkColor Color + * + * @author Karl Tauber + */ +public class FlatHelpButtonIcon + extends FlatAbstractIcon +{ + protected final int focusWidth = UIManager.getInt( "Component.focusWidth" ); + protected final Color focusColor = UIManager.getColor( "Component.focusColor" ); + + protected final Color borderColor = UIManager.getColor( "HelpButton.borderColor" ); + protected final Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" ); + protected final Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" ); + protected final Color background = UIManager.getColor( "HelpButton.background" ); + protected final Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" ); + protected final Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" ); + protected final Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" ); + + protected final int iconSize = 22 + (focusWidth * 2); + + public FlatHelpButtonIcon() { + super( 0, 0, null ); + } + + @Override + protected void paintIcon( Component c, Graphics2D g2 ) { + /* + + + + + + + + */ + + boolean enabled = c.isEnabled(); + boolean focused = c.hasFocus(); + + // paint focused border + if( focused ) { + g2.setColor( focusColor ); + g2.fill( new Ellipse2D.Float( 0.5f, 0.5f, iconSize - 1, iconSize - 1 ) ); + } + + // paint border + g2.setColor( enabled + ? (focused ? focusedBorderColor : borderColor) + : disabledBorderColor ); + g2.fill( new Ellipse2D.Float( focusWidth + 0.5f, focusWidth + 0.5f, 21, 21 ) ); + + // paint background + g2.setColor( enabled + ? background + : disabledBackground ); + g2.fill( new Ellipse2D.Float( focusWidth + 1.5f, focusWidth + 1.5f, 19, 19 ) ); + + // paint question mark + Path2D q = new Path2D.Float(); + q.moveTo( 11, 5 ); + q.curveTo( 8.8,5, 7,6.8, 7,9 ); + q.lineTo( 9, 9 ); + q.curveTo( 9,7.9, 9.9,7, 11,7 ); + q.curveTo( 12.1,7, 13,7.9, 13,9 ); + q.curveTo( 13,11, 10,10.75, 10,14 ); + q.lineTo( 12, 14 ); + q.curveTo( 12,11.75, 15,11.5, 15,9 ); + q.curveTo( 15,6.8, 13.2,5, 11,5 ); + q.closePath(); + + g2.translate( focusWidth, focusWidth ); + g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor ); + g2.fill( q ); + g2.fillRect( 10, 15, 2, 2 ); + } + + @Override + public int getIconWidth() { + return scale( iconSize ); + } + + @Override + public int getIconHeight() { + return scale( iconSize ); + } +} 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 cd0465b6..5af58fe3 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 @@ -54,7 +54,7 @@ public class FlatButtonBorder @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { - if( FlatButtonUI.isContentAreaFilled( c ) ) + if( FlatButtonUI.isContentAreaFilled( c ) && !FlatButtonUI.isHelpButton( 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 710cc0c7..7e2d2c89 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 @@ -16,15 +16,18 @@ package com.formdev.flatlaf.ui; +import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import javax.swing.AbstractButton; import javax.swing.ButtonModel; +import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.UIManager; @@ -59,6 +62,8 @@ public class FlatButtonUI protected Color toolbarHoverBackground; protected Color toolbarPressedBackground; + private Icon helpButtonIcon; + private static ComponentUI instance; public static ComponentUI createUI( JComponent c ) { @@ -81,6 +86,8 @@ public class FlatButtonUI defaultForeground = UIManager.getColor( prefix + "default.foreground" ); toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" ); toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" ); + + helpButtonIcon = UIManager.getIcon( "HelpButton.icon" ); } static boolean isContentAreaFilled( Component c ) { @@ -91,8 +98,18 @@ public class FlatButtonUI return c instanceof JButton && ((JButton)c).isDefaultButton(); } + static boolean isHelpButton( Component c ) { + return c instanceof JButton && clientPropertyEquals( (JButton) c, BUTTON_TYPE, BUTTON_TYPE_HELP ); + } + @Override public void update( Graphics g, JComponent c ) { + if( isHelpButton( c ) ) { + FlatUIUtils.paintParentBackground( g, c ); + helpButtonIcon.paintIcon( c, g, 0, 0 ); + return; + } + if( c.isOpaque() && isContentAreaFilled( c ) ) { FlatUIUtils.paintParentBackground( g, c ); @@ -119,6 +136,9 @@ public class FlatButtonUI @Override protected void paintText( Graphics g, JComponent c, Rectangle textRect, String text ) { + if( isHelpButton( c ) ) + return; + AbstractButton b = (AbstractButton) c; FontMetrics fm = c.getFontMetrics( c.getFont() ); int mnemonicIndex = b.getDisplayedMnemonicIndex(); @@ -154,4 +174,12 @@ public class FlatButtonUI boolean def = isDefaultButton( c ); return def ? defaultForeground : c.getForeground(); } + + @Override + public Dimension getPreferredSize( JComponent c ) { + if( isHelpButton( c ) ) + return new Dimension( helpButtonIcon.getIconWidth(), helpButtonIcon.getIconHeight() ); + + return super.getPreferredSize( c ); + } } 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 5b20e059..5d1e4606 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -141,6 +141,18 @@ FormattedTextField.background=@textComponentBackground FormattedTextField.margin=@textComponentMargin +#---- HelpButton ---- + +HelpButton.icon=com.formdev.flatlaf.icons.FlatHelpButtonIcon +HelpButton.borderColor=@@CheckBox.icon.borderColor +HelpButton.disabledBorderColor=@@CheckBox.icon.disabledBorderColor +HelpButton.focusedBorderColor=@@CheckBox.icon.focusedBorderColor +HelpButton.background=@@CheckBox.icon.background +HelpButton.disabledBackground=@@CheckBox.icon.disabledBackground +HelpButton.questionMarkColor=@@CheckBox.icon.checkmarkColor +HelpButton.disabledQuestionMarkColor=@@CheckBox.icon.disabledCheckmarkColor + + #---- List ---- List.border=1,0,1,0 diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties index 89831614..cedb77bf 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -109,6 +109,11 @@ Component.focusedBorderColor=87afda Component.focusColor=97c3f3 +#---- HelpButton ---- + +HelpButton.questionMarkColor=4D89C9 + + #---- List ---- List.background=@textComponentBackground diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java index 32faaf75..52b7ff7c 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.java @@ -53,6 +53,8 @@ public class FlatComponentsTest JButton button1 = new JButton(); JButton button2 = new JButton(); FlatComponentsTest.TestDefaultButton button5 = new FlatComponentsTest.TestDefaultButton(); + JButton button3 = new JButton(); + JButton button12 = new JButton(); JLabel toggleButtonLabel = new JLabel(); JToggleButton toggleButton1 = new JToggleButton(); JToggleButton toggleButton2 = new JToggleButton(); @@ -231,6 +233,17 @@ public class FlatComponentsTest button5.setDisplayedMnemonicIndex(0); add(button5, "cell 3 1"); + //---- button3 ---- + button3.setText("Help"); + button3.putClientProperty("JButton.buttonType", "help"); + add(button3, "cell 4 1"); + + //---- button12 ---- + button12.setText("Help"); + button12.putClientProperty("JButton.buttonType", "help"); + button12.setEnabled(false); + add(button12, "cell 4 1"); + //---- toggleButtonLabel ---- toggleButtonLabel.setText("JToggleButton:"); add(toggleButtonLabel, "cell 0 2"); diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd index 9ca1f460..2296912e 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/FlatComponentsTest.jfd @@ -61,6 +61,21 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 3 1" } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button3" + "text": "Help" + "$client.JButton.buttonType": "help" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 1" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button12" + "text": "Help" + "$client.JButton.buttonType": "help" + "enabled": false + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 1" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "toggleButtonLabel" "text": "JToggleButton:" diff --git a/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties index fb1ea527..a19111d9 100644 --- a/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties +++ b/flatlaf-core/src/test/resources/com/formdev/flatlaf/FlatTestLaf.properties @@ -95,6 +95,11 @@ Component.focusColor=97c3f3 #Component.arc=8 +#---- HelpButton ---- + +HelpButton.questionMarkColor=0000ff + + #---- Label ---- Label.foreground=008800 diff --git a/flatlaf-core/svg/FlatLaf Icons.sketch b/flatlaf-core/svg/FlatLaf Icons.sketch index 29901de5..ea8b1465 100644 Binary files a/flatlaf-core/svg/FlatLaf Icons.sketch and b/flatlaf-core/svg/FlatLaf Icons.sketch differ diff --git a/flatlaf-core/svg/HelpButtonIcon.svg b/flatlaf-core/svg/HelpButtonIcon.svg new file mode 100644 index 00000000..c1b89884 --- /dev/null +++ b/flatlaf-core/svg/HelpButtonIcon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java index 5cdeda20..a3da63eb 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java @@ -37,6 +37,8 @@ class BasicComponentsPanel JLabel buttonLabel = new JLabel(); JButton button1 = new JButton(); JButton button2 = new JButton(); + JButton button3 = new JButton(); + JButton button4 = new JButton(); JLabel toggleButtonLabel = new JLabel(); JToggleButton toggleButton1 = new JToggleButton(); JToggleButton toggleButton2 = new JToggleButton(); @@ -161,6 +163,17 @@ class BasicComponentsPanel button2.setEnabled(false); add(button2, "cell 2 1"); + //---- button3 ---- + button3.setText("Help"); + button3.putClientProperty("JButton.buttonType", "help"); + add(button3, "cell 3 1"); + + //---- button4 ---- + button4.setText("Help"); + button4.putClientProperty("JButton.buttonType", "help"); + button4.setEnabled(false); + add(button4, "cell 4 1"); + //---- toggleButtonLabel ---- toggleButtonLabel.setText("JToggleButton:"); add(toggleButtonLabel, "cell 0 2"); diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd index e4a2aeab..6d200401 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd @@ -54,6 +54,21 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 1" } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button3" + "text": "Help" + "$client.JButton.buttonType": "help" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 1" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "button4" + "text": "Help" + "$client.JButton.buttonType": "help" + "enabled": false + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 1" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "toggleButtonLabel" "text": "JToggleButton:"