1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.lf5.viewer.categoryexplorer;
18
19 import javax.swing.*;
20 import javax.swing.tree.TreePath;
21 import java.awt.*;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.awt.event.MouseAdapter;
25 import java.awt.event.MouseEvent;
26 import java.util.ArrayList;
27 import java.util.Enumeration;
28
29 /***
30 * CategoryNodeEditor
31 *
32 * @author Michael J. Sikorsky
33 * @author Robert Shaw
34 */
35
36
37
38 public class CategoryNodeEditor extends CategoryAbstractCellEditor {
39
40
41
42
43
44
45
46 protected CategoryNodeEditorRenderer _renderer;
47 protected CategoryNode _lastEditedNode;
48 protected JCheckBox _checkBox;
49 protected CategoryExplorerModel _categoryModel;
50 protected JTree _tree;
51
52
53
54
55
56
57
58
59
60 public CategoryNodeEditor(CategoryExplorerModel model) {
61 _renderer = new CategoryNodeEditorRenderer();
62 _checkBox = _renderer.getCheckBox();
63 _categoryModel = model;
64
65 _checkBox.addActionListener(new ActionListener() {
66 public void actionPerformed(ActionEvent e) {
67 _categoryModel.update(_lastEditedNode, _checkBox.isSelected());
68 stopCellEditing();
69 }
70 });
71
72 _renderer.addMouseListener(new MouseAdapter() {
73 public void mousePressed(MouseEvent e) {
74 if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
75 showPopup(_lastEditedNode, e.getX(), e.getY());
76 }
77 stopCellEditing();
78 }
79 });
80 }
81
82
83
84
85
86 public Component getTreeCellEditorComponent(JTree tree, Object value,
87 boolean selected, boolean expanded,
88 boolean leaf, int row) {
89 _lastEditedNode = (CategoryNode) value;
90 _tree = tree;
91
92 return _renderer.getTreeCellRendererComponent(tree,
93 value, selected, expanded,
94 leaf, row, true);
95
96 }
97
98 public Object getCellEditorValue() {
99 return _lastEditedNode.getUserObject();
100 }
101
102
103
104
105 protected JMenuItem createPropertiesMenuItem(final CategoryNode node) {
106 JMenuItem result = new JMenuItem("Properties");
107 result.addActionListener(new ActionListener() {
108 public void actionPerformed(ActionEvent e) {
109 showPropertiesDialog(node);
110 }
111 });
112 return result;
113 }
114
115 protected void showPropertiesDialog(CategoryNode node) {
116 JOptionPane.showMessageDialog(
117 _tree,
118 getDisplayedProperties(node),
119 "Category Properties: " + node.getTitle(),
120 JOptionPane.PLAIN_MESSAGE
121 );
122 }
123
124 protected Object getDisplayedProperties(CategoryNode node) {
125 ArrayList result = new ArrayList();
126 result.add("Category: " + node.getTitle());
127 if (node.hasFatalRecords()) {
128 result.add("Contains at least one fatal LogRecord.");
129 }
130 if (node.hasFatalChildren()) {
131 result.add("Contains descendants with a fatal LogRecord.");
132 }
133 result.add("LogRecords in this category alone: " +
134 node.getNumberOfContainedRecords());
135 result.add("LogRecords in descendant categories: " +
136 node.getNumberOfRecordsFromChildren());
137 result.add("LogRecords in this category including descendants: " +
138 node.getTotalNumberOfRecords());
139 return result.toArray();
140 }
141
142 protected void showPopup(CategoryNode node, int x, int y) {
143 JPopupMenu popup = new JPopupMenu();
144 popup.setSize(150, 400);
145
146
147
148 if (node.getParent() == null) {
149 popup.add(createRemoveMenuItem());
150 popup.addSeparator();
151 }
152 popup.add(createSelectDescendantsMenuItem(node));
153 popup.add(createUnselectDescendantsMenuItem(node));
154 popup.addSeparator();
155 popup.add(createExpandMenuItem(node));
156 popup.add(createCollapseMenuItem(node));
157 popup.addSeparator();
158 popup.add(createPropertiesMenuItem(node));
159 popup.show(_renderer, x, y);
160 }
161
162 protected JMenuItem createSelectDescendantsMenuItem(final CategoryNode node) {
163 JMenuItem selectDescendants =
164 new JMenuItem("Select All Descendant Categories");
165 selectDescendants.addActionListener(
166 new ActionListener() {
167 public void actionPerformed(ActionEvent e) {
168 _categoryModel.setDescendantSelection(node, true);
169 }
170 }
171 );
172 return selectDescendants;
173 }
174
175 protected JMenuItem createUnselectDescendantsMenuItem(final CategoryNode node) {
176 JMenuItem unselectDescendants =
177 new JMenuItem("Deselect All Descendant Categories");
178 unselectDescendants.addActionListener(
179
180 new ActionListener() {
181 public void actionPerformed(ActionEvent e) {
182 _categoryModel.setDescendantSelection(node, false);
183 }
184 }
185
186 );
187 return unselectDescendants;
188 }
189
190 protected JMenuItem createExpandMenuItem(final CategoryNode node) {
191 JMenuItem result = new JMenuItem("Expand All Descendant Categories");
192 result.addActionListener(new ActionListener() {
193 public void actionPerformed(ActionEvent e) {
194 expandDescendants(node);
195 }
196 });
197 return result;
198 }
199
200 protected JMenuItem createCollapseMenuItem(final CategoryNode node) {
201 JMenuItem result = new JMenuItem("Collapse All Descendant Categories");
202 result.addActionListener(new ActionListener() {
203 public void actionPerformed(ActionEvent e) {
204 collapseDescendants(node);
205 }
206 });
207 return result;
208 }
209
210 /***
211 * This featured was moved from the LogBrokerMonitor class
212 * to the CategoryNodeExplorer so that the Category tree
213 * could be pruned from the Category Explorer popup menu.
214 * This menu option only appears when a user right clicks on
215 * the Category parent node.
216 *
217 * See removeUnusedNodes()
218 */
219 protected JMenuItem createRemoveMenuItem() {
220 JMenuItem result = new JMenuItem("Remove All Empty Categories");
221 result.addActionListener(new ActionListener() {
222 public void actionPerformed(ActionEvent e) {
223 while (removeUnusedNodes() > 0) ;
224 }
225 });
226 return result;
227 }
228
229 protected void expandDescendants(CategoryNode node) {
230 Enumeration descendants = node.depthFirstEnumeration();
231 CategoryNode current;
232 while (descendants.hasMoreElements()) {
233 current = (CategoryNode) descendants.nextElement();
234 expand(current);
235 }
236 }
237
238 protected void collapseDescendants(CategoryNode node) {
239 Enumeration descendants = node.depthFirstEnumeration();
240 CategoryNode current;
241 while (descendants.hasMoreElements()) {
242 current = (CategoryNode) descendants.nextElement();
243 collapse(current);
244 }
245 }
246
247 /***
248 * Removes any inactive nodes from the Category tree.
249 */
250 protected int removeUnusedNodes() {
251 int count = 0;
252 CategoryNode root = _categoryModel.getRootCategoryNode();
253 Enumeration enumeration = root.depthFirstEnumeration();
254 while (enumeration.hasMoreElements()) {
255 CategoryNode node = (CategoryNode) enumeration.nextElement();
256 if (node.isLeaf() && node.getNumberOfContainedRecords() == 0
257 && node.getParent() != null) {
258 _categoryModel.removeNodeFromParent(node);
259 count++;
260 }
261 }
262
263 return count;
264 }
265
266 protected void expand(CategoryNode node) {
267 _tree.expandPath(getTreePath(node));
268 }
269
270 protected TreePath getTreePath(CategoryNode node) {
271 return new TreePath(node.getPath());
272 }
273
274 protected void collapse(CategoryNode node) {
275 _tree.collapsePath(getTreePath(node));
276 }
277
278
279
280
281
282
283
284
285
286 }