/*
 * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */



import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.*;
import javax.swing.tree.*;


/**
 * A demo for illustrating how to do different things with JTree.
 * The data that this displays is rather boring, that is each node will
 * have 7 children that have random names based on the fonts.  Each node
 * is then drawn with that font and in a different color.
 * While the data isn't interesting the example illustrates a number
 * of things:
 *
 * For an example of dynamicaly loading children refer to DynamicTreeNode.
 * For an example of adding/removing/inserting/reloading refer to the inner
 *     classes of this class, AddAction, RemovAction, InsertAction and
 *     ReloadAction.
 * For an example of creating your own cell renderer refer to
 *     SampleTreeCellRenderer.
 * For an example of subclassing JTreeModel for editing refer to
 *     SampleTreeModel.
 *
 * @author Scott Violet
 */
public final class SampleTree {

    /** Window for showing Tree. */
    protected JFrame frame;
    /** Tree used for the example. */
    protected JTree tree;
    /** Tree model. */
    protected DefaultTreeModel treeModel;

    /**
     * Constructs a new instance of SampleTree.
     */
    public SampleTree() {
        // Trying to set Nimbus look and feel
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception ignored) {
        }

        JMenuBar menuBar = constructMenuBar();
        JPanel panel = new JPanel(true);

        frame = new JFrame("SampleTree");
        frame.getContentPane().add("Center", panel);
        frame.setJMenuBar(menuBar);
        frame.setBackground(Color.lightGray);

        /* Create the JTreeModel. */
        DefaultMutableTreeNode root = createNewNode("Root");
        treeModel = new SampleTreeModel(root);

        /* Create the tree. */
        tree = new JTree(treeModel);

        /* Enable tool tips for the tree, without this tool tips will not
        be picked up. */
        ToolTipManager.sharedInstance().registerComponent(tree);

        /* Make the tree use an instance of SampleTreeCellRenderer for
        drawing. */
        tree.setCellRenderer(new SampleTreeCellRenderer());

        /* Make tree ask for the height of each row. */
        tree.setRowHeight(-1);

        /* Put the Tree in a scroller. */
        JScrollPane sp = new JScrollPane();
        sp.setPreferredSize(new Dimension(300, 300));
        sp.getViewport().add(tree);

        /* And show it. */
        panel.setLayout(new BorderLayout());
        panel.add("Center", sp);
        panel.add("South", constructOptionsPanel());

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    /** Constructs a JPanel containing check boxes for the different
     * options that tree supports. */
    private JPanel constructOptionsPanel() {
        JCheckBox aCheckbox;
        JPanel retPanel = new JPanel(false);
        JPanel borderPane = new JPanel(false);

        borderPane.setLayout(new BorderLayout());
        retPanel.setLayout(new FlowLayout());

        aCheckbox = new JCheckBox("show top level handles");
        aCheckbox.setSelected(tree.getShowsRootHandles());
        aCheckbox.addChangeListener(new ShowHandlesChangeListener());
        retPanel.add(aCheckbox);

        aCheckbox = new JCheckBox("show root");
        aCheckbox.setSelected(tree.isRootVisible());
        aCheckbox.addChangeListener(new ShowRootChangeListener());
        retPanel.add(aCheckbox);

        aCheckbox = new JCheckBox("editable");
        aCheckbox.setSelected(tree.isEditable());
        aCheckbox.addChangeListener(new TreeEditableChangeListener());
        aCheckbox.setToolTipText("Triple click to edit");
        retPanel.add(aCheckbox);

        borderPane.add(retPanel, BorderLayout.CENTER);

        /* Create a set of radio buttons that dictate what selection should
        be allowed in the tree. */
        ButtonGroup group = new ButtonGroup();
        JPanel buttonPane = new JPanel(false);
        JRadioButton button;

        buttonPane.setLayout(new FlowLayout());
        buttonPane.setBorder(new TitledBorder("Selection Mode"));
        button = new JRadioButton("Single");
        button.addActionListener(new AbstractAction() {

            @Override
            public boolean isEnabled() {
                return true;
            }

            public void actionPerformed(ActionEvent e) {
                tree.getSelectionModel().setSelectionMode(
                        TreeSelectionModel.SINGLE_TREE_SELECTION);
            }
        });
        group.add(button);
        buttonPane.add(button);
        button = new JRadioButton("Contiguous");
        button.addActionListener(new AbstractAction() {

            @Override
            public boolean isEnabled() {
                return true;
            }

            public void actionPerformed(ActionEvent e) {
                tree.getSelectionModel().setSelectionMode(
                        TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
            }
        });
        group.add(button);
        buttonPane.add(button);
        button = new JRadioButton("Discontiguous");
        button.addActionListener(new AbstractAction() {

            @Override
            public boolean isEnabled() {
                return true;
            }

            public void actionPerformed(ActionEvent e) {
                tree.getSelectionModel().setSelectionMode(
                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
            }
        });
        button.setSelected(true);
        group.add(button);
        buttonPane.add(button);

        borderPane.add(buttonPane, BorderLayout.SOUTH);

        // NOTE: This will be enabled in a future release.
        // Create a label and combobox to determine how many clicks are
        // needed to expand.
/*
        JPanel               clickPanel = new JPanel();
        Object[]             values = { "Never", new Integer(1),
        new Integer(2), new Integer(3) };
        final JComboBox      clickCBox = new JComboBox(values);

        clickPanel.setLayout(new FlowLayout());
        clickPanel.add(new JLabel("Click count to expand:"));
        clickCBox.setSelectedIndex(2);
        clickCBox.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {
        Object       selItem = clickCBox.getSelectedItem();

        if(selItem instanceof Integer)
        tree.setToggleClickCount(((Integer)selItem).intValue());
        else // Don't toggle
        tree.setToggleClickCount(0);
        }
        });
        clickPanel.add(clickCBox);
        borderPane.add(clickPanel, BorderLayout.NORTH);
         */
        return borderPane;
    }

    /** Construct a menu. */
    private JMenuBar constructMenuBar() {
        JMenu menu;
        JMenuBar menuBar = new JMenuBar();
        JMenuItem menuItem;

        /* Good ol exit. */
        menu = new JMenu("File");
        menuBar.add(menu);

        menuItem = menu.add(new JMenuItem("Exit"));
        menuItem.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        /* Tree related stuff. */
        menu = new JMenu("Tree");
        menuBar.add(menu);

        menuItem = menu.add(new JMenuItem("Add"));
        menuItem.addActionListener(new AddAction());

        menuItem = menu.add(new JMenuItem("Insert"));
        menuItem.addActionListener(new InsertAction());

        menuItem = menu.add(new JMenuItem("Reload"));
        menuItem.addActionListener(new ReloadAction());

        menuItem = menu.add(new JMenuItem("Remove"));
        menuItem.addActionListener(new RemoveAction());

        return menuBar;
    }

    /**
     * Returns the TreeNode instance that is selected in the tree.
     * If nothing is selected, null is returned.
     */
    protected DefaultMutableTreeNode getSelectedNode() {
        TreePath selPath = tree.getSelectionPath();

        if (selPath != null) {
            return (DefaultMutableTreeNode) selPath.getLastPathComponent();
        }
        return null;
    }

    /**
     * Returns the selected TreePaths in the tree, may return null if
     * nothing is selected.
     */
    protected TreePath[] getSelectedPaths() {
        return tree.getSelectionPaths();
    }

    protected DefaultMutableTreeNode createNewNode(String name) {
        return new DynamicTreeNode(new SampleData(null, Color.black, name));
    }


    /**
     * AddAction is used to add a new item after the selected item.
     */
    class AddAction extends Object implements ActionListener {

        /** Number of nodes that have been added. */
        public int addCount;

        /**
         * Messaged when the user clicks on the Add menu item.
         * Determines the selection from the Tree and adds an item
         * after that.  If nothing is selected, an item is added to
         * the root.
         */
        public void actionPerformed(ActionEvent e) {
            DefaultMutableTreeNode lastItem = getSelectedNode();
            DefaultMutableTreeNode parent;

            /* Determine where to create the new node. */
            if (lastItem != null) {
                parent = (DefaultMutableTreeNode) lastItem.getParent();
                if (parent == null) {
                    parent = (DefaultMutableTreeNode) treeModel.getRoot();
                    lastItem = null;
                }
            } else {
                parent = (DefaultMutableTreeNode) treeModel.getRoot();
            }
            if (parent == null) {
                // new root
                treeModel.setRoot(createNewNode("Added " + Integer.toString(
                        addCount++)));
            } else {
                int newIndex;
                if (lastItem == null) {
                    newIndex = treeModel.getChildCount(parent);
                } else {
                    newIndex = parent.getIndex(lastItem) + 1;
                }

                /* Let the treemodel know. */
                treeModel.insertNodeInto(createNewNode("Added " + Integer.
                        toString(addCount++)),
                        parent, newIndex);
            }
        }
    } // End of SampleTree.AddAction


    /**
     * InsertAction is used to insert a new item before the selected item.
     */
    class InsertAction extends Object implements ActionListener {

        /** Number of nodes that have been added. */
        public int insertCount;

        /**
         * Messaged when the user clicks on the Insert menu item.
         * Determines the selection from the Tree and inserts an item
         * after that.  If nothing is selected, an item is added to
         * the root.
         */
        public void actionPerformed(ActionEvent e) {
            DefaultMutableTreeNode lastItem = getSelectedNode();
            DefaultMutableTreeNode parent;

            /* Determine where to create the new node. */
            if (lastItem != null) {
                parent = (DefaultMutableTreeNode) lastItem.getParent();
                if (parent == null) {
                    parent = (DefaultMutableTreeNode) treeModel.getRoot();
                    lastItem = null;
                }
            } else {
                parent = (DefaultMutableTreeNode) treeModel.getRoot();
            }
            if (parent == null) {
                // new root
                treeModel.setRoot(createNewNode("Inserted " + Integer.toString(
                        insertCount++)));
            } else {
                int newIndex;

                if (lastItem == null) {
                    newIndex = treeModel.getChildCount(parent);
                } else {
                    newIndex = parent.getIndex(lastItem);
                }

                /* Let the treemodel know. */
                treeModel.insertNodeInto(createNewNode("Inserted " + Integer.
                        toString(insertCount++)),
                        parent, newIndex);
            }
        }
    } // End of SampleTree.InsertAction


    /**
     * ReloadAction is used to reload from the selected node.  If nothing
     * is selected, reload is not issued.
     */
    class ReloadAction extends Object implements ActionListener {

        /**
         * Messaged when the user clicks on the Reload menu item.
         * Determines the selection from the Tree and asks the treemodel
         * to reload from that node.
         */
        public void actionPerformed(ActionEvent e) {
            DefaultMutableTreeNode lastItem = getSelectedNode();

            if (lastItem != null) {
                treeModel.reload(lastItem);
            }
        }
    } // End of SampleTree.ReloadAction


    /**
     * RemoveAction removes the selected node from the tree.  If
     * The root or nothing is selected nothing is removed.
     */
    class RemoveAction extends Object implements ActionListener {

        /**
         * Removes the selected item as long as it isn't root.
         */
        public void actionPerformed(ActionEvent e) {
            TreePath[] selected = getSelectedPaths();

            if (selected != null && selected.length > 0) {
                TreePath shallowest;

                // The remove process consists of the following steps:
                // 1 - find the shallowest selected TreePath, the shallowest
                //     path is the path with the smallest number of path
                //     components.
                // 2 - Find the siblings of this TreePath
                // 3 - Remove from selected the TreePaths that are descendants
                //     of the paths that are going to be removed. They will
                //     be removed as a result of their ancestors being
                //     removed.
                // 4 - continue until selected contains only null paths.
                while ((shallowest = findShallowestPath(selected)) != null) {
                    removeSiblings(shallowest, selected);
                }
            }
        }

        /**
         * Removes the sibling TreePaths of <code>path</code>, that are
         * located in <code>paths</code>.
         */
        private void removeSiblings(TreePath path, TreePath[] paths) {
            // Find the siblings
            if (path.getPathCount() == 1) {
                // Special case, set the root to null
                for (int counter = paths.length - 1; counter >= 0; counter--) {
                    paths[counter] = null;
                }
                treeModel.setRoot(null);
            } else {
                // Find the siblings of path.
                TreePath parent = path.getParentPath();
                MutableTreeNode parentNode = (MutableTreeNode) parent.
                        getLastPathComponent();
                ArrayList<TreePath> toRemove = new ArrayList<TreePath>();

                // First pass, find paths with a parent TreePath of parent
                for (int counter = paths.length - 1; counter >= 0; counter--) {
                    if (paths[counter] != null && paths[counter].getParentPath().
                            equals(parent)) {
                        toRemove.add(paths[counter]);
                        paths[counter] = null;
                    }
                }

                // Second pass, remove any paths that are descendants of the
                // paths that are going to be removed. These paths are
                // implicitly removed as a result of removing the paths in
                // toRemove
                int rCount = toRemove.size();
                for (int counter = paths.length - 1; counter >= 0; counter--) {
                    if (paths[counter] != null) {
                        for (int rCounter = rCount - 1; rCounter >= 0;
                                rCounter--) {
                            if ((toRemove.get(rCounter)).isDescendant(
                                    paths[counter])) {
                                paths[counter] = null;
                            }
                        }
                    }
                }

                // Sort the siblings based on position in the model
                if (rCount > 1) {
                    Collections.sort(toRemove, new PositionComparator());
                }
                int[] indices = new int[rCount];
                Object[] removedNodes = new Object[rCount];
                for (int counter = rCount - 1; counter >= 0; counter--) {
                    removedNodes[counter] = (toRemove.get(counter)).
                            getLastPathComponent();
                    indices[counter] = treeModel.getIndexOfChild(parentNode,
                            removedNodes[counter]);
                    parentNode.remove(indices[counter]);
                }
                treeModel.nodesWereRemoved(parentNode, indices, removedNodes);
            }
        }

        /**
         * Returns the TreePath with the smallest path count in
         * <code>paths</code>. Will return null if there is no non-null
         * TreePath is <code>paths</code>.
         */
        private TreePath findShallowestPath(TreePath[] paths) {
            int shallowest = -1;
            TreePath shallowestPath = null;

            for (int counter = paths.length - 1; counter >= 0; counter--) {
                if (paths[counter] != null) {
                    if (shallowest != -1) {
                        if (paths[counter].getPathCount() < shallowest) {
                            shallowest = paths[counter].getPathCount();
                            shallowestPath = paths[counter];
                            if (shallowest == 1) {
                                return shallowestPath;
                            }
                        }
                    } else {
                        shallowestPath = paths[counter];
                        shallowest = paths[counter].getPathCount();
                    }
                }
            }
            return shallowestPath;
        }


        /**
         * An Comparator that bases the return value on the index of the
         * passed in objects in the TreeModel.
         * <p>
         * This is actually rather expensive, it would be more efficient
         * to extract the indices and then do the comparision.
         */
        private class PositionComparator implements Comparator<TreePath> {

            public int compare(TreePath p1, TreePath p2) {
                int p1Index = treeModel.getIndexOfChild(p1.getParentPath().
                        getLastPathComponent(), p1.getLastPathComponent());
                int p2Index = treeModel.getIndexOfChild(p2.getParentPath().
                        getLastPathComponent(), p2.getLastPathComponent());
                return p1Index - p2Index;
            }
        }
    } // End of SampleTree.RemoveAction


    /**
     * ShowHandlesChangeListener implements the ChangeListener interface
     * to toggle the state of showing the handles in the tree.
     */
    class ShowHandlesChangeListener extends Object implements ChangeListener {

        public void stateChanged(ChangeEvent e) {
            tree.setShowsRootHandles(((JCheckBox) e.getSource()).isSelected());
        }
    } // End of class SampleTree.ShowHandlesChangeListener


    /**
     * ShowRootChangeListener implements the ChangeListener interface
     * to toggle the state of showing the root node in the tree.
     */
    class ShowRootChangeListener extends Object implements ChangeListener {

        public void stateChanged(ChangeEvent e) {
            tree.setRootVisible(((JCheckBox) e.getSource()).isSelected());
        }
    } // End of class SampleTree.ShowRootChangeListener


    /**
     * TreeEditableChangeListener implements the ChangeListener interface
     * to toggle between allowing editing and now allowing editing in
     * the tree.
     */
    class TreeEditableChangeListener extends Object implements ChangeListener {

        public void stateChanged(ChangeEvent e) {
            tree.setEditable(((JCheckBox) e.getSource()).isSelected());
        }
    } // End of class SampleTree.TreeEditableChangeListener

    public static void main(String[] args) {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {

                @SuppressWarnings(value = "ResultOfObjectAllocationIgnored")
                public void run() {
                    new SampleTree();
                }
            });
        } catch (InterruptedException ex) {
            Logger.getLogger(SampleTree.class.getName()).log(Level.SEVERE, null,
                    ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(SampleTree.class.getName()).log(Level.SEVERE, null,
                    ex);
        }
    }
}
