mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
support painting separator line between window title and content (issue #184)
This commit is contained in:
@@ -3,6 +3,12 @@ FlatLaf Change Log
|
|||||||
|
|
||||||
## 0.44-SNAPSHOT
|
## 0.44-SNAPSHOT
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- Support painting separator line between window title and content (use UI value
|
||||||
|
`TitlePane.borderColor`). (issue #184)
|
||||||
|
|
||||||
|
|
||||||
#### Fixed bugs
|
#### Fixed bugs
|
||||||
|
|
||||||
- Custom window decorations: Not visible menu bar is now ignored in layout.
|
- Custom window decorations: Not visible menu bar is now ignored in layout.
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ import static com.formdev.flatlaf.util.UIScale.scale;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
@@ -40,16 +38,8 @@ public class FlatMenuBarBorder
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
float lineHeight = scale( (float) 1 );
|
||||||
try {
|
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||||
float lineHeight = scale( (float) 1 );
|
|
||||||
|
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
|
||||||
g2.setColor( borderColor );
|
|
||||||
g2.fill( new Rectangle2D.Float( x, y + height - lineHeight, width, lineHeight ) );
|
|
||||||
} finally {
|
|
||||||
g2.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import javax.swing.JMenuBar;
|
|||||||
import javax.swing.JRootPane;
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.BorderUIResource;
|
import javax.swing.plaf.BorderUIResource;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
@@ -45,6 +46,7 @@ import com.formdev.flatlaf.FlatClientProperties;
|
|||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}.
|
||||||
@@ -54,6 +56,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @uiDefault RootPane.border Border
|
* @uiDefault RootPane.border Border
|
||||||
* @uiDefault RootPane.activeBorderColor Color
|
* @uiDefault RootPane.activeBorderColor Color
|
||||||
* @uiDefault RootPane.inactiveBorderColor Color
|
* @uiDefault RootPane.inactiveBorderColor Color
|
||||||
|
* @uiDefault TitlePane.borderColor Color optional
|
||||||
*
|
*
|
||||||
* <!-- FlatWindowResizer -->
|
* <!-- FlatWindowResizer -->
|
||||||
*
|
*
|
||||||
@@ -71,6 +74,8 @@ public class FlatRootPaneUI
|
|||||||
static final boolean canUseJBRCustomDecorations
|
static final boolean canUseJBRCustomDecorations
|
||||||
= SystemInfo.isJetBrainsJVM_11_orLater && SystemInfo.isWindows_10_orLater;
|
= SystemInfo.isJetBrainsJVM_11_orLater && SystemInfo.isWindows_10_orLater;
|
||||||
|
|
||||||
|
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
||||||
|
|
||||||
protected JRootPane rootPane;
|
protected JRootPane rootPane;
|
||||||
protected FlatTitlePane titlePane;
|
protected FlatTitlePane titlePane;
|
||||||
protected FlatWindowResizer windowResizer;
|
protected FlatWindowResizer windowResizer;
|
||||||
@@ -89,11 +94,21 @@ public class FlatRootPaneUI
|
|||||||
|
|
||||||
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE )
|
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE )
|
||||||
installClientDecorations();
|
installClientDecorations();
|
||||||
|
else
|
||||||
|
installBorder();
|
||||||
|
|
||||||
if( canUseJBRCustomDecorations )
|
if( canUseJBRCustomDecorations )
|
||||||
JBRCustomDecorations.install( rootPane );
|
JBRCustomDecorations.install( rootPane );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void installBorder() {
|
||||||
|
if( borderColor != null ) {
|
||||||
|
Border b = rootPane.getBorder();
|
||||||
|
if( b == null || b instanceof UIResource )
|
||||||
|
rootPane.setBorder( new FlatWindowTitleBorder( borderColor ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uninstallUI( JComponent c ) {
|
public void uninstallUI( JComponent c ) {
|
||||||
super.uninstallUI( c );
|
super.uninstallUI( c );
|
||||||
@@ -119,11 +134,8 @@ public class FlatRootPaneUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enable dark window appearance on macOS when running in JetBrains Runtime
|
// enable dark window appearance on macOS when running in JetBrains Runtime
|
||||||
if( SystemInfo.isJetBrainsJVM && SystemInfo.isMacOS_10_14_Mojave_orLater ) {
|
if( SystemInfo.isJetBrainsJVM && SystemInfo.isMacOS_10_14_Mojave_orLater )
|
||||||
LookAndFeel laf = UIManager.getLookAndFeel();
|
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", FlatLaf.isLafDark() );
|
||||||
boolean isDark = laf instanceof FlatLaf && ((FlatLaf)laf).isDark();
|
|
||||||
c.putClientProperty( "jetbrains.awt.windowDarkAppearance", isDark );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void installClientDecorations() {
|
protected void installClientDecorations() {
|
||||||
@@ -203,6 +215,8 @@ public class FlatRootPaneUI
|
|||||||
uninstallClientDecorations();
|
uninstallClientDecorations();
|
||||||
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE )
|
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE )
|
||||||
installClientDecorations();
|
installClientDecorations();
|
||||||
|
else
|
||||||
|
installBorder();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FlatClientProperties.MENU_BAR_EMBEDDED:
|
case FlatClientProperties.MENU_BAR_EMBEDDED:
|
||||||
@@ -373,4 +387,40 @@ public class FlatRootPaneUI
|
|||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatWindowTitleBorder ----------------------------------------
|
||||||
|
|
||||||
|
private static class FlatWindowTitleBorder
|
||||||
|
extends BorderUIResource.EmptyBorderUIResource
|
||||||
|
{
|
||||||
|
private final Color borderColor;
|
||||||
|
|
||||||
|
FlatWindowTitleBorder( Color borderColor ) {
|
||||||
|
super( 0, 0, 0, 0 );
|
||||||
|
this.borderColor = borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
if( showBorder( c ) ) {
|
||||||
|
float lineHeight = UIScale.scale( (float) 1 );
|
||||||
|
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y, width, lineHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
|
insets.set( showBorder( c ) ? 1 : 0, 0, 0, 0 );
|
||||||
|
return insets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean showBorder( Component c ) {
|
||||||
|
Container parent = c.getParent();
|
||||||
|
return
|
||||||
|
(parent instanceof JFrame &&
|
||||||
|
(((JFrame)parent).getJMenuBar() == null ||
|
||||||
|
!((JFrame)parent).getJMenuBar().isVisible())) ||
|
||||||
|
parent instanceof JDialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TitlePane.foreground Color
|
* @uiDefault TitlePane.foreground Color
|
||||||
* @uiDefault TitlePane.inactiveForeground Color
|
* @uiDefault TitlePane.inactiveForeground Color
|
||||||
* @uiDefault TitlePane.embeddedForeground Color
|
* @uiDefault TitlePane.embeddedForeground Color
|
||||||
|
* @uiDefault TitlePane.borderColor Color optional
|
||||||
* @uiDefault TitlePane.iconSize Dimension
|
* @uiDefault TitlePane.iconSize Dimension
|
||||||
* @uiDefault TitlePane.iconMargins Insets
|
* @uiDefault TitlePane.iconMargins Insets
|
||||||
* @uiDefault TitlePane.titleMargins Insets
|
* @uiDefault TitlePane.titleMargins Insets
|
||||||
@@ -97,6 +98,7 @@ public class FlatTitlePane
|
|||||||
protected final Color activeForeground = UIManager.getColor( "TitlePane.foreground" );
|
protected final Color activeForeground = UIManager.getColor( "TitlePane.foreground" );
|
||||||
protected final Color inactiveForeground = UIManager.getColor( "TitlePane.inactiveForeground" );
|
protected final Color inactiveForeground = UIManager.getColor( "TitlePane.inactiveForeground" );
|
||||||
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
||||||
|
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
||||||
|
|
||||||
protected final Insets menuBarMargins = UIManager.getInsets( "TitlePane.menuBarMargins" );
|
protected final Insets menuBarMargins = UIManager.getInsets( "TitlePane.menuBarMargins" );
|
||||||
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
||||||
@@ -422,6 +424,10 @@ public class FlatTitlePane
|
|||||||
protected void menuBarChanged() {
|
protected void menuBarChanged() {
|
||||||
menuBarPlaceholder.invalidate();
|
menuBarPlaceholder.invalidate();
|
||||||
|
|
||||||
|
// necessary for the case that an embedded menu bar is made invisible
|
||||||
|
// and a border color is specified
|
||||||
|
repaint();
|
||||||
|
|
||||||
// update title foreground color
|
// update title foreground color
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
activeChanged( window == null || window.isActive() );
|
activeChanged( window == null || window.isActive() );
|
||||||
@@ -662,12 +668,13 @@ debug*/
|
|||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
super.getBorderInsets( c, insets );
|
super.getBorderInsets( c, insets );
|
||||||
|
|
||||||
// if menu bar is embedded, add bottom insets of menu bar border
|
|
||||||
Border menuBarBorder = getMenuBarBorder();
|
Border menuBarBorder = getMenuBarBorder();
|
||||||
if( menuBarBorder != null ) {
|
if( menuBarBorder != null ) {
|
||||||
|
// if menu bar is embedded, add bottom insets of menu bar border
|
||||||
Insets menuBarInsets = menuBarBorder.getBorderInsets( c );
|
Insets menuBarInsets = menuBarBorder.getBorderInsets( c );
|
||||||
insets.bottom += menuBarInsets.bottom;
|
insets.bottom += menuBarInsets.bottom;
|
||||||
}
|
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) )
|
||||||
|
insets.bottom += UIScale.scale( 1 );
|
||||||
|
|
||||||
if( hasJBRCustomDecoration() )
|
if( hasJBRCustomDecoration() )
|
||||||
insets = FlatUIUtils.addInsets( insets, JBRWindowTopBorder.getInstance().getBorderInsets() );
|
insets = FlatUIUtils.addInsets( insets, JBRWindowTopBorder.getInstance().getBorderInsets() );
|
||||||
@@ -677,10 +684,16 @@ debug*/
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
// if menu bar is embedded, paint menu bar border
|
// paint bottom border
|
||||||
Border menuBarBorder = getMenuBarBorder();
|
Border menuBarBorder = getMenuBarBorder();
|
||||||
if( menuBarBorder != null )
|
if( menuBarBorder != null ) {
|
||||||
|
// if menu bar is embedded, paint menu bar border
|
||||||
menuBarBorder.paintBorder( c, g, x, y, width, height );
|
menuBarBorder.paintBorder( c, g, x, y, width, height );
|
||||||
|
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) ) {
|
||||||
|
// paint border between title pane and content if border color is specified
|
||||||
|
float lineHeight = UIScale.scale( (float) 1 );
|
||||||
|
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||||
|
}
|
||||||
|
|
||||||
if( hasJBRCustomDecoration() )
|
if( hasJBRCustomDecoration() )
|
||||||
JBRWindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
|
JBRWindowTopBorder.getInstance().paintBorder( c, g, x, y, width, height );
|
||||||
|
|||||||
@@ -379,6 +379,17 @@ public class FlatUIUtils
|
|||||||
return new RoundRectangle2D.Float( x, y, w, h, arc, arc );
|
return new RoundRectangle2D.Float( x, y, w, h, arc, arc );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void paintFilledRectangle( Graphics g, Color color, float x, float y, float w, float h ) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
try {
|
||||||
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
g2.setColor( color );
|
||||||
|
g2.fill( new Rectangle2D.Float( x, y, w, h ) );
|
||||||
|
} finally {
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill background with parent's background color because the visible component
|
* Fill background with parent's background color because the visible component
|
||||||
* is smaller than its bounds (for the focus decoration).
|
* is smaller than its bounds (for the focus decoration).
|
||||||
|
|||||||
Reference in New Issue
Block a user