Hi Thomas. Here's a patch which makes handling GenericBridges more uniform. GenericBridge.handleElement is called from the GVTBuilder instead of from individual bridges' buildGraphicsNode method. The check for avoiding setting a tool tip for the root SVG element is done in JSVGCanvas.CanvasUserAgent.handleElement.
The patch also fixes a bug with tool tip handling where in a document like this: <svg> <g> <title>G title</title> <rect> <title>Rect title</title> </rect> <circle/> </g> </svg> where the g's tool tip would override the rect's because ToolTipModifiers are created for both title elements, and the one for the g happens to be called later. Cameron -- Cameron McCormack | Web: http://mcc.id.au/ | ICQ: 26955922
diff -ru xml-batik/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java xml-batik.test/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java --- xml-batik/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java 2003-10-06 10:56:00.000000000 +1000 +++ xml-batik.test/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java 2004-01-13 12:14:53.000000000 +1100 @@ -166,9 +166,6 @@ node.setPointerEventType(CSSUtilities.convertPointerEvents(e)); initializeDynamicSupport(ctx, e, node); - - // Handle children elements such as <title> - SVGUtilities.bridgeChildren(ctx, e); } /** diff -ru xml-batik/sources/org/apache/batik/bridge/GVTBuilder.java xml-batik.test/sources/org/apache/batik/bridge/GVTBuilder.java --- xml-batik/sources/org/apache/batik/bridge/GVTBuilder.java 2003-08-08 21:38:50.000000000 +1000 +++ xml-batik.test/sources/org/apache/batik/bridge/GVTBuilder.java 2004-01-13 16:33:53.000000000 +1100 @@ -143,7 +143,11 @@ public GraphicsNode build(BridgeContext ctx, Element e) { // get the appropriate bridge according to the specified element Bridge bridge = ctx.getBridge(e); - if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) { + if (bridge instanceof GenericBridge) { + // If it is a GenericBridge just handle it and return. + ((GenericBridge) bridge).handleElement(ctx, e); + return null; + } else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) { return null; } // create the associated graphics node @@ -156,6 +160,8 @@ if (gn != null) { if (gnBridge.isComposite()) { buildComposite(ctx, e, (CompositeGraphicsNode)gn); + } else { + handleGenericBridges(ctx, e); } gnBridge.buildGraphicsNode(ctx, e, gn); } @@ -207,7 +213,11 @@ } // get the appropriate bridge according to the specified element Bridge bridge = ctx.getBridge(e); - if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) { + if (bridge instanceof GenericBridge) { + // If it is a GenericBridge just handle it and return. + ((GenericBridge) bridge).handleElement(ctx, e); + return; + } else if (bridge == null || !(bridge instanceof GraphicsNodeBridge)) { return; } // check the display property @@ -224,6 +234,9 @@ // check if the element has children to build if (gnBridge.isComposite()) { buildComposite(ctx, e, (CompositeGraphicsNode)gn); + } else { + // if not then still handle the GenericBridges + handleGenericBridges(ctx, e); } gnBridge.buildGraphicsNode(ctx, e, gn); } @@ -241,5 +254,22 @@ throw ex; } } -} + /** + * Handles any GenericBridge elements which are children of the + * specified element. + * @param ctx the bridge context + * @param e the element whose child elements should be handled + */ + protected void handleGenericBridges(BridgeContext ctx, Element e) { + for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) { + if (n instanceof Element) { + Element e2 = (Element) n; + Bridge b = ctx.getBridge(e2); + if (b instanceof GenericBridge) { + ((GenericBridge) b).handleElement(ctx, e2); + } + } + } + } +} diff -ru xml-batik/sources/org/apache/batik/bridge/SVGSVGElementBridge.java xml-batik.test/sources/org/apache/batik/bridge/SVGSVGElementBridge.java --- xml-batik/sources/org/apache/batik/bridge/SVGSVGElementBridge.java 2003-11-06 09:21:09.000000000 +1100 +++ xml-batik.test/sources/org/apache/batik/bridge/SVGSVGElementBridge.java 2004-01-13 12:15:09.000000000 +1100 @@ -254,9 +254,6 @@ initializeDynamicSupport(ctx, e, node); - // Handle children elements such as <title> - //SVGUtilities.bridgeChildren(ctx, e); - //super.buildGraphicsNode(ctx, e, node); ctx.closeViewport(e); } diff -ru xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java xml-batik.test/sources/org/apache/batik/bridge/SVGTextElementBridge.java --- xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java 2003-09-08 08:25:28.000000000 +1000 +++ xml-batik.test/sources/org/apache/batik/bridge/SVGTextElementBridge.java 2004-01-13 12:15:27.000000000 +1100 @@ -251,9 +251,6 @@ node.setPointerEventType(CSSUtilities.convertPointerEvents(e)); initializeDynamicSupport(ctx, e, node); - - // Handle children elements such as <title> - SVGUtilities.bridgeChildren(ctx, e); } /** diff -ru xml-batik/sources/org/apache/batik/bridge/SVGUtilities.java xml-batik.test/sources/org/apache/batik/bridge/SVGUtilities.java --- xml-batik/sources/org/apache/batik/bridge/SVGUtilities.java 2003-08-10 02:58:37.000000000 +1000 +++ xml-batik.test/sources/org/apache/batik/bridge/SVGUtilities.java 2004-01-13 12:15:46.000000000 +1100 @@ -1140,31 +1140,4 @@ return new Rectangle2D.Double(); } } - - /** - * Scans the children of the input <tt>e</tt> element and - * invokes any registered bridge found for the children. - * - * @param ctx active BridgeContext - * @param e element to be scanned - */ - public static void bridgeChildren(BridgeContext ctx, - Element elt){ - for (Node n = elt.getFirstChild(); - n != null; - n = n.getNextSibling()) { - - if ((n.getNodeType() != Node.ELEMENT_NODE)) { - continue; - } - - Element e = (Element)n; - Bridge bridge = ctx.getBridge(e); - if (bridge == null || !(bridge instanceof GenericBridge)) { - continue; - } - - ((GenericBridge)bridge).handleElement(ctx, e); - } - } } diff -ru xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java xml-batik.test/sources/org/apache/batik/swing/JSVGCanvas.java --- xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java 2004-01-13 16:24:04.000000000 +1100 +++ xml-batik.test/sources/org/apache/batik/swing/JSVGCanvas.java 2004-01-13 17:25:49.000000000 +1100 @@ -785,6 +785,16 @@ = "JSVGCanvas.CanvasUserAgent.ToolTip.titleAndDesc"; /** + * The time of the last tool tip event. + */ + protected long lastToolTipEventTimeStamp; + + /** + * The target for which the last tool tip event was fired. + */ + protected EventTarget lastToolTipEventTarget; + + /** * The handleElement method builds a tool tip from the * content of a <title> element, a <desc> * element or both. <br/> @@ -811,6 +821,12 @@ if (!SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) return; + // Don't handle tool tips for the root SVG element. + if (elt.getParentNode() == + elt.getOwnerDocument().getDocumentElement()) { + return; + } + if (elt.getLocalName().equals(SVGConstants.SVG_TITLE_TAG)) { // If there is a <desc> peer, do nothing as the tooltip will // be handled when handleElement is invoked for the <desc> @@ -941,12 +957,12 @@ // On mouseover, set the tooltip to the title value target.addEventListener(SVGConstants.SVG_EVENT_MOUSEOVER, - new ToolTipModifier(toolTip), + new ToolTipModifier(toolTip, this), false); // On mouseout, remove the tooltip target.addEventListener(SVGConstants.SVG_EVENT_MOUSEOUT, - new ToolTipModifier(null), + new ToolTipModifier(null, this), false); if (locationListener == null) { @@ -985,6 +1001,23 @@ dialog.show(); // Safe to be called from any thread } } + + /** + * Sets the time and element of the last tool tip event handled. + */ + public void setLastToolTipEvent(long t, EventTarget et) { + lastToolTipEventTimeStamp = t; + lastToolTipEventTarget = et; + } + + /** + * Checks if the specified event time and element are the same + * as the last tool tip event. + */ + public boolean matchLastToolTipEvent(long t, EventTarget et) { + return lastToolTipEventTimeStamp == t + && lastToolTipEventTarget == et; + } } // ---------------------------------------------------------------------- @@ -1029,14 +1062,32 @@ protected String toolTip; /** + * The CanvasUserAgent used to track the last tool tip event. + */ + protected CanvasUserAgent canvasUserAgent; + + /** * @param toolTip value to which the JSVGCanvas should be * set when the event occurs. + * @param cua the CanvasUserAgent which will be used to track + * the last tool tip event. */ - public ToolTipModifier(String toolTip){ + public ToolTipModifier(String toolTip, CanvasUserAgent cua) { this.toolTip = toolTip; + canvasUserAgent = cua; } public void handleEvent(Event evt){ + // Don't set the tool tip if another ToolTipModifier + // has already handled this event (as it will have been + // a higher priority tool tip). + if (canvasUserAgent.matchLastToolTipEvent(evt.getTimeStamp(), + evt.getTarget())) { + return; + } + canvasUserAgent.setLastToolTipEvent(evt.getTimeStamp(), + evt.getTarget()); + EventQueue.invokeLater(new Runnable() { public void run() { setToolTipText(toolTip);
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]