From 16f3f9e6ffb47a797f9283781baad3a27f9c41bd Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 20 Aug 2022 19:42:38 +0200 Subject: [PATCH] Window decorations: added client property to mark components in embedded menu bar as "caption" (issue #569) --- CHANGELOG.md | 3 ++ .../formdev/flatlaf/FlatClientProperties.java | 13 +++++++ .../com/formdev/flatlaf/ui/FlatTitlePane.java | 38 +++++++++++-------- .../testing/FlatWindowDecorationsTest.java | 24 ++++++++++-- .../testing/FlatWindowDecorationsTest.jfd | 18 +++++++-- 5 files changed, 73 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d6bca82..b44ee9e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ FlatLaf Change Log - TabbedPane: New option to disable tab run rotation in wrap layout. Set UI value `TabbedPane.rotateTabRuns` to `false`. (issue #574) +- Native window decorations (Windows 10/11 only): Added client property to mark + components in embedded menu bar as "caption" (allow moving window). (issue + #569) #### Fixed bugs 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 18c64934..5819e274 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -253,6 +253,19 @@ public interface FlatClientProperties */ String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner"; + /** + * Specifies whether a component in a embedded menu bar should behave as caption + * (left-click allows moving window, right-click shows window system menu). + * The component does not receive mouse pressed/released/clicked/dragged events, + * but it gets mouse entered/exited/moved events. + *

+ * Component {@link javax.swing.JComponent}
+ * Value type {@link java.lang.Boolean} + * + * @since 2.5 + */ + String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption"; + //---- Popup -------------------------------------------------------------- /** 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 48301ab9..aa40c63b 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 @@ -861,26 +861,32 @@ debug*/ r.height -= resizeHeight; } - Component horizontalGlue = findHorizontalGlue( menuBar ); - if( horizontalGlue != null ) { - // If menu bar is embedded and contains a horizontal glue component, - // then split the hit test spot into two spots so that - // the glue component area can be used to move the window. + int count = menuBar.getComponentCount(); + for( int i = count - 1; i >= 0; i-- ) { + Component c = menuBar.getComponent( i ); + if( c instanceof Box.Filler || + (c instanceof JComponent && clientPropertyBoolean( (JComponent) c, COMPONENT_TITLE_BAR_CAPTION, false ) ) ) + { + // If menu bar is embedded and contains a horizontal glue or caption component, + // then split the hit test spot so that + // the glue/caption component area can be used to move the window. - Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window ); - int x2 = glueLocation.x + horizontalGlue.getWidth(); - Rectangle r2; - if( getComponentOrientation().isLeftToRight() ) { - r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height ); + Point glueLocation = SwingUtilities.convertPoint( c, 0, 0, window ); + int x2 = glueLocation.x + c.getWidth(); + Rectangle r2; + if( getComponentOrientation().isLeftToRight() ) { + r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height ); - r.width = glueLocation.x - r.x; - } else { - r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height ); + r.width = glueLocation.x - r.x; + } else { + r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height ); - r.width = (r.x + r.width) - x2; - r.x = x2; + r.width = (r.x + r.width) - x2; + r.x = x2; + } + if( r2.width > 0 ) + hitTestSpots.add( r2 ); } - hitTestSpots.add( r2 ); } hitTestSpots.add( r ); 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 c7e2937f..e605dd3c 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 @@ -262,6 +262,16 @@ debug*/ menuBar.revalidate(); } + private void addCaption() { + JLabel caption = new JLabel( "Caption" ); + caption.setBackground( Color.green ); + caption.setOpaque( true ); + caption.putClientProperty( FlatClientProperties.COMPONENT_TITLE_BAR_CAPTION, true ); + + menuBar.add( caption ); + menuBar.revalidate(); + } + private void removeMenu() { int menuCount = menuBar.getMenuCount(); if( menuCount <= 0 ) @@ -445,6 +455,7 @@ debug*/ JPanel panel3 = new JPanel(); addMenuButton = new JButton(); addGlueButton = new JButton(); + addCaptionButton = new JButton(); removeMenuButton = new JButton(); changeMenuButton = new JButton(); changeTitleButton = new JButton(); @@ -547,6 +558,7 @@ debug*/ "[]" + "[]" + "[]" + + "[]" + "[]unrel" + "[]")); @@ -560,20 +572,25 @@ debug*/ addGlueButton.addActionListener(e -> addGlue()); panel3.add(addGlueButton, "cell 0 1"); + //---- addCaptionButton ---- + addCaptionButton.setText("Add caption"); + addCaptionButton.addActionListener(e -> addCaption()); + panel3.add(addCaptionButton, "cell 0 2"); + //---- removeMenuButton ---- removeMenuButton.setText("Remove menu"); removeMenuButton.addActionListener(e -> removeMenu()); - panel3.add(removeMenuButton, "cell 0 2"); + panel3.add(removeMenuButton, "cell 0 3"); //---- changeMenuButton ---- changeMenuButton.setText("Change menu"); changeMenuButton.addActionListener(e -> changeMenu()); - panel3.add(changeMenuButton, "cell 0 3"); + panel3.add(changeMenuButton, "cell 0 4"); //---- changeTitleButton ---- changeTitleButton.setText("Change title"); changeTitleButton.addActionListener(e -> changeTitle()); - panel3.add(changeTitleButton, "cell 0 4"); + panel3.add(changeTitleButton, "cell 0 5"); } add(panel3, "cell 2 0 1 8,aligny top,growy 0"); @@ -961,6 +978,7 @@ debug*/ private JCheckBox rightCompCheckBox; private JButton addMenuButton; private JButton addGlueButton; + private JButton addCaptionButton; private JButton removeMenuButton; private JButton changeMenuButton; private JButton changeTitleButton; 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 c5aa442e..048d768f 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 @@ -36,7 +36,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "hidemode 3" "$columnConstraints": "[fill]" - "$rowConstraints": "[][][][]unrel[]" + "$rowConstraints": "[][][][][]unrel[]" } ) { name: "panel3" add( new FormComponent( "javax.swing.JButton" ) { @@ -59,6 +59,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 1" } ) + add( new FormComponent( "javax.swing.JButton" ) { + name: "addCaptionButton" + "text": "Add caption" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addCaption", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) add( new FormComponent( "javax.swing.JButton" ) { name: "removeMenuButton" "text": "Remove menu" @@ -67,7 +77,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 2" + "value": "cell 0 3" } ) add( new FormComponent( "javax.swing.JButton" ) { name: "changeMenuButton" @@ -77,7 +87,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 3" + "value": "cell 0 4" } ) add( new FormComponent( "javax.swing.JButton" ) { name: "changeTitleButton" @@ -87,7 +97,7 @@ new FormModel { } addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 4" + "value": "cell 0 5" } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 0 1 8,aligny top,growy 0"