001    /*
002     * Created on Mar 30, 2008
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 @2008-2010 the original author or authors.
015     */
016    package org.fest.swing.core;
017    
018    import static org.fest.swing.awt.AWT.invokerOf;
019    
020    import java.awt.Component;
021    import java.awt.Window;
022    
023    import javax.swing.MenuElement;
024    
025    import org.fest.swing.annotation.RunsInCurrentThread;
026    import org.fest.swing.hierarchy.ComponentHierarchy;
027    import org.fest.swing.hierarchy.ExistingHierarchy;
028    
029    /**
030     * Understands lookup of a component's <code>{@link java.awt.Window ancestor}</code>.
031     *
032     * @author Yvonne Wang
033     */
034    public final class WindowAncestorFinder {
035    
036      private static ComponentHierarchy hierarchy = new ExistingHierarchy();
037    
038      /**
039       * Similar to <code>{@link javax.swing.SwingUtilities#getWindowAncestor(Component)}</code>, but returns the
040       * <code>{@link Component}</code> itself if it is a <code>{@link Window}</code>, or the invoker's <code>Window</code>
041       * if on a pop-up.
042       * <p>
043       * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
044       * responsible for calling this method from the EDT.
045       * </p>
046       * @param c the <code>Component</code> to get the <code>Window</code> ancestor of.
047       * @return the <code>Window</code> ancestor of the given <code>Component</code>, the <code>Component</code> itself if
048       * it is a <code>Window</code>, or the invoker's <code>Window</code> if on a pop-up.
049       */
050      @RunsInCurrentThread
051      public static Window windowAncestorOf(Component c) {
052        if (c == null) return null;
053        if (c instanceof Window) return (Window) c;
054        if (c instanceof MenuElement) {
055          Component invoker = invokerOf(c);
056          if (invoker != null) return windowAncestorOf(invoker);
057        }
058        return windowAncestorOf(hierarchy.parentOf(c));
059      }
060    
061      private WindowAncestorFinder() {}
062    }