Hi,

found a strange behavior when dynamically update a style of element reused
by <use xlink:href="..."/>.
I have a drawing where a path element declared in defs like that:

    <defs>
        <g id="stage1src">
            <path id="propeller" d="M36.039,210c7.751,0,15.501,0,23.253,0
..... "/>
        </g>
    </defs>

    <g id="stage1">
        <use xlink:href="#stage1src"/>
    </g>

When I try to dynamically change the "propeller" path color as follows:

    final SVGDocument svgDocument = canvas.getSVGDocument();
    final SVGStylableElement propeller = (SVGStylableElement)
svgDocument.getElementById("propeller");

    updateInRunnableQueue(new Runnable()
    {
      public void run()
      {
        final SVGStylableElement propeller =
(SVGStylableElement) canvas.getSVGDocument().getElementById("propeller");
        CSSStyleDeclaration overrideStyle = propeller.getOverrideStyle();
        overrideStyle.setCssText("fill: " + htmlColor);
      }
    });

Nothing happens. But this is more or less predictable. Assume that Batik
can not dynamically track changes for <use xlink:href="#stage1src"/>.
OK. I dig this list and found that most common decision to make the Batik
to handle such changes is to reset affected document nodes.
So, let's reset the root node for simplicity after making a style changes
(in updateRunnableQueue):

final SVGStylableElement propeller =
(SVGStylableElement) canvas.getSVGDocument().getElementById("propeller");
CSSStyleDeclaration overrideStyle = propeller.getOverrideStyle();
overrideStyle.setCssText("fill: " + htmlColor);

final SVGSVGElement rootElement = svgDocument.getRootElement();
svgDocument.removeChild(rootElement);
svgDocument.appendChild(rootElement);

Viola! Now the drawing visually change it's color.

The problem begins when I add a style declaration in the drawing's SVG
file, even empty one:

    <style type="text/css">
    </style>

The root node resetting stops to make the drawing changes visible! The one
thing helps to dynamically see the changes is to completely reload the
document (in updateRunnableQueue):

final SVGStylableElement propeller =
(SVGStylableElement) canvas.getSVGDocument().getElementById("propeller");
CSSStyleDeclaration overrideStyle = propeller.getOverrideStyle();
overrideStyle.setCssText("fill: " + htmlColor);

canvas.setSVGDocument(canvas.getSVGDocument());

But completely reloading a document is a very expensive operation.

Can someone tell me why resetting the root node not works in this case?
How to avoid complete document reloading to see the document changes?

PS: A SVG file and a demo program are attached.

<<attachment: path.svg>>

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import javax.swing.*;

import org.apache.batik.bridge.*;
import org.apache.batik.dom.svg.*;
import org.apache.batik.swing.*;
import org.apache.batik.util.*;
import org.w3c.dom.css.*;
import org.w3c.dom.svg.*;
import sun.swing.*;

import static org.apache.batik.util.SVGConstants.*;
import static org.apache.batik.util.SVGConstants.SVG_HUNDRED_PERCENT_VALUE;

public class SvgDynamicTest
{
  private static JSVGCanvas canvas;
  private static SVGDocument doc;

  public static void main(String[] args)
  {
    try
    {
      createFrame();
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }

  private static void createFrame() throws IOException
  {
    String parser = XMLResourceDescriptor.getXMLParserClassName();
    SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);

    doc = (SVGDocument) f.createDocument("SVG", new FileInputStream(new File("resources/path.svg")));

    doc.getRootElement().setAttribute(SVG_X_ATTRIBUTE, SVG_ZERO_PERCENT_VALUE);
    doc.getRootElement().setAttribute(SVG_Y_ATTRIBUTE, SVG_ZERO_PERCENT_VALUE);
    doc.getRootElement().setAttribute(SVG_WIDTH_ATTRIBUTE, SVG_HUNDRED_PERCENT_VALUE);
    doc.getRootElement().setAttribute(SVG_HEIGHT_ATTRIBUTE, SVG_HUNDRED_PERCENT_VALUE);

    canvas = new JSVGCanvas();
    canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);
    canvas.setDocument(doc);

    final JButton changeAndNoResetButton = new JButton(new UIAction("W/o reset")
    {
      public void actionPerformed(ActionEvent e)
      {
        setColor("red");
      }
    });

    final JButton changeAndResetRootNodeButton = new JButton(new UIAction("Reset root node")
    {
      public void actionPerformed(ActionEvent e)
      {
        setColor("green");

        updateSVG(new Runnable()
        {
          public void run()
          {
            final SVGSVGElement rootElement = doc.getRootElement();
            doc.removeChild(rootElement);
            doc.appendChild(rootElement);
          }
        });
      }
    });

    final JButton changeAndReloadDocumentButton = new JButton(new UIAction("Reload document")
    {
      public void actionPerformed(ActionEvent e)
      {
        setColor("blue");

        updateSVG(new Runnable()
        {
          public void run()
          {
            canvas.setSVGDocument(doc);
          }
        });
      }
    });

    JFrame frame = new JFrame("SVG");

    final JPanel panel = new JPanel();
    panel.add(changeAndNoResetButton);
    panel.add(changeAndResetRootNodeButton);
    panel.add(changeAndReloadDocumentButton);

    frame.getContentPane().add(canvas, BorderLayout.CENTER);
    frame.getContentPane().add(panel, BorderLayout.SOUTH);

    frame.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        System.exit(0);
      }
    });

    frame.setSize(500, 500);
    frame.setVisible(true);
  }

  private static void setColor(final String htmlColor)
  {
    final SVGDocument svgDocument = canvas.getSVGDocument();
    final SVGStylableElement propeller = (SVGStylableElement) svgDocument.getElementById("propeller");

    updateSVG(new Runnable()
    {
      public void run()
      {
        CSSStyleDeclaration overrideStyle = propeller.getOverrideStyle();
        overrideStyle.setCssText("fill: " + htmlColor);
      }
    });
  }

  private static void updateSVG(Runnable r)
  {
    final UpdateManager updateManager = canvas.getUpdateManager();
    if (updateManager != null && updateManager.getUpdateRunnableQueue() != null)
    {
      updateManager.getUpdateRunnableQueue().invokeLater(r);
    }
  }

}
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscr...@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-h...@xmlgraphics.apache.org

Reply via email to