From 10a965d7653f4151aa4bac6c0b4d28f70df5adf5 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 13 Jul 2022 17:58:25 +0200 Subject: [PATCH] Window decorations: option to show window icon beside window title, if menu bar is embedded or title is centered --- CHANGELOG.md | 2 + .../com/formdev/flatlaf/ui/FlatTitlePane.java | 55 +++++++++++++++---- .../com/formdev/flatlaf/FlatLaf.properties | 1 + .../dumps/uidefaults/FlatDarkLaf_1.8.0.txt | 1 + .../dumps/uidefaults/FlatLightLaf_1.8.0.txt | 1 + .../dumps/uidefaults/FlatTestLaf_1.8.0.txt | 1 + .../flatlaf/themeeditor/FlatLafUIKeys.txt | 1 + 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ba535c5..83324d5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ FlatLaf Change Log - Window title now has a minimum width to always allow moving window (click-and-drag on window title). Instead, embedded menu bar is made smaller. + - Option to show window icon beside window title, if menu bar is embedded or + title is centered. Set UI value `TitlePane.showIconBesideTitle` to `true`. - No longer reduce height of window title bar if it has an embedded menu bar and is maximized. 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 754b03b2..97bc6bdf 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 @@ -89,6 +89,7 @@ import com.formdev.flatlaf.util.UIScale; * @uiDefault TitlePane.buttonMaximizedHeight int * @uiDefault TitlePane.centerTitle boolean * @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean + * @uiDefault TitlePane.showIconBesideTitle boolean * @uiDefault TitlePane.menuBarTitleGap int * @uiDefault TitlePane.menuBarResizeHeight int * @uiDefault TitlePane.closeIcon Icon @@ -116,6 +117,7 @@ public class FlatTitlePane protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" ); protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" ); protected final boolean centerTitleIfMenuBarEmbedded = FlatUIUtils.getUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", true ); + /** @since 2.4 */ protected final boolean showIconBesideTitle = UIManager.getBoolean( "TitlePane.showIconBesideTitle" ); protected final int menuBarTitleGap = FlatUIUtils.getUIInt( "TitlePane.menuBarTitleGap", 40 ); /** @since 2.4 */ protected final int menuBarTitleMinimumGap = FlatUIUtils.getUIInt( "TitlePane.menuBarTitleMinimumGap", 12 ); /** @since 2.4 */ protected final int menuBarResizeHeight = FlatUIUtils.getUIInt( "TitlePane.menuBarResizeHeight", 4 ); @@ -205,6 +207,14 @@ public class FlatTitlePane int titleWidth = w - leftWidth - buttonsWidth; int minTitleWidth = UIScale.scale( titleMinimumWidth ); + // increase minimum width if icon is show besides the title + Icon icon = titleLabel.getIcon(); + if( icon != null ) { + Insets iconInsets = iconLabel.getInsets(); + int iconTextGap = titleLabel.getComponentOrientation().isLeftToRight() ? iconInsets.right : iconInsets.left; + minTitleWidth += icon.getIconWidth() + iconTextGap; + } + // if title is too small, reduce width of buttons if( titleWidth < minTitleWidth ) { buttonsWidth = Math.max( buttonsWidth - (minTitleWidth - titleWidth), buttonPanel.getMinimumSize().width ); @@ -394,11 +404,12 @@ public class FlatTitlePane boolean hasIcon = (images != null && !images.isEmpty()); // set icon - iconLabel.setIcon( hasIcon ? new FlatTitlePaneIcon( images, iconSize ) : null ); + iconLabel.setIcon( hasIcon && !showIconBesideTitle ? new FlatTitlePaneIcon( images, iconSize ) : null ); + titleLabel.setIcon( hasIcon && showIconBesideTitle ? new FlatTitlePaneIcon( images, iconSize ) : null ); // show/hide icon - iconLabel.setVisible( hasIcon ); - leftPanel.setBorder( hasIcon ? null : FlatUIUtils.nonUIResource( new FlatEmptyBorder( 0, noIconLeftGap, 0, 0 ) ) ); + iconLabel.setVisible( hasIcon && !showIconBesideTitle ); + leftPanel.setBorder( hasIcon && !showIconBesideTitle ? null : FlatUIUtils.nonUIResource( new FlatEmptyBorder( 0, noIconLeftGap, 0, 0 ) ) ); updateNativeTitleBarHeightAndHitTestSpotsLater(); } @@ -971,11 +982,28 @@ debug*/ } } - String clippedText = super.layoutCL( label, fontMetrics, text, icon, viewR, iconR, textR ); + // compute icon width and gap (if icon is show besides the title) + int iconTextGap = 0; + int iconWidthAndGap = 0; + if( icon != null ) { + Insets iconInsets = iconLabel.getInsets(); + iconTextGap = leftToRight ? iconInsets.right : iconInsets.left; + iconWidthAndGap = icon.getIconWidth() + iconTextGap; + } + // layout title and icon (if show besides the title) + String clippedText = SwingUtilities.layoutCompoundLabel( label, fontMetrics, text, icon, + label.getVerticalAlignment(), label.getHorizontalAlignment(), + label.getVerticalTextPosition(), label.getHorizontalTextPosition(), + viewR, iconR, textR, + iconTextGap ); + + // compute text X location if( !clippedText.equals( text ) ) { // if text is clipped, align to left (or right) - textR.x = leftToRight ? viewR.x : viewR.x + viewR.width - textR.width; + textR.x = leftToRight + ? viewR.x + iconWidthAndGap + : viewR.x + viewR.width - iconWidthAndGap - textR.width; } else { int leadingGap = hasEmbeddedLeadingMenus ? UIScale.scale( menuBarTitleGap - menuBarTitleMinimumGap ) : 0; @@ -984,18 +1012,25 @@ debug*/ // If window is wide enough, center title within window bounds. // Otherwise, center within free space (label bounds). Container parent = label.getParent(); - int centeredTextX = (parent != null) ? ((parent.getWidth() - textR.width) / 2) - label.getX() : -1; + int centeredTextX = (parent != null) ? ((parent.getWidth() - textR.width - iconWidthAndGap) / 2) + iconWidthAndGap - label.getX() : -1; textR.x = (centeredTextX >= viewR.x + leadingGap && centeredTextX + textR.width <= viewR.x + viewR.width - leadingGap) ? centeredTextX - : viewR.x + ((viewR.width - textR.width) / 2); + : viewR.x + ((viewR.width - textR.width - iconWidthAndGap) / 2) + iconWidthAndGap; } else { - // leading aligned with leading gap, which is reduced is space is rare + // leading aligned with leading gap, which is reduced if space is rare textR.x = leftToRight - ? Math.min( viewR.x + leadingGap, viewR.x + viewR.width - textR.width ) - : Math.max( viewR.x + viewR.width - textR.width - leadingGap, viewR.x ); + ? Math.min( viewR.x + leadingGap + iconWidthAndGap, viewR.x + viewR.width - textR.width ) + : Math.max( viewR.x + viewR.width - leadingGap - iconWidthAndGap - textR.width, viewR.x ); } } + // compute icon X location (relative to text X location) + if( icon != null ) { + iconR.x = leftToRight + ? textR.x - iconWidthAndGap + : textR.x + textR.width + iconTextGap; + } + return clippedText; } 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 f100d89e..5d24952f 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -795,6 +795,7 @@ TitlePane.buttonMinimumWidth = 30 TitlePane.buttonMaximizedHeight = 22 TitlePane.centerTitle = false TitlePane.centerTitleIfMenuBarEmbedded = true +TitlePane.showIconBesideTitle = false TitlePane.menuBarTitleGap = 40 TitlePane.menuBarTitleMinimumGap = 12 TitlePane.menuBarResizeHeight = 4 diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index f0d83179..daeb5837 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -1240,6 +1240,7 @@ TitlePane.menuBarTitleMinimumGap 12 TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.showIcon true +TitlePane.showIconBesideTitle false TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMinimumWidth 60 TitlePane.unifiedBackground true diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt index 6a54fd96..f6448d31 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -1245,6 +1245,7 @@ TitlePane.menuBarTitleMinimumGap 12 TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.showIcon true +TitlePane.showIconBesideTitle false TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMinimumWidth 60 TitlePane.unifiedBackground true diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt index db0b76c8..7cdc3e39 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -1273,6 +1273,7 @@ TitlePane.menuBarTitleMinimumGap 12 TitlePane.noIconLeftGap 8 TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.showIcon true +TitlePane.showIconBesideTitle false TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMinimumWidth 60 TitlePane.unifiedBackground true 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 13eaa219..9f0d4025 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 @@ -1006,6 +1006,7 @@ TitlePane.menuBarTitleMinimumGap TitlePane.noIconLeftGap TitlePane.restoreIcon TitlePane.showIcon +TitlePane.showIconBesideTitle TitlePane.titleMargins TitlePane.titleMinimumWidth TitlePane.unifiedBackground