001package jmri.util;
002
003import java.awt.event.ActionEvent;
004import java.awt.event.ActionListener;
005import java.awt.event.MouseAdapter;
006import java.awt.event.MouseEvent;
007import javax.swing.JComponent;
008import javax.swing.JMenuItem;
009import javax.swing.JPopupMenu;
010import javax.swing.JTree;
011import javax.swing.tree.DefaultMutableTreeNode;
012import javax.swing.tree.DefaultTreeModel;
013import javax.swing.tree.TreePath;
014
015/**
016 * JTree subclass that supports a popup menu.
017 * <p>
018 * From the
019 * <A HREF="http://www.java-tips.org/java-se-tips/javax.swing/have-a-popup-attached-to-a-jtree.html">Java
020 * Tips</a> web site.
021 */
022class JTreeWithPopup extends JTree implements ActionListener {
023
024    JPopupMenu popup;
025    JMenuItem mi;
026
027    JTreeWithPopup(DefaultMutableTreeNode dmtn) {
028        super(dmtn);
029        // define the popup
030        popup = new JPopupMenu();
031        mi = new JMenuItem("Insert a children");
032        mi.addActionListener(this);
033        mi.setActionCommand("insert");
034        popup.add(mi);
035        mi = new JMenuItem("Remove this node");
036        mi.addActionListener(this);
037        mi.setActionCommand("remove");
038        popup.add(mi);
039        popup.setOpaque(true);
040        popup.setLightWeightPopupEnabled(true);
041
042        addMouseListener(
043                new MouseAdapter() {
044                    @Override
045                    public void mouseReleased(MouseEvent e) {
046                        if (e.isPopupTrigger()) {
047                            popup.show((JComponent) e.getSource(), e.getX(), e.getY());
048                        }
049                    }
050                }
051        );
052
053    }
054
055    @Override
056    public void actionPerformed(ActionEvent ae) {
057        DefaultMutableTreeNode dmtn, node;
058
059        TreePath path = this.getSelectionPath();
060        dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
061        if (ae.getActionCommand().equals("insert")) {
062            node = new DefaultMutableTreeNode("children");
063            dmtn.add(node);
064            // thanks to Yong Zhang for the tip for refreshing the tree structure.
065            ((DefaultTreeModel) this.getModel()).nodeStructureChanged(dmtn);
066        }
067        if (ae.getActionCommand().equals("remove")) {
068            node = (DefaultMutableTreeNode) dmtn.getParent();
069            // Bug fix by essam
070            int nodeIndex = node.getIndex(dmtn); // declare an integer to hold the selected nodes index
071            dmtn.removeAllChildren();          // remove any children of selected node
072            node.remove(nodeIndex);            // remove the selected node, retain its siblings
073            ((DefaultTreeModel) this.getModel()).nodeStructureChanged(dmtn);
074        }
075    }
076}