diff --git a/CHANGELOG.md b/CHANGELOG.md index bbab99e2..c4e46b71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,19 @@ FlatLaf Change Log - Typography defines several font styles for headers and various text sizes, which makes it easy to use consistent font styles across the application. (PR #396) -- 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): + - Unified backgrounds for window title bar is now enabled by default (window + title bar has now same background color as window content). Bottom separator + for menu bars is no longer painted (if unified background is enabled). + - Show Windows 11 snap layouts menu when hovering the mouse over the maximize + button. (issues #397 and #407) + - Possibility to hide window title bar icon (for single window set client + property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI + value `TitlePane.showIcon` to `false`). + - OptionPane: Hide window title bar icon by default. Can be be made visibly by + setting UI default `OptionPane.showIcon` to `true`. (issue #416) + - 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 93e7c6b6..4af43c96 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 324c8e8f..eb137bd8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -393,6 +393,7 @@ public abstract class FlatLaf "EditorPane.inactiveBackground", "FormattedTextField.disabledBackground", "PasswordField.disabledBackground", + "RootPane.background", "Spinner.disabledBackground", "TextArea.disabledBackground", "TextArea.inactiveBackground", @@ -411,7 +412,8 @@ public abstract class FlatLaf "Spinner.disabledForeground", "ToggleButton.disabledText" ); putDefaults( defaults, defaults.getColor( "textText" ), - "DesktopIcon.foreground" ); + "DesktopIcon.foreground", + "RootPane.foreground" ); initFonts( defaults ); initIconColors( defaults, isDark() ); @@ -421,7 +423,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 ); @@ -541,6 +543,9 @@ public abstract class FlatLaf if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) ) defaults.put( key, activeFont ); } + + // add fonts that are not set in BasicLookAndFeel + defaults.put( "RootPane.font", activeFont ); } private void initDefaultFont( UIDefaults defaults ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java index cc437a8d..6ba8d159 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java @@ -53,6 +53,9 @@ public class FlatMenuBarBorder @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { + if( !showBottomSeparator( c ) ) + return; + float lineHeight = scale( (float) 1 ); FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight ); } @@ -68,4 +71,9 @@ public class FlatMenuBarBorder insets.right = scale( margin.right ); return insets; } + + /** @since 2 */ + protected boolean showBottomSeparator( Component c ) { + return !FlatMenuBarUI.useUnifiedBackground( c ); + } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java index b2ffd44f..f1d9e038 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java @@ -17,6 +17,7 @@ package com.formdev.flatlaf.ui; import java.awt.Color; +import java.awt.Component; import java.awt.Graphics; import java.awt.Insets; import java.awt.Window; @@ -189,10 +190,8 @@ public class FlatMenuBarUI return background; // use parent background for unified title pane - // (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime) - if( UIManager.getBoolean( "TitlePane.unifiedBackground" ) && - FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ) ) - background = FlatUIUtils.getParentBackground( c ); + if( useUnifiedBackground( c ) ) + background = FlatUIUtils.getParentBackground( c ); // paint background in full screen mode if( FlatUIUtils.isFullScreen( rootPane ) ) @@ -202,6 +201,22 @@ public class FlatMenuBarUI return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background; } + /**@since 2 */ + static boolean useUnifiedBackground( Component c ) { + // check whether: + // - TitlePane.unifiedBackground is true and + // - menu bar is the "main" menu bar and + // - window has custom decorations enabled + + JRootPane rootPane; + // (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime) + return UIManager.getBoolean( "TitlePane.unifiedBackground" ) && + (rootPane = SwingUtilities.getRootPane( c )) != null && + rootPane.getParent() instanceof Window && + rootPane.getJMenuBar() == c && + FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ); + } + //---- class TakeFocus ---------------------------------------------------- /** diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java index d0413691..ae36668f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java @@ -22,18 +22,22 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.Insets; +import java.beans.PropertyChangeListener; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.basic.BasicOptionPaneUI; +import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.util.UIScale; /** @@ -79,6 +83,7 @@ import com.formdev.flatlaf.util.UIScale; * * * + * @uiDefault OptionPane.showIcon boolean * @uiDefault OptionPane.iconMessageGap int * @uiDefault OptionPane.messagePadding int * @uiDefault OptionPane.maxCharactersPerLine int @@ -88,6 +93,7 @@ import com.formdev.flatlaf.util.UIScale; public class FlatOptionPaneUI extends BasicOptionPaneUI { + /** @since 2 */ protected boolean showIcon; protected int iconMessageGap; protected int messagePadding; protected int maxCharactersPerLine; @@ -102,6 +108,7 @@ public class FlatOptionPaneUI protected void installDefaults() { super.installDefaults(); + showIcon = UIManager.getBoolean( "OptionPane.showIcon" ); iconMessageGap = UIManager.getInt( "OptionPane.iconMessageGap" ); messagePadding = UIManager.getInt( "OptionPane.messagePadding" ); maxCharactersPerLine = UIManager.getInt( "OptionPane.maxCharactersPerLine" ); @@ -116,6 +123,24 @@ public class FlatOptionPaneUI updateChildPanels( optionPane ); } + @Override + protected PropertyChangeListener createPropertyChangeListener() { + PropertyChangeListener superListener = super.createPropertyChangeListener(); + return e -> { + superListener.propertyChange( e ); + + // hide window title bar icon + // (only if showIcon is false, otherwise the default behavior is used) + if( !showIcon && "ancestor".equals( e.getPropertyName() ) && e.getNewValue() != null ) { + JRootPane rootPane = SwingUtilities.getRootPane( optionPane ); + if( rootPane != null && + rootPane.getContentPane().getComponentCount() > 0 && + rootPane.getContentPane().getComponent( 0 ) == optionPane ) + rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, false ); + } + }; + } + @Override public Dimension getMinimumOptionPaneSize() { return UIScale.scale( super.getMinimumOptionPaneSize() ); 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..61569936 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 @@ -66,6 +66,9 @@ import com.formdev.flatlaf.util.UIScale; * * * + * @uiDefault RootPane.font Font unused + * @uiDefault RootPane.background Color + * @uiDefault RootPane.foreground Color unused * @uiDefault RootPane.borderDragThickness int * @uiDefault RootPane.cornerDragWidth int * @uiDefault RootPane.honorFrameMinimumSizeOnResize boolean @@ -126,8 +129,23 @@ public class FlatRootPaneUI protected void installDefaults( JRootPane c ) { super.installDefaults( c ); + // Give the root pane useful background, foreground and font. + // Background is used for title bar and menu bar if native window decorations + // and unified background are enabled. + // Foreground and font are usually not used, but set for completeness. + // Not using LookAndFeel.installColorsAndFont() here because it will not work + // because the properties are null by default but inherit non-null values from parent. + if( !c.isBackgroundSet() || c.getBackground() instanceof UIResource ) + c.setBackground( UIManager.getColor( "RootPane.background" ) ); + if( !c.isForegroundSet() || c.getForeground() instanceof UIResource ) + c.setForeground( UIManager.getColor( "RootPane.foreground" ) ); + if( !c.isFontSet() || c.getFont() instanceof UIResource ) + c.setFont( UIManager.getFont( "RootPane.font" ) ); + // Update background color of JFrame or JDialog parent to avoid bad border // on HiDPI screens when switching from light to dark Laf. + // Window background color is also used in native window decorations + // to fill background when window is initially shown or when resizing window. // The background of JFrame is initialized in JFrame.frameInit() and // the background of JDialog in JDialog.dialogInit(), // but it was not updated when switching Laf. @@ -313,6 +331,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..8b2384fd 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(); } @@ -529,8 +520,8 @@ public class FlatTitlePane } paintRect( g, Color.cyan, debugCloseButtonBounds ); paintRect( g, Color.blue, debugAppIconBounds ); - paintRect( g, Color.magenta, debugMinimizeButtonBounds ); - paintRect( g, Color.blue, debugMaximizeButtonBounds ); + paintRect( g, Color.blue, debugMinimizeButtonBounds ); + paintRect( g, Color.magenta, debugMaximizeButtonBounds ); paintRect( g, Color.cyan, debugCloseButtonBounds ); } @@ -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( @@ -775,7 +766,7 @@ debug*/ JMenuBar menuBar = rootPane.getJMenuBar(); if( hasVisibleEmbeddedMenuBar( menuBar ) ) { - r = getNativeHitTestSpot( menuBarPlaceholder ); + r = getNativeHitTestSpot( menuBar ); if( r != null ) { Component horizontalGlue = findHorizontalGlue( menuBar ); if( horizontalGlue != null ) { @@ -784,18 +775,18 @@ debug*/ // the glue component area can used to move the window. Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window ); + int x2 = glueLocation.x + horizontalGlue.getWidth(); Rectangle r2; if( getComponentOrientation().isLeftToRight() ) { - int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x; - r.width -= trailingWidth; - r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height ); + r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height ); + + r.width = glueLocation.x - r.x; } else { - int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW); - r.x += leadingWidth; - r.width -= leadingWidth; - r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height ); + r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height ); + + r.width = (r.x + r.width) - x2; + r.x = x2; } - r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW ); hitTestSpots.add( r2 ); } @@ -834,13 +825,9 @@ debug*/ Point location = SwingUtilities.convertPoint( c, 0, 0, window ); Rectangle r = new Rectangle( location, size ); - // slightly increase rectangle so that component receives mouseExit events - r.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW ); return r; } - private static final int HIT_TEST_SPOT_GROW = 2; - /*debug private int debugTitleBarHeight; private List debugHitTestSpots; @@ -879,7 +866,7 @@ debug*/ Border menuBarBorder = getMenuBarBorder(); if( menuBarBorder != null ) { // if menu bar is embedded, paint menu bar border - menuBarBorder.paintBorder( c, g, x, y, width, height ); + menuBarBorder.paintBorder( rootPane.getJMenuBar(), g, x, y, width, height ); } else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) ) { // paint border between title pane and content if border color is specified float lineHeight = UIScale.scale( (float) 1 ); 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 eb5c8018..002fd997 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -456,6 +456,7 @@ OptionPane.messageAreaBorder = 0,0,0,0 OptionPane.buttonAreaBorder = 12,0,0,0 OptionPane.messageForeground = null +OptionPane.showIcon = false OptionPane.maxCharactersPerLine = 80 OptionPane.iconMessageGap = 16 OptionPane.messagePadding = 3 @@ -775,7 +776,9 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground TitlePane.useWindowDecorations = true TitlePane.menuBarEmbedded = true -TitlePane.unifiedBackground = false +TitlePane.unifiedBackground = true +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-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.java index c37891c7..678ed225 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.java @@ -215,6 +215,7 @@ class DemoFrame menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations ); unifiedTitleBarMenuItem.setEnabled( windowDecorations ); + showTitleBarIconMenuItem.setEnabled( windowDecorations ); } private void menuBarEmbeddedChanged() { @@ -227,6 +228,16 @@ class DemoFrame FlatLaf.repaintAllFramesAndDialogs(); } + private void showTitleBarIcon() { + boolean showIcon = showTitleBarIconMenuItem.isSelected(); + + // for main frame (because already created) + getRootPane().putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, showIcon ); + + // for other not yet created frames/dialogs + UIManager.put( "TitlePane.showIcon", showIcon ); + } + private void underlineMenuSelection() { UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null ); } @@ -466,6 +477,7 @@ class DemoFrame windowDecorationsCheckBoxMenuItem = new JCheckBoxMenuItem(); menuBarEmbeddedCheckBoxMenuItem = new JCheckBoxMenuItem(); unifiedTitleBarMenuItem = new JCheckBoxMenuItem(); + showTitleBarIconMenuItem = new JCheckBoxMenuItem(); underlineMenuSelectionMenuItem = new JCheckBoxMenuItem(); alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem(); animatedLafChangeMenuItem = new JCheckBoxMenuItem(); @@ -717,13 +729,11 @@ class DemoFrame //---- windowDecorationsCheckBoxMenuItem ---- windowDecorationsCheckBoxMenuItem.setText("Window decorations"); - windowDecorationsCheckBoxMenuItem.setSelected(true); windowDecorationsCheckBoxMenuItem.addActionListener(e -> windowDecorationsChanged()); optionsMenu.add(windowDecorationsCheckBoxMenuItem); //---- menuBarEmbeddedCheckBoxMenuItem ---- menuBarEmbeddedCheckBoxMenuItem.setText("Embedded menu bar"); - menuBarEmbeddedCheckBoxMenuItem.setSelected(true); menuBarEmbeddedCheckBoxMenuItem.addActionListener(e -> menuBarEmbeddedChanged()); optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem); @@ -732,6 +742,11 @@ class DemoFrame unifiedTitleBarMenuItem.addActionListener(e -> unifiedTitleBar()); optionsMenu.add(unifiedTitleBarMenuItem); + //---- showTitleBarIconMenuItem ---- + showTitleBarIconMenuItem.setText("Show window title bar icon"); + showTitleBarIconMenuItem.addActionListener(e -> showTitleBarIcon()); + optionsMenu.add(showTitleBarIconMenuItem); + //---- underlineMenuSelectionMenuItem ---- underlineMenuSelectionMenuItem.setText("Use underline menu selection"); underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection()); @@ -875,6 +890,11 @@ class DemoFrame pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() ); if( FlatLaf.supportsNativeWindowDecorations() ) { + windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() ); + menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) ); + unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) ); + showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) ); + if( JBRCustomDecorations.isSupported() ) { // If the JetBrains Runtime is used, it forces the use of it's own custom // window decoration, which can not disabled. @@ -884,6 +904,7 @@ class DemoFrame unsupported( windowDecorationsCheckBoxMenuItem ); unsupported( menuBarEmbeddedCheckBoxMenuItem ); unsupported( unifiedTitleBarMenuItem ); + unsupported( showTitleBarIconMenuItem ); } if( SystemInfo.isMacOS ) @@ -916,6 +937,7 @@ class DemoFrame private JCheckBoxMenuItem windowDecorationsCheckBoxMenuItem; private JCheckBoxMenuItem menuBarEmbeddedCheckBoxMenuItem; private JCheckBoxMenuItem unifiedTitleBarMenuItem; + private JCheckBoxMenuItem showTitleBarIconMenuItem; private JCheckBoxMenuItem underlineMenuSelectionMenuItem; private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem; private JCheckBoxMenuItem animatedLafChangeMenuItem; diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.jfd index 326c9828..65bb5670 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.jfd @@ -354,7 +354,6 @@ new FormModel { add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) { name: "windowDecorationsCheckBoxMenuItem" "text": "Window decorations" - "selected": true auxiliary() { "JavaCodeGenerator.variableLocal": false } @@ -363,7 +362,6 @@ new FormModel { add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) { name: "menuBarEmbeddedCheckBoxMenuItem" "text": "Embedded menu bar" - "selected": true auxiliary() { "JavaCodeGenerator.variableLocal": false } @@ -377,6 +375,14 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedTitleBar", false ) ) } ) + add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) { + name: "showTitleBarIconMenuItem" + "text": "Show window title bar icon" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) ) + } ) add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) { name: "underlineMenuSelectionMenuItem" "text": "Use underline menu selection" diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.java index 98de9d00..d1622644 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.java @@ -21,6 +21,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.*; import javax.swing.border.*; +import com.formdev.flatlaf.FlatLaf; import net.miginfocom.swing.*; /** @@ -44,6 +45,29 @@ class OptionPanePanel "OK", "Cancel", } ); + + if( FlatLaf.supportsNativeWindowDecorations() ) { + updateShowTitleBarIcon(); + + UIManager.getDefaults().addPropertyChangeListener( e -> { + switch( e.getPropertyName() ) { + case "TitlePane.showIcon": + case "TitlePane.useWindowDecorations": + updateShowTitleBarIcon(); + break; + } + } ); + } else + showTitleBarIconCheckBox.setEnabled( false ); + } + + private void updateShowTitleBarIcon() { + showTitleBarIconCheckBox.setEnabled( UIManager.getBoolean( "TitlePane.showIcon" ) && + FlatLaf.isUseNativeWindowDecorations() ); + } + + private void showTitleBarIcon() { + UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() ); } private void initComponents() { @@ -54,6 +78,7 @@ class OptionPanePanel JPanel panel1 = new JPanel(); JOptionPane plainOptionPane = new JOptionPane(); plainShowDialogLabel = new OptionPanePanel.ShowDialogLinkLabel(); + showTitleBarIconCheckBox = new JCheckBox(); JLabel errorLabel = new JLabel(); JPanel panel2 = new JPanel(); JOptionPane errorOptionPane = new JOptionPane(); @@ -93,7 +118,7 @@ class OptionPanePanel //======== panel9 ======== { panel9.setLayout(new MigLayout( - "flowy,insets dialog,hidemode 3", + "insets dialog,hidemode 3", // columns "[]" + "[]" + @@ -126,7 +151,12 @@ class OptionPanePanel //---- plainShowDialogLabel ---- plainShowDialogLabel.setOptionPane(plainOptionPane); plainShowDialogLabel.setTitleLabel(plainLabel); - panel9.add(plainShowDialogLabel, "cell 2 0"); + panel9.add(plainShowDialogLabel, "cell 1 0"); + + //---- showTitleBarIconCheckBox ---- + showTitleBarIconCheckBox.setText("Show window title bar icon"); + showTitleBarIconCheckBox.addActionListener(e -> showTitleBarIcon()); + panel9.add(showTitleBarIconCheckBox, "cell 2 0"); //---- errorLabel ---- errorLabel.setText("Error"); @@ -148,7 +178,7 @@ class OptionPanePanel //---- errorShowDialogLabel ---- errorShowDialogLabel.setTitleLabel(errorLabel); errorShowDialogLabel.setOptionPane(errorOptionPane); - panel9.add(errorShowDialogLabel, "cell 2 1"); + panel9.add(errorShowDialogLabel, "cell 1 1"); //---- informationLabel ---- informationLabel.setText("Information"); @@ -170,7 +200,7 @@ class OptionPanePanel //---- informationShowDialogLabel ---- informationShowDialogLabel.setOptionPane(informationOptionPane); informationShowDialogLabel.setTitleLabel(informationLabel); - panel9.add(informationShowDialogLabel, "cell 2 2"); + panel9.add(informationShowDialogLabel, "cell 1 2"); //---- questionLabel ---- questionLabel.setText("Question"); @@ -214,7 +244,7 @@ class OptionPanePanel //---- warningShowDialogLabel ---- warningShowDialogLabel.setOptionPane(warningOptionPane); warningShowDialogLabel.setTitleLabel(warningLabel); - panel9.add(warningShowDialogLabel, "cell 2 4"); + panel9.add(warningShowDialogLabel, "cell 1 4"); //---- inputLabel ---- inputLabel.setText("Input"); @@ -236,7 +266,7 @@ class OptionPanePanel //---- inputShowDialogLabel ---- inputShowDialogLabel.setOptionPane(inputOptionPane); inputShowDialogLabel.setTitleLabel(inputLabel); - panel9.add(inputShowDialogLabel, "cell 2 5"); + panel9.add(inputShowDialogLabel, "cell 1 5"); //---- inputIconLabel ---- inputIconLabel.setText("Input + icon"); @@ -259,7 +289,7 @@ class OptionPanePanel //---- inputIconShowDialogLabel ---- inputIconShowDialogLabel.setTitleLabel(inputIconLabel); inputIconShowDialogLabel.setOptionPane(inputIconOptionPane); - panel9.add(inputIconShowDialogLabel, "cell 2 6"); + panel9.add(inputIconShowDialogLabel, "cell 1 6"); //---- customLabel ---- customLabel.setText("Custom"); @@ -279,7 +309,7 @@ class OptionPanePanel //---- customShowDialogLabel ---- customShowDialogLabel.setOptionPane(customOptionPane); customShowDialogLabel.setTitleLabel(customLabel); - panel9.add(customShowDialogLabel, "cell 2 7"); + panel9.add(customShowDialogLabel, "cell 1 7"); } scrollPane1.setViewportView(panel9); } @@ -289,6 +319,7 @@ class OptionPanePanel // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private OptionPanePanel.ShowDialogLinkLabel plainShowDialogLabel; + private JCheckBox showTitleBarIconCheckBox; private OptionPanePanel.ShowDialogLinkLabel errorShowDialogLabel; private OptionPanePanel.ShowDialogLinkLabel informationShowDialogLabel; private JOptionPane customOptionPane; @@ -304,6 +335,7 @@ class OptionPanePanel ShowDialogLinkLabel() { setText( "Show dialog" ); + setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) ); addMouseListener( new MouseAdapter() { @Override diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.jfd index 23905510..7d58e157 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/OptionPanePanel.jfd @@ -12,7 +12,7 @@ new FormModel { name: "scrollPane1" "border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 ) add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { - "$layoutConstraints": "flowy,insets dialog,hidemode 3" + "$layoutConstraints": "insets dialog,hidemode 3" "$columnConstraints": "[][][fill]" "$rowConstraints": "[top][top][top][top][top][top][top][top]" } ) { @@ -42,6 +42,16 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showTitleBarIconCheckBox" + "text": "Show window title bar icon" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 0" } ) @@ -73,7 +83,7 @@ new FormModel { "JavaCodeGenerator.variableLocal": false } }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 1" + "value": "cell 1 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "informationLabel" @@ -103,7 +113,7 @@ new FormModel { "JavaCodeGenerator.variableLocal": false } }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 2" + "value": "cell 1 2" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "questionLabel" @@ -157,7 +167,7 @@ new FormModel { "optionPane": new FormReference( "warningOptionPane" ) "titleLabel": new FormReference( "warningLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 4" + "value": "cell 1 4" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "inputLabel" @@ -184,7 +194,7 @@ new FormModel { "optionPane": new FormReference( "inputOptionPane" ) "titleLabel": new FormReference( "inputLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 5" + "value": "cell 1 5" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "inputIconLabel" @@ -212,7 +222,7 @@ new FormModel { "titleLabel": new FormReference( "inputIconLabel" ) "optionPane": new FormReference( "inputIconOptionPane" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 6" + "value": "cell 1 6" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "customLabel" @@ -240,7 +250,7 @@ new FormModel { "optionPane": new FormReference( "customOptionPane" ) "titleLabel": new FormReference( "customLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 7" + "value": "cell 1 7" } ) } ) }, new FormLayoutConstraints( class java.lang.String ) { @@ -248,7 +258,7 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 840, 900 ) + "size": new java.awt.Dimension( 955, 900 ) } ) } } diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java index 48b3f3ef..da5efbad 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java @@ -474,9 +474,9 @@ public class FlatInspector if( c instanceof JComponent ) appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) ); - appendRow( buf, "Background", toString( c.getBackground() ) ); - appendRow( buf, "Foreground", toString( c.getForeground() ) ); - appendRow( buf, "Font", toString( c.getFont() ) ); + appendRow( buf, "Background", toString( c.getBackground() ) + (c.isBackgroundSet() ? "" : " NOT SET") ); + appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isBackgroundSet() ? "" : " NOT SET") ); + appendRow( buf, "Font", toString( c.getFont() ) + (c.isFontSet() ? "" : " NOT SET") ); if( c instanceof JComponent ) { try { diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index fdc94768..fca8199d 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -671,6 +671,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI] OptionPane.sameSizeButtons true OptionPane.setButtonMargin false +OptionPane.showIcon false OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI] OptionPane.windowBindings length=2 [Ljava.lang.Object; [0] ESCAPE @@ -818,6 +819,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F #---- RootPane ---- RootPane.activeBorderColor #4d5154 HSL 206 4 32 com.formdev.flatlaf.util.DerivedColor [UI] lighten(7% autoInverse) +RootPane.background #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI] RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI] RootPane.borderDragThickness 5 RootPane.cornerDragWidth 16 @@ -830,6 +832,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object; [5] press [6] ctrl released ENTER [7] release +RootPane.font [active] $defaultFont [UI] +RootPane.foreground #bbbbbb HSL 0 0 73 javax.swing.plaf.ColorUIResource [UI] RootPane.honorDialogMinimumSizeOnResize true RootPane.honorFrameMinimumSizeOnResize false RootPane.inactiveBorderColor #484c4e HSL 200 4 29 com.formdev.flatlaf.util.DerivedColor [UI] lighten(5% autoInverse) @@ -1215,9 +1219,11 @@ 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.unifiedBackground true 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 a1eb2677..e2162462 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -676,6 +676,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI] OptionPane.sameSizeButtons true OptionPane.setButtonMargin false +OptionPane.showIcon false OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI] OptionPane.windowBindings length=2 [Ljava.lang.Object; [0] ESCAPE @@ -823,6 +824,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F #---- RootPane ---- RootPane.activeBorderColor #737373 HSL 0 0 45 com.formdev.flatlaf.util.DerivedColor [UI] darken(50% autoInverse) +RootPane.background #f2f2f2 HSL 0 0 95 javax.swing.plaf.ColorUIResource [UI] RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI] RootPane.borderDragThickness 5 RootPane.cornerDragWidth 16 @@ -835,6 +837,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object; [5] press [6] ctrl released ENTER [7] release +RootPane.font [active] $defaultFont [UI] +RootPane.foreground #000000 HSL 0 0 0 javax.swing.plaf.ColorUIResource [UI] RootPane.honorDialogMinimumSizeOnResize true RootPane.honorFrameMinimumSizeOnResize false RootPane.inactiveBorderColor #a6a6a6 HSL 0 0 65 com.formdev.flatlaf.util.DerivedColor [UI] darken(30% autoInverse) @@ -1220,9 +1224,11 @@ 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.unifiedBackground true 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 df202d17..aff78d85 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -687,6 +687,7 @@ OptionPane.minimumSize 262,90 javax.swing.plaf.DimensionUIResource [U OptionPane.questionIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneQuestionIcon [UI] OptionPane.sameSizeButtons true OptionPane.setButtonMargin false +OptionPane.showIcon false OptionPane.warningIcon [lazy] 32,32 com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon [UI] OptionPane.windowBindings length=2 [Ljava.lang.Object; [0] ESCAPE @@ -833,6 +834,7 @@ Resizable.resizeBorder [lazy] 4,4,4,4 false com.formdev.flatlaf.ui.F #---- RootPane ---- +RootPane.background #ccffcc HSL 120 100 90 javax.swing.plaf.ColorUIResource [UI] RootPane.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder [UI] RootPane.borderDragThickness 5 RootPane.cornerDragWidth 16 @@ -845,6 +847,8 @@ RootPane.defaultButtonWindowKeyBindings length=8 [Ljava.lang.Object; [5] press [6] ctrl released ENTER [7] release +RootPane.font [active] $defaultFont [UI] +RootPane.foreground #ff0000 HSL 0 100 50 javax.swing.plaf.ColorUIResource [UI] RootPane.honorDialogMinimumSizeOnResize true RootPane.honorFrameMinimumSizeOnResize false RootPaneUI com.formdev.flatlaf.ui.FlatRootPaneUI @@ -1235,9 +1239,11 @@ 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.unifiedBackground true TitlePane.useWindowDecorations true diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java index 3c3cda88..4a832fcf 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java @@ -33,6 +33,7 @@ public class FlatOptionPaneTest public static void main( String[] args ) { SwingUtilities.invokeLater( () -> { FlatTestFrame frame = FlatTestFrame.create( args, "FlatOptionPaneTest" ); + frame.setIconImage( new ImageIcon( FlatOptionPaneTest.class.getResource( "/com/formdev/flatlaf/testing/test16.png" ) ).getImage() ); frame.showFrame( FlatOptionPaneTest::new ); } ); } @@ -54,6 +55,10 @@ public class FlatOptionPaneTest } ); } + private void showTitleBarIcon() { + UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() ); + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents ScrollablePanel panel9 = new ScrollablePanel(); @@ -61,6 +66,7 @@ public class FlatOptionPaneTest JPanel panel1 = new JPanel(); JOptionPane plainOptionPane = new JOptionPane(); plainShowDialogLabel = new FlatOptionPaneTest.ShowDialogLinkLabel(); + showTitleBarIconCheckBox = new JCheckBox(); JLabel errorLabel = new JLabel(); JPanel panel2 = new JPanel(); JOptionPane errorOptionPane = new JOptionPane(); @@ -100,7 +106,7 @@ public class FlatOptionPaneTest //======== panel9 ======== { panel9.setLayout(new MigLayout( - "flowy,ltr,insets dialog,hidemode 3", + "ltr,insets dialog,hidemode 3", // columns "[]" + "[]" + @@ -134,7 +140,12 @@ public class FlatOptionPaneTest //---- plainShowDialogLabel ---- plainShowDialogLabel.setOptionPane(plainOptionPane); plainShowDialogLabel.setTitleLabel(plainLabel); - panel9.add(plainShowDialogLabel, "cell 2 0"); + panel9.add(plainShowDialogLabel, "cell 1 0"); + + //---- showTitleBarIconCheckBox ---- + showTitleBarIconCheckBox.setText("Show window title bar icon"); + showTitleBarIconCheckBox.addActionListener(e -> showTitleBarIcon()); + panel9.add(showTitleBarIconCheckBox, "cell 2 0"); //---- errorLabel ---- errorLabel.setText("Error"); @@ -156,7 +167,7 @@ public class FlatOptionPaneTest //---- errorShowDialogLabel ---- errorShowDialogLabel.setTitleLabel(errorLabel); errorShowDialogLabel.setOptionPane(errorOptionPane); - panel9.add(errorShowDialogLabel, "cell 2 1"); + panel9.add(errorShowDialogLabel, "cell 1 1"); //---- informationLabel ---- informationLabel.setText("Information"); @@ -178,7 +189,7 @@ public class FlatOptionPaneTest //---- informationShowDialogLabel ---- informationShowDialogLabel.setOptionPane(informationOptionPane); informationShowDialogLabel.setTitleLabel(informationLabel); - panel9.add(informationShowDialogLabel, "cell 2 2"); + panel9.add(informationShowDialogLabel, "cell 1 2"); //---- questionLabel ---- questionLabel.setText("Question"); @@ -222,7 +233,7 @@ public class FlatOptionPaneTest //---- warningShowDialogLabel ---- warningShowDialogLabel.setOptionPane(warningOptionPane); warningShowDialogLabel.setTitleLabel(warningLabel); - panel9.add(warningShowDialogLabel, "cell 2 4"); + panel9.add(warningShowDialogLabel, "cell 1 4"); //---- inputLabel ---- inputLabel.setText("Input"); @@ -244,7 +255,7 @@ public class FlatOptionPaneTest //---- inputShowDialogLabel ---- inputShowDialogLabel.setOptionPane(inputOptionPane); inputShowDialogLabel.setTitleLabel(inputLabel); - panel9.add(inputShowDialogLabel, "cell 2 5"); + panel9.add(inputShowDialogLabel, "cell 1 5"); //---- inputIconLabel ---- inputIconLabel.setText("Input + icon"); @@ -267,7 +278,7 @@ public class FlatOptionPaneTest //---- inputIconShowDialogLabel ---- inputIconShowDialogLabel.setTitleLabel(inputIconLabel); inputIconShowDialogLabel.setOptionPane(inputIconOptionPane); - panel9.add(inputIconShowDialogLabel, "cell 2 6"); + panel9.add(inputIconShowDialogLabel, "cell 1 6"); //---- customLabel ---- customLabel.setText("Custom"); @@ -287,7 +298,7 @@ public class FlatOptionPaneTest //---- customShowDialogLabel ---- customShowDialogLabel.setOptionPane(customOptionPane); customShowDialogLabel.setTitleLabel(customLabel); - panel9.add(customShowDialogLabel, "cell 2 7"); + panel9.add(customShowDialogLabel, "cell 1 7"); //---- rightToLeftLabel ---- rightToLeftLabel.setText("Right-to-left:"); @@ -317,6 +328,7 @@ public class FlatOptionPaneTest // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private FlatOptionPaneTest.ShowDialogLinkLabel plainShowDialogLabel; + private JCheckBox showTitleBarIconCheckBox; private FlatOptionPaneTest.ShowDialogLinkLabel errorShowDialogLabel; private FlatOptionPaneTest.ShowDialogLinkLabel informationShowDialogLabel; private JOptionPane customOptionPane; @@ -333,6 +345,7 @@ public class FlatOptionPaneTest ShowDialogLinkLabel() { setText( "Show dialog" ); + setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) ); addMouseListener( new MouseAdapter() { @Override diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd index 78d9bf17..26deae19 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.jfd @@ -10,7 +10,7 @@ new FormModel { name: "this" "border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 ) add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { - "$layoutConstraints": "flowy,ltr,insets dialog,hidemode 3" + "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[][][fill]" "$rowConstraints": "[top][top][top][top][top][top][top][top][top]" } ) { @@ -40,6 +40,16 @@ new FormModel { auxiliary() { "JavaCodeGenerator.variableLocal": false } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showTitleBarIconCheckBox" + "text": "Show window title bar icon" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 0" } ) @@ -71,7 +81,7 @@ new FormModel { "JavaCodeGenerator.variableLocal": false } }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 1" + "value": "cell 1 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "informationLabel" @@ -101,7 +111,7 @@ new FormModel { "JavaCodeGenerator.variableLocal": false } }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 2" + "value": "cell 1 2" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "questionLabel" @@ -155,7 +165,7 @@ new FormModel { "optionPane": new FormReference( "warningOptionPane" ) "titleLabel": new FormReference( "warningLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 4" + "value": "cell 1 4" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "inputLabel" @@ -182,7 +192,7 @@ new FormModel { "optionPane": new FormReference( "inputOptionPane" ) "titleLabel": new FormReference( "inputLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 5" + "value": "cell 1 5" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "inputIconLabel" @@ -210,7 +220,7 @@ new FormModel { "titleLabel": new FormReference( "inputIconLabel" ) "optionPane": new FormReference( "inputIconOptionPane" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 6" + "value": "cell 1 6" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "customLabel" @@ -238,7 +248,7 @@ new FormModel { "optionPane": new FormReference( "customOptionPane" ) "titleLabel": new FormReference( "customLabel" ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 7" + "value": "cell 1 7" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "rightToLeftLabel" @@ -273,7 +283,7 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 895, 1080 ) + "size": new java.awt.Dimension( 995, 1080 ) } ) } } 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 a0d743ca..7a884b68 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 @@ -531,6 +531,7 @@ OptionPane.minimumSize OptionPane.questionIcon OptionPane.sameSizeButtons OptionPane.setButtonMargin +OptionPane.showIcon OptionPane.warningIcon OptionPane.windowBindings OptionPaneUI @@ -631,10 +632,13 @@ RangeSliderUI Resizable.resizeBorder RootPane.activeBorderColor RootPane.ancestorInputMap +RootPane.background RootPane.border RootPane.borderDragThickness RootPane.cornerDragWidth RootPane.defaultButtonWindowKeyBindings +RootPane.font +RootPane.foreground RootPane.honorDialogMinimumSizeOnResize RootPane.honorFrameMinimumSizeOnResize RootPane.inactiveBorderColor @@ -971,7 +975,9 @@ TitlePane.inactiveForeground TitlePane.maximizeIcon TitlePane.menuBarEmbedded TitlePane.menuBarTitleGap +TitlePane.noIconLeftGap TitlePane.restoreIcon +TitlePane.showIcon TitlePane.titleMargins TitlePane.unifiedBackground TitlePane.useWindowDecorations