001    /*
002     * Created on Oct 19, 2007
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2007-2010 the original author or authors.
015     */
016    package org.fest.swing.hierarchy;
017    
018    import static org.fest.swing.awt.AWT.isAppletViewer;
019    import static org.fest.swing.awt.AWT.isSharedInvisibleFrame;
020    
021    import java.awt.*;
022    import java.util.Collection;
023    
024    import org.fest.swing.annotation.RunsInCurrentThread;
025    import org.fest.swing.monitor.WindowMonitor;
026    import org.fest.util.VisibleForTesting;
027    
028    /**
029     * Understands access to the current AWT hierarchy.
030     *
031     * @author Alex Ruiz
032     * @author Yvonne Wang
033     */
034    public class ExistingHierarchy implements ComponentHierarchy {
035    
036      private static WindowMonitor windowMonitor = WindowMonitor.instance();
037    
038      private final ParentFinder parentFinder;
039      private final ChildrenFinder childrenFinder;
040    
041      /** Creates a new </code>{@link ExistingHierarchy}</code>. */
042      public ExistingHierarchy() {
043        this(new ParentFinder(), new ChildrenFinder());
044      }
045    
046      @VisibleForTesting
047      ExistingHierarchy(ParentFinder parentFinder, ChildrenFinder childrenFinder) {
048        this.parentFinder = parentFinder;
049        this.childrenFinder = childrenFinder;
050      }
051    
052      /** {@inheritDoc} */
053      public Collection<? extends Container> roots() {
054        return windowMonitor.rootWindows();
055      }
056    
057      /**
058       * Return the parent for the given component.
059       * <p>
060       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
061       * responsible for calling this method from the EDT.
062       * </p>
063       * @param c the given component.
064       * @return the parent for the given component.
065       */
066      @RunsInCurrentThread
067      public Container parentOf(Component c) {
068        return parentFinder.parentOf(c);
069      }
070    
071      /**
072       * Returns whether the given component is reachable from any of the root windows. The default is to consider all
073       * components to be contained in the hierarchy, whether they are reachable or not.
074       * @param c the given component.
075       * @return <code>true</code>.
076       */
077      public boolean contains(Component c) {
078        return true;
079      }
080    
081      /**
082       * Returns all descendants of interest of the given component.
083       * <p>
084       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
085       * responsible for calling this method from the EDT.
086       * </p>
087       * @param c the given component.
088       * @return all descendants of interest of the given component.
089       */
090      @RunsInCurrentThread
091      public Collection<Component> childrenOf(Component c) {
092        return childrenFinder.childrenOf(c);
093      }
094    
095      /**
096       * Properly dispose of the given window, making it and its native resources available for garbage collection.
097       * <p>
098       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
099       * responsible for calling this method from the EDT.
100       * </p>
101       * @param w the window to dispose.
102       */
103      @RunsInCurrentThread
104      public void dispose(Window w) {
105        if (isAppletViewer(w)) return;
106        for (Window owned : w.getOwnedWindows()) dispose(owned);
107        if (isSharedInvisibleFrame(w)) return;
108        w.dispose();
109      }
110    
111      ParentFinder parentFinder() { return parentFinder; }
112      ChildrenFinder childrenFinder() { return childrenFinder; }
113    }