Merge pull request #268 from title-pane-improvements

Title pane improvements (Windows 10 only)
This commit is contained in:
Karl Tauber
2021-03-14 17:39:50 +01:00
15 changed files with 479 additions and 92 deletions

View File

@@ -5,10 +5,20 @@ FlatLaf Change Log
#### New features and improvements #### New features and improvements
- Native window decorations for Windows 10 enables dark frame/dialog title bar - Windows 10 only:
- Native window decorations for Windows 10 enables dark frame/dialog title bar
and embedded menu bar with all JREs, while still having native Windows 10 and embedded menu bar with all JREs, while still having native Windows 10
border drop shadows, resize behavior, window snapping and system window menu. border drop shadows, resize behavior, window snapping and system window
(PR #267) menu. (PR #267)
- Custom window decorations: Support right aligned components in `JFrame`
title bar with embedded menu bar (using `Box.createHorizontalGlue()`). (PR
#268)
- Custom window decorations: Improved centering of window title with embedded
menu bar. (PR #268; issue #252)
- Custom window decorations: Support unified backgrounds for window title bar,
menu bar and main content. If enabled with `UIManager.put(
"TitlePane.unifiedBackground", true );` then window title bar and menu bar
use same background color as main content. (PR #268; issue #254)
#### Fixed bugs #### Fixed bugs

View File

@@ -16,17 +16,22 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.awt.Graphics;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.ActionMap; import javax.swing.ActionMap;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuBar; import javax.swing.JMenuBar;
import javax.swing.JRootPane;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement; import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager; import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicMenuBarUI; import javax.swing.plaf.basic.BasicMenuBarUI;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
@@ -40,12 +45,15 @@ import com.formdev.flatlaf.util.SystemInfo;
* @uiDefault MenuBar.background Color * @uiDefault MenuBar.background Color
* @uiDefault MenuBar.foreground Color * @uiDefault MenuBar.foreground Color
* @uiDefault MenuBar.border Border * @uiDefault MenuBar.border Border
* @uiDefault TitlePane.unifiedBackground boolean
* *
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatMenuBarUI public class FlatMenuBarUI
extends BasicMenuBarUI extends BasicMenuBarUI
{ {
protected boolean unifiedBackground;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatMenuBarUI(); return new FlatMenuBarUI();
} }
@@ -55,6 +63,15 @@ public class FlatMenuBarUI
* Do not add any functionality here. * Do not add any functionality here.
*/ */
@Override
protected void installDefaults() {
super.installDefaults();
LookAndFeel.installProperty( menuBar, "opaque", false );
unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
}
@Override @Override
protected void installKeyboardActions() { protected void installKeyboardActions() {
super.installKeyboardActions(); super.installKeyboardActions();
@@ -67,6 +84,35 @@ public class FlatMenuBarUI
map.put( "takeFocus", new TakeFocus() ); map.put( "takeFocus", new TakeFocus() );
} }
@Override
public void update( Graphics g, JComponent c ) {
// do not fill background if menubar is embedded into title pane
if( isFillBackground( c ) ) {
g.setColor( c.getBackground() );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
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 ---------------------------------------------------- //---- class TakeFocus ----------------------------------------------------
/** /**

View File

@@ -40,6 +40,7 @@ import javax.swing.UIManager;
import javax.swing.border.Border; 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.RootPaneUI;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicRootPaneUI; import javax.swing.plaf.basic.BasicRootPaneUI;
import com.formdev.flatlaf.FlatClientProperties; 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 ----------------------------------------------- //---- class FlatRootLayout -----------------------------------------------
protected class FlatRootLayout protected class FlatRootLayout
@@ -297,15 +305,16 @@ public class FlatRootPaneUI
rootPane.getGlassPane().setBounds( x, y, width, height ); rootPane.getGlassPane().setBounds( x, y, width, height );
int nextY = 0; int nextY = 0;
if( !isFullScreen && titlePane != null ) { if( titlePane != null ) {
Dimension prefSize = titlePane.getPreferredSize(); int prefHeight = !isFullScreen ? titlePane.getPreferredSize().height : 0;
titlePane.setBounds( 0, 0, width, prefSize.height ); titlePane.setBounds( 0, 0, width, prefHeight );
nextY += prefSize.height; nextY += prefHeight;
} }
JMenuBar menuBar = rootPane.getJMenuBar(); JMenuBar menuBar = rootPane.getJMenuBar();
if( menuBar != null && menuBar.isVisible() ) { if( menuBar != null && menuBar.isVisible() ) {
if( !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded() ) { boolean embedded = !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded();
if( embedded ) {
titlePane.validate(); titlePane.validate();
menuBar.setBounds( titlePane.getMenuBarBounds() ); menuBar.setBounds( titlePane.getMenuBarBounds() );
} else { } else {
@@ -342,6 +351,9 @@ public class FlatRootPaneUI
//---- class FlatWindowBorder --------------------------------------------- //---- class FlatWindowBorder ---------------------------------------------
/**
* Window border used for non-native window decorations.
*/
public static class FlatWindowBorder public static class FlatWindowBorder
extends BorderUIResource.EmptyBorderUIResource extends BorderUIResource.EmptyBorderUIResource
{ {
@@ -356,7 +368,7 @@ public class FlatRootPaneUI
@Override @Override
public Insets getBorderInsets( Component c, Insets insets ) { public Insets getBorderInsets( Component c, Insets insets ) {
if( isWindowMaximized( c ) || FlatUIUtils.isFullScreen( c ) ) { 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; insets.top = insets.left = insets.bottom = insets.right = 0;
return insets; return insets;
} else } else

View File

@@ -47,6 +47,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleContext;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout; import javax.swing.BoxLayout;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@@ -77,12 +78,15 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TitlePane.inactiveForeground Color * @uiDefault TitlePane.inactiveForeground Color
* @uiDefault TitlePane.embeddedForeground Color * @uiDefault TitlePane.embeddedForeground Color
* @uiDefault TitlePane.borderColor Color optional * @uiDefault TitlePane.borderColor Color optional
* @uiDefault TitlePane.unifiedBackground boolean
* @uiDefault TitlePane.iconSize Dimension * @uiDefault TitlePane.iconSize Dimension
* @uiDefault TitlePane.iconMargins Insets * @uiDefault TitlePane.iconMargins Insets
* @uiDefault TitlePane.titleMargins Insets * @uiDefault TitlePane.titleMargins Insets
* @uiDefault TitlePane.menuBarMargins Insets
* @uiDefault TitlePane.menuBarEmbedded boolean * @uiDefault TitlePane.menuBarEmbedded boolean
* @uiDefault TitlePane.buttonMaximizedHeight int * @uiDefault TitlePane.buttonMaximizedHeight int
* @uiDefault TitlePane.centerTitle boolean
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
* @uiDefault TitlePane.menuBarTitleGap int
* @uiDefault TitlePane.closeIcon Icon * @uiDefault TitlePane.closeIcon Icon
* @uiDefault TitlePane.iconifyIcon Icon * @uiDefault TitlePane.iconifyIcon Icon
* @uiDefault TitlePane.maximizeIcon Icon * @uiDefault TitlePane.maximizeIcon Icon
@@ -100,9 +104,12 @@ public class FlatTitlePane
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 Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
protected final Insets menuBarMargins = UIManager.getInsets( "TitlePane.menuBarMargins" ); protected final boolean unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" ); protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" ); protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
protected final boolean centerTitleIfMenuBarEmbedded = FlatUIUtils.getUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", true );
protected final int menuBarTitleGap = FlatUIUtils.getUIInt( "TitlePane.menuBarTitleGap", 20 );
protected final JRootPane rootPane; protected final JRootPane rootPane;
@@ -147,9 +154,15 @@ public class FlatTitlePane
protected void addSubComponents() { protected void addSubComponents() {
leftPanel = new JPanel(); leftPanel = new JPanel();
iconLabel = new JLabel(); iconLabel = new JLabel();
titleLabel = new JLabel(); titleLabel = new JLabel() {
@Override
public void updateUI() {
setUI( new FlatTitleLabelUI() );
}
};
iconLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.iconMargins" ) ) ); iconLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.iconMargins" ) ) );
titleLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.titleMargins" ) ) ); titleLabel.setBorder( new FlatEmptyBorder( UIManager.getInsets( "TitlePane.titleMargins" ) ) );
titleLabel.setHorizontalAlignment( SwingConstants.CENTER );
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) ); leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
leftPanel.setOpaque( false ); leftPanel.setOpaque( false );
@@ -159,9 +172,7 @@ public class FlatTitlePane
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
JMenuBar menuBar = rootPane.getJMenuBar(); JMenuBar menuBar = rootPane.getJMenuBar();
return (menuBar != null && menuBar.isVisible() && isMenuBarEmbedded()) return hasVisibleEmbeddedMenuBar( menuBar ) ? menuBar.getPreferredSize() : new Dimension();
? FlatUIUtils.addInsets( menuBar.getPreferredSize(), UIScale.scale( menuBarMargins ) )
: new Dimension();
} }
}; };
leftPanel.add( menuBarPlaceholder ); leftPanel.add( menuBarPlaceholder );
@@ -184,6 +195,18 @@ public class FlatTitlePane
if( !getComponentOrientation().isLeftToRight() ) if( !getComponentOrientation().isLeftToRight() )
leftPanel.setLocation( leftPanel.getX() + (oldWidth - newWidth), leftPanel.getY() ); leftPanel.setLocation( leftPanel.getX() + (oldWidth - newWidth), leftPanel.getY() );
} }
// If menu bar is embedded and contains a horizontal glue component,
// then move the title label to the same location as the glue component.
// This allows placing any component on the trailing side of the title pane.
JMenuBar menuBar = rootPane.getJMenuBar();
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
Component horizontalGlue = findHorizontalGlue( menuBar );
if( horizontalGlue != null ) {
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, titleLabel );
titleLabel.setLocation( titleLabel.getX() + glueLocation.x, titleLabel.getY() );
}
}
} }
} ); } );
@@ -240,7 +263,7 @@ public class FlatTitlePane
} }
protected void activeChanged( boolean active ) { protected void activeChanged( boolean active ) {
boolean hasEmbeddedMenuBar = rootPane.getJMenuBar() != null && rootPane.getJMenuBar().isVisible() && isMenuBarEmbedded(); boolean hasEmbeddedMenuBar = hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() );
Color background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground ); Color background = FlatUIUtils.nonUIResource( active ? activeBackground : inactiveBackground );
Color foreground = FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground ); Color foreground = FlatUIUtils.nonUIResource( active ? activeForeground : inactiveForeground );
Color titleForeground = (hasEmbeddedMenuBar && active) ? FlatUIUtils.nonUIResource( embeddedForeground ) : foreground; Color titleForeground = (hasEmbeddedMenuBar && active) ? FlatUIUtils.nonUIResource( embeddedForeground ) : foreground;
@@ -252,8 +275,6 @@ public class FlatTitlePane
restoreButton.setForeground( foreground ); restoreButton.setForeground( foreground );
closeButton.setForeground( foreground ); closeButton.setForeground( foreground );
titleLabel.setHorizontalAlignment( hasEmbeddedMenuBar ? SwingConstants.CENTER : SwingConstants.LEADING );
// this is necessary because hover/pressed colors are derived from background color // this is necessary because hover/pressed colors are derived from background color
iconifyButton.setBackground( background ); iconifyButton.setBackground( background );
maximizeButton.setBackground( background ); maximizeButton.setBackground( background );
@@ -394,6 +415,16 @@ public class FlatTitlePane
window.removeComponentListener( handler ); window.removeComponentListener( handler );
} }
/**
* Returns whether this title pane currently has an visible and embedded menubar.
*/
protected boolean hasVisibleEmbeddedMenuBar( JMenuBar menuBar ) {
return menuBar != null && menuBar.isVisible() && isMenuBarEmbedded();
}
/**
* Returns whether the menubar should be embedded into the title pane.
*/
protected boolean isMenuBarEmbedded() { protected boolean isMenuBarEmbedded() {
// not storing value of "TitlePane.menuBarEmbedded" in class to allow changing at runtime // not storing value of "TitlePane.menuBarEmbedded" in class to allow changing at runtime
return UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) && return UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) &&
@@ -412,13 +443,30 @@ public class FlatTitlePane
Insets borderInsets = getBorder().getBorderInsets( this ); Insets borderInsets = getBorder().getBorderInsets( this );
bounds.height += borderInsets.bottom; bounds.height += borderInsets.bottom;
return FlatUIUtils.subtractInsets( bounds, UIScale.scale( getMenuBarMargins() ) ); // If menu bar is embedded and contains a horizontal glue component,
// then make the menu bar wider so that it completely overlaps the title label.
// Since the menu bar is not opaque, the title label is still visible.
// The title label is moved to the location of the glue component by the layout manager.
// This allows placing any component on the trailing side of the title pane.
Component horizontalGlue = findHorizontalGlue( rootPane.getJMenuBar() );
if( horizontalGlue != null ) {
int titleWidth = Math.max( titleLabel.getWidth(), 0 ); // title width may be negative
bounds.width += titleWidth;
if( !getComponentOrientation().isLeftToRight() )
bounds.x -= titleWidth;
} }
protected Insets getMenuBarMargins() { return bounds;
return getComponentOrientation().isLeftToRight() }
? menuBarMargins
: new Insets( menuBarMargins.top, menuBarMargins.right, menuBarMargins.bottom, menuBarMargins.left ); protected Component findHorizontalGlue( JMenuBar menuBar ) {
int count = menuBar.getComponentCount();
for( int i = count - 1; i >= 0; i-- ) {
Component c = menuBar.getComponent( i );
if( c instanceof Box.Filler && c.getMaximumSize().width >= Short.MAX_VALUE )
return c;
}
return null;
} }
protected void menuBarChanged() { protected void menuBarChanged() {
@@ -436,6 +484,7 @@ public class FlatTitlePane
protected void menuBarLayouted() { protected void menuBarLayouted() {
updateNativeTitleBarHeightAndHitTestSpotsLater(); updateNativeTitleBarHeightAndHitTestSpotsLater();
revalidate();
} }
/*debug /*debug
@@ -464,9 +513,11 @@ debug*/
@Override @Override
protected void paintComponent( Graphics g ) { protected void paintComponent( Graphics g ) {
if( !unifiedBackground ) {
g.setColor( getBackground() ); g.setColor( getBackground() );
g.fillRect( 0, 0, getWidth(), getHeight() ); g.fillRect( 0, 0, getWidth(), getHeight() );
} }
}
protected void repaintWindowBorder() { protected void repaintWindowBorder() {
int width = rootPane.getWidth(); int width = rootPane.getWidth();
@@ -654,8 +705,37 @@ debug*/
else else
appIconBounds = iconBounds; appIconBounds = iconBounds;
} }
addNativeHitTestSpot( buttonPanel, false, hitTestSpots );
addNativeHitTestSpot( menuBarPlaceholder, true, hitTestSpots ); Rectangle r = getNativeHitTestSpot( buttonPanel );
if( r != null )
hitTestSpots.add( r );
r = getNativeHitTestSpot( menuBarPlaceholder );
if( r != null ) {
Component horizontalGlue = findHorizontalGlue( rootPane.getJMenuBar() );
if( horizontalGlue != null ) {
// If menu bar is embedded and contains a horizontal glue component,
// then split the hit test spot into two spots so that
// the glue component area can used to move the window.
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
Rectangle r2;
if( getComponentOrientation().isLeftToRight() ) {
int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x;
r.width -= trailingWidth;
r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height );
} else {
int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW);
r.x += leadingWidth;
r.width -= leadingWidth;
r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height );
}
r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
hitTestSpots.add( r2 );
}
hitTestSpots.add( r );
}
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds ); FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds );
@@ -667,27 +747,27 @@ debug*/
debug*/ debug*/
} }
protected void addNativeHitTestSpot( JComponent c, boolean subtractMenuBarMargins, List<Rectangle> hitTestSpots ) { protected Rectangle getNativeHitTestSpot( JComponent c ) {
Dimension size = c.getSize(); Dimension size = c.getSize();
if( size.width <= 0 || size.height <= 0 ) if( size.width <= 0 || size.height <= 0 )
return; return null;
Point location = SwingUtilities.convertPoint( c, 0, 0, window ); Point location = SwingUtilities.convertPoint( c, 0, 0, window );
Rectangle r = new Rectangle( location, size ); Rectangle r = new Rectangle( location, size );
if( subtractMenuBarMargins )
r = FlatUIUtils.subtractInsets( r, UIScale.scale( getMenuBarMargins() ) );
// slightly increase rectangle so that component receives mouseExit events // slightly increase rectangle so that component receives mouseExit events
r.grow( 2, 2 ); r.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
hitTestSpots.add( r ); return r;
} }
private static final int HIT_TEST_SPOT_GROW = 2;
/*debug /*debug
private int debugTitleBarHeight; private int debugTitleBarHeight;
private List<Rectangle> debugHitTestSpots; private List<Rectangle> debugHitTestSpots;
private Rectangle debugAppIconBounds; private Rectangle debugAppIconBounds;
debug*/ debug*/
//---- class TitlePaneBorder ---------------------------------------------- //---- class FlatTitlePaneBorder ------------------------------------------
protected class FlatTitlePaneBorder protected class FlatTitlePaneBorder
extends AbstractBorder extends AbstractBorder
@@ -729,7 +809,42 @@ debug*/
protected Border getMenuBarBorder() { protected Border getMenuBarBorder() {
JMenuBar menuBar = rootPane.getJMenuBar(); JMenuBar menuBar = rootPane.getJMenuBar();
return (menuBar != null && menuBar.isVisible() && isMenuBarEmbedded()) ? menuBar.getBorder() : null; return hasVisibleEmbeddedMenuBar( menuBar ) ? menuBar.getBorder() : null;
}
}
//---- class FlatTitleLabelUI ---------------------------------------------
protected class FlatTitleLabelUI
extends FlatLabelUI
{
@Override
protected void paintEnabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
boolean hasEmbeddedMenuBar = hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() );
int labelWidth = l.getWidth();
int textWidth = labelWidth - (textX * 2);
int gap = UIScale.scale( menuBarTitleGap );
// The passed in textX coordinate is always to horizontally center the text within the label bounds.
// Modify textX so that the text is painted either centered within the window bounds or leading aligned.
boolean center = hasEmbeddedMenuBar ? centerTitleIfMenuBarEmbedded : centerTitle;
if( center ) {
// If window is wide enough, center title within window bounds.
// Otherwise leave it centered within free space (label bounds).
int centeredTextX = ((l.getParent().getWidth() - textWidth) / 2) - l.getX();
if( centeredTextX >= gap && centeredTextX + textWidth <= labelWidth - gap )
textX = centeredTextX;
} else {
// leading aligned
boolean leftToRight = getComponentOrientation().isLeftToRight();
Insets insets = l.getInsets();
int leadingInset = hasEmbeddedMenuBar ? gap : (leftToRight ? insets.left : insets.right);
int leadingTextX = leftToRight ? leadingInset : labelWidth - leadingInset - textWidth;
if( leftToRight ? leadingTextX < textX : leadingTextX > textX )
textX = leadingTextX;
}
super.paintEnabledText( l, g, s, textX, textY );
} }
} }

View File

@@ -119,6 +119,11 @@ public class FlatUIUtils
return (color != null) ? color : UIManager.getColor( defaultKey ); return (color != null) ? color : UIManager.getColor( defaultKey );
} }
public static boolean getUIBoolean( String key, boolean defaultValue ) {
Object value = UIManager.get( key );
return (value instanceof Boolean) ? (Boolean) value : defaultValue;
}
public static int getUIInt( String key, int defaultValue ) { public static int getUIInt( String key, int defaultValue ) {
Object value = UIManager.get( key ); Object value = UIManager.get( key );
return (value instanceof Integer) ? (Integer) value : defaultValue; return (value instanceof Integer) ? (Integer) value : defaultValue;

View File

@@ -687,12 +687,15 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground
TitlePane.useWindowDecorations = true TitlePane.useWindowDecorations = true
TitlePane.menuBarEmbedded = true TitlePane.menuBarEmbedded = true
TitlePane.unifiedBackground = false
TitlePane.iconSize = 16,16 TitlePane.iconSize = 16,16
TitlePane.iconMargins = 3,8,3,0 TitlePane.iconMargins = 3,8,3,8
TitlePane.menuBarMargins = 0,8,0,22 TitlePane.titleMargins = 3,0,3,0
TitlePane.titleMargins = 3,8,3,8
TitlePane.buttonSize = 44,30 TitlePane.buttonSize = 44,30
TitlePane.buttonMaximizedHeight = 22 TitlePane.buttonMaximizedHeight = 22
TitlePane.centerTitle = false
TitlePane.centerTitleIfMenuBarEmbedded = true
TitlePane.menuBarTitleGap = 20
TitlePane.closeIcon = com.formdev.flatlaf.icons.FlatWindowCloseIcon TitlePane.closeIcon = com.formdev.flatlaf.icons.FlatWindowCloseIcon
TitlePane.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon TitlePane.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon
TitlePane.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon TitlePane.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon

View File

@@ -32,6 +32,8 @@ import com.formdev.flatlaf.demo.intellijthemes.*;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange; import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.formdev.flatlaf.extras.FlatSVGIcon; import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector; import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.extras.components.FlatButton;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
import com.formdev.flatlaf.extras.FlatSVGUtils; import com.formdev.flatlaf.extras.FlatSVGUtils;
import com.formdev.flatlaf.ui.FlatNativeWindowBorder; import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
import com.formdev.flatlaf.ui.JBRCustomDecorations; import com.formdev.flatlaf.ui.JBRCustomDecorations;
@@ -168,6 +170,11 @@ class DemoFrame
// repaint(); // repaint();
} }
private void unifiedTitleBar() {
UIManager.put( "TitlePane.unifiedBackground", unifiedTitleBarMenuItem.isSelected() );
FlatLaf.updateUI();
}
private void underlineMenuSelection() { private void underlineMenuSelection() {
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null ); UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
} }
@@ -332,6 +339,7 @@ class DemoFrame
optionsMenu = new JMenu(); optionsMenu = new JMenu();
windowDecorationsCheckBoxMenuItem = new JCheckBoxMenuItem(); windowDecorationsCheckBoxMenuItem = new JCheckBoxMenuItem();
menuBarEmbeddedCheckBoxMenuItem = new JCheckBoxMenuItem(); menuBarEmbeddedCheckBoxMenuItem = new JCheckBoxMenuItem();
unifiedTitleBarMenuItem = new JCheckBoxMenuItem();
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem(); underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem(); alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
animatedLafChangeMenuItem = new JCheckBoxMenuItem(); animatedLafChangeMenuItem = new JCheckBoxMenuItem();
@@ -593,6 +601,11 @@ class DemoFrame
menuBarEmbeddedCheckBoxMenuItem.addActionListener(e -> menuBarEmbeddedChanged()); menuBarEmbeddedCheckBoxMenuItem.addActionListener(e -> menuBarEmbeddedChanged());
optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem); optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem);
//---- unifiedTitleBarMenuItem ----
unifiedTitleBarMenuItem.setText("Unified Title Bar");
unifiedTitleBarMenuItem.addActionListener(e -> unifiedTitleBar());
optionsMenu.add(unifiedTitleBarMenuItem);
//---- underlineMenuSelectionMenuItem ---- //---- underlineMenuSelectionMenuItem ----
underlineMenuSelectionMenuItem.setText("Use underline menu selection"); underlineMenuSelectionMenuItem.setText("Use underline menu selection");
underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection()); underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection());
@@ -707,6 +720,15 @@ class DemoFrame
buttonGroup1.add(radioButtonMenuItem3); buttonGroup1.add(radioButtonMenuItem3);
// JFormDesigner - End of component initialization //GEN-END:initComponents // JFormDesigner - End of component initialization //GEN-END:initComponents
// add "Users" button to menubar
FlatButton usersButton = new FlatButton();
usersButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/users.svg" ) );
usersButton.setButtonType( ButtonType.toolBarButton );
usersButton.setFocusable( false );
usersButton.addActionListener( e -> JOptionPane.showMessageDialog( null, "Hello User! How are you?", "User", JOptionPane.INFORMATION_MESSAGE ) );
menuBar1.add( Box.createGlue() );
menuBar1.add( usersButton );
undoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/undo.svg" ) ); undoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/undo.svg" ) );
redoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/redo.svg" ) ); redoMenuItem.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/redo.svg" ) );
@@ -749,6 +771,7 @@ class DemoFrame
private JMenu optionsMenu; private JMenu optionsMenu;
private JCheckBoxMenuItem windowDecorationsCheckBoxMenuItem; private JCheckBoxMenuItem windowDecorationsCheckBoxMenuItem;
private JCheckBoxMenuItem menuBarEmbeddedCheckBoxMenuItem; private JCheckBoxMenuItem menuBarEmbeddedCheckBoxMenuItem;
private JCheckBoxMenuItem unifiedTitleBarMenuItem;
private JCheckBoxMenuItem underlineMenuSelectionMenuItem; private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem; private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
private JCheckBoxMenuItem animatedLafChangeMenuItem; private JCheckBoxMenuItem animatedLafChangeMenuItem;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8" JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -360,6 +360,14 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuBarEmbeddedChanged", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuBarEmbeddedChanged", false ) )
} ) } )
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
name: "unifiedTitleBarMenuItem"
"text": "Unified Title Bar"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedTitleBar", false ) )
} )
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) { add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
name: "underlineMenuSelectionMenuItem" name: "underlineMenuSelectionMenuItem"
"text": "Use underline menu selection" "text": "Use underline menu selection"

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect id="frame" width="16" height="16" fill="none"/><path d="M11.6 8.5c1.104 0 1.992-.88 1.992-1.964 0-1.085-.888-1.965-1.992-1.965s-2 .88-2 1.965c0 1.084.896 1.964 2 1.964zm-6-.786c1.328 0 2.392-1.053 2.392-2.357C7.992 4.053 6.928 3 5.6 3 4.272 3 3.2 4.053 3.2 5.357c0 1.304 1.072 2.357 2.4 2.357zm6 2.357c-1.464 0-4.4.723-4.4 2.161V14H16v-1.768c0-1.438-2.936-2.16-4.4-2.16zm-6-.785c-1.864 0-5.6.919-5.6 2.75V14h5.6v-1.768c0-.668.264-1.838 1.896-2.726-.696-.142-1.368-.22-1.896-.22z" fill="#6E6E6E"/></svg>

After

Width:  |  Height:  |  Size: 603 B

View File

@@ -1126,6 +1126,8 @@ TitlePane.buttonHoverBackground #484c4f com.formdev.flatlaf.util.DerivedColor
TitlePane.buttonMaximizedHeight 22 TitlePane.buttonMaximizedHeight 22
TitlePane.buttonPressedBackground #616569 com.formdev.flatlaf.util.DerivedColor [UI] lighten(20% autoInverse) TitlePane.buttonPressedBackground #616569 com.formdev.flatlaf.util.DerivedColor [UI] lighten(20% autoInverse)
TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI] TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.centerTitle false
TitlePane.centerTitleIfMenuBarEmbedded true
TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI] TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI]
@@ -1133,16 +1135,17 @@ TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResou
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #959595 javax.swing.plaf.ColorUIResource [UI] TitlePane.embeddedForeground #959595 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI] TitlePane.foreground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
TitlePane.iconMargins 3,8,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI] TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]
TitlePane.inactiveBackground #303234 javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveBackground #303234 javax.swing.plaf.ColorUIResource [UI]
TitlePane.inactiveForeground #888888 javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveForeground #888888 javax.swing.plaf.ColorUIResource [UI]
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
TitlePane.menuBarEmbedded true TitlePane.menuBarEmbedded true
TitlePane.menuBarMargins 0,8,0,22 javax.swing.plaf.InsetsUIResource [UI] TitlePane.menuBarTitleGap 20
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
TitlePane.titleMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.unifiedBackground false
TitlePane.useWindowDecorations true TitlePane.useWindowDecorations true

View File

@@ -1131,6 +1131,8 @@ TitlePane.buttonHoverBackground #e6e6e6 com.formdev.flatlaf.util.DerivedColor
TitlePane.buttonMaximizedHeight 22 TitlePane.buttonMaximizedHeight 22
TitlePane.buttonPressedBackground #cccccc com.formdev.flatlaf.util.DerivedColor [UI] darken(20% autoInverse) TitlePane.buttonPressedBackground #cccccc com.formdev.flatlaf.util.DerivedColor [UI] darken(20% autoInverse)
TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI] TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.centerTitle false
TitlePane.centerTitleIfMenuBarEmbedded true
TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI] TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI]
@@ -1138,16 +1140,17 @@ TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResou
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.embeddedForeground #595959 javax.swing.plaf.ColorUIResource [UI] TitlePane.embeddedForeground #595959 javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #000000 javax.swing.plaf.ColorUIResource [UI] TitlePane.foreground #000000 javax.swing.plaf.ColorUIResource [UI]
TitlePane.iconMargins 3,8,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI] TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]
TitlePane.inactiveBackground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveBackground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.inactiveForeground #8c8c8c javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveForeground #8c8c8c javax.swing.plaf.ColorUIResource [UI]
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
TitlePane.menuBarEmbedded true TitlePane.menuBarEmbedded true
TitlePane.menuBarMargins 0,8,0,22 javax.swing.plaf.InsetsUIResource [UI] TitlePane.menuBarTitleGap 20
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
TitlePane.titleMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.unifiedBackground false
TitlePane.useWindowDecorations true TitlePane.useWindowDecorations true

View File

@@ -1124,22 +1124,25 @@ TextPaneUI com.formdev.flatlaf.ui.FlatTextPaneUI
TitlePane.background #00ff00 javax.swing.plaf.ColorUIResource [UI] TitlePane.background #00ff00 javax.swing.plaf.ColorUIResource [UI]
TitlePane.buttonMaximizedHeight 22 TitlePane.buttonMaximizedHeight 22
TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI] TitlePane.buttonSize 44,30 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.centerTitle false
TitlePane.centerTitleIfMenuBarEmbedded true
TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverBackground #e81123 javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI] TitlePane.closeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowCloseIcon [UI]
TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedBackground #e8112399 60% javax.swing.plaf.ColorUIResource [UI]
TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.closePressedForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.foreground #0000ff javax.swing.plaf.ColorUIResource [UI] TitlePane.foreground #0000ff javax.swing.plaf.ColorUIResource [UI]
TitlePane.iconMargins 3,8,3,0 javax.swing.plaf.InsetsUIResource [UI] TitlePane.iconMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI] TitlePane.iconSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI] TitlePane.iconifyIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowIconifyIcon [UI]
TitlePane.inactiveBackground #008800 javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveBackground #008800 javax.swing.plaf.ColorUIResource [UI]
TitlePane.inactiveForeground #ffffff javax.swing.plaf.ColorUIResource [UI] TitlePane.inactiveForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI] TitlePane.maximizeIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowMaximizeIcon [UI]
TitlePane.menuBarEmbedded true TitlePane.menuBarEmbedded true
TitlePane.menuBarMargins 0,8,0,22 javax.swing.plaf.InsetsUIResource [UI] TitlePane.menuBarTitleGap 20
TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI] TitlePane.restoreIcon [lazy] 44,30 com.formdev.flatlaf.icons.FlatWindowRestoreIcon [UI]
TitlePane.titleMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI] TitlePane.titleMargins 3,0,3,0 javax.swing.plaf.InsetsUIResource [UI]
TitlePane.unifiedBackground false
TitlePane.useWindowDecorations true TitlePane.useWindowDecorations true

View File

@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import javax.swing.*; import javax.swing.*;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import net.miginfocom.swing.*; import net.miginfocom.swing.*;
/** /**
@@ -109,6 +110,11 @@ public class FlatWindowDecorationsTest
} }
} }
private void unifiedBackgroundChanged() {
UIManager.put( "TitlePane.unifiedBackground", unifiedBackgroundCheckBox.isSelected() );
FlatLaf.updateUI();
}
private void menuBarChanged() { private void menuBarChanged() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
if( window instanceof JFrame ) { if( window instanceof JFrame ) {
@@ -128,13 +134,48 @@ public class FlatWindowDecorationsTest
menuBar.setVisible( menuBarVisibleCheckBox.isSelected() ); menuBar.setVisible( menuBarVisibleCheckBox.isSelected() );
} }
private void colorizeMenuBar() {
boolean colorize = colorizeMenuBarCheckBox.isSelected();
Color menuBarBackground = colorize ? new Color( 0xffccff ) : UIManager.getColor( "MenuBar.background" );
menuBar.setOpaque( colorize );
menuBar.setBackground( menuBarBackground );
}
private void colorizeMenus() {
boolean colorize = colorizeMenusCheckBox.isSelected();
Color menuBackground = colorize ? new Color( 0xaaffff ) : UIManager.getColor( "Menu.background" );
for( Component c : menuBar.getComponents() ) {
if( c instanceof JMenu ) {
((JMenu)c).setOpaque( colorize );
c.setBackground( menuBackground );
}
}
}
private void addMenu() { private void addMenu() {
JMenu menu = new JMenu( "Hello" ); JMenu menu = new JMenu( "Hello" );
menu.add( new JMenuItem( "world" ) ); menu.add( new JMenuItem( "world" ) );
if( colorizeMenusCheckBox.isSelected() ) {
menu.setOpaque( true );
menu.setBackground( new Color( 0xaaffff ) );
}
menuBar.add( menu ); menuBar.add( menu );
menuBar.revalidate(); menuBar.revalidate();
} }
private void addGlue() {
for( Component c : menuBar.getComponents() ) {
if( c instanceof Box.Filler )
return;
}
menuBar.add( Box.createGlue() );
menuBar.revalidate();
}
private void removeMenu() { private void removeMenu() {
int menuCount = menuBar.getMenuCount(); int menuCount = menuBar.getMenuCount();
if( menuCount <= 0 ) if( menuCount <= 0 )
@@ -154,6 +195,14 @@ public class FlatWindowDecorationsTest
menuBar.getMenu( menuCount - 1 ).setText( text ); menuBar.getMenu( menuCount - 1 ).setText( text );
} }
private void changeTitle() {
Window window = SwingUtilities.windowForComponent( this );
if( window instanceof Frame )
((Frame)window).setTitle( ((Frame)window).getTitle() + " bla" );
else if( window instanceof Dialog )
((Dialog)window).setTitle( ((Dialog)window).getTitle() + " bla" );
}
private void resizableChanged() { private void resizableChanged() {
Window window = SwingUtilities.windowForComponent( this ); Window window = SwingUtilities.windowForComponent( this );
if( window instanceof Frame ) if( window instanceof Frame )
@@ -263,11 +312,17 @@ public class FlatWindowDecorationsTest
private void initComponents() { private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
menuBarCheckBox = new JCheckBox(); menuBarCheckBox = new JCheckBox();
unifiedBackgroundCheckBox = new JCheckBox();
JPanel panel3 = new JPanel();
addMenuButton = new JButton(); addMenuButton = new JButton();
JButton addGlueButton = new JButton();
removeMenuButton = new JButton(); removeMenuButton = new JButton();
changeMenuButton = new JButton(); changeMenuButton = new JButton();
JButton changeTitleButton = new JButton();
menuBarEmbeddedCheckBox = new JCheckBox(); menuBarEmbeddedCheckBox = new JCheckBox();
colorizeMenuBarCheckBox = new JCheckBox();
menuBarVisibleCheckBox = new JCheckBox(); menuBarVisibleCheckBox = new JCheckBox();
colorizeMenusCheckBox = new JCheckBox();
resizableCheckBox = new JCheckBox(); resizableCheckBox = new JCheckBox();
maximizedBoundsCheckBox = new JCheckBox(); maximizedBoundsCheckBox = new JCheckBox();
undecoratedCheckBox = new JCheckBox(); undecoratedCheckBox = new JCheckBox();
@@ -321,13 +376,14 @@ public class FlatWindowDecorationsTest
"ltr,insets dialog,hidemode 3", "ltr,insets dialog,hidemode 3",
// columns // columns
"[left]para" + "[left]para" +
"[left]", "[left]" +
"[fill]",
// rows // rows
"para[]0" + "para[]0" +
"[]0" + "[]0" +
"[]unrel" +
"[]0" + "[]0" +
"[]0" + "[]unrel" +
"[]" +
"[]" + "[]" +
"[top]" + "[top]" +
"[]")); "[]"));
@@ -338,20 +394,50 @@ public class FlatWindowDecorationsTest
menuBarCheckBox.addActionListener(e -> menuBarChanged()); menuBarCheckBox.addActionListener(e -> menuBarChanged());
add(menuBarCheckBox, "cell 0 0"); add(menuBarCheckBox, "cell 0 0");
//---- unifiedBackgroundCheckBox ----
unifiedBackgroundCheckBox.setText("unified background");
unifiedBackgroundCheckBox.addActionListener(e -> unifiedBackgroundChanged());
add(unifiedBackgroundCheckBox, "cell 1 0");
//======== panel3 ========
{
panel3.setLayout(new MigLayout(
"hidemode 3",
// columns
"[fill]",
// rows
"[]" +
"[]" +
"[]" +
"[]unrel" +
"[]"));
//---- addMenuButton ---- //---- addMenuButton ----
addMenuButton.setText("Add menu"); addMenuButton.setText("Add menu");
addMenuButton.addActionListener(e -> addMenu()); addMenuButton.addActionListener(e -> addMenu());
add(addMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); panel3.add(addMenuButton, "cell 0 0");
//---- addGlueButton ----
addGlueButton.setText("Add glue");
addGlueButton.addActionListener(e -> addGlue());
panel3.add(addGlueButton, "cell 0 1");
//---- removeMenuButton ---- //---- removeMenuButton ----
removeMenuButton.setText("Remove menu"); removeMenuButton.setText("Remove menu");
removeMenuButton.addActionListener(e -> removeMenu()); removeMenuButton.addActionListener(e -> removeMenu());
add(removeMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); panel3.add(removeMenuButton, "cell 0 2");
//---- changeMenuButton ---- //---- changeMenuButton ----
changeMenuButton.setText("Change menu"); changeMenuButton.setText("Change menu");
changeMenuButton.addActionListener(e -> changeMenu()); changeMenuButton.addActionListener(e -> changeMenu());
add(changeMenuButton, "cell 1 0 1 2,align left top,grow 0 0"); panel3.add(changeMenuButton, "cell 0 3");
//---- changeTitleButton ----
changeTitleButton.setText("Change title");
changeTitleButton.addActionListener(e -> changeTitle());
panel3.add(changeTitleButton, "cell 0 4");
}
add(panel3, "cell 2 0 1 6,aligny top,growy 0");
//---- menuBarEmbeddedCheckBox ---- //---- menuBarEmbeddedCheckBox ----
menuBarEmbeddedCheckBox.setText("embedded menu bar"); menuBarEmbeddedCheckBox.setText("embedded menu bar");
@@ -359,12 +445,22 @@ public class FlatWindowDecorationsTest
menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged()); menuBarEmbeddedCheckBox.addActionListener(e -> menuBarEmbeddedChanged());
add(menuBarEmbeddedCheckBox, "cell 0 1"); add(menuBarEmbeddedCheckBox, "cell 0 1");
//---- colorizeMenuBarCheckBox ----
colorizeMenuBarCheckBox.setText("colorize menu bar");
colorizeMenuBarCheckBox.addActionListener(e -> colorizeMenuBar());
add(colorizeMenuBarCheckBox, "cell 1 1");
//---- menuBarVisibleCheckBox ---- //---- menuBarVisibleCheckBox ----
menuBarVisibleCheckBox.setText("menu bar visible"); menuBarVisibleCheckBox.setText("menu bar visible");
menuBarVisibleCheckBox.setSelected(true); menuBarVisibleCheckBox.setSelected(true);
menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged()); menuBarVisibleCheckBox.addActionListener(e -> menuBarVisibleChanged());
add(menuBarVisibleCheckBox, "cell 0 2"); add(menuBarVisibleCheckBox, "cell 0 2");
//---- colorizeMenusCheckBox ----
colorizeMenusCheckBox.setText("colorize menus");
colorizeMenusCheckBox.addActionListener(e -> colorizeMenus());
add(colorizeMenusCheckBox, "cell 1 2");
//---- resizableCheckBox ---- //---- resizableCheckBox ----
resizableCheckBox.setText("resizable"); resizableCheckBox.setText("resizable");
resizableCheckBox.setSelected(true); resizableCheckBox.setSelected(true);
@@ -683,11 +779,14 @@ public class FlatWindowDecorationsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JCheckBox menuBarCheckBox; private JCheckBox menuBarCheckBox;
private JCheckBox unifiedBackgroundCheckBox;
private JButton addMenuButton; private JButton addMenuButton;
private JButton removeMenuButton; private JButton removeMenuButton;
private JButton changeMenuButton; private JButton changeMenuButton;
private JCheckBox menuBarEmbeddedCheckBox; private JCheckBox menuBarEmbeddedCheckBox;
private JCheckBox colorizeMenuBarCheckBox;
private JCheckBox menuBarVisibleCheckBox; private JCheckBox menuBarVisibleCheckBox;
private JCheckBox colorizeMenusCheckBox;
private JCheckBox resizableCheckBox; private JCheckBox resizableCheckBox;
private JCheckBox maximizedBoundsCheckBox; private JCheckBox maximizedBoundsCheckBox;
private JCheckBox undecoratedCheckBox; private JCheckBox undecoratedCheckBox;

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8" JFDML JFormDesigner: "7.0.3.1.342" Java: "15" encoding: "UTF-8"
new FormModel { new FormModel {
contentType: "form/swing" contentType: "form/swing"
@@ -8,8 +8,8 @@ new FormModel {
} }
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3" "$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[left]para[left]" "$columnConstraints": "[left]para[left][fill]"
"$rowConstraints": "para[]0[]0[]0[]0[][][top][]" "$rowConstraints": "para[]0[]0[]unrel[]0[]unrel[][top][]"
} ) { } ) {
name: "this" name: "this"
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
@@ -23,6 +23,22 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0" "value": "cell 0 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "unifiedBackgroundCheckBox"
"text": "unified background"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedBackgroundChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3"
"$columnConstraints": "[fill]"
"$rowConstraints": "[][][][]unrel[]"
} ) {
name: "panel3"
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "addMenuButton" name: "addMenuButton"
"text": "Add menu" "text": "Add menu"
@@ -31,7 +47,14 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addMenu", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0 1 2,align left top,grow 0 0" "value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "addGlueButton"
"text": "Add glue"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "addGlue", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "removeMenuButton" name: "removeMenuButton"
@@ -41,7 +64,7 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "removeMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0 1 2,align left top,grow 0 0" "value": "cell 0 2"
} ) } )
add( new FormComponent( "javax.swing.JButton" ) { add( new FormComponent( "javax.swing.JButton" ) {
name: "changeMenuButton" name: "changeMenuButton"
@@ -51,7 +74,17 @@ new FormModel {
} }
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) ) addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeMenu", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 0 1 2,align left top,grow 0 0" "value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "changeTitleButton"
"text": "Change title"
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeTitle", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0 1 6,aligny top,growy 0"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "menuBarEmbeddedCheckBox" name: "menuBarEmbeddedCheckBox"
@@ -64,6 +97,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1" "value": "cell 0 1"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenuBarCheckBox"
"text": "colorize menu bar"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenuBar", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "menuBarVisibleCheckBox" name: "menuBarVisibleCheckBox"
"text": "menu bar visible" "text": "menu bar visible"
@@ -75,6 +118,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 2" "value": "cell 0 2"
} ) } )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "colorizeMenusCheckBox"
"text": "colorize menus"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "colorizeMenus", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 2"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) { add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "resizableCheckBox" name: "resizableCheckBox"
"text": "resizable" "text": "resizable"
@@ -289,7 +342,7 @@ new FormModel {
} ) } )
}, new FormLayoutConstraints( null ) { }, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 ) "location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 550, 440 ) "size": new java.awt.Dimension( 690, 440 )
} ) } )
add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) { add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
name: "menuBar" name: "menuBar"

View File

@@ -836,6 +836,8 @@ TitlePane.buttonHoverBackground
TitlePane.buttonMaximizedHeight TitlePane.buttonMaximizedHeight
TitlePane.buttonPressedBackground TitlePane.buttonPressedBackground
TitlePane.buttonSize TitlePane.buttonSize
TitlePane.centerTitle
TitlePane.centerTitleIfMenuBarEmbedded
TitlePane.closeHoverBackground TitlePane.closeHoverBackground
TitlePane.closeHoverForeground TitlePane.closeHoverForeground
TitlePane.closeIcon TitlePane.closeIcon
@@ -850,9 +852,10 @@ TitlePane.inactiveBackground
TitlePane.inactiveForeground TitlePane.inactiveForeground
TitlePane.maximizeIcon TitlePane.maximizeIcon
TitlePane.menuBarEmbedded TitlePane.menuBarEmbedded
TitlePane.menuBarMargins TitlePane.menuBarTitleGap
TitlePane.restoreIcon TitlePane.restoreIcon
TitlePane.titleMargins TitlePane.titleMargins
TitlePane.unifiedBackground
TitlePane.useWindowDecorations TitlePane.useWindowDecorations
TitledBorder.border TitledBorder.border
TitledBorder.font TitledBorder.font