Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/common/awt/FlexFocusManager.java


1   /*
2    * FlexFocusManager.java
3    *
4    * Copyright $Date: 2003/08/11 02:22:32 $ FLEXSTOR.net Inc.
5    *
6    * This work is licensed for use and distribution under license terms found at
7    * http://www.flexstor.org/license.html
8    *
9    */
10  
11  package com.flexstor.common.awt;
12  
13  /**
14   * Posted as a workaround on the SUN bug parade for several focus bugs.
15   *
16   * A brute force method i have found to get around this
17   * bug, though im not crazy about it....it repeatedly
18   * calls requestFocus in successive threads (since requestFocus
19   * does not take effect until its current thread yields [or dies? hmm])
20   *
21   * Various methods are used to determine if the component
22   * actually got the focus or not, and if a compound-component
23   * (that proxies requestFocus to a child component) is the target,
24   * it figures that out also.
25   */
26  
27  
28  import java.awt.Component;
29  import java.awt.Container;
30  import java.awt.Window;
31  import java.awt.event.FocusAdapter;
32  import java.awt.event.FocusEvent;
33  
34  /**
35   * (almost) Foolproof component focus setter, will repeatedly call requestFocus for a
36   * component in a different thread each time.
37   * Uses getCurrentFocus() and focusGained methods to check for success.
38   * Brute forces its way through a myriad of
39   * jdk bugs that put the focus all over the place, kill the requestFocus method, etc.
40   */
41  
42  public class FlexFocusManager
43     extends FocusAdapter
44     implements Runnable
45  {
46     boolean   focusGained = false;
47     Window    surface;
48     Component targetfocus;
49     Component currentfocus;
50     int       recursion = 0;
51     int       countdown; // additional reqfocus calls after its hit
52  
53     public FlexFocusManager(Component targetfocus)
54     {
55        this(findWindow(targetfocus),targetfocus);
56     }
57  
58     public FlexFocusManager(Window surface,Component targetfocus)
59     {
60        this.surface=surface;
61        this.targetfocus=targetfocus;
62     }
63  
64     private static Window findWindow(Component c)
65     {
66        while (c!=null && !(c instanceof Window))
67           c=c.getParent();
68        if (c!=null)
69           return (Window)c;
70        else
71           return null;
72     }
73  
74     public void setFocus()
75     {
76        if (surface == null)
77           return;
78  
79        if (targetfocus == null)
80           targetfocus = getDefaultFocusComponent(surface);
81        if (targetfocus == null)
82           return;
83  
84        // send a focus lost to the current focus
85        currentfocus = surface.getFocusOwner();
86        if (currentfocus != null)
87        {
88           //Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
89           currentfocus.dispatchEvent(
90              new FocusEvent(currentfocus,FocusEvent.FOCUS_LOST,false));
91        }
92        focusGained = false;
93        recursion = 0;
94        countdown = 3;
95        targetfocus.addFocusListener(this);
96  
97        new Thread(this).start();
98     }
99  
100    public void focusGained(FocusEvent e)
101    {
102       focusGained=true;
103       targetfocus.removeFocusListener(this);
104    }
105 
106    private void reqFocus()
107    {
108       recursion++;
109       if (recursion > 20)
110       {
111          //System.err.println("FocusSetter recursion count exceeded 20");
112          recursion=0;
113          countdown=0;
114          return;
115       }
116 
117       // check if the component has focus
118       currentfocus=surface.getFocusOwner();
119       if (isEqualOrChild(currentfocus, targetfocus))
120       {
121          countdown--;
122          if (countdown<=0)
123          {
124             recursion=0;
125             return;
126          }
127       }
128 
129       // check if the component got a focusgained event
130       if (focusGained)
131       {
132          countdown--;
133          if (countdown<=0)
134          {
135             recursion=0;
136             return;
137          }
138       }
139 
140       // try requesting focus again
141       //new Thread(this).start();
142       targetfocus.requestFocus();
143    }
144 
145    public void run()
146    {
147       while(countdown > 0)
148       {
149          //targetfocus.requestFocus();
150          //System.out.println("FocusManager: requestFocus on " + targetfocus);
151          reqFocus();
152          try {Thread.currentThread().sleep(200);}catch (Exception e9) {}
153       }
154       //System.out.println("FocusManager: ended on " + targetfocus);
155    }
156 
157 
158    // determine if a==b or a is a child of b
159    private static boolean isEqualOrChild(Component currentFocus,Component targetFocus)
160    {
161       Container c;
162       if (targetFocus instanceof Container)
163          c = (Container)targetFocus;
164       else
165          return (currentFocus == targetFocus);
166 
167       while (currentFocus != null && currentFocus != targetFocus)
168          currentFocus = currentFocus.getParent();
169 
170       return (currentFocus!=null);
171    }
172 
173    public static Component getDefaultFocusComponent(Container start)
174    {
175       int len=start.getComponentCount();
176 
177       if (len == 0)
178          return null;
179 
180       for (int i=0; i<len; i++)
181       {
182          Component c=start.getComponent(i);
183 
184          // NOTE: isFocusTraversable is sometimes false for some java.awt.* components
185          // in some JDK's...you might want to replace this with a different method
186          if (c.isFocusTraversable())
187             return c;
188          else
189             if (c instanceof Container)
190             {
191                c = getDefaultFocusComponent((Container)c);
192                if (c == null)
193                   continue;
194                else
195                   return c;
196             }
197       }
198       return null;
199    }
200 
201 }  // end of class
202 
203