mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 06:57:13 -06:00
Window decorations: make sure that a horizontal glue in embedded menu bar has a minimum width and is always visible
This commit is contained in:
@@ -18,8 +18,10 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
@@ -27,6 +29,7 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
@@ -40,11 +43,13 @@ import javax.swing.plaf.ActionMapUIResource;
|
|||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicMenuBarUI;
|
import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||||
|
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
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.JMenuBar}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuBar}.
|
||||||
@@ -100,6 +105,10 @@ public class FlatMenuBarUI
|
|||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
LookAndFeel.installProperty( menuBar, "opaque", false );
|
LookAndFeel.installProperty( menuBar, "opaque", false );
|
||||||
|
|
||||||
|
LayoutManager layout = menuBar.getLayout();
|
||||||
|
if( layout == null || layout instanceof UIResource )
|
||||||
|
menuBar.setLayout( new FlatMenuBarLayout( menuBar ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -221,6 +230,130 @@ public class FlatMenuBarUI
|
|||||||
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatMenuBarLayout --------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
protected static class FlatMenuBarLayout
|
||||||
|
extends DefaultMenuLayout
|
||||||
|
{
|
||||||
|
public FlatMenuBarLayout( Container target ) {
|
||||||
|
super( target, BoxLayout.LINE_AXIS );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void layoutContainer( Container target ) {
|
||||||
|
super.layoutContainer( target );
|
||||||
|
|
||||||
|
|
||||||
|
// The only purpose of the code below is to make sure that a horizontal glue,
|
||||||
|
// which can be used to move window and displays the window title in embedded menu bar,
|
||||||
|
// is always visible within the menu bar bounds and has a minimum width.
|
||||||
|
// If this is not the case, the horizontal glue is made larger and
|
||||||
|
// components that are on the left side of the glue are made smaller.
|
||||||
|
|
||||||
|
|
||||||
|
// get root pane and check whether this menu bar is the root pane menu bar
|
||||||
|
JRootPane rootPane = SwingUtilities.getRootPane( target );
|
||||||
|
if( rootPane == null || rootPane.getJMenuBar() != target )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get title pane and check whether menu bar is embedded
|
||||||
|
FlatTitlePane titlePane = FlatRootPaneUI.getTitlePane( rootPane );
|
||||||
|
if( titlePane == null || !titlePane.isMenuBarEmbedded() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check whether there is a horizontal glue (used for window title in embedded menu bar)
|
||||||
|
// and check minimum width of horizontal glue
|
||||||
|
Component horizontalGlue = titlePane.findHorizontalGlue( (JMenuBar) target );
|
||||||
|
int minTitleWidth = UIScale.scale( titlePane.titleMinimumWidth );
|
||||||
|
if( horizontalGlue != null && horizontalGlue.getWidth() < minTitleWidth ) {
|
||||||
|
// get index of glue component
|
||||||
|
int glueIndex = -1;
|
||||||
|
Component[] components = target.getComponents();
|
||||||
|
for( int i = components.length - 1; i >= 0; i-- ) {
|
||||||
|
if( components[i] == horizontalGlue ) {
|
||||||
|
glueIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( glueIndex < 0 )
|
||||||
|
return; // should never happen
|
||||||
|
|
||||||
|
if( target.getComponentOrientation().isLeftToRight() ) {
|
||||||
|
// left-to-right
|
||||||
|
|
||||||
|
// make horizontal glue wider (minimum title width)
|
||||||
|
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||||
|
horizontalGlue.setSize( minTitleWidth, horizontalGlue.getHeight() );
|
||||||
|
|
||||||
|
// check whether glue is fully visible
|
||||||
|
int minGlueX = target.getWidth() - target.getInsets().right - minTitleWidth;
|
||||||
|
if( minGlueX < horizontalGlue.getX() ) {
|
||||||
|
// move glue to the left to make it fully visible
|
||||||
|
offset -= (horizontalGlue.getX() - minGlueX);
|
||||||
|
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||||
|
|
||||||
|
// shrink and move components that are on the left side of the glue
|
||||||
|
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||||
|
Component c = components[i];
|
||||||
|
if( c.getX() > minGlueX ) {
|
||||||
|
// move component and set width to zero
|
||||||
|
c.setBounds( minGlueX, c.getY(), 0, c.getHeight() );
|
||||||
|
} else {
|
||||||
|
// reduce size of component
|
||||||
|
c.setSize( minGlueX - c.getX(), c.getHeight() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move components that are on the right side of the glue
|
||||||
|
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||||
|
Component c = components[i];
|
||||||
|
c.setLocation( c.getX() + offset, c.getY() );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// right-to-left
|
||||||
|
|
||||||
|
// make horizontal glue wider (minimum title width)
|
||||||
|
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||||
|
horizontalGlue.setBounds( horizontalGlue.getX() - offset, horizontalGlue.getY(),
|
||||||
|
minTitleWidth, horizontalGlue.getHeight() );
|
||||||
|
|
||||||
|
// check whether glue is fully visible
|
||||||
|
int minGlueX = target.getInsets().left;
|
||||||
|
if( minGlueX > horizontalGlue.getX() ) {
|
||||||
|
// move glue to the right to make it fully visible
|
||||||
|
offset -= (horizontalGlue.getX() - minGlueX);
|
||||||
|
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||||
|
|
||||||
|
// shrink and move components that are on the right side of the glue
|
||||||
|
int x = horizontalGlue.getX() + horizontalGlue.getWidth();
|
||||||
|
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||||
|
Component c = components[i];
|
||||||
|
if( c.getX() + c.getWidth() < x ) {
|
||||||
|
// move component and set width to zero
|
||||||
|
c.setBounds( x, c.getY(), 0, c.getHeight() );
|
||||||
|
} else {
|
||||||
|
// move component and reduce size
|
||||||
|
c.setBounds( x, c.getY(), c.getWidth() - (x - c.getX()), c.getHeight() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move components that are on the left side of the glue
|
||||||
|
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||||
|
Component c = components[i];
|
||||||
|
c.setLocation( c.getX() - offset, c.getY() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- class TakeFocus ----------------------------------------------------
|
//---- class TakeFocus ----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public class FlatPopupMenuUI
|
|||||||
|
|
||||||
LayoutManager layout = popupMenu.getLayout();
|
LayoutManager layout = popupMenu.getLayout();
|
||||||
if( layout == null || layout instanceof UIResource )
|
if( layout == null || layout instanceof UIResource )
|
||||||
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
popupMenu.setLayout( new FlatPopupMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -230,12 +230,15 @@ public class FlatPopupMenuUI
|
|||||||
return screenBounds.height - screenInsets.top - screenInsets.bottom;
|
return screenBounds.height - screenInsets.top - screenInsets.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatMenuLayout -----------------------------------------------
|
//---- class FlatPopupMenuLayout ------------------------------------------
|
||||||
|
|
||||||
protected static class FlatMenuLayout
|
/**
|
||||||
|
* @since 2.4
|
||||||
|
*/
|
||||||
|
protected static class FlatPopupMenuLayout
|
||||||
extends DefaultMenuLayout
|
extends DefaultMenuLayout
|
||||||
{
|
{
|
||||||
public FlatMenuLayout( Container target, int axis ) {
|
public FlatPopupMenuLayout( Container target, int axis ) {
|
||||||
super( target, axis );
|
super( target, axis );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,6 +364,12 @@ public class FlatRootPaneUI
|
|||||||
((FlatRootPaneUI)ui).titlePane.isMenuBarEmbedded();
|
((FlatRootPaneUI)ui).titlePane.isMenuBarEmbedded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.4 */
|
||||||
|
protected static FlatTitlePane getTitlePane( JRootPane rootPane ) {
|
||||||
|
RootPaneUI ui = rootPane.getUI();
|
||||||
|
return ui instanceof FlatRootPaneUI ? ((FlatRootPaneUI)ui).titlePane : null;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatRootLayout -----------------------------------------------
|
//---- class FlatRootLayout -----------------------------------------------
|
||||||
|
|
||||||
protected class FlatRootLayout
|
protected class FlatRootLayout
|
||||||
|
|||||||
@@ -241,6 +241,23 @@ public class FlatWindowDecorationsTest
|
|||||||
if( c instanceof Box.Filler )
|
if( c instanceof Box.Filler )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
menuBar.add( new Box.Filler( new Dimension(), new Dimension(),
|
||||||
|
new Dimension( Short.MAX_VALUE, Short.MAX_VALUE ) )
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void paintComponent( Graphics g ) {
|
||||||
|
int w = getWidth();
|
||||||
|
int h = getHeight();
|
||||||
|
g.setColor( Color.blue );
|
||||||
|
g.drawRect( 0, 0, w - 1, h - 1 );
|
||||||
|
g.drawLine( 0, 0, w, h );
|
||||||
|
g.drawLine( 0, h, w, 0 );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
debug*/
|
||||||
|
|
||||||
menuBar.add( Box.createGlue() );
|
menuBar.add( Box.createGlue() );
|
||||||
menuBar.revalidate();
|
menuBar.revalidate();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user