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.edt.GuiActionRunner.execute;
019 import static org.fest.util.Collections.list;
020
021 import java.awt.Component;
022 import java.util.ArrayList;
023 import java.util.List;
024
025 import org.fest.swing.annotation.RunsInCurrentThread;
026 import org.fest.swing.annotation.RunsInEDT;
027 import org.fest.swing.edt.GuiQuery;
028 import org.fest.util.VisibleForTesting;
029
030 /**
031 * Understands lookup of a <code>{@link Component}</code> owning the input focus.
032 *
033 * @author Yvonne Wang
034 * @author Alex Ruiz
035 */
036 public final class FocusOwnerFinder {
037
038 private static final List<FocusOwnerFinderStrategy> STRATEGIES = new ArrayList<FocusOwnerFinderStrategy>();
039
040 static {
041 initializeStrategies();
042 }
043
044 @VisibleForTesting
045 static void initializeStrategies() {
046 replaceStrategiesWith(new ReflectionBasedFocusOwnerFinder(), new HierarchyBasedFocusOwnerFinder());
047 }
048
049 @VisibleForTesting
050 static void replaceStrategiesWith(FocusOwnerFinderStrategy...strategies) {
051 STRATEGIES.clear();
052 STRATEGIES.addAll(list(strategies));
053 }
054
055 @VisibleForTesting
056 static List<FocusOwnerFinderStrategy> strategies() {
057 return new ArrayList<FocusOwnerFinderStrategy>(STRATEGIES);
058 }
059
060 /**
061 * Returns the focus owner. This method is executed in the event dispatch thread.
062 * @return the focus owner.
063 */
064 @RunsInEDT
065 public static Component inEdtFocusOwner() {
066 return execute(new GuiQuery<Component>() {
067 protected Component executeInEDT() {
068 return focusOwner();
069 }
070 });
071 }
072
073 /**
074 * Returns the focus owner. <b>Note:</b> this method is <b>not</b> executed in the event dispatch thread. Callers are
075 * responsible for calling this method in the event dispatch thread.
076 * <p>
077 * <b>Note:</b> This method is <b>not</b> guaranteed to be executed in the event dispatch thread (EDT.) Clients are
078 * responsible for calling this method from the EDT.
079 * </p>
080 * @return the focus owner.
081 */
082 @RunsInCurrentThread
083 public static Component focusOwner() {
084 for (FocusOwnerFinderStrategy strategy : STRATEGIES) {
085 try {
086 return strategy.focusOwner();
087 } catch (Exception e) {
088 continue;
089 }
090 }
091 return null;
092 }
093
094 private FocusOwnerFinder() {}
095 }