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 }