From 005c9f471e6bc3ea5d708a08e8fb0b087b2c3382 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 10 Nov 2021 14:09:32 +0100 Subject: [PATCH] Window decorations: - option to hide window icon (via client property or UI default) - no longer show the Java "duke/cup" icon if no window icon image is set (issue #416) --- CHANGELOG.md | 10 ++++- .../formdev/flatlaf/FlatClientProperties.java | 18 ++++++++ .../java/com/formdev/flatlaf/FlatLaf.java | 2 +- .../formdev/flatlaf/ui/FlatRootPaneUI.java | 5 +++ .../com/formdev/flatlaf/ui/FlatTitlePane.java | 45 ++++++++----------- .../com/formdev/flatlaf/FlatLaf.properties | 2 + .../dumps/uidefaults/FlatDarkLaf_1.8.0.txt | 2 + .../dumps/uidefaults/FlatLightLaf_1.8.0.txt | 2 + .../dumps/uidefaults/FlatTestLaf_1.8.0.txt | 2 + .../testing/FlatWindowDecorationsTest.java | 20 ++++++++- .../testing/FlatWindowDecorationsTest.jfd | 14 +++++- .../flatlaf/themeeditor/FlatLafUIKeys.txt | 2 + 12 files changed, 91 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d15eca2..b372bd24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,14 @@ FlatLaf Change Log - Style classes allow defining style rules at a single place (in UI defaults) and use them in any component. (PR #388)\ E.g.: `mySlider.putClientProperty( "FlatLaf.styleClass", "myclass" );` -- Native window decorations: Show Windows 11 snap layouts menu when hovering the - mouse over the maximize button. (issues #397 and #407) +- Native window decorations (Windows 10/11 only): + - Show Windows 11 snap layouts menu when hovering the mouse over the maximize + button. (issues #397 and #407) + - Option to hide window icon (for single window set client property + `JRootPane.titleBarShowIcon` to `false`; for all windows set UI value + `TitlePane.showIcon` to `false`). + - No longer show the Java "duke/cup" icon if no window icon image is set. + (issue #416) - TextField, FormattedTextField and PasswordField: Support leading and trailing icons (set client property `JTextField.leadingIcon` or `JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368) 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 542fe963..a4360221 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -331,6 +331,24 @@ public interface FlatClientProperties */ String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"; + /** + * Specifies whether the window icon should be shown in the window title bar + * (requires enabled window decorations). + *

+ * Setting this shows/hides the windows icon + * for the {@code JFrame} or {@code JDialog} that contains the root pane. + *

+ * This client property has higher priority than UI default {@code TitlePane.showIcon}. + *

+ * (requires Window 10) + *

+ * Component {@link javax.swing.JRootPane}
+ * Value type {@link java.lang.Boolean} + * + * @since 2 + */ + String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon"; + /** * Background color of window title bar (requires enabled window decorations). *

diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 54ca5c34..bc94627e 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -421,7 +421,7 @@ public abstract class FlatLaf // (using defaults.remove() to avoid that lazy value is resolved and icon loaded here) Object icon = defaults.remove( "InternalFrame.icon" ); defaults.put( "InternalFrame.icon", icon ); - defaults.put( "TitlePane.icon", icon ); + defaults.put( "TitlePane.icon", icon ); // no longer used, but keep for compatibility // get addons and sort them by priority ServiceLoader addonLoader = ServiceLoader.load( FlatDefaultsAddon.class ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java index b5d0cfee..3441c83f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRootPaneUI.java @@ -313,6 +313,11 @@ public class FlatRootPaneUI } break; + case FlatClientProperties.TITLE_BAR_SHOW_ICON: + if( titlePane != null ) + titlePane.updateIcon(); + break; + case FlatClientProperties.TITLE_BAR_BACKGROUND: case FlatClientProperties.TITLE_BAR_FOREGROUND: if( titlePane != null ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java index 38a45cf5..7ff684e6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTitlePane.java @@ -50,8 +50,6 @@ import javax.accessibility.AccessibleContext; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; -import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; @@ -66,7 +64,6 @@ import javax.swing.border.Border; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder; -import com.formdev.flatlaf.util.ScaledImageIcon; import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.UIScale; @@ -80,6 +77,8 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault TitlePane.embeddedForeground Color * @uiDefault TitlePane.borderColor Color optional * @uiDefault TitlePane.unifiedBackground boolean + * @uiDefault TitlePane.showIcon boolean + * @uiDefault TitlePane.noIconLeftGap int * @uiDefault TitlePane.iconSize Dimension * @uiDefault TitlePane.iconMargins Insets * @uiDefault TitlePane.titleMargins Insets @@ -88,7 +87,6 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault TitlePane.centerTitle boolean * @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean * @uiDefault TitlePane.menuBarTitleGap int - * @uiDefault TitlePane.icon Icon * @uiDefault TitlePane.closeIcon Icon * @uiDefault TitlePane.iconifyIcon Icon * @uiDefault TitlePane.maximizeIcon Icon @@ -106,6 +104,8 @@ public class FlatTitlePane protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" ); protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" ); + /** @since 2 */ protected final boolean showIcon = FlatUIUtils.getUIBoolean( "TitlePane.showIcon", true ); + /** @since 2 */ protected final int noIconLeftGap = FlatUIUtils.getUIInt( "TitlePane.noIconLeftGap", 8 ); protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" ); protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" ); protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" ); @@ -340,36 +340,27 @@ public class FlatTitlePane protected void updateIcon() { // get window images - List images = window.getIconImages(); - if( images.isEmpty() ) { - // search in owners - for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) { - images = owner.getIconImages(); - if( !images.isEmpty() ) - break; + List images = null; + if( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICON, showIcon ) ) { + images = window.getIconImages(); + if( images.isEmpty() ) { + // search in owners + for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) { + images = owner.getIconImages(); + if( !images.isEmpty() ) + break; + } } } - boolean hasIcon = true; + boolean hasIcon = (images != null && !images.isEmpty()); // set icon - if( !images.isEmpty() ) - iconLabel.setIcon( new FlatTitlePaneIcon( images, iconSize ) ); - else { - // no icon set on window --> use default icon - Icon defaultIcon = UIManager.getIcon( "TitlePane.icon" ); - if( defaultIcon != null && (defaultIcon.getIconWidth() == 0 || defaultIcon.getIconHeight() == 0) ) - defaultIcon = null; - if( defaultIcon != null ) { - if( defaultIcon instanceof ImageIcon ) - defaultIcon = new ScaledImageIcon( (ImageIcon) defaultIcon, iconSize.width, iconSize.height ); - iconLabel.setIcon( defaultIcon ); - } else - hasIcon = false; - } + iconLabel.setIcon( hasIcon ? new FlatTitlePaneIcon( images, iconSize ) : null ); // show/hide icon iconLabel.setVisible( hasIcon ); + leftPanel.setBorder( hasIcon ? null : new FlatEmptyBorder( 0, noIconLeftGap, 0, 0 ) ); updateNativeTitleBarHeightAndHitTestSpotsLater(); } @@ -739,7 +730,7 @@ debug*/ Rectangle appIconBounds = null; if( iconLabel.isVisible() ) { - // compute real icon size (without insets; 1px wider for easier hitting) + // compute real icon size (without insets; 1px larger for easier hitting) Point location = SwingUtilities.convertPoint( iconLabel, 0, 0, window ); Insets iconInsets = iconLabel.getInsets(); Rectangle iconBounds = new Rectangle( 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 7d252e80..c6d5ecc9 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -710,6 +710,8 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground TitlePane.useWindowDecorations = true TitlePane.menuBarEmbedded = true TitlePane.unifiedBackground = false +TitlePane.showIcon = true +TitlePane.noIconLeftGap = 8 TitlePane.iconSize = 16,16 TitlePane.iconMargins = 3,8,3,8 TitlePane.titleMargins = 3,0,3,0 diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index ebe78cbd..006d39ea 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -1213,7 +1213,9 @@ TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.Colo TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.menuBarEmbedded true TitlePane.menuBarTitleGap 20 +TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] +TitlePane.showIcon true TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.unifiedBackground false TitlePane.useWindowDecorations true diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt index ffe60224..1f122661 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -1218,7 +1218,9 @@ TitlePane.inactiveForeground #8c8c8c HSL 0 0 55 javax.swing.plaf.Colo TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.menuBarEmbedded true TitlePane.menuBarTitleGap 20 +TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] +TitlePane.showIcon true TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.unifiedBackground false TitlePane.useWindowDecorations true diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt index 6110addd..df797d15 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -1233,7 +1233,9 @@ TitlePane.inactiveForeground #ffffff HSL 0 0 100 javax.swing.plaf.Colo TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.menuBarEmbedded true TitlePane.menuBarTitleGap 20 +TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] +TitlePane.showIcon true TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.unifiedBackground false TitlePane.useWindowDecorations true diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.java index e1621235..c8f99783 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Random; import javax.swing.*; import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox; import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.util.MultiResolutionImageSupport; import net.miginfocom.swing.*; @@ -73,6 +74,9 @@ public class FlatWindowDecorationsTest menuBarCheckBox.setSelected( window instanceof JFrame ); maximizedBoundsCheckBox.setEnabled( window instanceof Frame ); + menuBarEmbeddedCheckBox.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) ); + unifiedBackgroundCheckBox.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) ); + addMenuButton.setEnabled( menuBarCheckBox.isEnabled() ); addGlueButton.setEnabled( menuBarCheckBox.isEnabled() ); removeMenuButton.setEnabled( menuBarCheckBox.isEnabled() ); @@ -402,6 +406,12 @@ public class FlatWindowDecorationsTest } } + private void showIconChanged() { + JRootPane rootPane = getWindowRootPane(); + if( rootPane != null ) + rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, showIconCheckBox.getChecked() ); + } + private JRootPane getWindowRootPane() { Window window = SwingUtilities.windowForComponent( this ); if( window instanceof JFrame ) @@ -450,6 +460,7 @@ public class FlatWindowDecorationsTest iconTestRandomRadioButton = new JRadioButton(); iconTestMRIRadioButton = new JRadioButton(); iconTestDynMRIRadioButton = new JRadioButton(); + showIconCheckBox = new FlatTriStateCheckBox(); JButton openDialogButton = new JButton(); JButton openFrameButton = new JButton(); menuBar = new JMenuBar(); @@ -685,12 +696,13 @@ public class FlatWindowDecorationsTest panel2.setLayout(new MigLayout( "ltr,insets 0,hidemode 3,gap 0 0", // columns - "[fill]", + "[left]", // rows "[]" + "[]" + "[]" + "[]" + + "[]rel" + "[]")); //---- iconNoneRadioButton ---- @@ -718,6 +730,11 @@ public class FlatWindowDecorationsTest iconTestDynMRIRadioButton.setText("test dynamic multi-resolution (Java 9+)"); iconTestDynMRIRadioButton.addActionListener(e -> iconChanged()); panel2.add(iconTestDynMRIRadioButton, "cell 0 4"); + + //---- showIconCheckBox ---- + showIconCheckBox.setText("show icon"); + showIconCheckBox.addActionListener(e -> showIconChanged()); + panel2.add(showIconCheckBox, "cell 0 5"); } add(panel2, "cell 1 8"); @@ -955,6 +972,7 @@ public class FlatWindowDecorationsTest private JRadioButton iconTestRandomRadioButton; private JRadioButton iconTestMRIRadioButton; private JRadioButton iconTestDynMRIRadioButton; + private FlatTriStateCheckBox showIconCheckBox; private JMenuBar menuBar; // JFormDesigner - End of variables declaration //GEN-END:variables } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.jfd index bc655f8e..c5aa442e 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatWindowDecorationsTest.jfd @@ -327,8 +327,8 @@ new FormModel { "value": "cell 0 8" } ) add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { - "$columnConstraints": "[fill]" - "$rowConstraints": "[][][][][]" + "$columnConstraints": "[left]" + "$rowConstraints": "[][][][][]rel[]" "$layoutConstraints": "ltr,insets 0,hidemode 3,gap 0 0" } ) { name: "panel2" @@ -388,6 +388,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 4" } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) { + name: "showIconCheckBox" + "text": "show icon" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showIconChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 5" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 8" } ) diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 9d35f08c..3137b926 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -969,7 +969,9 @@ TitlePane.inactiveForeground TitlePane.maximizeIcon TitlePane.menuBarEmbedded TitlePane.menuBarTitleGap +TitlePane.noIconLeftGap TitlePane.restoreIcon +TitlePane.showIcon TitlePane.titleMargins TitlePane.unifiedBackground TitlePane.useWindowDecorations