package com.imyeyu.fx.ui.components; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import java.util.List; /** * 支持最小尺寸的菜单,默认 90 * * @author 夜雨 * @since 2023-03-10 11:14 */ public class ContextMenu extends javafx.scene.control.ContextMenu { /** 当菜单项 {@link Menu#getProperties()} 携带此标记时,该菜单不继承最小宽度属性 */ public static final String NOT_EXTENDS_FLAG = "NOT_EXTENDS_FLAG"; private static final String STYLE_TEMPLATE = "-fx-min-width: %s; -fx-pref-width: %s"; /** * 标准构造 * * @param items 菜单项 */ public ContextMenu(MenuItem... items) { super(items); getItems().addListener((ListChangeListener) c -> { while (c.next()) { if (c.wasAdded()) { updateMinWidth(getItems()); } } }); minWidthProperty().addListener((obs, o, n) -> updateMinWidth(getItems())); setMinWidth(90); } private void updateMinWidth(List items) { for (MenuItem item : items) { if (item instanceof Menu menu) { if (!menu.getProperties().containsKey(NOT_EXTENDS_FLAG)) { boolean isItemsMenu = false; // 为 true 时表示子菜单是一般菜单项,继续应用最小宽度 ObservableList subItems = menu.getItems(); for (MenuItem subItem : subItems) { if (subItem.getClass().equals(MenuItem.class)) { isItemsMenu = true; break; } } if (isItemsMenu) { updateMinWidth(menu.getItems()); } } } else { item.setStyle(STYLE_TEMPLATE.formatted(getMinWidth(), getMinWidth())); } } } }