Skip to content

Commit

Permalink
Merge pull request #268 from title-pane-improvements
Browse files Browse the repository at this point in the history
Title pane improvements (Windows 10 only)
  • Loading branch information
DevCharly committed Mar 14, 2021
2 parents e8a6f0c + 035a13d commit 04aa61c
Show file tree
Hide file tree
Showing 15 changed files with 479 additions and 92 deletions.
18 changes: 14 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ FlatLaf Change Log

#### New features and improvements

- 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
border drop shadows, resize behavior, window snapping and system window menu.
(PR #267)
- 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
border drop shadows, resize behavior, window snapping and system window
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,22 @@

package com.formdev.flatlaf.ui;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
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.FlatLaf;
import com.formdev.flatlaf.util.SystemInfo;
Expand All @@ -40,12 +45,15 @@
* @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();
}
Expand All @@ -55,6 +63,15 @@ public static ComponentUI createUI( JComponent c ) {
* Do not add any functionality here.
*/

@Override
protected void installDefaults() {
super.installDefaults();

LookAndFeel.installProperty( menuBar, "opaque", false );

unifiedBackground = UIManager.getBoolean( "TitlePane.unifiedBackground" );
}

@Override
protected void installKeyboardActions() {
super.installKeyboardActions();
Expand All @@ -67,6 +84,35 @@ protected void installKeyboardActions() {
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 ----------------------------------------------------

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
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;
Expand Down Expand Up @@ -227,6 +228,13 @@ public void propertyChange( PropertyChangeEvent e ) {
}
}

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
Expand Down Expand Up @@ -297,15 +305,16 @@ public void layoutContainer( Container parent ) {
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();
if( menuBar != null && menuBar.isVisible() ) {
if( !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded() ) {
boolean embedded = !isFullScreen && titlePane != null && titlePane.isMenuBarEmbedded();
if( embedded ) {
titlePane.validate();
menuBar.setBounds( titlePane.getMenuBarBounds() );
} else {
Expand Down Expand Up @@ -342,6 +351,9 @@ public float getLayoutAlignmentY( Container target ) {

//---- class FlatWindowBorder ---------------------------------------------

/**
* Window border used for non-native window decorations.
*/
public static class FlatWindowBorder
extends BorderUIResource.EmptyBorderUIResource
{
Expand All @@ -356,7 +368,7 @@ public FlatWindowBorder() {
@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
Expand Down
Loading

0 comments on commit 04aa61c

Please sign in to comment.