FlatLaf window decorations: added client property JRootPane.titleBarHeight to allow specifying a (larger) preferred height for the title bar (issue #897)
Some checks are pending
CI / build (11, ) (push) Waiting to run
CI / build (17, ) (push) Waiting to run
CI / build (21, ) (push) Waiting to run
CI / build (23, ) (push) Waiting to run
CI / build (8, ) (push) Waiting to run
CI / snapshot (push) Blocked by required conditions
CI / release (push) Blocked by required conditions

This commit is contained in:
Karl Tauber
2024-10-17 19:58:58 +02:00
parent 8eab86e489
commit 570cf6fc51
6 changed files with 96 additions and 10 deletions

View File

@@ -25,6 +25,9 @@ FlatLaf Change Log
#### Other Changes #### Other Changes
- FlatLaf window decorations: Added client property `JRootPane.titleBarHeight`
to allow specifying a (larger) preferred height for the title bar. (issue
#897)
- Added system property `flatlaf.useRoundedPopupBorder` to allow disabling - Added system property `flatlaf.useRoundedPopupBorder` to allow disabling
native rounded popup borders on Windows 11 and macOS. On macOS 14.4+, where native rounded popup borders on Windows 11 and macOS. On macOS 14.4+, where
rounded popup borders are disabled since FlatLaf 3.5 because of occasional rounded popup borders are disabled since FlatLaf 3.5 because of occasional

View File

@@ -626,6 +626,18 @@ public interface FlatClientProperties
*/ */
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"; String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
/**
* Specifies the preferred height of title bar (requires enabled window decorations).
* <p>
* (requires Windows 10/11)
* <p>
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
* <strong>Value type</strong> {@link java.lang.Integer}
*
* @since 3.5.2
*/
String TITLE_BAR_HEIGHT = "JRootPane.titleBarHeight";
/** /**
* Specifies whether the glass pane should have full height and overlap the title bar, * Specifies whether the glass pane should have full height and overlap the title bar,
* if FlatLaf window decorations are enabled. Default is {@code false}. * if FlatLaf window decorations are enabled. Default is {@code false}.

View File

@@ -448,6 +448,11 @@ public class FlatRootPaneUI
titlePane.titleBarColorsChanged(); titlePane.titleBarColorsChanged();
break; break;
case FlatClientProperties.TITLE_BAR_HEIGHT:
if( titlePane != null )
titlePane.revalidate();
break;
case FlatClientProperties.FULL_WINDOW_CONTENT: case FlatClientProperties.FULL_WINDOW_CONTENT:
if( titlePane != null ) { if( titlePane != null ) {
rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() ); rootPane.getLayeredPane().setLayer( titlePane, getLayerForTitlePane() );

View File

@@ -359,6 +359,10 @@ public class FlatTitlePane
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize(); Dimension size = super.getPreferredSize();
int titleBarHeight = clientPropertyInt( rootPane, TITLE_BAR_HEIGHT, -1 );
if( titleBarHeight >= 0 )
return new Dimension( size.width, UIScale.scale( titleBarHeight ) );
if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) { if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) {
// make title pane height smaller when frame is maximized // make title pane height smaller when frame is maximized
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) ); size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) );

View File

@@ -127,6 +127,9 @@ public class FlatWindowDecorationsTest
+ " @ " + bounds.x + ", " + bounds.y ); + " @ " + bounds.x + ", " + bounds.y );
} else } else
fullWindowContentButtonsBoundsField.setText( "null" ); fullWindowContentButtonsBoundsField.setText( "null" );
fullWindowContentButtonsBoundsLabel.setEnabled( bounds != null );
fullWindowContentButtonsBoundsField.setEnabled( bounds != null );
} ); } );
} }
} }
@@ -562,6 +565,16 @@ debug*/
} }
} }
private void titleBarHeightChanged() {
JRootPane rootPane = getWindowRootPane();
if( rootPane != null ) {
boolean enabled = titleBarHeightCheckBox.isSelected();
titleBarHeightField.setEnabled( enabled );
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_HEIGHT, enabled ? titleBarHeightField.getValue() : null );
}
}
private JRootPane getWindowRootPane() { private JRootPane getWindowRootPane() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
return (window instanceof RootPaneContainer) return (window instanceof RootPaneContainer)
@@ -588,12 +601,14 @@ debug*/
maximizedBoundsCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox();
JPanel panel4 = new JPanel(); JPanel panel4 = new JPanel();
showIconCheckBox = new FlatTriStateCheckBox(); showIconCheckBox = new FlatTriStateCheckBox();
titleBarHeightCheckBox = new JCheckBox();
showTitleCheckBox = new JCheckBox(); showTitleCheckBox = new JCheckBox();
titleBarHeightField = new JSpinner();
showIconifyCheckBox = new JCheckBox(); showIconifyCheckBox = new JCheckBox();
showMaximizeCheckBox = new JCheckBox(); showMaximizeCheckBox = new JCheckBox();
showCloseCheckBox = new JCheckBox(); showCloseCheckBox = new JCheckBox();
fullWindowContentCheckBox = new JCheckBox(); fullWindowContentCheckBox = new JCheckBox();
JLabel fullWindowContentButtonsBoundsLabel = new JLabel(); fullWindowContentButtonsBoundsLabel = new JLabel();
fullWindowContentButtonsBoundsField = new JLabel(); fullWindowContentButtonsBoundsField = new JLabel();
JPanel panel6 = new JPanel(); JPanel panel6 = new JPanel();
menuBarCheckBox = new JCheckBox(); menuBarCheckBox = new JCheckBox();
@@ -677,7 +692,8 @@ debug*/
"[fill]" + "[fill]" +
"[fill]" + "[fill]" +
"[]" + "[]" +
"[]")); "[]" +
"[40]"));
//======== panel7 ======== //======== panel7 ========
{ {
@@ -728,7 +744,8 @@ debug*/
panel4.setLayout(new MigLayout( panel4.setLayout(new MigLayout(
"ltr,hidemode 3,gap 0 0", "ltr,hidemode 3,gap 0 0",
// columns // columns
"[grow,left]", "[grow,left]" +
"[fill]",
// rows // rows
"[]" + "[]" +
"[]" + "[]" +
@@ -743,12 +760,23 @@ debug*/
showIconCheckBox.addActionListener(e -> showIconChanged()); showIconCheckBox.addActionListener(e -> showIconChanged());
panel4.add(showIconCheckBox, "cell 0 0"); panel4.add(showIconCheckBox, "cell 0 0");
//---- titleBarHeightCheckBox ----
titleBarHeightCheckBox.setText("Height:");
titleBarHeightCheckBox.addActionListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightCheckBox, "cell 1 0");
//---- showTitleCheckBox ---- //---- showTitleCheckBox ----
showTitleCheckBox.setText("show title"); showTitleCheckBox.setText("show title");
showTitleCheckBox.setSelected(true); showTitleCheckBox.setSelected(true);
showTitleCheckBox.addActionListener(e -> showTitleChanged()); showTitleCheckBox.addActionListener(e -> showTitleChanged());
panel4.add(showTitleCheckBox, "cell 0 1"); panel4.add(showTitleCheckBox, "cell 0 1");
//---- titleBarHeightField ----
titleBarHeightField.setEnabled(false);
titleBarHeightField.setModel(new SpinnerNumberModel(44, null, null, 2));
titleBarHeightField.addChangeListener(e -> titleBarHeightChanged());
panel4.add(titleBarHeightField, "cell 1 1");
//---- showIconifyCheckBox ---- //---- showIconifyCheckBox ----
showIconifyCheckBox.setText("show iconfiy"); showIconifyCheckBox.setText("show iconfiy");
showIconifyCheckBox.setSelected(true); showIconifyCheckBox.setSelected(true);
@@ -774,10 +802,12 @@ debug*/
//---- fullWindowContentButtonsBoundsLabel ---- //---- fullWindowContentButtonsBoundsLabel ----
fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:"); fullWindowContentButtonsBoundsLabel.setText("Buttons bounds:");
fullWindowContentButtonsBoundsLabel.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsLabel, "cell 0 6");
//---- fullWindowContentButtonsBoundsField ---- //---- fullWindowContentButtonsBoundsField ----
fullWindowContentButtonsBoundsField.setText("null"); fullWindowContentButtonsBoundsField.setText("null");
fullWindowContentButtonsBoundsField.setEnabled(false);
panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6"); panel4.add(fullWindowContentButtonsBoundsField, "cell 0 6");
} }
add(panel4, "cell 1 0"); add(panel4, "cell 1 0");
@@ -1266,11 +1296,14 @@ debug*/
private JCheckBox fullScreenCheckBox; private JCheckBox fullScreenCheckBox;
private JCheckBox maximizedBoundsCheckBox; private JCheckBox maximizedBoundsCheckBox;
private FlatTriStateCheckBox showIconCheckBox; private FlatTriStateCheckBox showIconCheckBox;
private JCheckBox titleBarHeightCheckBox;
private JCheckBox showTitleCheckBox; private JCheckBox showTitleCheckBox;
private JSpinner titleBarHeightField;
private JCheckBox showIconifyCheckBox; private JCheckBox showIconifyCheckBox;
private JCheckBox showMaximizeCheckBox; private JCheckBox showMaximizeCheckBox;
private JCheckBox showCloseCheckBox; private JCheckBox showCloseCheckBox;
private JCheckBox fullWindowContentCheckBox; private JCheckBox fullWindowContentCheckBox;
private JLabel fullWindowContentButtonsBoundsLabel;
private JLabel fullWindowContentButtonsBoundsField; private JLabel fullWindowContentButtonsBoundsField;
private JCheckBox menuBarCheckBox; private JCheckBox menuBarCheckBox;
private JCheckBox menuBarEmbeddedCheckBox; private JCheckBox menuBarEmbeddedCheckBox;

View File

@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left][fill][fill][fill]" "$columnConstraints": "[left][fill][fill][fill]"
"$rowConstraints": "[fill][fill][][]" "$rowConstraints": "[fill][fill][][][40]"
} ) { } ) {
name: "this" name: "this"
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
@@ -76,7 +76,7 @@ new FormModel {
} ) } )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,hidemode 3,gap 0 0" "$layoutConstraints": "ltr,hidemode 3,gap 0 0"
"$columnConstraints": "[grow,left]" "$columnConstraints": "[grow,left][fill]"
"$rowConstraints": "[][][][][]rel[]rel[]" "$rowConstraints": "[][][][][]rel[]rel[]"
} ) { } ) {
name: "panel4" name: "panel4"
@@ -91,6 +91,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0" "value": "cell 0 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "titleBarHeightCheckBox"
"text": "Height:"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "titleBarHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showTitleCheckBox" name: "showTitleCheckBox"
"text": "show title" "text": "show title"
@@ -102,6 +112,20 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1" "value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JSpinner" ) {
name: "titleBarHeightField"
"enabled": false
"model": new javax.swing.SpinnerNumberModel {
stepSize: 2
value: 44
}
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "titleBarHeightChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "showIconifyCheckBox" name: "showIconifyCheckBox"
"text": "show iconfiy" "text": "show iconfiy"
@@ -148,12 +172,17 @@ new FormModel {
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fullWindowContentButtonsBoundsLabel" name: "fullWindowContentButtonsBoundsLabel"
"text": "Buttons bounds:" "text": "Buttons bounds:"
"enabled": false
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 6" "value": "cell 0 6"
} ) } )
add( new FormComponent( "javax.swing.JLabel" ) { add( new FormComponent( "javax.swing.JLabel" ) {
name: "fullWindowContentButtonsBoundsField" name: "fullWindowContentButtonsBoundsField"
"text": "null" "text": "null"
"enabled": false
auxiliary() { auxiliary() {
"JavaCodeGenerator.variableLocal": false "JavaCodeGenerator.variableLocal": false
} }
@@ -610,7 +639,7 @@ new FormModel {
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 960, 495 ) "size": new java.awt.Dimension( 960, 570 )
} ) } )
add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) { add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
name: "menuBar" name: "menuBar"
@@ -776,23 +805,23 @@ new FormModel {
} ) } )
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 515 ) "location": new java.awt.Point( 0, 585 )
"size": new java.awt.Dimension( 255, 30 ) "size": new java.awt.Dimension( 255, 30 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "styleButtonGroup" name: "styleButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 565 ) "location": new java.awt.Point( 0, 635 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "iconButtonGroup" name: "iconButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 615 ) "location": new java.awt.Point( 0, 685 )
} ) } )
add( new FormNonVisual( "javax.swing.ButtonGroup" ) { add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
name: "typeButtonGroup" name: "typeButtonGroup"
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 669 ) "location": new java.awt.Point( 0, 740 )
} ) } )
} }
} }