From 7d0bdf3b9e5678f79639f85235e1adc006d9dfc2 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Tue, 14 Nov 2023 10:38:28 +0100 Subject: [PATCH] OptionPane: fixed styling custom panel background in `JOptionPane` (issue #761) --- CHANGELOG.md | 2 + .../formdev/flatlaf/ui/FlatOptionPaneUI.java | 55 ++++++++++++------- .../flatlaf/testing/FlatOptionPaneTest.java | 4 ++ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0df44842..99d635f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ FlatLaf Change Log foreground color. (issue 756) - Table: Switching theme looses table grid and intercell spacing. (issues #733 and #750) +- OptionPane: Fixed styling custom panel background in `JOptionPane`. (issue + #761) ## 3.2.5 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java index e1c8e69a..d6b74624 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatOptionPaneUI.java @@ -30,9 +30,7 @@ import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; -import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.basic.BasicOptionPaneUI; import com.formdev.flatlaf.FlatClientProperties; @@ -115,13 +113,6 @@ public class FlatOptionPaneUI sameSizeButtons = FlatUIUtils.getUIBoolean( "OptionPane.sameSizeButtons", true ); } - @Override - protected void installComponents() { - super.installComponents(); - - updateChildPanels( optionPane ); - } - @Override protected PropertyChangeListener createPropertyChangeListener() { PropertyChangeListener superListener = super.createPropertyChangeListener(); @@ -155,6 +146,13 @@ public class FlatOptionPaneUI protected Container createMessageArea() { Container messageArea = super.createMessageArea(); + // use non-UIResource OptionPane.messageAreaBorder to avoid that it is replaced when switching LaF + // and make panel non-opaque for OptionPane.background + updateAreaPanel( messageArea ); + + // make known sub-panels non-opaque for OptionPane.background + updateKnownChildPanels( messageArea ); + // set icon-message gap if( iconMessageGap > 0 ) { Component iconMessageSeparator = SwingUtils.getComponentByName( messageArea, "OptionPane.separator" ); @@ -169,6 +167,10 @@ public class FlatOptionPaneUI protected Container createButtonArea() { Container buttonArea = super.createButtonArea(); + // use non-UIResource OptionPane.buttonAreaBorder to avoid that it is replaced when switching LaF + // and make panel non-opaque for OptionPane.background + updateAreaPanel( buttonArea ); + // scale button padding and subtract focusWidth if( buttonArea.getLayout() instanceof ButtonAreaLayout ) { ButtonAreaLayout layout = (ButtonAreaLayout) buttonArea.getLayout(); @@ -218,22 +220,33 @@ public class FlatOptionPaneUI super.addMessageComponents( container, cons, msg, maxll, internallyCreated ); } - private void updateChildPanels( Container c ) { + private void updateAreaPanel( Container area ) { + if( !(area instanceof JPanel) ) + return; + + // use non-UIResource border to avoid that it is replaced when switching LaF + // and make panel non-opaque for OptionPane.background + JPanel panel = (JPanel) area; + panel.setBorder( FlatUIUtils.nonUIResource( panel.getBorder() ) ); + panel.setOpaque( false ); + } + + private void updateKnownChildPanels( Container c ) { for( Component child : c.getComponents() ) { - if( child.getClass() == JPanel.class ) { - JPanel panel = (JPanel)child; - - // make sub-panel non-opaque for OptionPane.background - panel.setOpaque( false ); - - // use non-UIResource borders to avoid that they are replaced when switching LaF - Border border = panel.getBorder(); - if( border instanceof UIResource ) - panel.setBorder( FlatUIUtils.nonUIResource( border ) ); + if( child instanceof JPanel && child.getName() != null ) { + switch( child.getName() ) { + case "OptionPane.realBody": + case "OptionPane.body": + case "OptionPane.separator": + case "OptionPane.break": + // make known sub-panels non-opaque for OptionPane.background + ((JPanel)child).setOpaque( false ); + break; + } } if( child instanceof Container ) - updateChildPanels( (Container) child ); + updateKnownChildPanels( (Container) child ); } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java index 4a832fcf..9eb2f325 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatOptionPaneTest.java @@ -41,11 +41,15 @@ public class FlatOptionPaneTest FlatOptionPaneTest() { initComponents(); + JPanel panel = new JPanel(); + panel.setBackground( Color.green ); + panel.add( new JLabel( "label in green panel" ) ); customOptionPane.setMessage( new Object[] { "string", "multi-\nline string", new JCheckBox( "check box" ), new JTextField( "text field" ), + panel, "more text", } ); customOptionPane.setOptions( new Object[] {