mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-09 16:25:10 +03:00
MenuItem: vertically align text if icons have different widths (issue #437)
This commit is contained in:
@@ -89,6 +89,7 @@ public class FlatCheckBoxMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
@@ -32,6 +33,7 @@ import java.awt.event.KeyEvent;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.KeyStroke;
|
||||
@@ -39,6 +41,7 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.text.View;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||
import com.formdev.flatlaf.icons.FlatMenuArrowIcon;
|
||||
@@ -52,6 +55,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
/**
|
||||
* Renderer for menu items.
|
||||
*
|
||||
* @uiDefault MenuItem.verticallyAlignText boolean
|
||||
* @uiDefault MenuItem.minimumWidth int
|
||||
* @uiDefault MenuItem.minimumIconSize Dimension
|
||||
* @uiDefault MenuItem.textAcceleratorGap int
|
||||
@@ -67,12 +71,15 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
*/
|
||||
public class FlatMenuItemRenderer
|
||||
{
|
||||
private static final String KEY_MAX_ICONS_WIDTH = "FlatLaf.internal.FlatMenuItemRenderer.maxIconWidth";
|
||||
|
||||
protected final JMenuItem menuItem;
|
||||
protected Icon checkIcon;
|
||||
protected Icon arrowIcon;
|
||||
protected final Font acceleratorFont;
|
||||
protected final String acceleratorDelimiter;
|
||||
|
||||
/** @since 2 */ @Styleable protected boolean verticallyAlignText = FlatUIUtils.getUIBoolean( "MenuItem.verticallyAlignText", true );
|
||||
@Styleable protected int minimumWidth = UIManager.getInt( "MenuItem.minimumWidth" );
|
||||
@Styleable protected Dimension minimumIconSize;
|
||||
@Styleable protected int textAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textAcceleratorGap", 28 );
|
||||
@@ -405,11 +412,10 @@ debug*/
|
||||
return;
|
||||
|
||||
// center because the real icon may be smaller than dimension in iconRect
|
||||
int x = iconRect.x + centerOffset( iconRect.width, icon.getIconWidth() );
|
||||
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
||||
|
||||
// paint
|
||||
icon.paintIcon( menuItem, g, x, y );
|
||||
icon.paintIcon( menuItem, g, iconRect.x, y );
|
||||
}
|
||||
|
||||
protected static void paintText( Graphics g, JMenuItem menuItem,
|
||||
@@ -570,6 +576,44 @@ debug*/
|
||||
shiftGlyph = 0x21E7,
|
||||
commandGlyph = 0x2318;
|
||||
|
||||
/**
|
||||
* Calculates the maximum width of all menu item icons in the popup.
|
||||
*/
|
||||
private int getMaxIconsWidth() {
|
||||
if( !verticallyAlignText )
|
||||
return 0;
|
||||
|
||||
Container parent = menuItem.getParent();
|
||||
if( !(parent instanceof JComponent) )
|
||||
return 0;
|
||||
|
||||
int maxWidth = FlatClientProperties.clientPropertyInt( (JComponent) parent, KEY_MAX_ICONS_WIDTH, -1 );
|
||||
if( maxWidth >= 0 )
|
||||
return maxWidth;
|
||||
|
||||
maxWidth = 0;
|
||||
|
||||
for( Component c : parent.getComponents() ) {
|
||||
if( !(c instanceof JMenuItem) )
|
||||
continue;
|
||||
|
||||
Icon icon = ((JMenuItem)c).getIcon();
|
||||
if( icon != null )
|
||||
maxWidth = Math.max( maxWidth, icon.getIconWidth() );
|
||||
}
|
||||
|
||||
((JComponent)parent).putClientProperty( KEY_MAX_ICONS_WIDTH, maxWidth );
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
static void clearClientProperties( Component c ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return;
|
||||
|
||||
JComponent jc = (JComponent) c;
|
||||
jc.putClientProperty( FlatMenuItemRenderer.KEY_MAX_ICONS_WIDTH, null );
|
||||
}
|
||||
|
||||
//---- class MinSizeIcon --------------------------------------------------
|
||||
|
||||
private class MinSizeIcon
|
||||
@@ -584,6 +628,7 @@ debug*/
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
int iconWidth = (delegate != null) ? delegate.getIconWidth() : 0;
|
||||
iconWidth = Math.max( iconWidth, getMaxIconsWidth() );
|
||||
return Math.max( iconWidth, scale( minimumIconSize.width ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ public class FlatMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ public class FlatMenuUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.LayoutManager;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
||||
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
@@ -64,6 +70,15 @@ public class FlatPopupMenuUI
|
||||
borderShared = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
LayoutManager layout = popupMenu.getLayout();
|
||||
if( layout == null || layout instanceof UIResource )
|
||||
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
@@ -106,4 +121,21 @@ public class FlatPopupMenuUI
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() );
|
||||
}
|
||||
|
||||
//---- class FlatMenuLayout -----------------------------------------------
|
||||
|
||||
protected static class FlatMenuLayout
|
||||
extends DefaultMenuLayout
|
||||
{
|
||||
public FlatMenuLayout( Container target, int axis ) {
|
||||
super( target, axis );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize( Container target ) {
|
||||
FlatMenuItemRenderer.clearClientProperties( target );
|
||||
|
||||
return super.preferredLayoutSize( target );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public class FlatRadioButtonMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -430,6 +430,7 @@ MenuItem.checkIcon = null
|
||||
MenuItem.margin = @menuItemMargin
|
||||
MenuItem.opaque = false
|
||||
MenuItem.borderPainted = true
|
||||
MenuItem.verticallyAlignText = true
|
||||
MenuItem.background = @menuBackground
|
||||
MenuItem.checkBackground = @menuCheckBackground
|
||||
MenuItem.checkMargins = 2,2,2,2
|
||||
|
||||
@@ -346,6 +346,7 @@ public class TestFlatStyleableInfo
|
||||
|
||||
private void menuItemRenderer( Map<String, Class<?>> expected ) {
|
||||
expectedMap( expected,
|
||||
"verticallyAlignText", boolean.class,
|
||||
"minimumWidth", int.class,
|
||||
"minimumIconSize", Dimension.class,
|
||||
"textAcceleratorGap", int.class,
|
||||
|
||||
@@ -495,6 +495,7 @@ public class TestFlatStyling
|
||||
}
|
||||
|
||||
private void menuItemRenderer( Consumer<String> applyStyle ) {
|
||||
applyStyle.accept( "verticallyAlignText: false" );
|
||||
applyStyle.accept( "minimumWidth: 10" );
|
||||
applyStyle.accept( "minimumIconSize: 16,16" );
|
||||
applyStyle.accept( "textAcceleratorGap: 28" );
|
||||
|
||||
Reference in New Issue
Block a user