如果通过DynamicMenuContent隐藏所有菜单项,如何自动隐藏父菜单

时间:2017-08-10 10:03:05

标签: netbeans-8 netbeans-platform

我使用DynamicMenuContent

实现了基于用户身份验证和角色的菜单隐藏功能
/**
 * Presenter that displays menu item if, and only if the user has the specified role.
 */
public class RoleMenuPresenter
        extends JMenuItem
        implements DynamicMenuContent {
    private static final JComponent[] EMPTY = new JComponent[0];
    private final String roleName;
    private final AuthenticationDelegate delegate = (AuthenticationDelegate) SpringSingleton
            .getBean("authenticationDelegate");
    private final JComponent[] components = {this};
    private final JComponent[] emptyComponents = EMPTY;

    //~ Constructors ===================================================================================================
    /**
     * Constructs this presenter.
     *
     * @param a action to execute
     * @param roleName the rolename
     */
    public RoleMenuPresenter(Action a, String roleName) {
        super(a);
        this.roleName = roleName;
    }
    //~ Methods ========================================================================================================

    @Override
    public JComponent[] getMenuPresenters() {

        if (delegate.getStatusBean().hasRole(roleName)) {
            return components;
        }

        return emptyComponents;
    }

    @Override
    public JComponent[] synchMenuPresenters(JComponent[] jComponents) {
        return getMenuPresenters();
    }

    public String getRoleName() {
        return roleName;
    }

    public interface Provider
            extends Presenter.Menu {
        @Override
        RoleMenuPresenter getMenuPresenter();
    }
}

安全Action实施RoleMenuPresenter.Provider。菜单项按预期隐藏。但是,如果隐藏了菜单的所有项目,则会出现问题,仍然会显示菜单。例如:

  • 文件
    • 打印
    • 退出
  • 交易
    • A
    • C

如果隐藏了A,B和C,则交易仍然可见。我的问题是如何自动隐藏交易?谢谢。

1 个答案:

答案 0 :(得分:0)

我终于成功了。 JavaScript用于计算空文件夹路径。 MenuFolderUtil用于预热菜单。 ReheatMenus是文件系统提供程序,用于在内存DynamicLayerContent文件夹中提供。 *_hidden是主要条目。

MenuFolderUtil

MenuVisibilityUtil

ReheatMenus

final class MenuFolderUtil {

    static Set<String> findEmptyFolder() {
        Set<String> folderPaths = new LinkedHashSet<>();
        FileObject file = FileUtil.getConfigFile("Menu");
        Enumeration<? extends FileObject> folderEnumerations = file.getFolders(
                true);
        while (folderEnumerations.hasMoreElements()) {
            FileObject element = folderEnumerations.nextElement();
            folderPaths.add(element.getPath());
        }

        Enumeration<? extends FileObject> childrenEnum = file.getChildren(true);
        while (childrenEnum.hasMoreElements()) {
            FileObject element = childrenEnum.nextElement();

            if (element.isFolder()) {
                continue;
            }
            FileObject parent = element.getParent();
            String parentPath = parent.getPath();
            if (!folderPaths.contains(parentPath)) {
                continue;
            }

            Action action = FileUtil.getConfigObject(
                    element.getPath(),
                    Action.class);
            if (action instanceof Presenter.Menu) {
                JMenuItem presenter = ((Presenter.Menu) action).getMenuPresenter();
                if (presenter instanceof DynamicMenuContent) {
                    treatDynamicMenuContent(
                            (DynamicMenuContent) presenter,
                            folderPaths, buildParentPaths(element));
                } else {
                    folderPaths.removeAll(buildParentPaths(element));
                }
            } else if (action instanceof DynamicMenuContent) {
                treatDynamicMenuContent(
                        (DynamicMenuContent) action,
                        folderPaths,
                        buildParentPaths(element));
            } else if (action != null) {
                folderPaths.removeAll(buildParentPaths(element));
            }
        }
        return folderPaths;
    }

    private static void treatDynamicMenuContent(DynamicMenuContent presenter,
            Set<String> folderPaths, Set<String> c) {
        JComponent[] presenters = presenter.getMenuPresenters();
        if (presenters != null && presenters.length > 0) {
            folderPaths.removeAll(c);
        }
    }

    private static Set<String> buildParentPaths(FileObject fo) {
        Set<String> paths = new LinkedHashSet<>();
        for (FileObject parent = fo.getParent();
                parent != null; parent = parent.getParent()) {
            paths.add(parent.getPath());
        }
        return paths;
    }
}

DynamicLayerContent

/**
 * Adapted from {@code org.netbeans.core.ui.warmup.MenuWarmUpTask}.
 */
class ReheatMenus
        implements Runnable {

    static void launch() {
        EventQueue.invokeLater(new ReheatMenus());
    }

    private ReheatMenus() {}

    private static final RequestProcessor RP = new RequestProcessor(ReheatMenus.class);

    private MenuBar bar;
    private Component[] comps;

    @Override
    public void run() {
        if (EventQueue.isDispatchThread()) {
            if (bar == null) {
                Frame main = WindowManager.getDefault().getMainWindow();
                assert main != null;
                if (main instanceof JFrame) {
                    JMenuBar menuBar = ((JFrame) main).getJMenuBar();
                    if (menuBar instanceof MenuBar) {
                        bar = (MenuBar) menuBar;
                        RP.post(this);
                    }
                }
            } else {
                comps = bar.getComponents();
                RP.post(this);
            }
        } else if (comps != null) {
            walkMenu(comps);
        } else {
            bar.waitFinished();
            EventQueue.invokeLater(this);
        }
    }

    private void walkMenu(Component[] items) {
        for (Component item : items) {
            if (!(item instanceof JMenu)) {
                continue;
            }
            try {
                Class<?> cls = item.getClass();
                //noinspection JavaReflectionMemberAccess
                Method m = cls.getDeclaredMethod("doInitialize");
                m.setAccessible(true);
                m.invoke(item);
                walkMenu(((JMenu) item).getMenuComponents());
            } catch (Exception x) {
                // most likely a NoSuchMethodException on a dynamic submenu
            }
        }
    }

}

MenuVisibilityUtil

/**
 * File system which add system hidden folders.
 *
 * @author Thomas Edwin Santosa
 */
@ServiceProvider(service = FileSystem.class)
public class DynamicLayerContent
        extends MultiFileSystem {
    private static DynamicLayerContent INSTANCE;

    public DynamicLayerContent() {
        // will be created on startup, exactly once
        INSTANCE = this;
        setPropagateMasks(true); // permit *_hidden masks to be used
    }

    static void clear() {
        INSTANCE.setDelegates();
    }

    static void setHidden(Set<String> paths)
            throws IOException {
        FileSystem fileSystem = FileUtil.createMemoryFileSystem();
        for (String path : paths) {
            String pathHidden = path + "_hidden";
            String[] pathSplits = pathHidden.split("/");
            FileObject fo = fileSystem.getRoot();
            for (String folder : pathSplits) {
                fo = FileUtil.createFolder(fo, folder);
            }
        }
        INSTANCE.setDelegates(fileSystem);
    }
}

要使用此功能,请在插件中创建一个安装程序并调用/** * Utility for menu security. * * @author Thomas Edwin Santosa */ final class MenuVisibilityUtil { private static final Logger log = LoggerFactory.getLogger(MenuVisibilityUtil.class); private MenuVisibilityUtil() { } static void refresh() { Runnable run = new Runnable() { public void run() { Set<String> hiddenPaths = new HashSet<>(); Frame main = WindowManager.getDefault().getMainWindow(); assert main != null; if (main instanceof JFrame) { JFrame frame = (JFrame) main; JMenuBar menuBar = frame.getJMenuBar(); frame.setJMenuBar(null); DynamicLayerContent.clear(); try { DynamicLayerContent.setHidden(MenuFolderUtil.findEmptyFolder()); } catch (IOException e) { log.error("cannot delete menu {}", hiddenPaths, e); } frame.setJMenuBar(menuBar); ReheatMenus.launch(); } } }; if (EventQueue.isDispatchThread()) { run.run(); } else { EventQueue.invokeLater(run); } } } 如果有任何用户切换,您可能需要再次呼叫MenuVisibilityUtil.refresh();