package krasa.mavenrun.analyzer.action; import java.awt.*; import java.util.ArrayList; import java.util.Enumeration; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import krasa.mavenrun.analyzer.MyTreeUserObject; import org.jetbrains.idea.maven.model.MavenArtifactNode; import org.jetbrains.idea.maven.project.MavenProject; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.Project; import com.intellij.ui.PopupHandler; /** * @author Vojtech Krasa */ public class RightTreePopupHandler extends PopupHandler { private final Project project; private final MavenProject mavenProject; protected final JTree tree; public RightTreePopupHandler(Project project, MavenProject mavenProject, JTree tree) { this.project = project; this.mavenProject = mavenProject; this.tree = tree; } private DefaultMutableTreeNode getRoot() { return (DefaultMutableTreeNode) getModel().getRoot(); } private DefaultTreeModel getModel() { return (DefaultTreeModel) tree.getModel(); } @SuppressWarnings("Duplicates") public void invokePopup(final Component comp, final int x, final int y) { final DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if (selectedNode == null) { return; } final MyTreeUserObject myTreeUserObject = (MyTreeUserObject) selectedNode.getUserObject(); final MavenArtifactNode mavenArtifactNode = myTreeUserObject.getMavenArtifactNode(); DefaultActionGroup actionGroup = new DefaultActionGroup(); if (myTreeUserObject.getMavenArtifactNode().getParent() == null) { actionGroup.add(new JumpToSourceAction(project, mavenProject, mavenArtifactNode)); } else { actionGroup.add(new JumpToSourceAction(project, mavenProject, mavenArtifactNode)); actionGroup.add(getExcludeAction(selectedNode, mavenArtifactNode)); } ActionManager.getInstance().createActionPopupMenu("", actionGroup).getComponent().show(comp, x, y); } private ExcludeDependencyAction getExcludeAction(final DefaultMutableTreeNode selectedNode, MavenArtifactNode mavenArtifactNode) { return new ExcludeDependencyAction(project, mavenProject, mavenArtifactNode) { @Override public void dependencyExcluded() { removeTreeNodes(); } private void removeTreeNodes() { // imagine conflict for d3 // root // L d1 // | L d2 // | | L d3 // | L d3 // L ... something else containing d3 // After d3 is excluded; must remove d2 and also d1 from the tree. But when d2 is excluded, remove only // d2. // when d2 is excluded, remove d3 for d2, but not d3 for d1 if (selectedNode.getParent() != getRoot()) { removeNodeNearestToRoot(selectedNode); return; } // find d1 DefaultMutableTreeNode oldestParentDependency = (DefaultMutableTreeNode) selectedNode.getFirstChild(); while (oldestParentDependency.getChildCount() > 0) { oldestParentDependency = (DefaultMutableTreeNode) oldestParentDependency.getFirstChild(); } // find d1, d2 java.util.List<DefaultMutableTreeNode> leafsForRemoval = findAllLeafs((MyTreeUserObject) oldestParentDependency.getUserObject()); // remove both d3s for d1 and d2 for (DefaultMutableTreeNode defaultMutableTreeNode : leafsForRemoval) { removeNodeNearestToRoot(defaultMutableTreeNode); } } private void removeNodeNearestToRoot(DefaultMutableTreeNode nodeForRemoval) { TreeNode nodeForRemovalNearestToRoot = nodeForRemoval; while (nodeForRemovalNearestToRoot.getParent() != null && nodeForRemovalNearestToRoot.getParent() != getRoot()) { nodeForRemovalNearestToRoot = nodeForRemovalNearestToRoot.getParent(); } getModel().removeNodeFromParent((MutableTreeNode) nodeForRemovalNearestToRoot); } private java.util.List<DefaultMutableTreeNode> findAllLeafs(MyTreeUserObject userObject) { final ArrayList<DefaultMutableTreeNode> result = new ArrayList<DefaultMutableTreeNode>(); visitAllNodes(getRoot(), userObject, result); return result; } private void visitAllNodes(DefaultMutableTreeNode node, MyTreeUserObject lookedUpObject, ArrayList<DefaultMutableTreeNode> result) { if (node.getChildCount() > 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement(); visitAllNodes(n, lookedUpObject, result); } } else { // only leafs process(node, lookedUpObject, result); } } private void process(DefaultMutableTreeNode node, MyTreeUserObject lookedUpObject, ArrayList<DefaultMutableTreeNode> result) { final MyTreeUserObject userObject = (MyTreeUserObject) node.getUserObject(); if (userObject != null && lookedUpObject.getArtifact().equals(userObject.getArtifact())) { result.add(node); } } }; } }