0N/A/*
3840N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions
0N/A * are met:
0N/A *
0N/A * - Redistributions of source code must retain the above copyright
0N/A * notice, this list of conditions and the following disclaimer.
0N/A *
0N/A * - Redistributions in binary form must reproduce the above copyright
0N/A * notice, this list of conditions and the following disclaimer in the
0N/A * documentation and/or other materials provided with the distribution.
0N/A *
2362N/A * - Neither the name of Oracle nor the names of its
0N/A * contributors may be used to endorse or promote products derived
0N/A * from this software without specific prior written permission.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0N/A * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0N/A * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0N/A * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0N/A * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0N/A * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0N/A * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0N/A * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0N/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
4378N/A/*
4378N/A * This source code is provided to illustrate the usage of a given feature
4378N/A * or technique and has been deliberately simplified. Additional steps
4378N/A * required for a production-quality application, such as security checks,
4378N/A * input validation and proper error handling, might not be present in
4378N/A * this sample code.
4378N/A */
4378N/A
4378N/A
0N/A
3840N/Aimport java.lang.reflect.InvocationTargetException;
3840N/Aimport java.util.logging.Level;
3840N/Aimport java.util.logging.Logger;
0N/Aimport javax.swing.*;
0N/Aimport javax.swing.event.*;
0N/Aimport java.awt.BorderLayout;
0N/Aimport java.awt.Color;
0N/Aimport java.awt.Dimension;
0N/Aimport java.awt.FlowLayout;
0N/Aimport java.awt.event.ActionEvent;
0N/Aimport java.awt.event.ActionListener;
0N/Aimport java.util.*;
3840N/Aimport javax.swing.UIManager.LookAndFeelInfo;
0N/Aimport javax.swing.border.*;
0N/Aimport javax.swing.tree.*;
0N/A
3840N/A
0N/A/**
3840N/A * A demo for illustrating how to do different things with JTree.
3840N/A * The data that this displays is rather boring, that is each node will
3840N/A * have 7 children that have random names based on the fonts. Each node
3840N/A * is then drawn with that font and in a different color.
3840N/A * While the data isn't interesting the example illustrates a number
3840N/A * of things:
3840N/A *
3840N/A * For an example of dynamicaly loading children refer to DynamicTreeNode.
3840N/A * For an example of adding/removing/inserting/reloading refer to the inner
3840N/A * classes of this class, AddAction, RemovAction, InsertAction and
3840N/A * ReloadAction.
3840N/A * For an example of creating your own cell renderer refer to
3840N/A * SampleTreeCellRenderer.
3840N/A * For an example of subclassing JTreeModel for editing refer to
3840N/A * SampleTreeModel.
3840N/A *
3840N/A * @author Scott Violet
3840N/A */
3840N/Apublic final class SampleTree {
0N/A
0N/A /** Window for showing Tree. */
3840N/A protected JFrame frame;
0N/A /** Tree used for the example. */
3840N/A protected JTree tree;
0N/A /** Tree model. */
3840N/A protected DefaultTreeModel treeModel;
0N/A
0N/A /**
3840N/A * Constructs a new instance of SampleTree.
3840N/A */
0N/A public SampleTree() {
3840N/A // Trying to set Nimbus look and feel
0N/A try {
3840N/A for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
3840N/A if ("Nimbus".equals(info.getName())) {
3840N/A UIManager.setLookAndFeel(info.getClassName());
3840N/A break;
3840N/A }
3840N/A }
3840N/A } catch (Exception ignored) {
0N/A }
0N/A
3840N/A JMenuBar menuBar = constructMenuBar();
3840N/A JPanel panel = new JPanel(true);
0N/A
0N/A frame = new JFrame("SampleTree");
0N/A frame.getContentPane().add("Center", panel);
0N/A frame.setJMenuBar(menuBar);
0N/A frame.setBackground(Color.lightGray);
0N/A
0N/A /* Create the JTreeModel. */
0N/A DefaultMutableTreeNode root = createNewNode("Root");
0N/A treeModel = new SampleTreeModel(root);
0N/A
0N/A /* Create the tree. */
0N/A tree = new JTree(treeModel);
0N/A
0N/A /* Enable tool tips for the tree, without this tool tips will not
3840N/A be picked up. */
0N/A ToolTipManager.sharedInstance().registerComponent(tree);
0N/A
0N/A /* Make the tree use an instance of SampleTreeCellRenderer for
3840N/A drawing. */
0N/A tree.setCellRenderer(new SampleTreeCellRenderer());
0N/A
0N/A /* Make tree ask for the height of each row. */
0N/A tree.setRowHeight(-1);
0N/A
0N/A /* Put the Tree in a scroller. */
3840N/A JScrollPane sp = new JScrollPane();
0N/A sp.setPreferredSize(new Dimension(300, 300));
0N/A sp.getViewport().add(tree);
0N/A
0N/A /* And show it. */
0N/A panel.setLayout(new BorderLayout());
0N/A panel.add("Center", sp);
0N/A panel.add("South", constructOptionsPanel());
0N/A
3840N/A frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
0N/A frame.pack();
3840N/A frame.setVisible(true);
0N/A }
0N/A
0N/A /** Constructs a JPanel containing check boxes for the different
3840N/A * options that tree supports. */
3840N/A @SuppressWarnings("serial")
0N/A private JPanel constructOptionsPanel() {
3840N/A JCheckBox aCheckbox;
3840N/A JPanel retPanel = new JPanel(false);
3840N/A JPanel borderPane = new JPanel(false);
0N/A
0N/A borderPane.setLayout(new BorderLayout());
0N/A retPanel.setLayout(new FlowLayout());
0N/A
0N/A aCheckbox = new JCheckBox("show top level handles");
0N/A aCheckbox.setSelected(tree.getShowsRootHandles());
0N/A aCheckbox.addChangeListener(new ShowHandlesChangeListener());
0N/A retPanel.add(aCheckbox);
0N/A
0N/A aCheckbox = new JCheckBox("show root");
0N/A aCheckbox.setSelected(tree.isRootVisible());
0N/A aCheckbox.addChangeListener(new ShowRootChangeListener());
0N/A retPanel.add(aCheckbox);
0N/A
0N/A aCheckbox = new JCheckBox("editable");
0N/A aCheckbox.setSelected(tree.isEditable());
0N/A aCheckbox.addChangeListener(new TreeEditableChangeListener());
0N/A aCheckbox.setToolTipText("Triple click to edit");
0N/A retPanel.add(aCheckbox);
0N/A
0N/A borderPane.add(retPanel, BorderLayout.CENTER);
0N/A
0N/A /* Create a set of radio buttons that dictate what selection should
3840N/A be allowed in the tree. */
3840N/A ButtonGroup group = new ButtonGroup();
3840N/A JPanel buttonPane = new JPanel(false);
3840N/A JRadioButton button;
0N/A
0N/A buttonPane.setLayout(new FlowLayout());
0N/A buttonPane.setBorder(new TitledBorder("Selection Mode"));
0N/A button = new JRadioButton("Single");
0N/A button.addActionListener(new AbstractAction() {
3840N/A
3840N/A @Override
3840N/A public boolean isEnabled() {
3840N/A return true;
3840N/A }
3840N/A
0N/A public void actionPerformed(ActionEvent e) {
3840N/A tree.getSelectionModel().setSelectionMode(
3840N/A TreeSelectionModel.SINGLE_TREE_SELECTION);
0N/A }
0N/A });
0N/A group.add(button);
0N/A buttonPane.add(button);
0N/A button = new JRadioButton("Contiguous");
0N/A button.addActionListener(new AbstractAction() {
3840N/A
3840N/A @Override
3840N/A public boolean isEnabled() {
3840N/A return true;
3840N/A }
3840N/A
0N/A public void actionPerformed(ActionEvent e) {
3840N/A tree.getSelectionModel().setSelectionMode(
3840N/A TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
0N/A }
0N/A });
0N/A group.add(button);
0N/A buttonPane.add(button);
0N/A button = new JRadioButton("Discontiguous");
0N/A button.addActionListener(new AbstractAction() {
3840N/A
3840N/A @Override
3840N/A public boolean isEnabled() {
3840N/A return true;
3840N/A }
3840N/A
0N/A public void actionPerformed(ActionEvent e) {
3840N/A tree.getSelectionModel().setSelectionMode(
3840N/A TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
0N/A }
0N/A });
0N/A button.setSelected(true);
0N/A group.add(button);
0N/A buttonPane.add(button);
0N/A
0N/A borderPane.add(buttonPane, BorderLayout.SOUTH);
0N/A
0N/A // NOTE: This will be enabled in a future release.
0N/A // Create a label and combobox to determine how many clicks are
0N/A // needed to expand.
0N/A/*
0N/A JPanel clickPanel = new JPanel();
0N/A Object[] values = { "Never", new Integer(1),
3840N/A new Integer(2), new Integer(3) };
0N/A final JComboBox clickCBox = new JComboBox(values);
0N/A
0N/A clickPanel.setLayout(new FlowLayout());
0N/A clickPanel.add(new JLabel("Click count to expand:"));
0N/A clickCBox.setSelectedIndex(2);
0N/A clickCBox.addActionListener(new ActionListener() {
3840N/A public void actionPerformed(ActionEvent ae) {
3840N/A Object selItem = clickCBox.getSelectedItem();
0N/A
3840N/A if(selItem instanceof Integer)
3840N/A tree.setToggleClickCount(((Integer)selItem).intValue());
3840N/A else // Don't toggle
3840N/A tree.setToggleClickCount(0);
3840N/A }
0N/A });
0N/A clickPanel.add(clickCBox);
0N/A borderPane.add(clickPanel, BorderLayout.NORTH);
3840N/A */
0N/A return borderPane;
0N/A }
0N/A
0N/A /** Construct a menu. */
0N/A private JMenuBar constructMenuBar() {
3840N/A JMenu menu;
3840N/A JMenuBar menuBar = new JMenuBar();
3840N/A JMenuItem menuItem;
0N/A
0N/A /* Good ol exit. */
0N/A menu = new JMenu("File");
0N/A menuBar.add(menu);
0N/A
0N/A menuItem = menu.add(new JMenuItem("Exit"));
0N/A menuItem.addActionListener(new ActionListener() {
3840N/A
0N/A public void actionPerformed(ActionEvent e) {
0N/A System.exit(0);
3840N/A }
3840N/A });
0N/A
0N/A /* Tree related stuff. */
0N/A menu = new JMenu("Tree");
0N/A menuBar.add(menu);
0N/A
0N/A menuItem = menu.add(new JMenuItem("Add"));
0N/A menuItem.addActionListener(new AddAction());
0N/A
0N/A menuItem = menu.add(new JMenuItem("Insert"));
0N/A menuItem.addActionListener(new InsertAction());
0N/A
0N/A menuItem = menu.add(new JMenuItem("Reload"));
0N/A menuItem.addActionListener(new ReloadAction());
0N/A
0N/A menuItem = menu.add(new JMenuItem("Remove"));
0N/A menuItem.addActionListener(new RemoveAction());
0N/A
0N/A return menuBar;
0N/A }
0N/A
0N/A /**
3840N/A * Returns the TreeNode instance that is selected in the tree.
3840N/A * If nothing is selected, null is returned.
3840N/A */
0N/A protected DefaultMutableTreeNode getSelectedNode() {
3840N/A TreePath selPath = tree.getSelectionPath();
0N/A
3840N/A if (selPath != null) {
3840N/A return (DefaultMutableTreeNode) selPath.getLastPathComponent();
3840N/A }
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * Returns the selected TreePaths in the tree, may return null if
0N/A * nothing is selected.
0N/A */
0N/A protected TreePath[] getSelectedPaths() {
0N/A return tree.getSelectionPaths();
0N/A }
0N/A
0N/A protected DefaultMutableTreeNode createNewNode(String name) {
0N/A return new DynamicTreeNode(new SampleData(null, Color.black, name));
0N/A }
0N/A
3840N/A
0N/A /**
3840N/A * AddAction is used to add a new item after the selected item.
3840N/A */
3840N/A class AddAction extends Object implements ActionListener {
3840N/A
0N/A /** Number of nodes that have been added. */
3840N/A public int addCount;
0N/A
0N/A /**
3840N/A * Messaged when the user clicks on the Add menu item.
3840N/A * Determines the selection from the Tree and adds an item
3840N/A * after that. If nothing is selected, an item is added to
3840N/A * the root.
3840N/A */
0N/A public void actionPerformed(ActionEvent e) {
3840N/A DefaultMutableTreeNode lastItem = getSelectedNode();
3840N/A DefaultMutableTreeNode parent;
0N/A
0N/A /* Determine where to create the new node. */
3840N/A if (lastItem != null) {
3840N/A parent = (DefaultMutableTreeNode) lastItem.getParent();
3840N/A if (parent == null) {
3840N/A parent = (DefaultMutableTreeNode) treeModel.getRoot();
0N/A lastItem = null;
0N/A }
3840N/A } else {
3840N/A parent = (DefaultMutableTreeNode) treeModel.getRoot();
0N/A }
0N/A if (parent == null) {
0N/A // new root
3840N/A treeModel.setRoot(createNewNode("Added " + Integer.toString(
3840N/A addCount++)));
3840N/A } else {
3840N/A int newIndex;
3840N/A if (lastItem == null) {
0N/A newIndex = treeModel.getChildCount(parent);
3840N/A } else {
0N/A newIndex = parent.getIndex(lastItem) + 1;
3840N/A }
0N/A
0N/A /* Let the treemodel know. */
3840N/A treeModel.insertNodeInto(createNewNode("Added " + Integer.
3840N/A toString(addCount++)),
3840N/A parent, newIndex);
0N/A }
0N/A }
0N/A } // End of SampleTree.AddAction
0N/A
0N/A
0N/A /**
3840N/A * InsertAction is used to insert a new item before the selected item.
3840N/A */
3840N/A class InsertAction extends Object implements ActionListener {
3840N/A
0N/A /** Number of nodes that have been added. */
3840N/A public int insertCount;
0N/A
0N/A /**
3840N/A * Messaged when the user clicks on the Insert menu item.
3840N/A * Determines the selection from the Tree and inserts an item
3840N/A * after that. If nothing is selected, an item is added to
3840N/A * the root.
3840N/A */
0N/A public void actionPerformed(ActionEvent e) {
3840N/A DefaultMutableTreeNode lastItem = getSelectedNode();
3840N/A DefaultMutableTreeNode parent;
0N/A
0N/A /* Determine where to create the new node. */
3840N/A if (lastItem != null) {
3840N/A parent = (DefaultMutableTreeNode) lastItem.getParent();
3840N/A if (parent == null) {
3840N/A parent = (DefaultMutableTreeNode) treeModel.getRoot();
0N/A lastItem = null;
0N/A }
3840N/A } else {
3840N/A parent = (DefaultMutableTreeNode) treeModel.getRoot();
0N/A }
0N/A if (parent == null) {
0N/A // new root
3840N/A treeModel.setRoot(createNewNode("Inserted " + Integer.toString(
3840N/A insertCount++)));
3840N/A } else {
3840N/A int newIndex;
0N/A
3840N/A if (lastItem == null) {
0N/A newIndex = treeModel.getChildCount(parent);
3840N/A } else {
0N/A newIndex = parent.getIndex(lastItem);
3840N/A }
0N/A
0N/A /* Let the treemodel know. */
3840N/A treeModel.insertNodeInto(createNewNode("Inserted " + Integer.
3840N/A toString(insertCount++)),
3840N/A parent, newIndex);
0N/A }
0N/A }
0N/A } // End of SampleTree.InsertAction
0N/A
0N/A
0N/A /**
3840N/A * ReloadAction is used to reload from the selected node. If nothing
3840N/A * is selected, reload is not issued.
3840N/A */
3840N/A class ReloadAction extends Object implements ActionListener {
3840N/A
0N/A /**
3840N/A * Messaged when the user clicks on the Reload menu item.
3840N/A * Determines the selection from the Tree and asks the treemodel
3840N/A * to reload from that node.
3840N/A */
0N/A public void actionPerformed(ActionEvent e) {
3840N/A DefaultMutableTreeNode lastItem = getSelectedNode();
0N/A
3840N/A if (lastItem != null) {
0N/A treeModel.reload(lastItem);
3840N/A }
0N/A }
0N/A } // End of SampleTree.ReloadAction
0N/A
3840N/A
0N/A /**
3840N/A * RemoveAction removes the selected node from the tree. If
3840N/A * The root or nothing is selected nothing is removed.
3840N/A */
3840N/A class RemoveAction extends Object implements ActionListener {
3840N/A
0N/A /**
3840N/A * Removes the selected item as long as it isn't root.
3840N/A */
0N/A public void actionPerformed(ActionEvent e) {
0N/A TreePath[] selected = getSelectedPaths();
0N/A
0N/A if (selected != null && selected.length > 0) {
0N/A TreePath shallowest;
0N/A
0N/A // The remove process consists of the following steps:
0N/A // 1 - find the shallowest selected TreePath, the shallowest
0N/A // path is the path with the smallest number of path
0N/A // components.
0N/A // 2 - Find the siblings of this TreePath
0N/A // 3 - Remove from selected the TreePaths that are descendants
0N/A // of the paths that are going to be removed. They will
0N/A // be removed as a result of their ancestors being
0N/A // removed.
0N/A // 4 - continue until selected contains only null paths.
0N/A while ((shallowest = findShallowestPath(selected)) != null) {
0N/A removeSiblings(shallowest, selected);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Removes the sibling TreePaths of <code>path</code>, that are
0N/A * located in <code>paths</code>.
0N/A */
0N/A private void removeSiblings(TreePath path, TreePath[] paths) {
0N/A // Find the siblings
0N/A if (path.getPathCount() == 1) {
0N/A // Special case, set the root to null
0N/A for (int counter = paths.length - 1; counter >= 0; counter--) {
0N/A paths[counter] = null;
0N/A }
0N/A treeModel.setRoot(null);
3840N/A } else {
0N/A // Find the siblings of path.
0N/A TreePath parent = path.getParentPath();
3840N/A MutableTreeNode parentNode = (MutableTreeNode) parent.
3840N/A getLastPathComponent();
3840N/A ArrayList<TreePath> toRemove = new ArrayList<TreePath>();
0N/A
0N/A // First pass, find paths with a parent TreePath of parent
0N/A for (int counter = paths.length - 1; counter >= 0; counter--) {
3840N/A if (paths[counter] != null && paths[counter].getParentPath().
3840N/A equals(parent)) {
0N/A toRemove.add(paths[counter]);
0N/A paths[counter] = null;
0N/A }
0N/A }
0N/A
0N/A // Second pass, remove any paths that are descendants of the
0N/A // paths that are going to be removed. These paths are
0N/A // implicitly removed as a result of removing the paths in
0N/A // toRemove
0N/A int rCount = toRemove.size();
0N/A for (int counter = paths.length - 1; counter >= 0; counter--) {
0N/A if (paths[counter] != null) {
0N/A for (int rCounter = rCount - 1; rCounter >= 0;
3840N/A rCounter--) {
3840N/A if ((toRemove.get(rCounter)).isDescendant(
3840N/A paths[counter])) {
0N/A paths[counter] = null;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Sort the siblings based on position in the model
0N/A if (rCount > 1) {
0N/A Collections.sort(toRemove, new PositionComparator());
0N/A }
0N/A int[] indices = new int[rCount];
0N/A Object[] removedNodes = new Object[rCount];
0N/A for (int counter = rCount - 1; counter >= 0; counter--) {
3840N/A removedNodes[counter] = (toRemove.get(counter)).
3840N/A getLastPathComponent();
3840N/A indices[counter] = treeModel.getIndexOfChild(parentNode,
3840N/A removedNodes[counter]);
0N/A parentNode.remove(indices[counter]);
0N/A }
0N/A treeModel.nodesWereRemoved(parentNode, indices, removedNodes);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the TreePath with the smallest path count in
0N/A * <code>paths</code>. Will return null if there is no non-null
0N/A * TreePath is <code>paths</code>.
0N/A */
0N/A private TreePath findShallowestPath(TreePath[] paths) {
0N/A int shallowest = -1;
0N/A TreePath shallowestPath = null;
0N/A
0N/A for (int counter = paths.length - 1; counter >= 0; counter--) {
0N/A if (paths[counter] != null) {
0N/A if (shallowest != -1) {
0N/A if (paths[counter].getPathCount() < shallowest) {
0N/A shallowest = paths[counter].getPathCount();
0N/A shallowestPath = paths[counter];
0N/A if (shallowest == 1) {
0N/A return shallowestPath;
0N/A }
0N/A }
3840N/A } else {
0N/A shallowestPath = paths[counter];
0N/A shallowest = paths[counter].getPathCount();
0N/A }
0N/A }
0N/A }
0N/A return shallowestPath;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * An Comparator that bases the return value on the index of the
0N/A * passed in objects in the TreeModel.
0N/A * <p>
0N/A * This is actually rather expensive, it would be more efficient
0N/A * to extract the indices and then do the comparision.
0N/A */
3840N/A private class PositionComparator implements Comparator<TreePath> {
0N/A
3840N/A public int compare(TreePath p1, TreePath p2) {
3840N/A int p1Index = treeModel.getIndexOfChild(p1.getParentPath().
3840N/A getLastPathComponent(), p1.getLastPathComponent());
3840N/A int p2Index = treeModel.getIndexOfChild(p2.getParentPath().
3840N/A getLastPathComponent(), p2.getLastPathComponent());
3840N/A return p1Index - p2Index;
0N/A }
0N/A }
0N/A } // End of SampleTree.RemoveAction
0N/A
0N/A
0N/A /**
3840N/A * ShowHandlesChangeListener implements the ChangeListener interface
3840N/A * to toggle the state of showing the handles in the tree.
3840N/A */
3840N/A class ShowHandlesChangeListener extends Object implements ChangeListener {
3840N/A
0N/A public void stateChanged(ChangeEvent e) {
3840N/A tree.setShowsRootHandles(((JCheckBox) e.getSource()).isSelected());
0N/A }
0N/A } // End of class SampleTree.ShowHandlesChangeListener
0N/A
0N/A
0N/A /**
3840N/A * ShowRootChangeListener implements the ChangeListener interface
3840N/A * to toggle the state of showing the root node in the tree.
3840N/A */
3840N/A class ShowRootChangeListener extends Object implements ChangeListener {
3840N/A
0N/A public void stateChanged(ChangeEvent e) {
3840N/A tree.setRootVisible(((JCheckBox) e.getSource()).isSelected());
0N/A }
0N/A } // End of class SampleTree.ShowRootChangeListener
0N/A
0N/A
0N/A /**
3840N/A * TreeEditableChangeListener implements the ChangeListener interface
3840N/A * to toggle between allowing editing and now allowing editing in
3840N/A * the tree.
3840N/A */
3840N/A class TreeEditableChangeListener extends Object implements ChangeListener {
3840N/A
0N/A public void stateChanged(ChangeEvent e) {
3840N/A tree.setEditable(((JCheckBox) e.getSource()).isSelected());
0N/A }
0N/A } // End of class SampleTree.TreeEditableChangeListener
0N/A
3840N/A public static void main(String args[]) {
3840N/A try {
3840N/A SwingUtilities.invokeAndWait(new Runnable() {
0N/A
3840N/A @SuppressWarnings(value = "ResultOfObjectAllocationIgnored")
3840N/A public void run() {
3840N/A new SampleTree();
3840N/A }
3840N/A });
3840N/A } catch (InterruptedException ex) {
3840N/A Logger.getLogger(SampleTree.class.getName()).log(Level.SEVERE, null,
3840N/A ex);
3840N/A } catch (InvocationTargetException ex) {
3840N/A Logger.getLogger(SampleTree.class.getName()).log(Level.SEVERE, null,
3840N/A ex);
3840N/A }
0N/A }
0N/A}