Clover coverage report - clover
Coverage timestamp: Sat Oct 8 2005 22:54:17 EDT
file stats: LOC: 191   Methods: 10
NCLOC: 149   Classes: 4
 
 Source file Conditionals Statements Methods TOTAL
ComponentTree.java 80% 98.7% 100% 94%
coverage coverage
 1   
 package abbot.editor;
 2   
 
 3   
 import java.awt.*;
 4   
 import java.awt.event.*;
 5   
 import javax.swing.*;
 6   
 import javax.swing.event.*;
 7   
 import javax.swing.tree.*;
 8   
 import java.net.URL;
 9   
 
 10   
 import abbot.finder.*;
 11   
 import abbot.util.*;
 12   
 
 13   
 /** Provides a Tree view into a given Hierarchy of components.  Refreshes its
 14   
     display based on changes to the default AWT hierarchy.  
 15   
     The selection path is preserved to the extent possible across changes in
 16   
     the hierarchy.
 17   
  */
 18   
 public class ComponentTree extends JTree {
 19   
     private Hierarchy hierarchy;
 20   
     private ComponentNode root;
 21   
     private HierarchyMonitor monitor;
 22   
     private DefaultTreeModel model;
 23   
     private transient boolean ignoreSelectionChanges;
 24   
     /** Hash of class name to icon. */
 25   
     private ComponentTreeIcons icons = new ComponentTreeIcons();
 26   
 
 27   
     /** Supports optionally suppressing selection notifications while
 28   
         the hierarchy is reloading.
 29   
     */ 
 30   
     private class SelectionModel extends DefaultTreeSelectionModel {
 31   
         private transient boolean settingSelection;
 32  12
         protected void fireValueChanged(TreeSelectionEvent e) {
 33  12
             if (settingSelection || ignoreSelectionChanges)
 34  7
                 return;
 35  5
             super.fireValueChanged(e);
 36   
         }
 37   
     }
 38   
 
 39   
     private class HierarchyMonitor implements AWTEventListener {
 40  1712
         public void eventDispatched(AWTEvent ev) {
 41  1712
             switch(ev.getID()) {
 42  8
             case WindowEvent.WINDOW_OPENED:
 43  22
             case WindowEvent.WINDOW_CLOSED:
 44  10
             case ComponentEvent.COMPONENT_SHOWN: {
 45  40
                 Component c = ((ComponentEvent)ev).getComponent();
 46  40
                 if (hierarchy.contains(c)) {
 47  26
                     reload(hierarchy.getParent(c));
 48   
                 }
 49  40
                 break;
 50   
             }
 51  1114
             case ContainerEvent.COMPONENT_ADDED:
 52  150
             case ContainerEvent.COMPONENT_REMOVED: {
 53  1264
                 ContainerEvent e = (ContainerEvent)ev;
 54  1264
                 Component c = e.getComponent();
 55  1264
                 Window w = AWT.getWindow(c);
 56   
                 // CellRendererPanes send out these events in swarms,
 57   
                 // every time they repaint a cell, so ignore them
 58  1264
                 if (!(c instanceof CellRendererPane)
 59   
                     && hierarchy.contains(c)
 60   
                     && w != null && hierarchy.contains(w)) {
 61   
                     // TODO: delay reload on tooltip hide to allow access to
 62   
                     // the tooltip; otherwise the tooltip will go away and be
 63   
                     // removed from the tree as soon as the cursor moves to
 64   
                     // the tree to manipulate it.
 65  122
                     reload(c);
 66   
                 }
 67  1264
                 break;
 68   
             }
 69  408
             default:
 70  408
                 break;
 71   
             }
 72   
         }
 73   
     }
 74   
 
 75   
     private class Renderer extends DefaultTreeCellRenderer {
 76  8
         public Renderer() {
 77  8
             URL url = getClass().getResource("icons/component.gif");
 78  8
             if (url != null) {
 79  8
                 setLeafIcon(new ImageIcon(url));
 80   
             }
 81  8
             url = getClass().getResource("icons/container.gif");
 82  8
             if (url != null) {
 83  8
                 setOpenIcon(new ImageIcon(url));
 84  8
                 setClosedIcon(new ImageIcon(url));
 85   
             }
 86   
         }
 87  285
         public Component getTreeCellRendererComponent(JTree tree,
 88   
                                                       Object value,
 89   
                                                       boolean sel,
 90   
                                                       boolean exp,
 91   
                                                       boolean leaf,
 92   
                                                       int row,
 93   
                                                       boolean focus) {
 94  285
             Component c =
 95   
                 super.getTreeCellRendererComponent(tree, value,
 96   
                                                    sel, exp, leaf,
 97   
                                                    row, focus);
 98  285
             if (c instanceof JLabel) {
 99  285
                 JLabel label = (JLabel)c;
 100  285
                 Icon icon = null;
 101  285
                 if (value == root) {
 102  129
                     URL url = getClass().
 103   
                         getResource("icons/hierarchy-root.gif");
 104  129
                     if (url != null)
 105  129
                         icon = new ImageIcon(url);
 106   
                 }
 107   
                 else {
 108  156
                     Component c1 = ((ComponentNode)value).getComponent();
 109  156
                     if (c1 != null) {
 110  132
                         icon = icons.getIcon(c1.getClass());
 111   
                     }
 112   
                 }
 113  285
                 if (icon != null) {
 114  261
                     label.setIcon(icon);
 115   
                 }
 116   
             }
 117  285
             return c;
 118   
         }
 119   
     }
 120   
 
 121  8
     public ComponentTree(Hierarchy h) {
 122  8
         super(new ComponentNode(h));
 123  8
         setSelectionModel(new SelectionModel());
 124  8
         setCellRenderer(new Renderer());
 125  8
         setShowsRootHandles(true);
 126  8
         setScrollsOnExpand(true);
 127   
 
 128  8
         hierarchy = h;
 129  8
         model = (DefaultTreeModel)getModel();
 130  8
         root = (ComponentNode)model.getRoot();
 131   
 
 132  8
         monitor = new HierarchyMonitor();
 133  8
         long mask = ContainerEvent.CONTAINER_EVENT_MASK
 134   
             | ComponentEvent.COMPONENT_EVENT_MASK
 135   
             | WindowEvent.WINDOW_EVENT_MASK;
 136  8
         new WeakAWTEventListener(monitor, mask);
 137   
     }
 138   
 
 139  2
     public void setHierarchy(Hierarchy h) {
 140  2
         hierarchy = h;
 141  2
         root.reload(h);
 142  2
         reload();
 143   
     }
 144   
 
 145   
     /** Set the current selection path, ensuring that it is visible. */
 146  13
     public void setSelectionPath(TreePath path) {
 147  13
         super.setSelectionPath(path);
 148  13
         makeVisible(path);
 149  13
         Rectangle rect = getPathBounds(path);
 150  13
         if (rect != null)
 151  13
             scrollRectToVisible(rect);
 152   
     }
 153   
 
 154   
     /** Returns the path to the given component.  If the component does not
 155   
      * exist in the current hierarchy, returns as much of its parent path as
 156   
      * does exist.  
 157   
      */
 158  7
     public TreePath getPath(Component comp) {
 159  7
         return root.getPath(comp);
 160   
     }
 161   
 
 162   
     /** Reloads the entire hierarchy. */
 163  3
     public void reload() {
 164  3
         reload(null);
 165   
     }
 166   
 
 167   
     /** Reloads the hierarchy starting at the given component. */
 168  180
     public void reload(Component comp) {
 169  180
         ComponentNode node = comp != null ? root.getNode(comp) : root;
 170  180
         TreePath path = getSelectionPath();
 171  180
         Component selected = path == null 
 172   
             ? null : ((ComponentNode)path.getLastPathComponent()).getComponent();
 173  180
         if (node == null)
 174  0
             node = root;
 175   
 
 176   
         // suppress selection change notifications until we're certain we
 177   
         // can't restore the original selection.
 178  180
         ignoreSelectionChanges = true;
 179  180
         node.reload();
 180  180
         model.reload(node);
 181  180
         if (selected != null) {
 182  10
             TreePath newPath = root.getPath(selected);
 183   
             // if the selection is exactly the same as it was before the
 184   
             // reload, suppress selection change notifications
 185  10
             ignoreSelectionChanges = path.equals(newPath);
 186  10
             setSelectionPath(newPath);
 187   
         }
 188  180
         ignoreSelectionChanges = false;
 189   
     }
 190   
 }
 191