001: /*
002: * Copyright (c) 2004 Christopher M Butler Copyright of changes to original ViewListener (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.AWTEvent;
020: import java.awt.Component;
021: import java.awt.Container;
022: import java.awt.EventQueue;
023: import java.awt.KeyboardFocusManager;
024: import java.awt.Point;
025: import java.awt.Toolkit;
026: import java.awt.event.AWTEventListener;
027: import java.awt.event.MouseEvent;
028: import java.beans.PropertyChangeEvent;
029: import java.beans.PropertyChangeListener;
030: import java.util.HashSet;
031:
032: import javax.swing.JTabbedPane;
033: import javax.swing.SwingUtilities;
034: import javax.swing.event.ChangeEvent;
035: import javax.swing.event.ChangeListener;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039:
040: /**
041: * Supports focus tracking for {@link org.gui4j.core.swing.IView}s.
042: */
043: public class IViewListener implements PropertyChangeListener,
044: ChangeListener, AWTEventListener {
045:
046: private static final Log log = LogFactory
047: .getLog(IViewListener.class);
048:
049: private static final String PERMANENT_FOCUS_OWNER = "permanentFocusOwner";
050: private static final String ACTIVE_WINDOW = "activeWindow";
051:
052: private static final IViewListener SINGLETON = new IViewListener();
053: private static HashSet PROP_EVENTS = new HashSet();
054:
055: static {
056: log.debug("IViewListener static initializer");
057: primeImpl();
058: }
059:
060: /**
061: * Call this to cause class loading. Everything else is automatically taken
062: * care of.
063: */
064: public static void prime() {
065: }
066:
067: private static void primeImpl() {
068: PROP_EVENTS.add(PERMANENT_FOCUS_OWNER);
069: PROP_EVENTS.add(ACTIVE_WINDOW);
070:
071: EventQueue.invokeLater(new Runnable() {
072: public void run() {
073: KeyboardFocusManager focusManager = KeyboardFocusManager
074: .getCurrentKeyboardFocusManager();
075: focusManager.addPropertyChangeListener(SINGLETON);
076: }
077: });
078:
079: Toolkit.getDefaultToolkit().addAWTEventListener(SINGLETON,
080: AWTEvent.MOUSE_EVENT_MASK);
081: }
082:
083: public static IViewListener getInstance() {
084: return SINGLETON;
085: }
086:
087: private IViewListener() {
088: }
089:
090: public void eventDispatched(AWTEvent event) {
091: // catch all mousePressed events
092: if (event.getID() != MouseEvent.MOUSE_PRESSED)
093: return;
094:
095: MouseEvent evt = (MouseEvent) event;
096: Component c = (Component) evt.getSource();
097:
098: // check to see if the event was targeted at the deepest component at
099: // the current mouse loaction
100: Container container = c instanceof Container ? (Container) c
101: : null;
102: if (container != null && container.getComponentCount() > 1) {
103: // if not, find the deepest component
104: Point p = evt.getPoint();
105: c = SwingUtilities.getDeepestComponentAt(c, p.x, p.y);
106: }
107:
108: // request activation of the view that encloses this component
109: IViewTracker.requestViewActivation(c);
110: }
111:
112: public void propertyChange(PropertyChangeEvent evt) {
113: String pName = evt.getPropertyName();
114: if (!PROP_EVENTS.contains(pName))
115: return;
116:
117: Component oldVal = toComponent(evt.getOldValue());
118: Component newVal = toComponent(evt.getNewValue());
119: boolean switchTo = newVal != null;
120:
121: log.debug("Focus change signalled from " + oldVal + " to "
122: + newVal);
123:
124: if (ACTIVE_WINDOW.equals(pName))
125: handleWindowChange(evt, oldVal, newVal, switchTo);
126: else
127: handleFocusChange(evt, oldVal, newVal, switchTo);
128: }
129:
130: private void handleWindowChange(PropertyChangeEvent evt,
131: Component oldVal, Component newVal, boolean activate) {
132: // notify the IViewTracker of the window change
133: IViewTracker.windowActivated(newVal);
134:
135: Component srcComponent = activate ? newVal : oldVal;
136: IViewTracker tracker = IViewTracker.getTracker(srcComponent);
137: if (tracker != null)
138: tracker.setActive(activate);
139: }
140:
141: private void handleFocusChange(PropertyChangeEvent evt,
142: Component oldVal, Component newVal, boolean switchTo) {
143: if (!switchTo)
144: return;
145:
146: if (newVal instanceof JTabbedPane) {
147: final JTabbedPane tabbed = (JTabbedPane) newVal;
148: if (tabbed.getClientProperty("gui4jPortletContainer") != null) {
149: // if tabbed pane is container for stacked portlets/views,
150: // we transfer focus to tab content
151: EventQueue.invokeLater(new Runnable() {
152: public void run() {
153: Component selected = tabbed
154: .getSelectedComponent();
155: if (selected != null) {
156: selected.requestFocus();
157: } else {
158: tabbed.requestFocus();
159: }
160: }
161: });
162: } else {
163: activateComponent(tabbed.getSelectedComponent());
164: }
165: } else {
166: activateComponent(newVal);
167: }
168: }
169:
170: private void activateComponent(Component c) {
171: log.debug("Will activate component: " + c);
172: IViewTracker tracker = IViewTracker.getTracker(c);
173: if (tracker != null) {
174: IView view = c instanceof IView ? (IView) c
175: : (IView) SwingUtilities.getAncestorOfClass(
176: IView.class, c);
177: tracker.setActive(view);
178: }
179: }
180:
181: public void stateChanged(ChangeEvent e) {
182: Object obj = e.getSource();
183: if (obj instanceof JTabbedPane) {
184: JTabbedPane pane = (JTabbedPane) obj;
185: Component c = pane.getSelectedComponent();
186: if (c instanceof IView)
187: activateComponent(c);
188: }
189: }
190:
191: private static Component toComponent(Object obj) {
192: return obj instanceof Component ? (Component) obj : null;
193: }
194:
195: }
|