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 c812f993..db5fa9c5 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 @@ -48,11 +48,25 @@ import com.formdev.flatlaf.util.SystemInfo; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}. * + * + * + * @uiDefault RootPane.border Border + * + * + * + * @uiDefault RootPane.borderDragThickness int + * @uiDefault RootPane.cornerDragWidth int + * @uiDefault RootPane.honorMinimumSizeOnResize boolean + * * @author Karl Tauber */ public class FlatRootPaneUI extends BasicRootPaneUI { + // check this field before using class JBRCustomDecorations to avoid unnecessary loading of that class + static final boolean canUseJBRCustomDecorations + = SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER && SystemInfo.IS_WINDOWS_10_OR_LATER; + private JRootPane rootPane; private FlatTitlePane titlePane; private LayoutManager oldLayout; @@ -71,7 +85,7 @@ public class FlatRootPaneUI if( rootPane.getWindowDecorationStyle() != JRootPane.NONE ) installClientDecorations(); - if( SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER && SystemInfo.IS_WINDOWS_10_OR_LATER ) + if( canUseJBRCustomDecorations ) JBRCustomDecorations.install( rootPane ); } @@ -108,8 +122,10 @@ public class FlatRootPaneUI } private void installClientDecorations() { + boolean isJBRSupported = canUseJBRCustomDecorations && JBRCustomDecorations.isSupported(); + // install border - if( rootPane.getWindowDecorationStyle() != JRootPane.NONE && !JBRCustomDecorations.isSupported() ) + if( rootPane.getWindowDecorationStyle() != JRootPane.NONE && !isJBRSupported ) LookAndFeel.installBorder( rootPane, "RootPane.border" ); else LookAndFeel.uninstallBorder( rootPane ); @@ -122,7 +138,7 @@ public class FlatRootPaneUI rootPane.setLayout( new FlatRootLayout() ); // install window resizer - if( !JBRCustomDecorations.isSupported() ) + if( !isJBRSupported ) windowResizer = new FlatWindowResizer( rootPane ); } 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 399d1949..793027cd 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 @@ -446,7 +446,9 @@ class FlatTitlePane } private boolean hasJBRCustomDecoration() { - return window != null && JBRCustomDecorations.hasCustomDecoration( window ); + return window != null && + FlatRootPaneUI.canUseJBRCustomDecorations && + JBRCustomDecorations.hasCustomDecoration( window ); } private void updateJBRHitTestSpotsAndTitleBarHeight() { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java index 2ded0eb8..d06069f8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/JBRCustomDecorations.java @@ -68,65 +68,26 @@ public class JBRCustomDecorations } static void install( JRootPane rootPane ) { - boolean frameIsDefaultLookAndFeelDecorated = JFrame.isDefaultLookAndFeelDecorated(); - boolean dialogIsDefaultLookAndFeelDecorated = JDialog.isDefaultLookAndFeelDecorated(); - boolean lafSupportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations(); - - // check whether decorations are enabled - if( !frameIsDefaultLookAndFeelDecorated && !dialogIsDefaultLookAndFeelDecorated ) - return; - - // do not enable JBR decorations if JFrame and JDialog will use LaF decorations - if( lafSupportsWindowDecorations && - frameIsDefaultLookAndFeelDecorated && - dialogIsDefaultLookAndFeelDecorated ) - return; - if( !isSupported() ) return; - // use hierarchy listener to wait until the root pane is added to a window + // check whether root pane already has a parent, which is the case when switching LaF + if( rootPane.getParent() != null ) + return; + + // Use hierarchy listener to wait until the root pane is added to a window. + // Enabling JBR decorations must be done very early, probably before + // window becomes displayable (window.isDisplayable()). Tried also using + // "ancestor" property change event on root pane, but this is invoked too late. HierarchyListener addListener = new HierarchyListener() { @Override public void hierarchyChanged( HierarchyEvent e ) { - if( (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0 ) + if( e.getChanged() != rootPane || (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0 ) return; Container parent = e.getChangedParent(); - if( parent instanceof JFrame ) { - JFrame frame = (JFrame) parent; - - // do not enable JBR decorations if JFrame will use LaF decorations - if( lafSupportsWindowDecorations && frameIsDefaultLookAndFeelDecorated ) - return; - - // do not enable JBR decorations if frame is undecorated - if( frame.isUndecorated() ) - return; - - // enable JBR custom window decoration for window - setHasCustomDecoration( frame ); - - // enable Swing window decoration - rootPane.setWindowDecorationStyle( JRootPane.FRAME ); - - } else if( parent instanceof JDialog ) { - JDialog dialog = (JDialog)parent; - - // do not enable JBR decorations if JDialog will use LaF decorations - if( lafSupportsWindowDecorations && dialogIsDefaultLookAndFeelDecorated ) - return; - - // do not enable JBR decorations if dialog is undecorated - if( dialog.isUndecorated() ) - return; - - // enable JBR custom window decoration for window - setHasCustomDecoration( dialog ); - - // enable Swing window decoration - rootPane.setWindowDecorationStyle( JRootPane.PLAIN_DIALOG ); - } + if( parent instanceof Window ) + install( (Window) parent ); // use invokeLater to remove listener to avoid that listener // is removed while listener queue is processed @@ -138,6 +99,50 @@ public class JBRCustomDecorations rootPane.addHierarchyListener( addListener ); } + static void install( Window window ) { + if( !isSupported() ) + return; + + // do not enable JBR decorations if LaF provides decorations + if( UIManager.getLookAndFeel().getSupportsWindowDecorations() ) + return; + + if( window instanceof JFrame ) { + JFrame frame = (JFrame) window; + + // do not enable JBR decorations if JFrame should use system window decorations + if( !JFrame.isDefaultLookAndFeelDecorated() ) + return; + + // do not enable JBR decorations if frame is undecorated + if( frame.isUndecorated() ) + return; + + // enable JBR custom window decoration for window + setHasCustomDecoration( frame ); + + // enable Swing window decoration + frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME ); + + } else if( window instanceof JDialog ) { + JDialog dialog = (JDialog) window; + + // do not enable JBR decorations if JDialog should use system window decorations + if( !JDialog.isDefaultLookAndFeelDecorated() ) + return; + + // do not enable JBR decorations if dialog is undecorated + if( dialog.isUndecorated() ) + return; + + // enable JBR custom window decoration for window + setHasCustomDecoration( dialog ); + + // enable Swing window decoration + dialog.getRootPane().setWindowDecorationStyle( JRootPane.PLAIN_DIALOG ); + } + } + static boolean hasCustomDecoration( Window window ) { if( !isSupported() ) return false;