vhardy 2003/07/09 06:31:45
Modified: samples/tests/spec/scripting use.svg
test-references/samples/tests/spec/scripting use.png
sources/org/apache/batik/bridge SVGUseElementBridge.java
Log:
Fixed bug 21358. It is now possible (even though sub-optimal) to modify the
xlink:href on a <use> and to modify the content referenced by a <use>. See the
samples/tests/spec/scripting/use.svg sample. New reference image for test.
Revision Changes Path
1.3 +90 -24 xml-batik/samples/tests/spec/scripting/use.svg
Index: use.svg
===================================================================
RCS file: /home/cvs/xml-batik/samples/tests/spec/scripting/use.svg,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- use.svg 24 Jul 2002 11:50:25 -0000 1.2
+++ use.svg 9 Jul 2003 13:31:42 -0000 1.3
@@ -24,18 +24,57 @@
<text x="50%" y="45" class="title">x/y/transform update on <use></text>
<script type="text/ecmascript"> <![CDATA[
+ var xlinkNS = 'http://www.w3.org/1999/xlink';
+ var svgNS = 'http://www.w3.org/2000/svg';
function runTest(){
document.getElementById('x').setAttributeNS(null, 'x', '20');
document.getElementById('y').setAttributeNS(null, 'y', '15');
document.getElementById('transform').setAttributeNS(null, 'transform',
'rotate(20)');
+ document.getElementById('xlink').setAttributeNS(xlinkNS, 'xlink:href',
'#symbol2');
+
+ var mutated = document.getElementById('mutatedSymbol');
+ while(mutated.firstChild != null) {
+ mutated.removeChild(mutated.firstChild);
+ }
+ var r = document.createElementNS(svgNS, 'rect');
+ r.setAttributeNS(null, "x", "-10");
+ r.setAttributeNS(null, "y", "-10");
+ r.setAttributeNS(null, "width", "20");
+ r.setAttributeNS(null, "height", "20");
+ r.setAttributeNS(null, "stroke-width", "4");
+ r.setAttributeNS(null, "stroke", "gold");
+ r.setAttributeNS(null, "fill", "crimson");
+ mutated.appendChild(r);
+
+ var t = document.createElementNS(svgNS, "text");
+ mutated.appendChild(t);
+ t.setAttributeNS(null, "text-anchor", "middle");
+ t.setAttributeNS(null, "fill", "gold");
+ t.setAttributeNS(null, "stroke", "none");
+ t.setAttributeNS(null, "y", "5");
+ var msg = document.createTextNode("Hello");
+ t.appendChild(msg);
+
+ msg.data = "Hi";
}
- ]]> </script>
+ ]]> </script> <rect id="symbol" x="-10" y="-10" width="20" height="20" />
+
<defs>
<rect id="symbol" x="-10" y="-10" width="20" height="20" />
+ <rect id="symbol2" x="-10" y="-10" width="20" height="20" stroke-width="4"
stroke="gold" fill="crimson" />
+
+ <g id="mutatedSymbolReference">
+ <rect x="-10" y="-10" width="20" height="20" stroke-width="4"
stroke="gold" fill="crimson" />
+ <text text-anchor="middle" y="5" fill="gold" stroke="none">Hi</text>
+ </g>
+
+ <g id="mutatedSymbol">
+ <rect x="-12" y="-12" width="24" height="24" class="reference" />
+ </g>
<rect id="titleCell" x="-60" y="-15" width="120" height="20" />
<rect id="tableCell" x="-60" y="-20" width="120" height="40" />
@@ -90,7 +129,7 @@
]]></style>
- <g transform="translate(165, 160)">
+ <g transform="translate(165, 120)">
<g id="tableHeader" class="tableHeader">
<g>
<use class="tableHeader" xlink:href="#titleCell" />
@@ -147,31 +186,58 @@
</g>
- <g onclick="runTest()">
+ <g id="xlinkRow" transform="translate(0,145)">
+ <g>
+ <use class="tableCell" xlink:href="#tableCell" />
+ <text class="tableCell">xlink:href</text>
+ </g>
+
+ <g transform="translate(120,0)" >
+ <use class="tableCell" xlink:href="#tableCell" />
+ <use id="xlink"
+ x="5" y="0" class="symbol" xlink:href="#symbol"/>
+ <use x="5" y="0" class="reference" xlink:href="#symbol"/>
+ </g>
+
+ </g>
+
+ <g id="mutation" transform="translate(0,185)">
+ <g>
+ <use class="tableCell" xlink:href="#tableCell" />
+ <text class="tableCell">mutation</text>
+ </g>
+
+ <g transform="translate(120,0)" >
+ <use class="tableCell" xlink:href="#tableCell" />
+ <use id="xlink"
+ x="-25" y="0" class="symbol"
xlink:href="#mutatedSymbolReference"/>
+ <use x="25" y="0" class="reference" xlink:href="#mutatedSymbol"/>
+ </g>
+
+ </g>
+
+ <g onclick="runTest()" transform="translate(0, 80)">
<use class="button" xlink:href="#button" x="60" y="200" />
<text class="button" x="60" y="200">Run Test</text>
</g>
</g>
-<!--
- <use id="use" xlink:href="#Rect" x="20" y="40" width="100" height="80"
- transform="scale(1.2)" onclick="scale('use')" />
-
- <a onclick="removeChangeAdd('use')">
- <text x="80" y="35" text-anchor="middle">Remove, modify, add</text>
- </a>
-
- <a onclick="removeChangeAdd('rect')" transform="translate(160,0)">
- <text x="80" y="35" text-anchor="middle">Remove, modify, add</text>
- </a>
-
- <rect id="rect" x="150" y="40" width="100" height="80" transform="scale(1.2)"
- style="fill:green; stroke:yellow" onclick="scale('rect')" />
-
-
- <text x="175" y="190" style="font-size:20pt; text-anchor:middle">
- Transform problem.
- </text>
--->
+
+
+ <script type="text/ecmascript"><![CDATA[
+function onDone() {
+ if (!(regardTestInstance == null)) {
+ regardTestInstance.scriptDone();
+ } else {
+ alert("This button only works when run in the regard framework");
+ }
+}
+ ]]></script>
+ <g id="done" transform="translate(195, 468)" cursor="pointer"
onclick="onDone()">
+ <rect rx="5" ry="5" width="60" height="25" fill="#eeeeee" stroke="black" />
+ <text x="30" y="18" font-size="14" font-weight="bold"
text-anchor="middle">Done</text>
+ </g>
+
+
</svg>
1.3 +26 -28 xml-batik/test-references/samples/tests/spec/scripting/use.png
<<Binary file>>
1.33 +113 -2
xml-batik/sources/org/apache/batik/bridge/SVGUseElementBridge.java
Index: SVGUseElementBridge.java
===================================================================
RCS file:
/home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGUseElementBridge.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- SVGUseElementBridge.java 11 Jun 2003 22:07:25 -0000 1.32
+++ SVGUseElementBridge.java 9 Jul 2003 13:31:44 -0000 1.33
@@ -34,6 +34,12 @@
* @version $Id$
*/
public class SVGUseElementBridge extends AbstractGraphicsNodeBridge {
+ /*
+ * Used to handle mutation of the referenced content. This is
+ * only used in dynamic context and only for reference to local
+ * content.
+ */
+ protected ReferencedElementMutationListener l;
/**
* Constructs a new bridge for the <use> element.
@@ -67,6 +73,25 @@
return null;
}
+ CompositeGraphicsNode gn = buildCompositeGraphicsNode(ctx, e,
+ null, null);
+
+ return gn;
+ }
+
+ /**
+ * Creates a <tt>GraphicsNode</tt> from the input element and
+ * populates the input <tt>CompositeGraphicsNode</tt>
+ *
+ * @param ctx the bridge context to use
+ * @param e the element that describes the graphics node to build
+ * @param gn the CompositeGraphicsNode where the use graphical
+ * content will be appended. The composite node is emptied
+ * before appending new content.
+ */
+ public CompositeGraphicsNode buildCompositeGraphicsNode(BridgeContext ctx,
Element e,
+ CompositeGraphicsNode
gn,
+
ReferencedElementMutationListener l) {
// get the referenced element
String uri = XLinkSupport.getXLinkHref(e);
if (uri.length() == 0)
@@ -142,8 +167,19 @@
GraphicsNode refNode = builder.build(ctx, g);
///////////////////////////////////////////////////////////////////////
+ boolean update = true;
+ if (gn == null) {
+ gn = new CompositeGraphicsNode();
+ update = false;
+ }
+
+ if (update) {
+ int s = gn.size();
+ for (int i=0; i<s; i++) {
+ gn.remove(0);
+ }
+ }
- CompositeGraphicsNode gn = new CompositeGraphicsNode();
gn.getChildren().add(refNode);
gn.setTransform(computeTransform(e, ctx));
@@ -159,6 +195,59 @@
if (r != null) {
gn.setBackgroundEnable(r);
}
+
+ ///////////////////////////////////////////////////////////////////////
+
+ // Handle mutations on content referenced in the same file if
+ // we are in a dynamic context.
+ if (isLocal && ctx.isDynamic()) {
+ if (l == null) {
+ l = new ReferencedElementMutationListener();
+ l.target = (EventTarget)refElement;
+ } else {
+ // Remove event listeners
+ EventTarget target = l.target;
+ target.removeEventListener("DOMAttrModified",
+ l,
+ true);
+
+ target.removeEventListener("DOMNodeInserted",
+ l,
+ true);
+
+ target.removeEventListener("DOMNodeRemoved",
+ l,
+ true);
+
+ target.removeEventListener("DOMCharacterDataModified",
+ l,
+ true);
+ }
+
+ EventTarget target = (EventTarget)refElement;
+ l.target = target;
+
+ target.addEventListener("DOMAttrModified",
+ l,
+ true);
+ ctx.storeEventListener(target, "DOMAttrModified", l, true);
+
+ target.addEventListener("DOMNodeInserted",
+ l,
+ true);
+ ctx.storeEventListener(target, "DOMNodeInserted", l, true);
+
+ target.addEventListener("DOMNodeRemoved",
+ l,
+ true);
+ ctx.storeEventListener(target, "DOMNodeRemoved", l, true);
+
+ target.addEventListener("DOMCharacterDataModified",
+ l,
+ true);
+ ctx.storeEventListener(target, "DOMCharacterDataModified", l, true);
+ }
+
return gn;
}
@@ -262,6 +351,22 @@
}
}
+ /**
+ * Used to handle modifications to the referenced content
+ */
+ public class ReferencedElementMutationListener implements EventListener {
+ EventTarget target;
+
+ public void handleEvent(Event evt) {
+ // We got a mutation in the referenced content. We need to
+ // build the content again, just in case.
+ // Note that this is way sub-optimal, because multiple changes
+ // to the referenced content will cause multiple updates to the
+ // referencing <use>. However, this provides the desired behavior
+ buildCompositeGraphicsNode(ctx, e, (CompositeGraphicsNode)node, this);
+ }
+ }
+
// BridgeUpdateHandler implementation //////////////////////////////////
/**
@@ -269,12 +374,18 @@
*/
public void handleDOMAttrModifiedEvent(MutationEvent evt) {
String attrName = evt.getAttrName();
+ Node evtNode = evt.getRelatedNode();
+
if (attrName.equals(SVG_X_ATTRIBUTE) ||
attrName.equals(SVG_Y_ATTRIBUTE) ||
attrName.equals(SVG_TRANSFORM_ATTRIBUTE)) {
String s = evt.getNewValue();
node.setTransform(computeTransform(e, ctx));
handleGeometryChanged();
+ } else if (( XLinkSupport.XLINK_NAMESPACE_URI.equals
+ (evtNode.getNamespaceURI()) )
+ && SVG_HREF_ATTRIBUTE.equals(evtNode.getLocalName()) ){
+ buildCompositeGraphicsNode(ctx, e, (CompositeGraphicsNode)node, l);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]