com.smardec.ideaplugin.ideamousegestures.ActionHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.smardec.ideaplugin.ideamousegestures.ActionHelper.java

Source

/*
MouseGestures - pure Java library for recognition and processing mouse gestures.
Copyright (C) 2003-2005 Smardec
    
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
    
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package com.smardec.ideaplugin.ideamousegestures;

import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.geom.GeneralPath;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class ActionHelper {
    private static final Node[] EMPTY_NODE_ARRAY = new Node[0];
    private static final Icon GROUP_ICON = UIManager.getIcon("Tree.openIcon");
    private static final String ROOT_NODE_TEXT = "root";
    private static final Icon UNSELECTED_ARROW_ICON = new ArrowIcon(false);
    private static final Icon SELECTED_ARROW_ICON = new ArrowIcon(true);

    private static ActionHelper instance;

    private Node rootNode;
    private List<Node> actionNodes;

    public static ActionHelper getInstance() {
        if (instance == null) {
            instance = new ActionHelper();
        }
        return instance;
    }

    private static enum NodeType {
        GROUP, SIMPLE, SEPARATOR
    }

    private static class Node {
        private Node parent;
        private String text;
        private Icon icon;
        private NodeType nodeType;
        private AnAction action;
        private Node[] children;
        private String[] actionPath;

        private Node(NodeType nodeType, Node parent, String text, Icon icon, AnAction action) {
            this.nodeType = nodeType;
            this.parent = parent;
            this.text = text;
            this.icon = icon;
            this.action = action;
            this.children = null;
            if (this.nodeType == NodeType.SIMPLE) {
                List<String> strings = new LinkedList<String>();
                strings.add(text);
                while (parent != null && parent.parent != null) {
                    strings.add(parent.text);
                    parent = parent.parent;
                }
                Collections.reverse(strings);
                actionPath = strings.toArray(new String[strings.size()]);
            } else {
                actionPath = null;
            }
        }
    }

    private static class ArrowIcon implements Icon {
        private boolean selected;

        public ArrowIcon(boolean selected) {
            this.selected = selected;
        }

        public void paintIcon(Component c, Graphics g1D, int x, int y) {
            Graphics2D g = (Graphics2D) g1D;
            Object antialias = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
            Color color = g.getColor();

            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.translate(x, y);

            GeneralPath gp = new GeneralPath();
            gp.moveTo(3.5f, 3.5f);
            gp.lineTo(12.5f, 8);
            gp.lineTo(3.5f, 12.5f);
            gp.closePath();
            g.setColor(selected ? Color.LIGHT_GRAY : Color.DARK_GRAY);
            g.fill(gp);
            g.setColor(selected ? Color.WHITE : Color.BLACK);
            g.draw(gp);

            g.translate(-x, -y);
            g.setColor(color);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialias);
        }

        public int getIconWidth() {
            return 16;
        }

        public int getIconHeight() {
            return 16;
        }
    }

    private ActionHelper() {
        actionNodes = new LinkedList<Node>();
        rootNode = new Node(NodeType.GROUP, null, ROOT_NODE_TEXT, GROUP_ICON, null);
        AnAction anAction = ActionManager.getInstance().getAction(IdeActions.GROUP_MAIN_MENU);
        if (anAction instanceof DefaultActionGroup) {
            AnAction[] mainMenus = ((DefaultActionGroup) anAction).getChildren(null);
            List<Node> childrenNodes = new LinkedList<Node>();
            for (AnAction mainMenu : mainMenus) {
                childrenNodes.addAll(Arrays.asList(convert(rootNode, mainMenu, actionNodes)));
            }
            rootNode.children = childrenNodes.toArray(new Node[childrenNodes.size()]);
        }
    }

    public boolean isValidAction(String[] actionPath) {
        if (actionPath == null || actionPath.length == 0)
            return false;
        for (Node actionNode : actionNodes) {
            if (Arrays.equals(actionNode.actionPath, actionPath))
                return true;
        }
        return false;
    }

    public void invoke(String[] actionPath) {
        Node actionNode = findActionNode(actionPath);
        if (actionNode == null || actionNode.nodeType != NodeType.SIMPLE)
            return;
        actionNode.action.actionPerformed(new AnActionEvent(null, DataManager.getInstance().getDataContext(),
                ActionPlaces.UNKNOWN, actionNode.action.getTemplatePresentation(),
                com.intellij.openapi.actionSystem.ActionManager.getInstance(), 0));
    }

    public JPopupMenu createActionSelectionPopup(final IActionNodeSelectionListener selectionListener) {
        JPopupMenu actionSelectionPopupMenu = new JPopupMenu();
        Node root = rootNode;
        Node[] children = root.children;
        for (Node child : children) {
            if (child.nodeType == NodeType.SEPARATOR) {
                actionSelectionPopupMenu.addSeparator();
            } else {
                actionSelectionPopupMenu.add(createMenuItem(child, selectionListener));
            }
        }
        return actionSelectionPopupMenu;
    }

    public void constructView(JPanel panel, String[] actionPath, Color foreGround, boolean selected) {
        panel.removeAll();
        Node actionNode = findActionNode(actionPath);
        if (actionNode == null) {
            JLabel emptyLabel = new JLabel(" ");
            emptyLabel.setFont(emptyLabel.getFont().deriveFont(12f));
            panel.add(emptyLabel);
            panel.revalidate();
            return;
        }
        List<JLabel> labels = new LinkedList<JLabel>();
        Node parentNode = actionNode.parent;
        labels.add(getLabel(actionNode, foreGround));
        while (parentNode != null && parentNode.parent != null) {
            labels.add(getLabel(parentNode, foreGround));
            parentNode = parentNode.parent;
        }
        for (int i = labels.size() - 1; i >= 0; i--) {
            JLabel label = labels.get(i);
            panel.add(label);
            panel.add(Box.createHorizontalStrut(3));
            if (i > 0) {
                panel.add(new JLabel(selected ? SELECTED_ARROW_ICON : UNSELECTED_ARROW_ICON));
                panel.add(Box.createHorizontalStrut(3));
            }
        }
    }

    private Node findActionNode(String[] actionPath) {
        if (actionPath == null || actionPath.length == 0)
            return null;
        for (Node actionNode : actionNodes) {
            if (Arrays.equals(actionNode.actionPath, actionPath))
                return actionNode;
        }
        return null;
    }

    private static JMenuItem createMenuItem(final Node actionNode,
            final IActionNodeSelectionListener selectionListener) {
        switch (actionNode.nodeType) {
        case SIMPLE: {
            return new JMenuItem(new AbstractAction(actionNode.text, actionNode.icon) {
                public void actionPerformed(ActionEvent e) {
                    selectionListener.onSelect(actionNode.actionPath);
                }
            });
        }
        case GROUP: {
            JMenu menu = new JMenu(new AbstractAction(actionNode.text, actionNode.icon) {
                public void actionPerformed(ActionEvent e) {
                }
            });
            Node[] children = actionNode.children;
            for (Node child : children) {
                if (child.nodeType == NodeType.SEPARATOR) {
                    menu.addSeparator();
                } else {
                    menu.add(createMenuItem(child, selectionListener));
                }
            }
            return menu;
        }
        default:
            throw new IllegalArgumentException("Unexpected node type");
        }
    }

    private static Node[] convert(Node parent, AnAction action, List<Node> actionNodes) {
        if (action instanceof Separator)
            return new Node[] { new Node(NodeType.SEPARATOR, parent, null, null, null) };
        if (action instanceof DefaultActionGroup) {
            DefaultActionGroup defaultActionGroup = (DefaultActionGroup) action;
            Presentation presentation = defaultActionGroup.getTemplatePresentation();
            String text = presentation.getText();
            if (text == null) {
                List<Node> childrenNodes = new LinkedList<Node>();
                AnAction[] childrenActions = defaultActionGroup.getChildren(null);
                for (AnAction childAction : childrenActions) {
                    childrenNodes.addAll(Arrays.asList(convert(parent, childAction, actionNodes)));
                }
                return childrenNodes.toArray(new Node[childrenNodes.size()]);
            } else {
                Node groupActionNode = new Node(NodeType.GROUP, parent, text, GROUP_ICON, null);
                List<Node> childrenNodes = new LinkedList<Node>();
                AnAction[] childrenActions = defaultActionGroup.getChildren(null);
                for (AnAction childAction : childrenActions) {
                    childrenNodes.addAll(Arrays.asList(convert(groupActionNode, childAction, actionNodes)));
                }
                groupActionNode.children = childrenNodes.toArray(new Node[childrenNodes.size()]);
                return new Node[] { groupActionNode };
            }
        } else {
            if (action == null)
                return EMPTY_NODE_ARRAY;
            Presentation presentation = action.getTemplatePresentation();
            if (presentation == null)
                return EMPTY_NODE_ARRAY;
            String text = presentation.getText();
            if (text == null)
                return EMPTY_NODE_ARRAY;
            Node actionNode = new Node(NodeType.SIMPLE, parent, text, presentation.getIcon(), action);
            actionNodes.add(actionNode);
            return new Node[] { actionNode };
        }
    }

    private static JLabel getLabel(Node node, Color foreGround) {
        JLabel label = new JLabel(node.text, node.icon, JLabel.LEADING);
        label.setFont(label.getFont().deriveFont(12f));
        label.setForeground(foreGround);
        return label;
    }
}