001: /*
002: * Copyright (c) 2004 Christopher M Butler Copyright of changes to original ViewTracker (c) 2005 Kay
003: * Krüger-Barvels Permission is hereby granted, free of charge, to any person obtaining a copy of this
004: * software and associated documentation files (the "Software"), to deal in the Software without restriction,
005: * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
006: * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
007: * subject to the following conditions: The above copyright notice and this permission notice shall be
008: * included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
009: * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
010: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
011: * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
012: * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
013: */
014:
015: /* Changes to original code (c) 2005 beck et al. projects GmbH */
016:
017: package org.gui4j.core.swing;
018:
019: import java.awt.Component;
020: import java.awt.Container;
021: import java.awt.EventQueue;
022: import java.awt.KeyboardFocusManager;
023: import java.util.WeakHashMap;
024:
025: import javax.swing.SwingUtilities;
026:
027: /**
028: * Implements focus tracking for {@link org.gui4j.core.swing.IView}s.
029: */
030: public class IViewTracker {
031: private static final WeakHashMap TRACKERS_BY_WINDOW = new WeakHashMap();
032: private static IViewTracker currentTracker;
033: private static final Object LOCK = new Object();
034: private IView currentView;
035:
036: public static IViewTracker getTracker(Component component) {
037: RootWindow window = RootWindow.getRootContainer(component);
038: return getTracker(window);
039: }
040:
041: public static IViewTracker getCurrentTracker() {
042: synchronized (LOCK) {
043: return currentTracker;
044: }
045: }
046:
047: private static IViewTracker getTracker(RootWindow window) {
048: if (window == null)
049: return null;
050:
051: Component root = window.getRootContainer();
052: IViewTracker tracker = (IViewTracker) TRACKERS_BY_WINDOW
053: .get(root);
054:
055: if (tracker == null) {
056: tracker = new IViewTracker();
057:
058: TRACKERS_BY_WINDOW.put(root, tracker);
059: }
060: return tracker;
061: }
062:
063: static void windowActivated(Component c) {
064: RootWindow window = RootWindow.getRootContainer(c);
065: IViewTracker tracker = getTracker(window);
066: synchronized (LOCK) {
067: currentTracker = tracker;
068: }
069: }
070:
071: public static void requestViewActivation(Component c) {
072: if (c == null)
073: return;
074:
075: IView view = c instanceof IView ? (IView) c
076: : (IView) SwingUtilities.getAncestorOfClass(
077: IView.class, c);
078: if (view != null) {
079: requestViewActivation(c, view);
080: }
081: }
082:
083: public static void requestViewActivation(final Component c,
084: final IView view) {
085: if (c == null || view == null)
086: return;
087:
088: // make sure the window is currently active
089: activateWindow(c);
090:
091: Thread t = new Thread() {
092: public void run() {
093: Runnable r = new Runnable() {
094: public void run() {
095: focusView(c, view);
096: }
097: };
098: EventQueue.invokeLater(r);
099: }
100: };
101: t.start();
102: }
103:
104: private static void focusView(Component child, IView parentView) {
105: // if the view is already active, then leave it alone
106: if (parentView.isActive())
107: return;
108:
109: Component focuser = getNearestFocusableComponent(child,
110: parentView.getContainer());
111: if (focuser == null)
112: focuser = parentView.getContainer();
113: focuser.requestFocus();
114: }
115:
116: public IViewTracker() {
117:
118: }
119:
120: public void setActive(boolean b) {
121: if (currentView == null)
122: return;
123:
124: currentView.setActive(b);
125: }
126:
127: public void setActive(IView view) {
128: if (view != currentView) {
129: setActive(false);
130: currentView = view;
131: setActive(true);
132: }
133: }
134:
135: // copied from org.flexdock.util.SwingUtility
136: private static void activateWindow(Component c) {
137: RootWindow window = RootWindow.getRootContainer(c);
138: if (window != null && !window.isActive())
139: window.toFront();
140: }
141:
142: // copied from org.flexdock.util.SwingUtility
143: private static Component getNearestFocusableComponent(Component c,
144: Container desiredRoot) {
145: if (c == null)
146: c = desiredRoot;
147: if (c == null)
148: c = KeyboardFocusManager.getCurrentKeyboardFocusManager()
149: .getActiveWindow();
150:
151: boolean cachedFocusCycleRoot = false;
152: // make the desiredRoot into a focusCycleRoot
153: if (desiredRoot != null) {
154: cachedFocusCycleRoot = desiredRoot.isFocusCycleRoot();
155: if (!cachedFocusCycleRoot)
156: desiredRoot.setFocusCycleRoot(true);
157: }
158:
159: Container focusRoot = null;
160: if (c instanceof Container) {
161: Container cnt = (Container) c;
162: focusRoot = cnt.isFocusCycleRoot(cnt) ? cnt : cnt
163: .getFocusCycleRootAncestor();
164: } else
165: focusRoot = c.getFocusCycleRootAncestor();
166:
167: Component focuser = null;
168: if (focusRoot != null)
169: focuser = focusRoot.getFocusTraversalPolicy()
170: .getLastComponent(focusRoot);
171:
172: // restore the desiredRoot to its previous state
173: if (desiredRoot != null && !cachedFocusCycleRoot) {
174: desiredRoot.setFocusCycleRoot(cachedFocusCycleRoot);
175: }
176: return focuser;
177: }
178:
179: }
|