diff --git a/CHANGELOG.md b/CHANGELOG.md index c1998569..10420b8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ FlatLaf Change Log `frame.setVisible(true)`. (issue #277) - Custom window decorations: Fixed NPE in `FlatTitlePane.findHorizontalGlue()`. (issue #275) +- Custom window decorations: Fixed right aligned progress bar in embedded menu + bar was overlapping window title. (issue #272) - InternalFrame: Fixed translucent internal frame menu bar background if `TitlePane.unifiedBackground` is `true`. (issue #274) 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 5a399432..ca722822 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 @@ -197,14 +197,16 @@ public class FlatTitlePane } // If menu bar is embedded and contains a horizontal glue component, - // then move the title label to the same location as the glue component. + // then move the title label to the same location as the glue component + // and give it the same width. // This allows placing any component on the trailing side of the title pane. JMenuBar menuBar = rootPane.getJMenuBar(); if( hasVisibleEmbeddedMenuBar( menuBar ) ) { Component horizontalGlue = findHorizontalGlue( menuBar ); if( horizontalGlue != null ) { Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, titleLabel ); - titleLabel.setLocation( titleLabel.getX() + glueLocation.x, titleLabel.getY() ); + titleLabel.setBounds( titleLabel.getX() + glueLocation.x, titleLabel.getY(), + horizontalGlue.getWidth(), titleLabel.getHeight() ); } } } @@ -450,9 +452,13 @@ public class FlatTitlePane // This allows placing any component on the trailing side of the title pane. Component horizontalGlue = findHorizontalGlue( rootPane.getJMenuBar() ); if( horizontalGlue != null ) { - int titleWidth = Math.max( titleLabel.getWidth(), 0 ); // title width may be negative + boolean leftToRight = getComponentOrientation().isLeftToRight(); + int titleWidth = leftToRight + ? buttonPanel.getX() - (leftPanel.getX() + leftPanel.getWidth()) + : leftPanel.getX() - (buttonPanel.getX() + buttonPanel.getWidth()); + titleWidth = Math.max( titleWidth, 0 ); // title width may be negative bounds.width += titleWidth; - if( !getComponentOrientation().isLeftToRight() ) + if( !leftToRight ) bounds.x -= titleWidth; } 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 9b791068..2e878c0a 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 @@ -135,6 +135,48 @@ public class FlatWindowDecorationsTest menuBar.setVisible( menuBarVisibleCheckBox.isSelected() ); } + private void rightCompChanged() { + removeNonMenusFromMenuBar(); + + if( rightCompCheckBox.isSelected() ) { + rightStretchCompCheckBox.setSelected( false ); + + JButton myButton = new JButton( "?" ); + myButton.putClientProperty( "JButton.buttonType", "toolBarButton" ); + myButton.setFocusable( false ); + + menuBar.add( Box.createGlue() ); + menuBar.add( myButton ); + } + + menuBar.revalidate(); + menuBar.repaint(); + } + + private void rightStretchCompChanged() { + removeNonMenusFromMenuBar(); + + if( rightStretchCompCheckBox.isSelected() ) { + rightCompCheckBox.setSelected( false ); + + menuBar.add( Box.createGlue() ); + menuBar.add( new JProgressBar() ); + } + + menuBar.revalidate(); + menuBar.repaint(); + } + + private void removeNonMenusFromMenuBar() { + Component[] components = menuBar.getComponents(); + for( int i = components.length - 1; i >= 0; i-- ) { + if( !(components[i] instanceof JMenu) ) + menuBar.remove( i ); + else + break; + } + } + private void colorizeMenuBar() { boolean colorize = colorizeMenuBarCheckBox.isSelected(); Color menuBarBackground = colorize ? new Color( 0xffccff ) : UIManager.getColor( "MenuBar.background" ); @@ -324,7 +366,7 @@ public class FlatWindowDecorationsTest private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents menuBarCheckBox = new JCheckBox(); - unifiedBackgroundCheckBox = new JCheckBox(); + rightCompCheckBox = new JCheckBox(); JPanel panel3 = new JPanel(); addMenuButton = new JButton(); addGlueButton = new JButton(); @@ -332,8 +374,10 @@ public class FlatWindowDecorationsTest changeMenuButton = new JButton(); changeTitleButton = new JButton(); menuBarEmbeddedCheckBox = new JCheckBox(); - colorizeMenuBarCheckBox = new JCheckBox(); + rightStretchCompCheckBox = new JCheckBox(); menuBarVisibleCheckBox = new JCheckBox(); + colorizeMenuBarCheckBox = new JCheckBox(); + unifiedBackgroundCheckBox = new JCheckBox(); colorizeMenusCheckBox = new JCheckBox(); resizableCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox(); @@ -394,6 +438,7 @@ public class FlatWindowDecorationsTest // rows "para[]0" + "[]0" + + "[]0" + "[]unrel" + "[]0" + "[]unrel" + @@ -407,10 +452,10 @@ public class FlatWindowDecorationsTest menuBarCheckBox.addActionListener(e -> menuBarChanged()); add(menuBarCheckBox, "cell 0 0"); - //---- unifiedBackgroundCheckBox ---- - unifiedBackgroundCheckBox.setText("unified background"); - unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged()); - add(unifiedBackgroundCheckBox, "cell 1 0"); + //---- rightCompCheckBox ---- + rightCompCheckBox.setText("right aligned component"); + rightCompCheckBox.addActionListener(e -> rightCompChanged()); + add(rightCompCheckBox, "cell 1 0"); //======== panel3 ======== { @@ -450,7 +495,7 @@ public class FlatWindowDecorationsTest changeTitleButton.addActionListener(e -> changeTitle()); panel3.add(changeTitleButton, "cell 0 4"); } - add(panel3, "cell 2 0 1 6,aligny top,growy 0"); + add(panel3, "cell 2 0 1 7,aligny top,growy 0"); //---- menuBarEmbeddedCheckBox ---- menuBarEmbeddedCheckBox.setText("embedded menu bar"); @@ -458,10 +503,10 @@ public class FlatWindowDecorationsTest menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged()); add(menuBarEmbeddedCheckBox, "cell 0 1"); - //---- colorizeMenuBarCheckBox ---- - colorizeMenuBarCheckBox.setText("colorize menu bar"); - colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar()); - add(colorizeMenuBarCheckBox, "cell 1 1"); + //---- rightStretchCompCheckBox ---- + rightStretchCompCheckBox.setText("right aligned stretching component"); + rightStretchCompCheckBox.addActionListener(e -> rightStretchCompChanged()); + add(rightStretchCompCheckBox, "cell 1 1"); //---- menuBarVisibleCheckBox ---- menuBarVisibleCheckBox.setText("menu bar visible"); @@ -469,39 +514,49 @@ public class FlatWindowDecorationsTest menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged()); add(menuBarVisibleCheckBox, "cell 0 2"); + //---- colorizeMenuBarCheckBox ---- + colorizeMenuBarCheckBox.setText("colorize menu bar"); + colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar()); + add(colorizeMenuBarCheckBox, "cell 1 2"); + + //---- unifiedBackgroundCheckBox ---- + unifiedBackgroundCheckBox.setText("unified background"); + unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged()); + add(unifiedBackgroundCheckBox, "cell 0 3"); + //---- colorizeMenusCheckBox ---- colorizeMenusCheckBox.setText("colorize menus"); colorizeMenusCheckBox.addActionListener(e -> colorizeMenus()); - add(colorizeMenusCheckBox, "cell 1 2"); + add(colorizeMenusCheckBox, "cell 1 3"); //---- resizableCheckBox ---- resizableCheckBox.setText("resizable"); resizableCheckBox.setSelected(true); resizableCheckBox.addActionListener(e -> resizableChanged()); - add(resizableCheckBox, "cell 0 3"); + add(resizableCheckBox, "cell 0 4"); //---- maximizedBoundsCheckBox ---- maximizedBoundsCheckBox.setText("maximized bounds (50,100, 1000,700)"); maximizedBoundsCheckBox.addActionListener(e -> maximizedBoundsChanged()); - add(maximizedBoundsCheckBox, "cell 1 3"); + add(maximizedBoundsCheckBox, "cell 1 4"); //---- undecoratedCheckBox ---- undecoratedCheckBox.setText("undecorated"); undecoratedCheckBox.addActionListener(e -> undecoratedChanged()); - add(undecoratedCheckBox, "cell 0 4"); + add(undecoratedCheckBox, "cell 0 5"); //---- fullScreenCheckBox ---- fullScreenCheckBox.setText("full screen"); fullScreenCheckBox.addActionListener(e -> fullScreenChanged()); - add(fullScreenCheckBox, "cell 1 4"); + add(fullScreenCheckBox, "cell 1 5"); //---- label1 ---- label1.setText("Style:"); - add(label1, "cell 0 5"); + add(label1, "cell 0 6"); //---- label2 ---- label2.setText("Icon:"); - add(label2, "cell 1 5"); + add(label2, "cell 1 6"); //======== panel1 ======== { @@ -566,7 +621,7 @@ public class FlatWindowDecorationsTest styleFileChooserRadioButton.addActionListener(e -> decorationStyleChanged()); panel1.add(styleFileChooserRadioButton, "cell 0 8"); } - add(panel1, "cell 0 6"); + add(panel1, "cell 0 7"); //======== panel2 ======== { @@ -595,18 +650,18 @@ public class FlatWindowDecorationsTest iconTestRandomRadioButton.addActionListener(e -> iconChanged()); panel2.add(iconTestRandomRadioButton, "cell 0 2"); } - add(panel2, "cell 1 6"); + add(panel2, "cell 1 7"); //---- openDialogButton ---- openDialogButton.setText("Open Dialog"); openDialogButton.addActionListener(e -> openDialog()); - add(openDialogButton, "cell 0 7 2 1"); + add(openDialogButton, "cell 0 8 2 1"); //---- openFrameButton ---- openFrameButton.setText("Open Frame"); openFrameButton.setMnemonic('A'); openFrameButton.addActionListener(e -> openFrame()); - add(openFrameButton, "cell 0 7 2 1"); + add(openFrameButton, "cell 0 8 2 1"); //======== menuBar ======== { @@ -798,15 +853,17 @@ public class FlatWindowDecorationsTest // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private JCheckBox menuBarCheckBox; - private JCheckBox unifiedBackgroundCheckBox; + private JCheckBox rightCompCheckBox; private JButton addMenuButton; private JButton addGlueButton; private JButton removeMenuButton; private JButton changeMenuButton; private JButton changeTitleButton; private JCheckBox menuBarEmbeddedCheckBox; - private JCheckBox colorizeMenuBarCheckBox; + private JCheckBox rightStretchCompCheckBox; private JCheckBox menuBarVisibleCheckBox; + private JCheckBox colorizeMenuBarCheckBox; + private JCheckBox unifiedBackgroundCheckBox; private JCheckBox colorizeMenusCheckBox; private JCheckBox resizableCheckBox; private JCheckBox maximizedBoundsCheckBox; 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 fc243485..02c0167c 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 @@ -9,7 +9,7 @@ new FormModel { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" "$columnConstraints": "[left]para[left][fill]" - "$rowConstraints": "para[]0[]0[]unrel[]0[]unrel[][top][]" + "$rowConstraints": "para[]0[]0[]0[]unrel[]0[]unrel[][top][]" } ) { name: "this" add( new FormComponent( "javax.swing.JCheckBox" ) { @@ -24,12 +24,12 @@ new FormModel { "value": "cell 0 0" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { - name: "unifiedBackgroundCheckBox" - "text": "unified background" + name: "rightCompCheckBox" + "text": "right aligned component" auxiliary() { "JavaCodeGenerator.variableLocal": false } - addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedBackgroundChanged", false ) ) + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "rightCompChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 0" } ) @@ -90,7 +90,7 @@ new FormModel { "value": "cell 0 4" } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 2 0 1 6,aligny top,growy 0" + "value": "cell 2 0 1 7,aligny top,growy 0" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "menuBarEmbeddedCheckBox" @@ -104,12 +104,12 @@ new FormModel { "value": "cell 0 1" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { - name: "colorizeMenuBarCheckBox" - "text": "colorize menu bar" + name: "rightStretchCompCheckBox" + "text": "right aligned stretching component" auxiliary() { "JavaCodeGenerator.variableLocal": false } - addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenuBar", false ) ) + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "rightStretchCompChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 1" } ) @@ -124,6 +124,26 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 2" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "colorizeMenuBarCheckBox" + "text": "colorize menu bar" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenuBar", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 2" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "unifiedBackgroundCheckBox" + "text": "unified background" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedBackgroundChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "colorizeMenusCheckBox" "text": "colorize menus" @@ -132,7 +152,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenus", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 2" + "value": "cell 1 3" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "resizableCheckBox" @@ -143,7 +163,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "resizableChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 3" + "value": "cell 0 4" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "maximizedBoundsCheckBox" @@ -153,7 +173,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "maximizedBoundsChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 3" + "value": "cell 1 4" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "undecoratedCheckBox" @@ -163,7 +183,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "undecoratedChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 4" + "value": "cell 0 5" } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "fullScreenCheckBox" @@ -173,19 +193,19 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "fullScreenChanged", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 4" + "value": "cell 1 5" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "label1" "text": "Style:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 5" + "value": "cell 0 6" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "label2" "text": "Icon:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 5" + "value": "cell 1 6" } ) add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$columnConstraints": "[fill]" @@ -294,7 +314,7 @@ new FormModel { "value": "cell 0 8" } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 6" + "value": "cell 0 7" } ) add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$columnConstraints": "[fill]" @@ -337,14 +357,14 @@ new FormModel { "value": "cell 0 2" } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 6" + "value": "cell 1 7" } ) add( new FormComponent( "javax.swing.JButton" ) { name: "openDialogButton" "text": "Open Dialog" addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDialog", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 7 2 1" + "value": "cell 0 8 2 1" } ) add( new FormComponent( "javax.swing.JButton" ) { name: "openFrameButton" @@ -352,7 +372,7 @@ new FormModel { "mnemonic": 65 addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openFrame", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 7 2 1" + "value": "cell 0 8 2 1" } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 )