Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Title pane improvements (Windows 10 only) #268

Merged
merged 4 commits into from
Mar 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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