Clover coverage report - clover
Coverage timestamp: Sat Oct 8 2005 22:54:17 EDT
file stats: LOC: 207   Methods: 13
NCLOC: 148   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CompactHierarchy.java 84.5% 94.9% 92.3% 90.6%
coverage coverage
 1   
 package abbot.editor;
 2   
 
 3   
 import java.awt.*;
 4   
 import javax.swing.*;
 5   
 import java.util.*;
 6   
 
 7   
 import abbot.util.AWT;
 8   
 import abbot.finder.Hierarchy;
 9   
 
 10   
 /** Provides a condensed, more easily readable version of the original
 11   
     hierarchy.
 12   
 */ 
 13   
 // TODO: figure out how to more cleanly put popups under their invokers (maybe
 14   
 // have to scan the whole hierarchy each time).
 15   
 public class CompactHierarchy implements Hierarchy {
 16   
     
 17   
     private boolean compact = true;
 18   
     private Hierarchy hierarchy;
 19   
 
 20  15
     public CompactHierarchy(Hierarchy original) {
 21  15
         this.hierarchy = original;
 22   
     }
 23   
 
 24  2
     public void setCompact(boolean compact) {
 25  2
         this.compact = compact;
 26   
     }
 27   
 
 28  1545
     public boolean isCompact() { return compact; }
 29   
 
 30  75
     public Collection getRoots() {
 31  75
         return hierarchy.getRoots();
 32   
     }
 33   
 
 34  1055
     public Container getParent(Component c) {
 35   
         // In the component hierarchy, show popup menus directly beneath their
 36   
         // invoker 
 37  1055
         if (compact && c instanceof JPopupMenu) {
 38  138
             Component invoker = ((JPopupMenu)c).getInvoker();
 39  138
             if (invoker instanceof Container)
 40  138
                 return (Container)invoker;
 41   
         }
 42  917
         if (compact && c instanceof JToolTip) {
 43  0
             return ((JToolTip)c).getComponent();
 44   
         }
 45  917
         Container parent = hierarchy.getParent(c);
 46  917
         if (compact) {
 47  908
             while (parent != null && isElided(parent)) {
 48  258
                 parent = getParent(parent);
 49   
             }
 50   
         }
 51  917
         return parent;
 52   
     }
 53   
 
 54  1228
     public boolean contains(Component c) {
 55  1228
         return hierarchy.contains(c);
 56   
     }
 57   
 
 58  0
     public void dispose(Window w) {
 59  0
         hierarchy.dispose(w);
 60   
     }
 61   
 
 62   
     /** Returns whether the given component is completely ignored (including
 63   
         its children) in the hierarchy.
 64   
     */
 65  241
     private boolean isIgnored(Component c) {
 66  241
         if (AWT.isTransientPopup(c))
 67  8
             return true;
 68  233
         return c instanceof JScrollBar
 69   
             && c.getParent() instanceof JScrollPane;
 70   
     }
 71   
 
 72   
     /** Returns whether the given component is omitted from the component
 73   
      * hierarchy when compact is turned on (its children may be shown).
 74   
      * For example, a JScrollPane's viewport is elided so that the scrolled
 75   
      * content shows up directly beneath the scroll pane.
 76   
      */
 77  1785
     private boolean isElided(Component c) {
 78   
         // JPanel or JWindow transient popups
 79  1785
         if (AWT.isTransientPopup(c)) {
 80  9
             return true;
 81   
         }
 82  1776
         if (c instanceof Container) {
 83   
             // Only windows that are heavyweight popups are elided
 84  1776
             if (c instanceof Window)
 85  345
                 return false;
 86  1431
             if (c instanceof JPopupMenu
 87   
                 && ((JPopupMenu)c).getInvoker() instanceof JMenu)
 88  27
                 return true;
 89   
             // Content pane on heavyweight popup
 90  1404
             if (AWT.isContentPane(c)
 91   
                 && AWT.isTransientPopup(SwingUtilities.getWindowAncestor(c)))
 92  0
                 return true;
 93   
         }
 94   
 
 95  1404
         Container parent = c.getParent();
 96  1404
         if (parent instanceof JScrollPane) {
 97   
             // Ignore scrollbars and viewport, but not headers
 98  90
             return c instanceof JScrollBar
 99   
                 || c instanceof JViewport;
 100   
         }
 101   
 
 102  1314
         return parent instanceof RootPaneContainer
 103   
             || parent instanceof JRootPane;
 104   
     }
 105   
 
 106   
     /** Provide a list of a Component's children, sans any transient popups
 107   
      * Keep track of any popups encountered.
 108   
      */
 109   
     // heavyweights are subwindows of Window?
 110   
     // lightweights are subpanels of Window?
 111  418
     public Collection getComponents(Component c) {
 112  418
         if (c == null || !(c instanceof Container))
 113  0
             return new ArrayList();
 114   
 
 115  418
         ArrayList list = new ArrayList();
 116  418
         if (compact) {
 117   
             // Display menu contents directly beneath menus
 118  418
             if (c instanceof JMenu) {
 119  38
                 return getComponents(((JMenu)c).getPopupMenu());
 120   
             }
 121   
         }
 122  380
         Iterator iter = hierarchy.getComponents(c).iterator();
 123  380
         while (iter.hasNext()) {
 124  764
             Component k = (Component)iter.next();
 125  764
             if (compact && isElided(k)) {
 126   
                 // Only add children if the component itself is not totally
 127   
                 // ignored. 
 128  241
                 if (!isIgnored(k)) {
 129  187
                     list.addAll(getComponents(k));
 130   
                 }
 131   
             }
 132   
             else {
 133  523
                 list.add(k);
 134   
             }
 135   
         }
 136   
 
 137  380
         list.addAll(findInvokerPopups(c));
 138   
 
 139  380
         return list;
 140   
     }
 141   
 
 142   
     /** Scan for popups which have been invoked by the given invoker. */
 143  380
     private Collection findInvokerPopups(Component invoker) {
 144  380
         ArrayList popups = new ArrayList();
 145  380
         Window root = AWT.getWindow(invoker);
 146   
         // heavyweight popups are sub-windows of the invoker's window
 147  380
         Collection parents =
 148   
             new ArrayList(Arrays.asList(root.getOwnedWindows()));
 149   
         // lightweight popups show up on the window's layered pane
 150  380
         if (root instanceof JWindow
 151   
             || root instanceof JFrame
 152   
             || root instanceof JDialog) {
 153  345
             JRootPane rp = ((RootPaneContainer)root).getRootPane();
 154   
             // work around VM bug on RootPaneContainer.getLayeredPane()
 155   
             // which sometimes results in a NPE
 156  345
             if (rp != null) {
 157  345
                 JLayeredPane lp = rp.getLayeredPane();
 158  345
                 if (lp != null) {
 159  345
                     parents.addAll(Arrays.asList(lp.getComponents()));
 160   
                 }
 161   
             }
 162   
         }
 163  380
         Iterator iter = parents.iterator();
 164  380
         while (iter.hasNext()) {
 165  559
             Component c = (Component)iter.next();
 166  559
             JComponent popup = findInvokedPopup(invoker, c);
 167  559
             if (popup != null) {
 168  5
                 popups.add(popup);
 169   
             }
 170   
         }
 171  380
         return popups;
 172   
     }
 173   
 
 174   
     /** Returns the invoked popup found under the given parent (if any). */
 175  559
     private JComponent findInvokedPopup(Component invoker, Component parent) {
 176  559
         if (AWT.isTransientPopup(parent)) {
 177  39
             JComponent popup = findPopup((Container)parent);
 178  39
             if (popup != null
 179   
                 && (!(popup instanceof JPopupMenu)
 180   
                     || !(getParent(popup) instanceof JMenu))) {
 181  35
                 if (getParent(popup) == invoker) {
 182  5
                     return popup;
 183   
                 }
 184   
             }
 185   
         }
 186  554
         return null;
 187   
     }
 188   
 
 189   
     /** Return the popup descendent of the given known transient popup
 190   
      * container.
 191   
      */
 192  159
     private JComponent findPopup(Container c) {
 193  159
         JComponent popup = null;
 194  159
         Component[] kids = c.getComponents();
 195  159
         for (int i=0;i < kids.length && popup == null;i++) {
 196  155
             if (kids[i] instanceof JPopupMenu
 197   
                 || kids[i] instanceof JToolTip) {
 198  35
                 popup = (JComponent)kids[i];
 199   
             }
 200  120
             else if (kids[i] instanceof Container) {
 201  120
                 popup = findPopup((Container)kids[i]);
 202   
             }
 203   
         }
 204  159
         return popup;
 205   
     }
 206   
 }
 207