001: /*
002: * Copyright (C) 2004 NNL Technology AB
003: * Visit www.infonode.net for information about InfoNode(R)
004: * products and how to contact NNL Technology AB.
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
019: * MA 02111-1307, USA.
020: */
021:
022: // $Id: FocusManager.java,v 1.13 2007/01/28 19:00:30 jesper Exp $
023: package net.infonode.docking;
024:
025: import javax.swing.*;
026: import java.awt.*;
027: import java.awt.event.ActionEvent;
028: import java.awt.event.ActionListener;
029: import java.beans.PropertyChangeEvent;
030: import java.beans.PropertyChangeListener;
031: import java.lang.ref.Reference;
032: import java.lang.ref.WeakReference;
033: import java.util.ArrayList;
034:
035: /**
036: * @author $Author: jesper $
037: * @version $Revision: 1.13 $
038: */
039: class FocusManager {
040: private static final FocusManager INSTANCE = new FocusManager();
041:
042: private int ignoreFocusChanges;
043: private Timer focusTimer = new Timer(20, new ActionListener() {
044: public void actionPerformed(ActionEvent e) {
045: updateFocus();
046: focusUpdateTriggered = false;
047: }
048: });
049: private boolean focusUpdateTriggered;
050: private ArrayList lastFocusedWindows = new ArrayList();
051: private Component focusedComponent;
052: private PropertyChangeListener focusListener = new PropertyChangeListener() {
053: public void propertyChange(PropertyChangeEvent evt) {
054: if (ignoreFocusChanges > 0)
055: return;
056:
057: ignoreFocusChanges++;
058:
059: try {
060: triggerFocusUpdate();
061: } finally {
062: ignoreFocusChanges--;
063: }
064: }
065:
066: private void triggerFocusUpdate() {
067: if (focusUpdateTriggered)
068: return;
069:
070: focusUpdateTriggered = true;
071: focusTimer.setRepeats(false);
072: focusTimer.start();
073: }
074:
075: };
076:
077: private FocusManager() {
078: KeyboardFocusManager.getCurrentKeyboardFocusManager()
079: .addPropertyChangeListener("focusOwner", focusListener);
080: updateFocus();
081: }
082:
083: static FocusManager getInstance() {
084: return INSTANCE;
085: }
086:
087: private void updateFocus() {
088: focusedComponent = KeyboardFocusManager
089: .getCurrentKeyboardFocusManager().getFocusOwner();
090: // System.out.println("Focus: " + System.identityHashCode(focusedComponent) + ", " + focusedComponent);
091: ArrayList oldFocusedWindows = lastFocusedWindows;
092: lastFocusedWindows = new ArrayList();
093: updateWindows(focusedComponent, focusedComponent,
094: oldFocusedWindows);
095:
096: for (int i = 0; i < oldFocusedWindows.size(); i++) {
097: RootWindow w = (RootWindow) ((Reference) oldFocusedWindows
098: .get(i)).get();
099:
100: if (w != null)
101: w.setFocusedView(null);
102: }
103:
104: }
105:
106: void pinFocus(Runnable runnable) {
107: ignoreFocusChanges++;
108: final Component c = focusedComponent;
109:
110: try {
111: runnable.run();
112: } finally {
113: if (--ignoreFocusChanges == 0 && c != null) {
114: c.requestFocusInWindow();
115:
116: SwingUtilities.invokeLater(new Runnable() {
117: public void run() {
118: SwingUtilities.invokeLater(new Runnable() {
119: public void run() {
120: c.requestFocusInWindow();
121: }
122: });
123: }
124: });
125: }
126: }
127: }
128:
129: void startIgnoreFocusChanges() {
130: ignoreFocusChanges++;
131: }
132:
133: void stopIgnoreFocusChanges() {
134: if (--ignoreFocusChanges == 0) {
135: updateFocus();
136: }
137: }
138:
139: static void focusWindow(final DockingWindow window) {
140: if (window == null)
141: return;
142:
143: window.restoreFocus();
144:
145: SwingUtilities.invokeLater(new Runnable() {
146: public void run() {
147: SwingUtilities.invokeLater(new Runnable() {
148: public void run() {
149: window.restoreFocus();
150: }
151: });
152: }
153: });
154: }
155:
156: private static View getViewContaining(Component component) {
157: return component == null ? null
158: : component instanceof View ? (View) component
159: : getViewContaining(component.getParent());
160: }
161:
162: private void updateWindows(Component focusedComponent,
163: Component component, ArrayList oldFocusedWindows) {
164: while (true) {
165: View view = getViewContaining(component);
166:
167: if (view == null)
168: break;
169:
170: view.setLastFocusedComponent(focusedComponent);
171: RootWindow rw = view.getRootWindow();
172:
173: if (rw == null)
174: break;
175:
176: rw.setFocusedView(view);
177: lastFocusedWindows.add(new WeakReference(rw));
178: component = rw;
179:
180: for (int i = 0; i < oldFocusedWindows.size(); i++) {
181: if (((Reference) oldFocusedWindows.get(i)).get() == component)
182: oldFocusedWindows.remove(i);
183: }
184: }
185: }
186:
187: }
|