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 &lt;title&gt; element, a &lt;desc&gt;
          * 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]

Reply via email to