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:"