diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java index 8a5dd591..463ebe42 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java @@ -25,7 +25,9 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.GridLayout; import java.awt.Insets; +import java.awt.LayoutManager; import java.awt.Paint; import java.awt.Rectangle; import java.awt.event.InputEvent; @@ -35,6 +37,7 @@ import java.util.Map; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; +import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; @@ -222,7 +225,7 @@ public class FlatMenuItemRenderer } // arrow size - if( !isTopLevelMenu && arrowIcon != null ) { + if( arrowIcon != null && (!isTopLevelMenu || isInVerticalMenuBar( menuItem )) ) { // gap between text and arrow if( accelText == null ) width += scale( textNoAcceleratorGap ); @@ -254,7 +257,8 @@ public class FlatMenuItemRenderer boolean isTopLevelMenu = isTopLevelMenu( menuItem ); // layout arrow - if( !isTopLevelMenu && arrowIcon != null ) { + boolean showArrowIcon = (arrowIcon != null && (!isTopLevelMenu || isInVerticalMenuBar( menuItem ))); + if( showArrowIcon ) { arrowRect.width = arrowIcon.getIconWidth(); arrowRect.height = arrowIcon.getIconHeight(); } else @@ -288,7 +292,7 @@ public class FlatMenuItemRenderer int accelArrowWidth = accelRect.width + arrowRect.width; if( accelText != null ) accelArrowWidth += scale( !isTopLevelMenu ? textAcceleratorGap : menuItem.getIconTextGap() ); - if( !isTopLevelMenu && arrowIcon != null ) { + if( showArrowIcon ) { if( accelText == null ) accelArrowWidth += scale( textNoAcceleratorGap ); accelArrowWidth += scale( acceleratorArrowGap ); @@ -355,7 +359,7 @@ debug*/ paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground, selectionBackground ); paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground ); paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground ); - if( !isTopLevelMenu( menuItem ) ) + if( arrowIcon != null && (!isTopLevelMenu( menuItem ) || isInVerticalMenuBar( menuItem )) ) paintArrowIcon( g, arrowRect, arrowIcon ); } @@ -520,6 +524,15 @@ debug*/ return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu(); } + /** @since 3.5 */ + public static boolean isInVerticalMenuBar( JMenuItem menuItem ) { + if( !(menuItem instanceof JMenu) || !(menuItem.getParent() instanceof JMenuBar) ) + return false; + + LayoutManager layout = menuItem.getParent().getLayout(); + return layout instanceof GridLayout && ((GridLayout)layout).getRows() != 1; + } + protected boolean isUnderlineSelection() { return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) ); } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.java index 2fe51c10..a9a91046 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.java @@ -22,6 +22,7 @@ import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.GridLayout; import java.awt.event.*; import java.util.function.Supplier; import javax.swing.*; @@ -49,6 +50,7 @@ public class FlatMenusTest initComponents(); largerCheckBox.setSelected( LargerMenuItem.useLargerSize ); + verticalMenuBar.setLayout( new GridLayout( 0, 1 ) ); } private void armedChanged() { @@ -246,7 +248,15 @@ public class FlatMenusTest JLabel popupMenuLabel = new JLabel(); JButton showPopupMenuButton = new JButton(); showScrollingPopupMenuButton = new JButton(); + JLabel label1 = new JLabel(); armedCheckBox = new JCheckBox(); + verticalMenuBar = new JMenuBar(); + JMenu menu14 = new JMenu(); + JMenuItem menuItem53 = new JMenuItem(); + JMenu menu15 = new JMenu(); + JMenuItem menuItem54 = new JMenuItem(); + JMenu menu16 = new JMenu(); + JMenuItem menuItem55 = new JMenuItem(); underlineCheckBox = new JCheckBox(); popupMenubackgroundCheckBox = new JCheckBox(); @@ -884,6 +894,10 @@ public class FlatMenusTest showScrollingPopupMenuButton.addActionListener(e -> showScrollingPopupMenu(e)); add(showScrollingPopupMenuButton, "cell 2 2"); + //---- label1 ---- + label1.setText("Vertical JMenuBar:"); + add(label1, "cell 4 2"); + //---- armedCheckBox ---- armedCheckBox.setText("armed"); armedCheckBox.setMnemonic('A'); @@ -891,6 +905,42 @@ public class FlatMenusTest armedCheckBox.addActionListener(e -> armedChanged()); add(armedCheckBox, "cell 0 3"); + //======== verticalMenuBar ======== + { + + //======== menu14 ======== + { + menu14.setText("menu"); + + //---- menuItem53 ---- + menuItem53.setText("text"); + menu14.add(menuItem53); + } + verticalMenuBar.add(menu14); + + //======== menu15 ======== + { + menu15.setText("another menu"); + + //---- menuItem54 ---- + menuItem54.setText("text"); + menu15.add(menuItem54); + } + verticalMenuBar.add(menu15); + + //======== menu16 ======== + { + menu16.setText("menu 3"); + menu16.setIcon(new ImageIcon(getClass().getResource("/com/formdev/flatlaf/testing/test16.png"))); + + //---- menuItem55 ---- + menuItem55.setText("text"); + menu16.add(menuItem55); + } + verticalMenuBar.add(menu16); + } + add(verticalMenuBar, "cell 4 3 1 3"); + //---- underlineCheckBox ---- underlineCheckBox.setText("underline menu selection"); underlineCheckBox.putClientProperty("FlatLaf.internal.testing.ignore", true); @@ -931,6 +981,7 @@ public class FlatMenusTest private JCheckBox accelCheckBox; private JButton showScrollingPopupMenuButton; private JCheckBox armedCheckBox; + private JMenuBar verticalMenuBar; private JCheckBox underlineCheckBox; private JCheckBox popupMenubackgroundCheckBox; // JFormDesigner - End of variables declaration //GEN-END:variables diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.jfd index e07f9af0..87379d5a 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatMenusTest.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.5.0.404" Java: "16" encoding: "UTF-8" +JFDML JFormDesigner: "8.2.3.0.386" Java: "21" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -662,6 +662,12 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 2 2" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label1" + "text": "Vertical JMenuBar:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 2" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "armedCheckBox" "text": "armed" @@ -674,6 +680,39 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 3" } ) + add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) { + name: "verticalMenuBar" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) { + name: "menu14" + "text": "menu" + add( new FormComponent( "javax.swing.JMenuItem" ) { + name: "menuItem53" + "text": "text" + } ) + } ) + add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) { + name: "menu15" + "text": "another menu" + add( new FormComponent( "javax.swing.JMenuItem" ) { + name: "menuItem54" + "text": "text" + } ) + } ) + add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) { + name: "menu16" + "text": "menu 3" + "icon": new com.jformdesigner.model.SwingIcon( 0, "/com/formdev/flatlaf/testing/test16.png" ) + add( new FormComponent( "javax.swing.JMenuItem" ) { + name: "menuItem55" + "text": "text" + } ) + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 3 1 3" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "underlineCheckBox" "text": "underline menu selection"