tkormann 02/04/22 07:24:58 Modified: sources/org/apache/batik/bridge BridgeEventSupport.java SVGTextElementBridge.java Log: - <a> now works on tspan - huge cleanup of BridgeEventSupport - bug fix, relatedNode now contains the correct info when needed next step, implementation of DOMFocusIn/Out and DOMActive events Revision Changes Path 1.30 +216 -115 xml-batik/sources/org/apache/batik/bridge/BridgeEventSupport.java Index: BridgeEventSupport.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/BridgeEventSupport.java,v retrieving revision 1.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- BridgeEventSupport.java 22 Apr 2002 09:45:49 -0000 1.29 +++ BridgeEventSupport.java 22 Apr 2002 14:24:57 -0000 1.30 @@ -67,9 +67,10 @@ * A class to attach listeners on the <code>Document</code> to * call pieces of script when necessary and to attach a listener * on the GVT root to propagate GVT events to the DOM. + * * @author <a href="mailto:[EMAIL PROTECTED]>Christophe Jolif</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephane Hillion</a> - * @version $Id: BridgeEventSupport.java,v 1.29 2002/04/22 09:45:49 tkormann Exp $ + * @version $Id: BridgeEventSupport.java,v 1.30 2002/04/22 14:24:57 tkormann Exp $ */ class BridgeEventSupport implements SVGConstants { @@ -88,188 +89,288 @@ dispatcher.addGraphicsNodeMouseListener(listener); // add an unload listener on the SVGDocument to remove // that listener for dispatching events - ((EventTarget)svgRoot). - addEventListener("SVGUnload", - new GVTUnloadListener(dispatcher, - listener), - false); + ((EventTarget)svgRoot).addEventListener + ("SVGUnload", + new GVTUnloadListener(dispatcher, listener), + false); } } } - private static class GVTUnloadListener implements EventListener { + protected static class GVTUnloadListener implements EventListener { + private EventDispatcher dispatcher; private Listener listener; - GVTUnloadListener(EventDispatcher dispatcher, Listener listener) { + + public GVTUnloadListener(EventDispatcher dispatcher, + Listener listener) { this.dispatcher = dispatcher; this.listener = listener; } + public void handleEvent(Event evt) { dispatcher.removeGraphicsNodeMouseListener(listener); evt.getTarget().removeEventListener("SVGUnload", this, false); } } - private static class Listener - implements GraphicsNodeMouseListener { + /** + * A GraphicsNodeMouseListener that dispatch DOM events accordingly. + */ + protected static class Listener implements GraphicsNodeMouseListener { + private BridgeContext context; private UserAgent ua; - private GraphicsNode lastTarget; + private Element lastTargetElement; + public Listener(BridgeContext ctx, UserAgent u) { context = ctx; ua = u; } + public void mouseClicked(GraphicsNodeMouseEvent evt) { dispatchMouseEvent("click", evt, true); } + public void mousePressed(GraphicsNodeMouseEvent evt) { dispatchMouseEvent("mousedown", evt, true); } + public void mouseReleased(GraphicsNodeMouseEvent evt) { dispatchMouseEvent("mouseup", evt, true); } + public void mouseEntered(GraphicsNodeMouseEvent evt) { dispatchMouseEvent("mouseover", evt, true); } + public void mouseExited(GraphicsNodeMouseEvent evt) { dispatchMouseEvent("mouseout", evt, true); } + public void mouseDragged(GraphicsNodeMouseEvent evt) { - GraphicsNode node = evt.getRelatedNode(); - GraphicsNodeMouseEvent evt2 = null; - if (lastTarget != node) { - if (lastTarget != null) { - evt2 = new GraphicsNodeMouseEvent(lastTarget, - evt.MOUSE_EXITED, - evt.getWhen(), - evt.getModifiers(), - evt.getX(), - evt.getY(), - evt.getClickCount(), - lastTarget); - dispatchMouseEvent("mouseout", - evt2, + dispatchMouseEvent("mousemove", evt, false); + } + + public void mouseMoved(GraphicsNodeMouseEvent evt) { + Point clientXY = getClientMouseLocation(evt.getPoint2D()); + GraphicsNode node = evt.getGraphicsNode(); + Element targetElement = getEventTarget(node, clientXY); + if (lastTargetElement != targetElement) { + if (lastTargetElement != null) { + dispatchMouseEvent("mouseout", + lastTargetElement, // target + targetElement, // relatedTarget + clientXY, + evt, true); } - if (node != null) { - evt2 = new GraphicsNodeMouseEvent(node, - evt.MOUSE_ENTERED, - evt.getWhen(), - evt.getModifiers(), - evt.getX(), - evt.getY(), - evt.getClickCount(), - lastTarget); - dispatchMouseEvent("mouseover", - evt2, + if (targetElement != null) { + dispatchMouseEvent("mouseover", + targetElement, // target + lastTargetElement, // relatedTarget + clientXY, + evt, true); } } + dispatchMouseEvent("mousemove", + targetElement, // target + null, // relatedTarget + clientXY, + evt, + false); + } + + /** + * Dispatches a DOM MouseEvent according to the specified + * parameters. + * + * @param eventType the event type + * @param evt the GVT GraphicsNodeMouseEvent + * @param cancelable true means the event is cancelable + */ + protected void dispatchMouseEvent(String eventType, + GraphicsNodeMouseEvent evt, + boolean cancelable) { + Point clientXY = getClientMouseLocation(evt.getPoint2D()); + GraphicsNode node = evt.getGraphicsNode(); + Element targetElement = getEventTarget(node, clientXY); + Element relatedElement = getRelatedElement(evt); + dispatchMouseEvent(eventType, + targetElement, + relatedElement, + clientXY, + evt, + cancelable); + } + + /** + * Dispatches a DOM MouseEvent according to the specified + * parameters. + * + * @param eventType the event type + * @param targetElement the target of the event + * @param relatedElement the related target if any + * @param clientXY the mouse coordinates in the client space + * @param evt the GVT GraphicsNodeMouseEvent + * @param cancelable true means the event is cancelable + */ + protected void dispatchMouseEvent(String eventType, + Element targetElement, + Element relatedElement, + Point clientXY, + GraphicsNodeMouseEvent evt, + boolean cancelable) { + if (targetElement == null) { + return; + } + /* + if (relatedElement != null) { + System.out.println + ("dispatching "+eventType+ + " target:"+targetElement.getLocalName()+ + " relatedElement:"+relatedElement.getLocalName()); + } else { + System.out.println + ("dispatching "+eventType+ + " target:"+targetElement.getLocalName()); + + }*/ + + short button = getButton(evt); + Point screenXY = getScreenMouseLocation(clientXY); + // create the coresponding DOM MouseEvent + DocumentEvent d = (DocumentEvent)targetElement.getOwnerDocument(); + MouseEvent mouseEvt = (MouseEvent)d.createEvent("MouseEvents"); + mouseEvt.initMouseEvent(eventType, + true, + cancelable, + null, + evt.getClickCount(), + screenXY.x, + screenXY.y, + clientXY.x, + clientXY.y, + evt.isControlDown(), + evt.isAltDown(), + evt.isShiftDown(), + evt.isMetaDown(), + button, + (EventTarget)relatedElement); + try { - if (node != null) { - evt2 = new GraphicsNodeMouseEvent(node, - evt.MOUSE_MOVED, - evt.getWhen(), - evt.getModifiers(), - evt.getX(), - evt.getY(), - evt.getClickCount(), - null); - dispatchMouseEvent("mousemove", - evt2, - true); - } + ((EventTarget)targetElement).dispatchEvent(mouseEvt); + } catch (RuntimeException e) { + ua.displayError(e); } finally { - lastTarget = node; + lastTargetElement = targetElement; } } - public void mouseMoved(GraphicsNodeMouseEvent evt) { - dispatchMouseEvent("mousemove", evt, false); + + /** + * Dispatches a DOM UIEvent according to the specified + * parameters. + * + * @param eventType the event type + * @param evt the GVT GraphicsNodeMouseEvent + * @param cancelable true means the event is cancelable + */ + protected void dispatchUIEvent(String eventType, + GraphicsNodeMouseEvent evt, + boolean cancelable) { + } + /** + * Returns the related element according to the specified event. + * + * @param evt the GVT GraphicsNodeMouseEvent + */ + protected Element getRelatedElement(GraphicsNodeMouseEvent evt) { + GraphicsNode relatedNode = evt.getRelatedNode(); + Element relatedElement = null; + if (relatedNode != null) { + relatedElement = context.getElement(relatedNode); + } + return relatedElement; + } + + /** + * Returns the mouse event button. + * + * @param evt the GVT GraphicsNodeMouseEvent + */ + protected short getButton(GraphicsNodeMouseEvent evt) { + short button = 1; + if ((evt.BUTTON1_MASK & evt.getModifiers()) != 0) { + button = 0; + } else if ((evt.BUTTON3_MASK & evt.getModifiers()) != 0) { + button = 2; + } + return button; + } - private void dispatchMouseEvent(String eventType, - GraphicsNodeMouseEvent evt, - boolean cancelok) { - Point2D pos = evt.getPoint2D(); + /** + * Returns the client mouse coordinates using the specified + * mouse coordinates in the GVT Tree space. + * + * @param coords the mouse coordinates in the GVT tree space + */ + protected Point getClientMouseLocation(Point2D coords) { AffineTransform transform = ua.getTransform(); - if (transform != null && !transform.isIdentity()) - transform.transform(pos, pos); - Point screen = ua.getClientAreaLocationOnScreen(); - screen.translate((int)Math.floor(pos.getX()), - (int)Math.floor(pos.getY())); - // compute screen coordinates - GraphicsNode node = evt.getGraphicsNode(); - Element elmt = context.getElement(node); - if (elmt == null) // should not appeared if binding on - return; + Point2D p = coords; + if (transform != null && !transform.isIdentity()) { + p = transform.transform(coords, null); + } + return new Point((int)Math.floor(coords.getX()), + (int)Math.floor(coords.getY())); + } - // see whether or not the GraphicsNode is a TextNode + /** + * Returns the mouse coordinates on the screen using the + * specified client mouse coordinates. + * + * @param coords the mouse coordinates in the client space + */ + protected Point getScreenMouseLocation(Point coords) { + Point screen = new Point(ua.getClientAreaLocationOnScreen()); + screen.translate(coords.x, coords.y); + return screen; + } + + /** + * Returns the element that is the target of the specified + * event or null if any. + * + * @param node the graphics node that received the event + * @param coords the mouse coordinates in the GVT tree space + */ + protected Element getEventTarget(GraphicsNode node, Point2D coords) { + Element target = context.getElement(node); + // Lookup inside the text element children to see if the target + // is a tspan or textPath if (node instanceof TextNode) { - // handle tspan or textPath if any TextNode textNode = (TextNode)node; List list = textNode.getTextRuns(); for (int i = 0 ; i < list.size(); i++) { StrokingTextPainter.TextRun run = (StrokingTextPainter.TextRun)list.get(i); AttributedCharacterIterator aci = run.getACI(); - //printACI(aci); TextSpanLayout layout = run.getLayout(); - float x = (float)pos.getX(); - float y = (float)pos.getY(); + float x = (float)coords.getX(); + float y = (float)coords.getY(); TextHit textHit = layout.hitTestChar(x, y); if (textHit != null && layout.getBounds().contains(x, y)) { Object delimiter = aci.getAttribute (GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); if (delimiter instanceof Element) { - elmt = (Element)delimiter; - break; + return (Element)delimiter; } } } } - - EventTarget target = (EventTarget)elmt; - // <!> TODO dispatch it only if pointers-event property ask for - short button = 1; - if ((evt.BUTTON1_MASK & evt.getModifiers()) != 0) - button = 0; - else - if ((evt.BUTTON3_MASK & evt.getModifiers()) != 0) - button = 2; - MouseEvent mevent = (MouseEvent) - // DOM Level 2 6.5 cast from Document to DocumentEvent is ok - ((DocumentEvent)elmt.getOwnerDocument()).createEvent("MouseEvents"); - // deal with the related node/target - node = evt.getRelatedNode(); - EventTarget relatedTarget = - (EventTarget)context.getElement(node); - mevent.initMouseEvent(eventType, true, cancelok, null, - evt.getClickCount(), - screen.x, screen.y, - (int)Math.floor(pos.getX()), - (int)Math.floor(pos.getY()), - evt.isControlDown(), evt.isAltDown(), - evt.isShiftDown(), evt.isMetaDown(), - button, relatedTarget); - try { - target.dispatchEvent(mevent); - } catch (RuntimeException e) { - // runtime exceptions may appear we need to display them... - ua.displayError(new Exception("scripting error in event handling: "+ - e.getMessage())); - } + return (Element)target; } } - /* - public static void printACI(AttributedCharacterIterator aci) { - AttributedCharacterIterator newAci = (AttributedCharacterIterator)aci.clone(); - newAci.first(); - while (newAci.current() != AttributedCharacterIterator.DONE && - newAci.getIndex() < newAci.getEndIndex()) { - System.out.print(newAci.current()); - newAci.next(); - } - System.out.println("\n---------------------------------------"); - }*/ } 1.61 +25 -5 xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java Index: SVGTextElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java,v retrieving revision 1.60 retrieving revision 1.61 diff -u -r1.60 -r1.61 --- SVGTextElementBridge.java 29 Mar 2002 20:00:54 -0000 1.60 +++ SVGTextElementBridge.java 22 Apr 2002 14:24:57 -0000 1.61 @@ -69,7 +69,7 @@ * * @author <a href="[EMAIL PROTECTED]">Stephane Hillion</a> * @author <a href="[EMAIL PROTECTED]">Bill Haneman</a> - * @version $Id: SVGTextElementBridge.java,v 1.60 2002/03/29 20:00:54 deweese Exp $ + * @version $Id: SVGTextElementBridge.java,v 1.61 2002/04/22 14:24:57 tkormann Exp $ */ public class SVGTextElementBridge extends AbstractGraphicsNodeBridge { @@ -387,12 +387,10 @@ } nodeElement = (Element)n; - String ln = n.getLocalName(); if (ln.equals(SVG_TSPAN_TAG) || - ln.equals(SVG_ALT_GLYPH_TAG) || - ln.equals(SVG_A_TAG)) { + ln.equals(SVG_ALT_GLYPH_TAG)) { fillAttributedStringBuffer(ctx, nodeElement, false, @@ -423,9 +421,31 @@ Map m = getAttributeMap(ctx, nodeElement, textPath); asb.append(s, m); } + } else if (ln.equals(SVG_A_TAG)) { + EventTarget target = (EventTarget)nodeElement; + System.out.println(ln); + UserAgent ua = ctx.getUserAgent(); + target.addEventListener + (SVG_EVENT_CLICK, + new SVGAElementBridge.AnchorListener(ua), + false); + + target.addEventListener + (SVG_EVENT_MOUSEOVER, + new SVGAElementBridge.CursorMouseOverListener(ua), + false); + + target.addEventListener + (SVG_EVENT_MOUSEOUT, + new SVGAElementBridge.CursorMouseOutListener(ua), + false); + fillAttributedStringBuffer(ctx, + nodeElement, + false, + textPath, + asb); } break; - case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: s = n.getNodeValue();
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]