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    }