001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import org.apache.batik.dom.events.DOMUIEvent;
022: import org.apache.batik.dom.events.NodeEventTarget;
023: import org.apache.batik.util.XMLConstants;
024:
025: import org.w3c.dom.Document;
026: import org.w3c.dom.Element;
027: import org.w3c.dom.events.DocumentEvent;
028: import org.w3c.dom.events.Event;
029: import org.w3c.dom.events.EventListener;
030: import org.w3c.dom.events.EventTarget;
031: import org.w3c.dom.events.MouseEvent;
032:
033: /**
034: * A class that manages focus on elements.
035: *
036: * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
037: * @version $Id: FocusManager.java 475477 2006-11-15 22:44:28Z cam $
038: */
039: public class FocusManager {
040:
041: /**
042: * The element that has the focus so far.
043: */
044: protected EventTarget lastFocusEventTarget;
045:
046: /**
047: * The document.
048: */
049: protected Document document;
050:
051: /**
052: * The EventListener that tracks 'mouseclick' events.
053: */
054: protected EventListener mouseclickListener;
055:
056: /**
057: * The EventListener that tracks 'DOMFocusIn' events.
058: */
059: protected EventListener domFocusInListener;
060:
061: /**
062: * The EventListener that tracks 'DOMFocusOut' events.
063: */
064: protected EventListener domFocusOutListener;
065:
066: /**
067: * The EventListener that tracks 'mouseover' events.
068: */
069: protected EventListener mouseoverListener;
070:
071: /**
072: * The EventListener that tracks 'mouseout' events.
073: */
074: protected EventListener mouseoutListener;
075:
076: /**
077: * Constructs a new <tt>FocusManager</tt> for the specified document.
078: *
079: * @param doc the document
080: */
081: public FocusManager(Document doc) {
082: document = doc;
083: addEventListeners(doc);
084: }
085:
086: /**
087: * Adds the event listeners to the document.
088: */
089: protected void addEventListeners(Document doc) {
090: NodeEventTarget target = (NodeEventTarget) doc;
091:
092: mouseclickListener = new MouseClickTracker();
093: target.addEventListenerNS(
094: XMLConstants.XML_EVENTS_NAMESPACE_URI, "click",
095: mouseclickListener, true, null);
096:
097: mouseoverListener = new MouseOverTracker();
098: target.addEventListenerNS(
099: XMLConstants.XML_EVENTS_NAMESPACE_URI, "mouseover",
100: mouseoverListener, true, null);
101:
102: mouseoutListener = new MouseOutTracker();
103: target.addEventListenerNS(
104: XMLConstants.XML_EVENTS_NAMESPACE_URI, "mouseout",
105: mouseoutListener, true, null);
106:
107: domFocusInListener = new DOMFocusInTracker();
108: target.addEventListenerNS(
109: XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMFocusIn",
110: domFocusInListener, true, null);
111:
112: domFocusOutListener = new DOMFocusOutTracker();
113: target.addEventListenerNS(
114: XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMFocusOut",
115: domFocusOutListener, true, null);
116: }
117:
118: /**
119: * Removes the event listeners from the document.
120: */
121: protected void removeEventListeners(Document doc) {
122: NodeEventTarget target = (NodeEventTarget) doc;
123:
124: target.removeEventListenerNS(
125: XMLConstants.XML_EVENTS_NAMESPACE_URI, "click",
126: mouseclickListener, true);
127: target.removeEventListenerNS(
128: XMLConstants.XML_EVENTS_NAMESPACE_URI, "mouseover",
129: mouseoverListener, true);
130: target.removeEventListenerNS(
131: XMLConstants.XML_EVENTS_NAMESPACE_URI, "mouseout",
132: mouseoutListener, true);
133: target.removeEventListenerNS(
134: XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMFocusIn",
135: domFocusInListener, true);
136: target.removeEventListenerNS(
137: XMLConstants.XML_EVENTS_NAMESPACE_URI, "DOMFocusOut",
138: domFocusOutListener, true);
139: }
140:
141: /**
142: * Returns the current element that has the focus or null if any.
143: */
144: public EventTarget getCurrentEventTarget() {
145: return lastFocusEventTarget;
146: }
147:
148: /**
149: * Removes all listeners attached to the document and that manage focus.
150: */
151: public void dispose() {
152: if (document == null)
153: return;
154: removeEventListeners(document);
155: lastFocusEventTarget = null;
156: document = null;
157: }
158:
159: /**
160: * The class that is responsible for tracking 'mouseclick' changes.
161: */
162: protected class MouseClickTracker implements EventListener {
163:
164: public void handleEvent(Event evt) {
165: MouseEvent mevt = (MouseEvent) evt;
166: fireDOMActivateEvent(evt.getTarget(), mevt.getDetail());
167: }
168: }
169:
170: /**
171: * The class that is responsible for tracking 'DOMFocusIn' changes.
172: */
173: protected class DOMFocusInTracker implements EventListener {
174:
175: public void handleEvent(Event evt) {
176: EventTarget newTarget = evt.getTarget();
177: if (lastFocusEventTarget != null
178: && lastFocusEventTarget != newTarget) {
179: fireDOMFocusOutEvent(lastFocusEventTarget, newTarget);
180: }
181: lastFocusEventTarget = evt.getTarget();
182: }
183: }
184:
185: /**
186: * The class that is responsible for tracking 'DOMFocusOut' changes.
187: */
188: protected class DOMFocusOutTracker implements EventListener {
189:
190: public DOMFocusOutTracker() {
191: }
192:
193: public void handleEvent(Event evt) {
194: lastFocusEventTarget = null;
195: }
196: }
197:
198: /**
199: * The class that is responsible to update the focus according to
200: * 'mouseover' event.
201: */
202: protected class MouseOverTracker implements EventListener {
203:
204: public void handleEvent(Event evt) {
205: MouseEvent me = (MouseEvent) evt;
206: EventTarget target = evt.getTarget();
207: EventTarget relatedTarget = me.getRelatedTarget();
208: fireDOMFocusInEvent(target, relatedTarget);
209: }
210: }
211:
212: /**
213: * The class that is responsible to update the focus according to
214: * 'mouseout' event.
215: */
216: protected class MouseOutTracker implements EventListener {
217:
218: public void handleEvent(Event evt) {
219: MouseEvent me = (MouseEvent) evt;
220: EventTarget target = evt.getTarget();
221: EventTarget relatedTarget = me.getRelatedTarget();
222: fireDOMFocusOutEvent(target, relatedTarget);
223: }
224: }
225:
226: /**
227: * Fires a 'DOMFocusIn' event to the specified target.
228: *
229: * @param target the newly focussed event target
230: * @param relatedTarget the previously focussed event target
231: */
232: protected void fireDOMFocusInEvent(EventTarget target,
233: EventTarget relatedTarget) {
234: DocumentEvent docEvt = (DocumentEvent) ((Element) target)
235: .getOwnerDocument();
236: DOMUIEvent uiEvt = (DOMUIEvent) docEvt.createEvent("UIEvents");
237: uiEvt.initUIEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
238: "DOMFocusIn", true, // canBubbleArg
239: false, // cancelableArg
240: null, // viewArg
241: 0); // detailArg
242: target.dispatchEvent(uiEvt);
243: }
244:
245: /**
246: * Fires a 'DOMFocusOut' event to the specified target.
247: *
248: * @param target the previously focussed event target
249: * @param relatedTarget the newly focussed event target
250: */
251: protected void fireDOMFocusOutEvent(EventTarget target,
252: EventTarget relatedTarget) {
253: DocumentEvent docEvt = (DocumentEvent) ((Element) target)
254: .getOwnerDocument();
255: DOMUIEvent uiEvt = (DOMUIEvent) docEvt.createEvent("UIEvents");
256: uiEvt.initUIEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
257: "DOMFocusOut", true, // canBubbleArg
258: false, // cancelableArg
259: null, // viewArg
260: 0); // detailArg
261: target.dispatchEvent(uiEvt);
262: }
263:
264: /**
265: * Fires a 'DOMActivate' event to the specified target.
266: *
267: * @param target the event target
268: * @param detailArg the detailArg parameter of the event
269: */
270: protected void fireDOMActivateEvent(EventTarget target,
271: int detailArg) {
272: DocumentEvent docEvt = (DocumentEvent) ((Element) target)
273: .getOwnerDocument();
274: DOMUIEvent uiEvt = (DOMUIEvent) docEvt.createEvent("UIEvents");
275: uiEvt.initUIEventNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
276: "DOMActivate", true, // canBubbleArg
277: true, // cancelableArg
278: null, // viewArg
279: 0); // detailArg
280: target.dispatchEvent(uiEvt);
281: }
282: }
|