001 package nl.cwi.sen1.error.viewer;
002
003 import java.awt.BorderLayout;
004 import java.awt.event.ActionEvent;
005 import java.net.URL;
006 import java.util.Enumeration;
007
008 import javax.swing.AbstractAction;
009 import javax.swing.Action;
010 import javax.swing.ImageIcon;
011 import javax.swing.JFrame;
012 import javax.swing.JPanel;
013 import javax.swing.JScrollPane;
014 import javax.swing.JToolBar;
015 import javax.swing.JTree;
016 import javax.swing.SwingConstants;
017 import javax.swing.tree.DefaultMutableTreeNode;
018 import javax.swing.tree.DefaultTreeCellRenderer;
019 import javax.swing.tree.DefaultTreeModel;
020 import javax.swing.tree.TreeNode;
021 import javax.swing.tree.TreePath;
022 import javax.swing.tree.TreeSelectionModel;
023
024 import nl.cwi.sen1.error.model.ErrorDecorator;
025 import errorapi.types.Summary;
026
027 public class ErrorPanel extends JPanel {
028 private JTree tree;
029
030 private ErrorDecorator errorDecorator;
031
032 private DefaultMutableTreeNode top;
033
034 private DefaultTreeModel treeModel;
035
036 private Enumeration<TreePath> expansionState;
037
038 public ErrorPanel() {
039 super(new BorderLayout());
040
041 JToolBar toolBar = new JToolBar("Error ToolBar",
042 SwingConstants.VERTICAL);
043 addButtons(toolBar);
044
045 errorDecorator = new ErrorDecorator();
046
047 top = new DefaultMutableTreeNode("Errors");
048 treeModel = new DefaultTreeModel(top);
049
050 tree = new JTree(treeModel);
051 tree.getSelectionModel().setSelectionMode(
052 TreeSelectionModel.SINGLE_TREE_SELECTION);
053 tree.setRootVisible(false);
054 tree.setShowsRootHandles(true);
055
056 DefaultTreeCellRenderer renderer = new ErrorTreeCellRenderer();
057
058 tree.setCellRenderer(renderer);
059
060 JScrollPane scrollPane = new JScrollPane(tree);
061 add(toolBar, BorderLayout.WEST);
062 add(scrollPane, BorderLayout.CENTER);
063 }
064
065 public JTree getTree() {
066 return tree;
067 }
068
069 public void saveExpansionState() {
070 expansionState = tree.getExpandedDescendants(new TreePath(tree
071 .getModel().getRoot()));
072 }
073
074 public void loadExpansionState() {
075 if (expansionState != null) {
076 while (expansionState.hasMoreElements()) {
077 TreePath treePath = expansionState.nextElement();
078 tree.expandPath(treePath);
079 }
080 }
081 }
082
083 public void addError(Summary summary) {
084 errorDecorator.addErrors(top, summary);
085 saveExpansionState();
086 ((DefaultTreeModel) tree.getModel()).reload();
087 loadExpansionState();
088 tree.expandPath(new TreePath(top));
089 }
090
091 public void removeAllMatchingErrors(String producer, String id) {
092 errorDecorator.removeAllMatchingErrors(top, producer, id);
093 saveExpansionState();
094 treeModel.reload();
095 loadExpansionState();
096 }
097
098 public void removeAllMatchingErrors(String path) {
099 errorDecorator.removeAllMatchingErrors(top, path);
100 saveExpansionState();
101 treeModel.reload();
102 loadExpansionState();
103 }
104
105 public void expandAll(JTree tree, boolean expand) {
106 TreeNode root = (TreeNode) tree.getModel().getRoot();
107
108 // Traverse tree from root
109 expandAll(tree, new TreePath(root), expand);
110 }
111
112 private void expandAll(JTree tree, TreePath parent, boolean expand) {
113 // Traverse children
114 TreeNode node = (TreeNode) parent.getLastPathComponent();
115 if (node.getChildCount() >= 0) {
116 for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
117 TreeNode n = (TreeNode) e.nextElement();
118 TreePath path = parent.pathByAddingChild(n);
119 expandAll(tree, path, expand);
120 }
121 }
122
123 // Expansion or collapse must be done bottom-up
124 if (expand) {
125 tree.expandPath(parent);
126 } else {
127 tree.collapsePath(parent);
128 }
129 }
130
131 private void addButtons(JToolBar toolBar) {
132 URL zoomInUrl = getClass().getResource(
133 "/toolbarButtonGraphics/general/ZoomIn16.gif");
134 Action expandAction = new AbstractAction("Expand All", new ImageIcon(
135 zoomInUrl)) {
136 {
137 putValue(Action.SHORT_DESCRIPTION, "Expand All");
138 }
139
140 public void actionPerformed(ActionEvent e) {
141 expandAll(tree, true);
142 }
143 };
144 toolBar.add(expandAction);
145 URL zoomOutUrl = getClass().getResource(
146 "/toolbarButtonGraphics/general/ZoomOut16.gif");
147 Action collapseAction = new AbstractAction("Collapse All",
148 new ImageIcon(zoomOutUrl)) {
149 {
150 putValue(Action.SHORT_DESCRIPTION, "Collapse All");
151 }
152 public void actionPerformed(ActionEvent e) {
153 expandAll(tree, false);
154 tree.expandPath(new TreePath(tree.getModel().getRoot()));
155 }
156 };
157 toolBar.add(collapseAction);
158
159 URL errorGroupUrl = getClass().getResource(
160 "/toolbarButtonGraphics/general/Stop16.gif");
161 Action groupAction = new AbstractAction("Group by error",
162 new ImageIcon(errorGroupUrl)) {
163 {
164 putValue(Action.SHORT_DESCRIPTION, "Group by error");
165 }
166 public void actionPerformed(ActionEvent e) {
167 errorDecorator.groupOnDescription((DefaultMutableTreeNode) tree
168 .getModel().getRoot());
169 ((DefaultTreeModel) tree.getModel()).reload();
170 tree.expandPath(new TreePath(top));
171 }
172 };
173 toolBar.add(groupAction);
174
175 URL fileGroupUrl = getClass().getResource(
176 "/toolbarButtonGraphics/general/Edit16.gif");
177 Action fileGroupAction = new AbstractAction("Group by file",
178 new ImageIcon(fileGroupUrl)) {
179 {
180 putValue(Action.SHORT_DESCRIPTION, "Group by file");
181 }
182 public void actionPerformed(ActionEvent e) {
183 errorDecorator.groupOnFile((DefaultMutableTreeNode) tree
184 .getModel().getRoot());
185 ((DefaultTreeModel) tree.getModel()).reload();
186 tree.expandPath(new TreePath(top));
187 }
188 };
189 toolBar.add(fileGroupAction);
190
191 URL unGroupUrl = getClass().getResource(
192 "/toolbarButtonGraphics/general/Undo16.gif");
193 Action unGroupAction = new AbstractAction("Ungroup", new ImageIcon(
194 unGroupUrl)) {
195 {
196 putValue(Action.SHORT_DESCRIPTION, "Ungroup");
197 }
198 public void actionPerformed(ActionEvent e) {
199 errorDecorator.unGroup((DefaultMutableTreeNode) tree.getModel()
200 .getRoot());
201 ((DefaultTreeModel) tree.getModel()).reload();
202 tree.expandPath(new TreePath(top));
203 }
204 };
205 toolBar.add(unGroupAction);
206 }
207
208 private static void createAndShowGUI() {
209 JFrame frame = new JFrame("Error Viewer");
210 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
211
212 ErrorPanel newContentPane = new ErrorPanel();
213 newContentPane.setOpaque(true); // content panes must be opaque
214 frame.setContentPane(newContentPane);
215
216 frame.pack();
217 frame.setVisible(true);
218 }
219
220 public static void main(String[] args) {
221 javax.swing.SwingUtilities.invokeLater(new Runnable() {
222 public void run() {
223 createAndShowGUI();
224 }
225 });
226 }
227 }