From b0426b81a7e27e3145a37648371fd17b3d8b5bbe Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 6 Aug 2020 11:45:47 +0200 Subject: [PATCH] Window decorations: embedded menu bar did not always respond to mouse events after adding menus and when running in JetBrains Runtime (issue #151) --- CHANGELOG.md | 8 ++++ .../formdev/flatlaf/ui/FlatRootPaneUI.java | 3 ++ .../com/formdev/flatlaf/ui/FlatTitlePane.java | 40 ++++++++++++++-- .../testing/FlatWindowDecorationsTest.java | 47 ++++++++++++++++++- .../testing/FlatWindowDecorationsTest.jfd | 27 +++++++++-- 5 files changed, 117 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4a6a5a..f14665b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ FlatLaf Change Log ================== +## Unreleased + +#### Fixed bugs + +- Custom window decorations: Embedded menu bar did not always respond to mouse + events after adding menus and when running in JetBrains Runtime. (issue #151) + + ## 0.39 #### New features 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 5dad1903..048d3ac6 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 @@ -304,6 +304,9 @@ public class FlatRootPaneUI Container contentPane = rootPane.getContentPane(); if( contentPane != null ) contentPane.setBounds( 0, nextY, width, Math.max( height - nextY, 0 ) ); + + if( titlePane != null ) + titlePane.menuBarLayouted(); } @Override 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 0939494a..1e0e247e 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 @@ -391,6 +391,12 @@ public class FlatTitlePane return FlatUIUtils.subtractInsets( bounds, UIScale.scale( getMenuBarMargins() ) ); } + protected Insets getMenuBarMargins() { + return getComponentOrientation().isLeftToRight() + ? menuBarMargins + : new Insets( menuBarMargins.top, menuBarMargins.right, menuBarMargins.bottom, menuBarMargins.left ); + } + protected void menuBarChanged() { menuBarPlaceholder.invalidate(); @@ -400,12 +406,27 @@ public class FlatTitlePane } ); } - protected Insets getMenuBarMargins() { - return getComponentOrientation().isLeftToRight() - ? menuBarMargins - : new Insets( menuBarMargins.top, menuBarMargins.right, menuBarMargins.bottom, menuBarMargins.left ); + protected void menuBarLayouted() { + updateJBRHitTestSpotsAndTitleBarHeightLater(); } +/*debug + @Override + public void paint( Graphics g ) { + super.paint( g ); + + if( debugTitleBarHeight > 0 ) { + g.setColor( Color.green ); + g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight ); + } + if( debugHitTestSpots != null ) { + g.setColor( Color.blue ); + for( Rectangle r : debugHitTestSpots ) + g.drawRect( r.x, r.y, r.width, r.height ); + } + } +debug*/ + @Override protected void paintComponent( Graphics g ) { g.setColor( getBackground() ); @@ -583,6 +604,12 @@ public class FlatTitlePane titleBarHeight--; JBRCustomDecorations.setHitTestSpotsAndTitleBarHeight( window, hitTestSpots, titleBarHeight ); + +/*debug + debugHitTestSpots = hitTestSpots; + debugTitleBarHeight = titleBarHeight; + repaint(); +debug*/ } protected void addJBRHitTestSpot( JComponent c, boolean subtractMenuBarMargins, List hitTestSpots ) { @@ -599,6 +626,11 @@ public class FlatTitlePane hitTestSpots.add( r ); } +/*debug + private List debugHitTestSpots; + private int debugTitleBarHeight; +debug*/ + //---- class TitlePaneBorder ---------------------------------------------- protected class FlatTitlePaneBorder 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 13b77661..136cafcf 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 @@ -22,6 +22,7 @@ import java.awt.event.*; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Random; import javax.swing.*; import com.formdev.flatlaf.FlatClientProperties; import net.miginfocom.swing.*; @@ -117,6 +118,32 @@ public class FlatWindowDecorationsTest rootPane.putClientProperty( FlatClientProperties.MENU_BAR_EMBEDDED, menuBarEmbeddedCheckBox.isSelected() ); } + private void addMenu() { + JMenu menu = new JMenu( "Hello" ); + menu.add( new JMenuItem( "world" ) ); + menuBar.add( menu ); + menuBar.revalidate(); + } + + private void removeMenu() { + int menuCount = menuBar.getMenuCount(); + if( menuCount <= 0 ) + return; + + menuBar.remove( menuCount - 1 ); + menuBar.revalidate(); + } + + private void changeMenu() { + int menuCount = menuBar.getMenuCount(); + if( menuCount <= 0 ) + return; + + int len = new Random().nextInt( 20 ); + String text = "1234567890abcdefghij".substring( 0, len + 1 ); + menuBar.getMenu( menuCount - 1 ).setText( text ); + } + private void resizableChanged() { Window window = SwingUtilities.windowForComponent( this ); if( window instanceof Frame ) @@ -218,6 +245,9 @@ public class FlatWindowDecorationsTest private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents menuBarCheckBox = new JCheckBox(); + JButton addMenuButton = new JButton(); + JButton removeMenuButton = new JButton(); + JButton changeMenuButton = new JButton(); menuBarEmbeddedCheckBox = new JCheckBox(); resizableCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox(); @@ -271,7 +301,7 @@ public class FlatWindowDecorationsTest "ltr,insets dialog,hidemode 3", // columns "[left]para" + - "[fill]", + "[left]", // rows "para[]0" + "[]0" + @@ -287,6 +317,21 @@ public class FlatWindowDecorationsTest menuBarCheckBox.addActionListener(e -> menuBarChanged()); add(menuBarCheckBox, "cell 0 0"); + //---- addMenuButton ---- + addMenuButton.setText("Add menu"); + addMenuButton.addActionListener(e -> addMenu()); + add(addMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); + + //---- removeMenuButton ---- + removeMenuButton.setText("Remove menu"); + removeMenuButton.addActionListener(e -> removeMenu()); + add(removeMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); + + //---- changeMenuButton ---- + changeMenuButton.setText("Change menu"); + changeMenuButton.addActionListener(e -> changeMenu()); + add(changeMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); + //---- menuBarEmbeddedCheckBox ---- menuBarEmbeddedCheckBox.setText("embedded menu bar"); menuBarEmbeddedCheckBox.setSelected(true); 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 e5021fd8..378f3e31 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 @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.2.0.298" Java: "13.0.2" encoding: "UTF-8" +JFDML JFormDesigner: "7.0.2.0.298" Java: "14" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -8,7 +8,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[fill]" + "$columnConstraints": "[left]para[left]" "$rowConstraints": "para[]0[]0[]0[][][top][]" } ) { name: "this" @@ -23,6 +23,27 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 0" } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "addMenuButton" + "text": "Add menu" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addMenu", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0 1 2,align left top,grow 0 0" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "removeMenuButton" + "text": "Remove menu" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0 1 2,align left top,grow 0 0" + } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "changeMenuButton" + "text": "Change menu" + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0 1 2,align left top,grow 0 0" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "menuBarEmbeddedCheckBox" "text": "embedded menu bar" @@ -238,7 +259,7 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 450, 380 ) + "size": new java.awt.Dimension( 550, 380 ) } ) add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) { name: "menuBar"