Window decorations: support unified backgrounds for window title bar, menu bar and main content (issue #254)

This commit is contained in:
Karl Tauber
2021-03-14 15:13:26 +01:00
parent 30c7b442a8
commit 035a13df54
13 changed files with 217 additions and 109 deletions

View File

@@ -23,14 +23,16 @@ import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicMenuBarUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.SystemInfo;
@@ -43,12 +45,15 @@ import com.formdev.flatlaf.util.SystemInfo;
* @uiDefault MenuBar.background Color
* @uiDefault MenuBar.foreground Color
* @uiDefault MenuBar.border Border
* @uiDefault TitlePane.unifiedBackground boolean
*
* @author Karl Tauber
*/
public class FlatMenuBarUI
extends BasicMenuBarUI
{
protected boolean unifiedBackground;
public static ComponentUI createUI( JComponent c ) {
return new FlatMenuBarUI();
}
@@ -63,6 +68,8 @@ public class FlatMenuBarUI
super.installDefaults();
LookAndFeel.installProperty( menuBar, "opaque", false );
unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
}
@Override
@@ -80,9 +87,7 @@ public class FlatMenuBarUI
@Override
public void update( Graphics g, JComponent c ) {
// do not fill background if menubar is embedded into title pane
if( c.isOpaque() ||
!FlatClientProperties.clientPropertyBoolean( menuBar, "flatlaf.internal.menuBarEmbedded", false ) )
{
if( isFillBackground( c ) ) {
g.setColor( c.getBackground() );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
@@ -90,6 +95,24 @@ public class FlatMenuBarUI
paint( g, c );
}
protected boolean isFillBackground( JComponent c ) {
// paint background in opaque or having custom background color
if( c.isOpaque() || !(c.getBackground() instanceof UIResource) )
return true;
// do not paint background for unified title pane
if( unifiedBackground )
return false;
// paint background in full screen mode
JRootPane rootPane = SwingUtilities.getRootPane( c );
if( rootPane == null || FlatUIUtils.isFullScreen( rootPane ) )
return true;
// do not paint background if menu bar is embedded into title pane
return rootPane.getJMenuBar() != c || !FlatRootPaneUI.isMenuBarEmbedded( rootPane );
}
//---- class TakeFocus ----------------------------------------------------
/**

View File

@@ -40,6 +40,7 @@ import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.RootPaneUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicRootPaneUI;
import com.formdev.flatlaf.FlatClientProperties;
@@ -227,6 +228,13 @@ public class FlatRootPaneUI
}
}
protected static boolean isMenuBarEmbedded( JRootPane rootPane ) {
RootPaneUI ui = rootPane.getUI();
return ui instanceof FlatRootPaneUI &&
((FlatRootPaneUI)ui).titlePane != null &&
((FlatRootPaneUI)ui).titlePane.isMenuBarEmbedded();
}
//---- class FlatRootLayout -----------------------------------------------
protected class FlatRootLayout
@@ -297,10 +305,10 @@ public class FlatRootPaneUI
rootPane.getGlassPane().setBounds( x, y, width, height );
int nextY = 0;
if( !isFullScreen && titlePane != null ) {
Dimension prefSize = titlePane.getPreferredSize();
titlePane.setBounds( 0, 0, width, prefSize.height );
nextY += prefSize.height;
if( titlePane != null ) {
int prefHeight = !isFullScreen ? titlePane.getPreferredSize().height : 0;
titlePane.setBounds( 0, 0, width, prefHeight );
nextY += prefHeight;
}
JMenuBar menuBar = rootPane.getJMenuBar();
@@ -314,9 +322,6 @@ public class FlatRootPaneUI
menuBar.setBounds( 0, nextY, width, prefSize.height );
nextY += prefSize.height;
}
// mark menubar as embedded, which is used when painting menubar background
menuBar.putClientProperty( "flatlaf.internal.menuBarEmbedded", embedded ? true : null );
}
Container contentPane = rootPane.getContentPane();
@@ -346,6 +351,9 @@ public class FlatRootPaneUI
//---- class FlatWindowBorder ---------------------------------------------
/**
* Window border used for non-native window decorations.
*/
public static class FlatWindowBorder
extends BorderUIResource.EmptyBorderUIResource
{
@@ -360,7 +368,7 @@ public class FlatRootPaneUI
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
if( isWindowMaximized( c ) || FlatUIUtils.isFullScreen( c ) ) {
// hide border if window is maximized
// hide border if window is maximized or full screen
insets.top = insets.left = insets.bottom = insets.right = 0;
return insets;
} else

View File

@@ -78,6 +78,7 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TitlePane.inactiveForeground Color
* @uiDefault TitlePane.embeddedForeground Color
* @uiDefault TitlePane.borderColor Color optional
* @uiDefault TitlePane.unifiedBackground boolean
* @uiDefault TitlePane.iconSize Dimension
* @uiDefault TitlePane.iconMargins Insets
* @uiDefault TitlePane.titleMargins Insets
@@ -103,6 +104,7 @@ public class FlatTitlePane
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
protected final boolean unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
@@ -511,8 +513,10 @@ debug*/
@Override
protected void paintComponent( Graphics g ) {
g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
if( !unifiedBackground ) {
g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() );
}
}
protected void repaintWindowBorder() {

View File

@@ -687,6 +687,7 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground
TitlePane.useWindowDecorations = true
TitlePane.menuBarEmbedded = true
TitlePane.unifiedBackground = false
TitlePane.iconSize = 16,16
TitlePane.iconMargins = 3,8,3,8
TitlePane.titleMargins = 3,0,3,0