Source code: ledestin/swing/JEditableTree.java
1 /*
2 * Copyright (C) 2000-2001 Dmitry Macsema. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted under the terms of the following
6 * Open Source license:
7 *
8 * The GNU General Public License, version 2, or any later version, as
9 * published by the Free Software Foundation
10 * (http://www.fsf.org/copyleft/gpl.html);
11 */
12
13 package ledestin.swing;
14
15 import java.util.*;
16 import java.awt.event.*;
17 import javax.swing.*;
18 import javax.swing.tree.*;
19
20 public class JEditableTree extends JTree {
21 // strings to use as action names (for setActionCommand())
22 public static final String ACTION_ADD = "add_element";
23 public static final String ACTION_EDIT = "edit_element";
24 public static final String ACTION_REMOVE = "remove_element";
25 /**
26 A map to contain pairs of <code>Class</code>es and <code>JDialog</code>s
27 to show when adding or editing nodes of particular classes to the tree.
28 Thus, typical use of it would be
29 <code>dialogMap.put(<object implementing TreeNode>.getClass(), <instance of JDialog>)</code>
30 */
31 private HashMap dialogMap = new HashMap();
32
33 public JEditableTree(DefaultTreeModel newModel) {
34 super(newModel);
35 initInputMap();
36 }
37 public HashMap getDialogMap() {
38 return dialogMap;
39 }
40 protected void initInputMap() {
41 /*
42 InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
43
44 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0),
45 ACTION_ADD);
46 */
47 InputMap map = getInputMap();
48 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0),
49 ACTION_ADD);
50 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
51 ACTION_EDIT);
52 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
53 ACTION_REMOVE);
54 ActionMap actionMap = getActionMap();
55 actionMap.put(ACTION_ADD, new AddAction());
56 actionMap.put(ACTION_EDIT, new EditAction());
57 actionMap.put(ACTION_REMOVE, new RemoveAction());
58 }
59
60 //**********inner classes***************
61 class AddAction extends AbstractAction {
62 public void actionPerformed(ActionEvent e) {
63 // Check if the node allows children.
64 Object c = getLastSelectedPathComponent();
65 if (!(c instanceof EditableTreeNode)) {
66 return;
67 }
68 EditableTreeNode node = (EditableTreeNode)c;
69 if (node != null) {
70 //look if there's dialog for the selected node
71 Map map = getDialogMap();
72 try {
73 Class nodeClass = node.getChildClass();
74 if (map.containsKey(nodeClass)) {
75 JDialog dialog = (JDialog)map.get(nodeClass);
76 EditableDialog eDlg = (EditableDialog)dialog;
77 eDlg.setData(node.createNewChild());
78 dialog.setLocationRelativeTo(JEditableTree.this);
79 dialog.pack();
80 dialog.show();
81 if (eDlg.getReturnValue() == JOptionPane.OK_OPTION) {
82 node.insert((MutableTreeNode)eDlg.getData(), 0);
83 TreePath path = getSelectionPath();
84 TreePath newPath = getSelectionPath().pathByAddingChild(node);
85 TreeNode changed = node.getParent();
86 if (changed == null) {
87 changed = node;
88 }
89 ((DefaultTreeModel)getModel()).nodeStructureChanged(changed);
90 scrollPathToVisible(newPath);
91 setSelectionPath(path);
92 }
93 }
94 } catch (Exception ie) {
95 ie.printStackTrace();
96 }
97 }
98 }
99 }
100 class EditAction extends AbstractAction {
101 public void actionPerformed(ActionEvent e) {
102 MutableTreeNode node = (MutableTreeNode)getLastSelectedPathComponent();
103 if (node != null) {
104 //look if there's dialog for the selected node
105 Map map = getDialogMap();
106 Class nodeClass = node.getClass();
107 if (map.containsKey(nodeClass)) {
108 JDialog dialog = (JDialog)map.get(nodeClass);
109 EditableDialog eDlg = (EditableDialog)dialog;
110 try {
111 eDlg.setData(node);
112 dialog.setLocationRelativeTo(JEditableTree.this);
113 dialog.pack();
114 dialog.show();
115 if (eDlg.getReturnValue() == JOptionPane.OK_OPTION) {
116 eDlg.getData();
117 ((DefaultTreeModel)getModel()).nodeChanged(node);
118 }
119 } catch (Exception ie) {
120 ie.printStackTrace();
121 }
122 }
123 }
124 }
125 }
126 class RemoveAction extends AbstractAction {
127 public void actionPerformed(ActionEvent e) {
128 MutableTreeNode node = (MutableTreeNode)getLastSelectedPathComponent();
129 if (node != null) {
130 //look if there's dialog for the selected node
131 //if there's one, then it is allowed to remove
132 //given kind of node from the tree
133 Map map = getDialogMap();
134 Class nodeClass = node.getClass();
135 if (map.containsKey(nodeClass)) {
136 int result = JOptionPane.showConfirmDialog(JEditableTree.this,
137 "Delete the node?", "Delete node", 2);
138 if (result == JOptionPane.YES_OPTION) {
139 TreePath path = getSelectionPath().getParentPath();
140 MutableTreeNode parent = (MutableTreeNode)node.getParent();
141 if (parent != null && parent.getParent() != null) {
142 parent = (MutableTreeNode)parent.getParent();
143 }
144 node.removeFromParent();
145 ((DefaultTreeModel)getModel()).nodeStructureChanged(parent);
146 scrollPathToVisible(path);
147 expandPath(path);
148 setSelectionPath(path);
149 }
150 }
151 }
152 }
153 }
154 }