ASF Bugzilla – Attachment 20530 Details for
Bug 42741
Error Console and Timeline Viewer for Squiggle
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Added search and other gui enhancements to Error Console
patch19072007.txt (text/plain), 420.56 KB, created by
Jasleen Singh
on 2007-07-19 01:08:17 UTC
(
hide
)
Description:
Added search and other gui enhancements to Error Console
Filename:
MIME Type:
Creator:
Jasleen Singh
Created:
2007-07-19 01:08:17 UTC
Size:
420.56 KB
patch
obsolete
>Index: sources/org/apache/batik/dom/AbstractDocument.java >=================================================================== >--- sources/org/apache/batik/dom/AbstractDocument.java (revision 549415) >+++ sources/org/apache/batik/dom/AbstractDocument.java (working copy) >@@ -137,6 +137,11 @@ > protected transient WeakHashMap elementsByTagNamesNS; > > /** >+ * The Imported Nodes lists. >+ */ >+ protected transient WeakHashMap importedNodes; >+ >+ /** > * Input encoding of this document. > */ > protected String inputEncoding; >@@ -414,6 +419,11 @@ > result.appendChild(importNode(n, true)); > } > } >+ >+ // Store in importedNodes hashmap so that the original >+ // node is available >+ putImportedNode(result, importedNode); >+ > return result; > } > >@@ -675,6 +685,20 @@ > } > t.put(ns, ln, l); > } >+ >+ public Node getImportedNode(Node clone) { >+ if (importedNodes == null) { >+ return null; >+ } >+ return (Node)importedNodes.get(clone); >+ } >+ >+ public void putImportedNode(Node clone, Node importedNode) { >+ if (importedNodes == null) { >+ importedNodes = new WeakHashMap(); >+ } >+ importedNodes.put(clone, importedNode); >+ } > > // DocumentEvent ///////////////////////////////////////////////////////// > >Index: sources/org/apache/batik/dom/svg/SVGContext.java >=================================================================== >--- sources/org/apache/batik/dom/svg/SVGContext.java (revision 549415) >+++ sources/org/apache/batik/dom/svg/SVGContext.java (working copy) >@@ -94,4 +94,9 @@ > * Returns the font-size on the associated element. > */ > float getFontSize(); >+ >+ /** >+ * Whether parsing should be strict (throw exception on error) or not >+ */ >+ boolean strictParsing = false; > } >Index: sources/org/apache/batik/dom/util/DocumentDescriptor.java >=================================================================== >--- sources/org/apache/batik/dom/util/DocumentDescriptor.java (revision 549415) >+++ sources/org/apache/batik/dom/util/DocumentDescriptor.java (working copy) >@@ -18,10 +18,10 @@ > */ > package org.apache.batik.dom.util; > >+import org.apache.batik.dom.AbstractDocument; >+import org.apache.batik.util.CleanerThread; > import org.w3c.dom.Element; > >-import org.apache.batik.util.CleanerThread; >- > /** > * This class contains informations about a document. > * >@@ -87,7 +87,7 @@ > */ > public int getLocationColumn(Element elt) { > synchronized (this) { >- int hash = elt.hashCode() & 0x7FFFFFFF; >+ int hash = elt.hashCode() & 0x7FFFFFFF; > int index = hash % table.length; > > for (Entry e = table[index]; e != null; e = e.next) { >Index: sources/org/apache/batik/dom/util/SAXDocumentFactory.java >=================================================================== >--- sources/org/apache/batik/dom/util/SAXDocumentFactory.java (revision 549415) >+++ sources/org/apache/batik/dom/util/SAXDocumentFactory.java (working copy) >@@ -1,19 +1,19 @@ > /* > >- Licensed to the Apache Software Foundation (ASF) under one or more >- contributor license agreements. See the NOTICE file distributed with >- this work for additional information regarding copyright ownership. >- The ASF licenses this file to You under the Apache License, Version 2.0 >- (the "License"); you may not use this file except in compliance with >- the License. You may obtain a copy of the License at >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at > >- http://www.apache.org/licenses/LICENSE-2.0 >+ http://www.apache.org/licenses/LICENSE-2.0 > >- Unless required by applicable law or agreed to in writing, software >- distributed under the License is distributed on an "AS IS" BASIS, >- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >- See the License for the specific language governing permissions and >- limitations under the License. >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. > > */ > package org.apache.batik.dom.util; >@@ -30,6 +30,7 @@ > import javax.xml.parsers.SAXParser; > import javax.xml.parsers.SAXParserFactory; > >+import org.apache.batik.dom.svg.SVGOMRectElement; > import org.apache.batik.util.HaltingThread; > import org.apache.batik.util.XMLConstants; > >@@ -51,742 +52,787 @@ > import org.w3c.dom.Node; > > /** >- * This class contains methods for creating Document instances >- * from an URI using SAX2. >- * >+ * This class contains methods for creating Document instances from an URI using >+ * SAX2. >+ * > * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> > * @version $Id$ > */ >-public class SAXDocumentFactory >- extends DefaultHandler >- implements LexicalHandler, >- DocumentFactory { >+public class SAXDocumentFactory extends DefaultHandler implements >+ LexicalHandler, DocumentFactory { > >- /** >- * The DOM implementation used to create the document. >- */ >- protected DOMImplementation implementation; >+ /** >+ * The DOM implementation used to create the document. >+ */ >+ protected DOMImplementation implementation; > >- /** >- * The SAX2 parser classname. >- */ >- protected String parserClassName; >+ /** >+ * The SAX2 parser classname. >+ */ >+ protected String parserClassName; > >- /** >- * The SAX2 parser object. >- */ >- protected XMLReader parser; >+ /** >+ * The SAX2 parser object. >+ */ >+ protected XMLReader parser; > >- /** >- * The created document. >- */ >- protected Document document; >+ /** >+ * The created document. >+ */ >+ protected Document document; > >- /** >- * The created document descriptor. >- */ >- protected DocumentDescriptor documentDescriptor; >+ /** >+ * The created document descriptor. >+ */ >+ protected DocumentDescriptor documentDescriptor; > >- /** >- * Whether a document descriptor must be generated. >- */ >- protected boolean createDocumentDescriptor; >+ /** >+ * Whether a document descriptor must be generated. >+ */ >+ protected boolean createDocumentDescriptor; > >- /** >- * The current node. >- */ >- protected Node currentNode; >+ /** >+ * The current node. >+ */ >+ protected Node currentNode; > >- /** >- * The locator. >- */ >- protected Locator locator; >+ /** >+ * The locator. >+ */ >+ protected Locator locator; > >- /** >- * Contains collected string data. May be Text, CDATA or Comment. >- */ >- protected StringBuffer stringBuffer = new StringBuffer(); >- /** >- * Indicates if stringBuffer has content, needed in case of >- * zero sized "text" content. >- */ >- protected boolean stringContent; >+ /** >+ * Contains collected string data. May be Text, CDATA or Comment. >+ */ >+ protected StringBuffer stringBuffer = new StringBuffer(); > >- /** >- * True if the parser is currently parsing a DTD. >- */ >- protected boolean inDTD; >+ /** >+ * Indicates if stringBuffer has content, needed in case of zero sized >+ * "text" content. >+ */ >+ protected boolean stringContent; > >- /** >- * True if the parser is currently parsing a CDATA section. >- */ >- protected boolean inCDATA; >+ /** >+ * True if the parser is currently parsing a DTD. >+ */ >+ protected boolean inDTD; > >- /** >- * Whether the parser still hasn't read the document element's >- * opening tag. >- */ >- protected boolean inProlog; >+ /** >+ * True if the parser is currently parsing a CDATA section. >+ */ >+ protected boolean inCDATA; > >- /** >- * Whether the parser is in validating mode. >- */ >- protected boolean isValidating; >+ /** >+ * Whether the parser still hasn't read the document element's opening tag. >+ */ >+ protected boolean inProlog; > >- /** >- * Whether the document just parsed was standalone. >- */ >- protected boolean isStandalone; >+ /** >+ * Whether the parser is in validating mode. >+ */ >+ protected boolean isValidating; > >- /** >- * XML version of the document just parsed. >- */ >- protected String xmlVersion; >+ /** >+ * Whether the document just parsed was standalone. >+ */ >+ protected boolean isStandalone; > >- /** >- * The stack used to store the namespace URIs. >- */ >- protected HashTableStack namespaces; >+ /** >+ * XML version of the document just parsed. >+ */ >+ protected String xmlVersion; > >- /** >- * The error handler. >- */ >- protected ErrorHandler errorHandler; >+ /** >+ * The stack used to store the namespace URIs. >+ */ >+ protected HashTableStack namespaces; > >- protected interface PreInfo { >- Node createNode(Document doc); >- } >+ /** >+ * The error handler. >+ */ >+ protected ErrorHandler errorHandler; > >- static class ProcessingInstructionInfo implements PreInfo { >- public String target, data; >- public ProcessingInstructionInfo(String target, String data) { >- this.target = target; >- this.data = data; >- } >- public Node createNode(Document doc) { >- return doc.createProcessingInstruction(target, data); >- } >- } >+ protected interface PreInfo { >+ Node createNode(Document doc); >+ } > >- static class CommentInfo implements PreInfo { >- public String comment; >- public CommentInfo(String comment) { >- this.comment = comment; >- } >- public Node createNode(Document doc) { >- return doc.createComment(comment); >- } >- } >+ static class ProcessingInstructionInfo implements PreInfo { >+ public String target, data; > >- static class CDataInfo implements PreInfo { >- public String cdata; >- public CDataInfo(String cdata) { >- this.cdata = cdata; >- } >- public Node createNode(Document doc) { >- return doc.createCDATASection(cdata); >- } >- } >+ public ProcessingInstructionInfo(String target, String data) { >+ this.target = target; >+ this.data = data; >+ } > >- static class TextInfo implements PreInfo { >- public String text; >- public TextInfo(String text) { >- this.text = text; >- } >- public Node createNode(Document doc) { >- return doc.createTextNode(text); >- } >- } >+ public Node createNode(Document doc) { >+ return doc.createProcessingInstruction(target, data); >+ } >+ } > >- /** >- * Various elements encountered prior to real document root element. >- * List of PreInfo objects. >- */ >- protected List preInfo; >+ static class CommentInfo implements PreInfo { >+ public String comment; > >- /** >- * Creates a new SAXDocumentFactory object. >- * No document descriptor will be created while generating a document. >- * @param impl The DOM implementation to use for building the DOM tree. >- * @param parser The SAX2 parser classname. >- */ >- public SAXDocumentFactory(DOMImplementation impl, >- String parser) { >- implementation = impl; >- parserClassName = parser; >- } >+ public CommentInfo(String comment) { >+ this.comment = comment; >+ } > >- /** >- * Creates a new SAXDocumentFactory object. >- * @param impl The DOM implementation to use for building the DOM tree. >- * @param parser The SAX2 parser classname. >- * @param dd Whether a document descriptor must be generated. >- */ >- public SAXDocumentFactory(DOMImplementation impl, >- String parser, >- boolean dd) { >- implementation = impl; >- parserClassName = parser; >- createDocumentDescriptor = dd; >- } >+ public Node createNode(Document doc) { >+ return doc.createComment(comment); >+ } >+ } > >- /** >- * Creates a Document instance. >- * @param ns The namespace URI of the root element of the document. >- * @param root The name of the root element of the document. >- * @param uri The document URI. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String ns, String root, String uri) >- throws IOException { >- return createDocument(ns, root, uri, new InputSource(uri)); >- } >+ static class CDataInfo implements PreInfo { >+ public String cdata; > >- /** >- * Creates a Document instance. >- * @param uri The document URI. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String uri) >- throws IOException { >- return createDocument(new InputSource(uri)); >- } >+ public CDataInfo(String cdata) { >+ this.cdata = cdata; >+ } > >- /** >- * Creates a Document instance. >- * @param ns The namespace URI of the root element of the document. >- * @param root The name of the root element of the document. >- * @param uri The document URI. >- * @param is The document input stream. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String ns, String root, String uri, >- InputStream is) throws IOException { >- InputSource inp = new InputSource(is); >- inp.setSystemId(uri); >- return createDocument(ns, root, uri, inp); >- } >+ public Node createNode(Document doc) { >+ return doc.createCDATASection(cdata); >+ } >+ } > >- /** >- * Creates a Document instance. >- * @param uri The document URI. >- * @param is The document input stream. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String uri, InputStream is) >- throws IOException { >- InputSource inp = new InputSource(is); >- inp.setSystemId(uri); >- return createDocument(inp); >- } >+ static class TextInfo implements PreInfo { >+ public String text; > >- /** >- * Creates a Document instance. >- * @param ns The namespace URI of the root element of the document. >- * @param root The name of the root element of the document. >- * @param uri The document URI. >- * @param r The document reader. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String ns, String root, String uri, >- Reader r) throws IOException { >- InputSource inp = new InputSource(r); >- inp.setSystemId(uri); >- return createDocument(ns, root, uri, inp); >- } >+ public TextInfo(String text) { >+ this.text = text; >+ } > >- /** >- * Creates a Document instance. >- * @param ns The namespace URI of the root element of the document. >- * @param root The name of the root element of the document. >- * @param uri The document URI. >- * @param r an XMLReaderInstance >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String ns, String root, String uri, >- XMLReader r) throws IOException { >- r.setContentHandler(this); >- r.setDTDHandler(this); >- r.setEntityResolver(this); >- try { >- r.parse(uri); >- } catch (SAXException e) { >- Exception ex = e.getException(); >- if (ex != null && ex instanceof InterruptedIOException) { >- throw (InterruptedIOException) ex; >- } >- throw new SAXIOException(e); >- } >- currentNode = null; >- Document ret = document; >- document = null; >- return ret; >- } >+ public Node createNode(Document doc) { >+ return doc.createTextNode(text); >+ } >+ } > >- /** >- * Creates a Document instance. >- * @param uri The document URI. >- * @param r The document reader. >- * @exception IOException if an error occured while reading the document. >- */ >- public Document createDocument(String uri, Reader r) throws IOException { >- InputSource inp = new InputSource(r); >- inp.setSystemId(uri); >- return createDocument(inp); >- } >+ /** >+ * Various elements encountered prior to real document root element. List of >+ * PreInfo objects. >+ */ >+ protected List preInfo; > >- /** >- * Creates a Document. >- * @param ns The namespace URI of the root element. >- * @param root The name of the root element. >- * @param uri The document URI. >- * @param is The document input source. >- * @exception IOException if an error occured while reading the document. >- */ >- protected Document createDocument(String ns, String root, String uri, >- InputSource is) >- throws IOException { >- Document ret = createDocument(is); >- Element docElem = ret.getDocumentElement(); >+ /** >+ * Creates a new SAXDocumentFactory object. No document descriptor will be >+ * created while generating a document. >+ * >+ * @param impl >+ * The DOM implementation to use for building the DOM tree. >+ * @param parser >+ * The SAX2 parser classname. >+ */ >+ public SAXDocumentFactory(DOMImplementation impl, String parser) { >+ implementation = impl; >+ parserClassName = parser; >+ } > >- String lname = root; >- String nsURI = ns; >- if (ns == null) { >- int idx = lname.indexOf(':'); >- String nsp = (idx == -1 || idx == lname.length()-1) >- ? "" >- : lname.substring(0, idx); >- nsURI = namespaces.get(nsp); >- if (idx != -1 && idx != lname.length()-1) { >- lname = lname.substring(idx+1); >- } >- } >+ /** >+ * Creates a new SAXDocumentFactory object. >+ * >+ * @param impl >+ * The DOM implementation to use for building the DOM tree. >+ * @param parser >+ * The SAX2 parser classname. >+ * @param dd >+ * Whether a document descriptor must be generated. >+ */ >+ public SAXDocumentFactory(DOMImplementation impl, String parser, boolean dd) { >+ implementation = impl; >+ parserClassName = parser; >+ createDocumentDescriptor = dd; >+ } > >+ /** >+ * Creates a Document instance. >+ * >+ * @param ns >+ * The namespace URI of the root element of the document. >+ * @param root >+ * The name of the root element of the document. >+ * @param uri >+ * The document URI. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String ns, String root, String uri) >+ throws IOException { >+ return createDocument(ns, root, uri, new InputSource(uri)); >+ } > >- String docElemNS = docElem.getNamespaceURI(); >- if ((docElemNS != nsURI) && >- ((docElemNS == null) || (!docElemNS.equals(nsURI)))) >- throw new IOException >- ("Root element namespace does not match that requested:\n" + >- "Requested: " + nsURI + "\n" + >- "Found: " + docElemNS); >+ /** >+ * Creates a Document instance. >+ * >+ * @param uri >+ * The document URI. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String uri) throws IOException { >+ return createDocument(new InputSource(uri)); >+ } > >- if (docElemNS != null) { >- if (!docElem.getLocalName().equals(lname)) >- throw new IOException >- ("Root element does not match that requested:\n" + >- "Requested: " + lname + "\n" + >- "Found: " + docElem.getLocalName()); >- } else { >- if (!docElem.getNodeName().equals(lname)) >- throw new IOException >- ("Root element does not match that requested:\n" + >- "Requested: " + lname + "\n" + >- "Found: " + docElem.getNodeName()); >- } >+ /** >+ * Creates a Document instance. >+ * >+ * @param ns >+ * The namespace URI of the root element of the document. >+ * @param root >+ * The name of the root element of the document. >+ * @param uri >+ * The document URI. >+ * @param is >+ * The document input stream. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String ns, String root, String uri, >+ InputStream is) throws IOException { >+ InputSource inp = new InputSource(is); >+ inp.setSystemId(uri); >+ return createDocument(ns, root, uri, inp); >+ } > >- return ret; >- } >+ /** >+ * Creates a Document instance. >+ * >+ * @param uri >+ * The document URI. >+ * @param is >+ * The document input stream. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String uri, InputStream is) >+ throws IOException { >+ InputSource inp = new InputSource(is); >+ inp.setSystemId(uri); >+ return createDocument(inp); >+ } > >- static SAXParserFactory saxFactory; >- static { >- saxFactory = SAXParserFactory.newInstance(); >- } >+ /** >+ * Creates a Document instance. >+ * >+ * @param ns >+ * The namespace URI of the root element of the document. >+ * @param root >+ * The name of the root element of the document. >+ * @param uri >+ * The document URI. >+ * @param r >+ * The document reader. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String ns, String root, String uri, Reader r) >+ throws IOException { >+ InputSource inp = new InputSource(r); >+ inp.setSystemId(uri); >+ return createDocument(ns, root, uri, inp); >+ } > >- /** >- * Creates a Document. >- * @param is The document input source. >- * @exception IOException if an error occured while reading the document. >- */ >- protected Document createDocument(InputSource is) >- throws IOException { >- try { >- if (parserClassName != null) { >- parser = XMLReaderFactory.createXMLReader(parserClassName); >- } else { >- SAXParser saxParser; >- try { >- saxParser = saxFactory.newSAXParser(); >- } catch (ParserConfigurationException pce) { >- throw new IOException("Could not create SAXParser: " >- + pce.getMessage()); >- } >- parser = saxParser.getXMLReader(); >- } >+ /** >+ * Creates a Document instance. >+ * >+ * @param ns >+ * The namespace URI of the root element of the document. >+ * @param root >+ * The name of the root element of the document. >+ * @param uri >+ * The document URI. >+ * @param r >+ * an XMLReaderInstance >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String ns, String root, String uri, >+ XMLReader r) throws IOException { >+ r.setContentHandler(this); >+ r.setDTDHandler(this); >+ r.setEntityResolver(this); >+ try { >+ r.parse(uri); >+ } catch (SAXException e) { >+ Exception ex = e.getException(); >+ if (ex != null && ex instanceof InterruptedIOException) { >+ throw (InterruptedIOException) ex; >+ } >+ throw new SAXIOException(e); >+ } >+ currentNode = null; >+ Document ret = document; >+ document = null; >+ return ret; >+ } > >- parser.setContentHandler(this); >- parser.setDTDHandler(this); >- parser.setEntityResolver(this); >- parser.setErrorHandler((errorHandler == null) ? >- this : errorHandler); >+ /** >+ * Creates a Document instance. >+ * >+ * @param uri >+ * The document URI. >+ * @param r >+ * The document reader. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ public Document createDocument(String uri, Reader r) throws IOException { >+ InputSource inp = new InputSource(r); >+ inp.setSystemId(uri); >+ return createDocument(inp); >+ } > >- parser.setFeature("http://xml.org/sax/features/namespaces", >- true); >- parser.setFeature("http://xml.org/sax/features/namespace-prefixes", >- true); >- parser.setFeature("http://xml.org/sax/features/validation", >- isValidating); >- parser.setProperty("http://xml.org/sax/properties/lexical-handler", >- this); >- parser.parse(is); >- } catch (SAXException e) { >- Exception ex = e.getException(); >- if (ex != null && ex instanceof InterruptedIOException) { >- throw (InterruptedIOException)ex; >- } >- throw new SAXIOException(e); >- } >+ /** >+ * Creates a Document. >+ * >+ * @param ns >+ * The namespace URI of the root element. >+ * @param root >+ * The name of the root element. >+ * @param uri >+ * The document URI. >+ * @param is >+ * The document input source. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ protected Document createDocument(String ns, String root, String uri, >+ InputSource is) throws IOException { >+ Document ret = createDocument(is); >+ Element docElem = ret.getDocumentElement(); > >- currentNode = null; >- Document ret = document; >- document = null; >- locator = null; >- parser = null; >- return ret; >- } >+ String lname = root; >+ String nsURI = ns; >+ if (ns == null) { >+ int idx = lname.indexOf(':'); >+ String nsp = (idx == -1 || idx == lname.length() - 1) ? "" : lname >+ .substring(0, idx); >+ nsURI = namespaces.get(nsp); >+ if (idx != -1 && idx != lname.length() - 1) { >+ lname = lname.substring(idx + 1); >+ } >+ } > >- /** >- * Returns the document descriptor associated with the latest created >- * document. >- * @return null if no document or descriptor was previously generated. >- */ >- public DocumentDescriptor getDocumentDescriptor() { >- return documentDescriptor; >- } >+ String docElemNS = docElem.getNamespaceURI(); >+ if ((docElemNS != nsURI) >+ && ((docElemNS == null) || (!docElemNS.equals(nsURI)))) >+ throw new IOException( >+ "Root element namespace does not match that requested:\n" >+ + "Requested: " + nsURI + "\n" + "Found: " >+ + docElemNS); > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#setDocumentLocator(Locator)}. >- */ >- public void setDocumentLocator(Locator l) { >- locator = l; >- } >+ if (docElemNS != null) { >+ if (!docElem.getLocalName().equals(lname)) >+ throw new IOException( >+ "Root element does not match that requested:\n" >+ + "Requested: " + lname + "\n" + "Found: " >+ + docElem.getLocalName()); >+ } else { >+ if (!docElem.getNodeName().equals(lname)) >+ throw new IOException( >+ "Root element does not match that requested:\n" >+ + "Requested: " + lname + "\n" + "Found: " >+ + docElem.getNodeName()); >+ } > >- /** >- * Sets whether or not the XML parser will validate the XML document >- * depending on the specified parameter. >- * >- * @param isValidating indicates that the XML parser will validate the XML >- * document >- */ >- public void setValidating(boolean isValidating) { >- this.isValidating = isValidating; >- } >+ return ret; >+ } > >- /** >- * Returns true if the XML parser validates the XML stream, false >- * otherwise. >- */ >- public boolean isValidating() { >- return isValidating; >- } >+ static SAXParserFactory saxFactory; >+ static { >+ saxFactory = SAXParserFactory.newInstance(); >+ } > >- /** >- * Sets a custom error handler. >- */ >- public void setErrorHandler(ErrorHandler eh) { >- errorHandler = eh; >- } >+ /** >+ * Creates a Document. >+ * >+ * @param is >+ * The document input source. >+ * @exception IOException >+ * if an error occured while reading the document. >+ */ >+ protected Document createDocument(InputSource is) throws IOException { >+ try { >+ if (parserClassName != null) { >+ parser = XMLReaderFactory.createXMLReader(parserClassName); >+ } else { >+ SAXParser saxParser; >+ try { >+ saxParser = saxFactory.newSAXParser(); >+ } catch (ParserConfigurationException pce) { >+ throw new IOException("Could not create SAXParser: " >+ + pce.getMessage()); >+ } >+ parser = saxParser.getXMLReader(); >+ } > >- public DOMImplementation getDOMImplementation(String ver) { >- return implementation; >- } >+ parser.setContentHandler(this); >+ parser.setDTDHandler(this); >+ parser.setEntityResolver(this); >+ parser >+ .setErrorHandler((errorHandler == null) ? this >+ : errorHandler); > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ErrorHandler#fatalError(SAXParseException)}. >- */ >- public void fatalError(SAXParseException ex) throws SAXException { >- throw ex; >- } >+ parser.setFeature("http://xml.org/sax/features/namespaces", true); >+ parser.setFeature("http://xml.org/sax/features/namespace-prefixes", >+ true); >+ parser.setFeature("http://xml.org/sax/features/validation", >+ isValidating); >+ parser.setProperty("http://xml.org/sax/properties/lexical-handler", >+ this); >+ parser.parse(is); >+ } catch (SAXException e) { >+ Exception ex = e.getException(); >+ if (ex != null && ex instanceof InterruptedIOException) { >+ throw (InterruptedIOException) ex; >+ } >+ throw new SAXIOException(e); >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ErrorHandler#error(SAXParseException)}. >- */ >- public void error(SAXParseException ex) throws SAXException { >- throw ex; >- } >+ currentNode = null; >+ Document ret = document; >+ document = null; >+ locator = null; >+ parser = null; >+ return ret; >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ErrorHandler#warning(SAXParseException)}. >- */ >- public void warning(SAXParseException ex) throws SAXException { >- } >+ /** >+ * Returns the document descriptor associated with the latest created >+ * document. >+ * >+ * @return null if no document or descriptor was previously generated. >+ */ >+ public DocumentDescriptor getDocumentDescriptor() { >+ return documentDescriptor; >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#startDocument()}. >- */ >- public void startDocument() throws SAXException { >- preInfo = new LinkedList(); >- namespaces = new HashTableStack(); >- namespaces.put("xml", XMLSupport.XML_NAMESPACE_URI); >- namespaces.put("xmlns", XMLSupport.XMLNS_NAMESPACE_URI); >- namespaces.put("", null); >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#setDocumentLocator(Locator)}. >+ */ >+ public void setDocumentLocator(Locator l) { >+ locator = l; >+ } > >- inDTD = false; >- inCDATA = false; >- inProlog = true; >- currentNode = null; >- document = null; >- isStandalone = false; >- xmlVersion = XMLConstants.XML_VERSION_10; >+ /** >+ * Sets whether or not the XML parser will validate the XML document >+ * depending on the specified parameter. >+ * >+ * @param isValidating >+ * indicates that the XML parser will validate the XML document >+ */ >+ public void setValidating(boolean isValidating) { >+ this.isValidating = isValidating; >+ } > >- stringBuffer.setLength(0); >- stringContent = false; >+ /** >+ * Returns true if the XML parser validates the XML stream, false otherwise. >+ */ >+ public boolean isValidating() { >+ return isValidating; >+ } > >- if (createDocumentDescriptor) { >- documentDescriptor = new DocumentDescriptor(); >- } else { >- documentDescriptor = null; >- } >- } >+ /** >+ * Sets a custom error handler. >+ */ >+ public void setErrorHandler(ErrorHandler eh) { >+ errorHandler = eh; >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#startElement(String,String,String,Attributes)}. >- */ >- public void startElement(String uri, >- String localName, >- String rawName, >- Attributes attributes) throws SAXException { >- // Check If we should halt early. >- if (HaltingThread.hasBeenHalted()) { >- throw new SAXException(new InterruptedIOException()); >- } >+ public DOMImplementation getDOMImplementation(String ver) { >+ return implementation; >+ } > >- if (inProlog) { >- inProlog = false; >- try { >- isStandalone = parser.getFeature >- ("http://xml.org/sax/features/is-standalone"); >- } catch (SAXNotRecognizedException ex) { >- } >- try { >- xmlVersion = (String) parser.getProperty >- ("http://xml.org/sax/properties/document-xml-version"); >- } catch (SAXNotRecognizedException ex) { >- } >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ErrorHandler#fatalError(SAXParseException)}. >+ */ >+ public void fatalError(SAXParseException ex) throws SAXException { >+ throw ex; >+ } > >- // Namespaces resolution >- int len = attributes.getLength(); >- namespaces.push(); >- String version = null; >- for (int i = 0; i < len; i++) { >- String aname = attributes.getQName(i); >- int slen = aname.length(); >- if (slen < 5) >- continue; >- if (aname.equals("version")) { >- version = attributes.getValue(i); >- continue; >- } >- if (!aname.startsWith("xmlns")) >- continue; >- if (slen == 5) { >- String ns = attributes.getValue(i); >- if (ns.length() == 0) >- ns = null; >- namespaces.put("", ns); >- } else if (aname.charAt(5) == ':') { >- String ns = attributes.getValue(i); >- if (ns.length() == 0) { >- ns = null; >- } >- namespaces.put(aname.substring(6), ns); >- } >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ErrorHandler#error(SAXParseException)}. >+ */ >+ public void error(SAXParseException ex) throws SAXException { >+ throw ex; >+ } > >- // Add any collected String Data before element. >- appendStringData(); >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ErrorHandler#warning(SAXParseException)}. >+ */ >+ public void warning(SAXParseException ex) throws SAXException { >+ } > >- // Element creation >- Element e; >- int idx = rawName.indexOf(':'); >- String nsp = (idx == -1 || idx == rawName.length()-1) >- ? "" >- : rawName.substring(0, idx); >- String nsURI = namespaces.get(nsp); >- if (currentNode == null) { >- implementation = getDOMImplementation(version); >- document = implementation.createDocument(nsURI, rawName, null); >- Iterator i = preInfo.iterator(); >- currentNode = e = document.getDocumentElement(); >- while (i.hasNext()) { >- PreInfo pi = (PreInfo)i.next(); >- Node n = pi.createNode(document); >- document.insertBefore(n, e); >- } >- preInfo = null; >- } else { >- e = document.createElementNS(nsURI, rawName); >- currentNode.appendChild(e); >- currentNode = e; >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#startDocument()}. >+ */ >+ public void startDocument() throws SAXException { >+ preInfo = new LinkedList(); >+ namespaces = new HashTableStack(); >+ namespaces.put("xml", XMLSupport.XML_NAMESPACE_URI); >+ namespaces.put("xmlns", XMLSupport.XMLNS_NAMESPACE_URI); >+ namespaces.put("", null); > >- // Storage of the line number. >- if (createDocumentDescriptor && locator != null) { >- documentDescriptor.setLocation(e, >- locator.getLineNumber(), >- locator.getColumnNumber()); >- } >+ inDTD = false; >+ inCDATA = false; >+ inProlog = true; >+ currentNode = null; >+ document = null; >+ isStandalone = false; >+ xmlVersion = XMLConstants.XML_VERSION_10; > >- // Attributes creation >- for (int i = 0; i < len; i++) { >- String aname = attributes.getQName(i); >- if (aname.equals("xmlns")) { >- e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, >- aname, >- attributes.getValue(i)); >- } else { >- idx = aname.indexOf(':'); >- nsURI = (idx == -1) >- ? null >- : namespaces.get(aname.substring(0, idx)); >- e.setAttributeNS(nsURI, aname, attributes.getValue(i)); >- } >- } >- } >+ stringBuffer = new StringBuffer(); >+ stringContent = false; > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#endElement(String,String,String)}. >- */ >- public void endElement(String uri, String localName, String rawName) >- throws SAXException { >- appendStringData(); // add string data if any. >+ if (createDocumentDescriptor) { >+ documentDescriptor = new DocumentDescriptor(); >+ } else { >+ documentDescriptor = null; >+ } >+ } > >- if (currentNode != null) >- currentNode = currentNode.getParentNode(); >- namespaces.pop(); >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#startElement(String,String,String,Attributes)}. >+ */ >+ public void startElement(String uri, String localName, String rawName, >+ Attributes attributes) throws SAXException { >+ // Check If we should halt early. >+ if (HaltingThread.hasBeenHalted()) { >+ throw new SAXException(new InterruptedIOException()); >+ } > >- public void appendStringData() { >- if (!stringContent) return; >+ if (inProlog) { >+ inProlog = false; >+ try { >+ isStandalone = parser >+ .getFeature("http://xml.org/sax/features/is-standalone"); >+ } catch (SAXNotRecognizedException ex) { >+ } >+ try { >+ xmlVersion = (String) parser >+ .getProperty("http://xml.org/sax/properties/document-xml-version"); >+ } catch (SAXNotRecognizedException ex) { >+ } >+ } > >- String str = stringBuffer.toString(); >- stringBuffer.setLength(0); // reuse buffer. >- stringContent = false; >- if (currentNode == null) { >- if (inCDATA) preInfo.add(new CDataInfo(str)); >- else preInfo.add(new TextInfo(str)); >- } else { >- Node n; >- if (inCDATA) n = document.createCDATASection(str); >- else n = document.createTextNode(str); >- currentNode.appendChild(n); >- } >- } >+ // Namespaces resolution >+ int len = attributes.getLength(); >+ namespaces.push(); >+ String version = null; >+ for (int i = 0; i < len; i++) { >+ String aname = attributes.getQName(i); >+ int slen = aname.length(); >+ if (slen < 5) >+ continue; >+ if (aname.equals("version")) { >+ version = attributes.getValue(i); >+ continue; >+ } >+ if (!aname.startsWith("xmlns")) >+ continue; >+ if (slen == 5) { >+ String ns = attributes.getValue(i); >+ if (ns.length() == 0) >+ ns = null; >+ namespaces.put("", ns); >+ } else if (aname.charAt(5) == ':') { >+ String ns = attributes.getValue(i); >+ if (ns.length() == 0) { >+ ns = null; >+ } >+ namespaces.put(aname.substring(6), ns); >+ } >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#characters(char[],int,int)}. >- */ >- public void characters(char[] ch, int start, int length) >- throws SAXException { >- stringBuffer.append(ch, start, length); >- stringContent = true; >- } >+ // Add any collected String Data before element. >+ appendStringData(); > >+ // Element creation >+ Element e; >+ int idx = rawName.indexOf(':'); >+ String nsp = (idx == -1 || idx == rawName.length() - 1) ? "" : rawName >+ .substring(0, idx); >+ String nsURI = namespaces.get(nsp); >+ if (currentNode == null) { >+ implementation = getDOMImplementation(version); >+ document = implementation.createDocument(nsURI, rawName, null); >+ Iterator i = preInfo.iterator(); >+ currentNode = e = document.getDocumentElement(); >+ while (i.hasNext()) { >+ PreInfo pi = (PreInfo) i.next(); >+ Node n = pi.createNode(document); >+ document.insertBefore(n, e); >+ } >+ preInfo = null; >+ } else { >+ e = document.createElementNS(nsURI, rawName); >+ currentNode.appendChild(e); >+ currentNode = e; >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#ignorableWhitespace(char[],int,int)}. >- */ >- public void ignorableWhitespace(char[] ch, >- int start, >- int length) >- throws SAXException { >- stringBuffer.append(ch, start, length); >- stringContent = true; >- } >+ // Storage of the line number. >+ if (createDocumentDescriptor && locator != null) { >+ documentDescriptor.setLocation(e, locator.getLineNumber(), locator >+ .getColumnNumber()); >+ } > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ContentHandler#processingInstruction(String,String)}. >- */ >- public void processingInstruction(String target, String data) >- throws SAXException { >- if (inDTD) >- return; >+ // Attributes creation >+ for (int i = 0; i < len; i++) { >+ String aname = attributes.getQName(i); >+ if (aname.equals("xmlns")) { >+ e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, aname, >+ attributes.getValue(i)); >+ } else { >+ idx = aname.indexOf(':'); >+ nsURI = (idx == -1) ? null : namespaces.get(aname.substring(0, >+ idx)); >+ e.setAttributeNS(nsURI, aname, attributes.getValue(i)); >+ } >+ } >+ } > >- appendStringData(); // Add any collected String Data before PI >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#endElement(String,String,String)}. >+ */ >+ public void endElement(String uri, String localName, String rawName) >+ throws SAXException { >+ appendStringData(); // add string data if any. > >- if (currentNode == null) >- preInfo.add(new ProcessingInstructionInfo(target, data)); >- else >- currentNode.appendChild >- (document.createProcessingInstruction(target, data)); >- } >+ if (currentNode != null) >+ currentNode = currentNode.getParentNode(); >+ namespaces.pop(); >+ } > >- // LexicalHandler ///////////////////////////////////////////////////////// >+ public void appendStringData() { >+ if (!stringContent) >+ return; > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ext.LexicalHandler#startDTD(String,String,String)}. >- */ >- public void startDTD(String name, String publicId, String systemId) >- throws SAXException { >- appendStringData(); // Add collected string data before entering DTD >- inDTD = true; >- } >+ String str = stringBuffer.toString(); >+ stringBuffer.setLength(0); // reuse buffer. >+ stringContent = false; >+ if (currentNode == null) { >+ if (inCDATA) >+ preInfo.add(new CDataInfo(str)); >+ else >+ preInfo.add(new TextInfo(str)); >+ } else { >+ Node n; >+ if (inCDATA) >+ n = document.createCDATASection(str); >+ else >+ n = document.createTextNode(str); >+ currentNode.appendChild(n); >+ } >+ } > >- /** >- * <b>SAX</b>: Implements {@link org.xml.sax.ext.LexicalHandler#endDTD()}. >- */ >- public void endDTD() throws SAXException { >- inDTD = false; >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#characters(char[],int,int)}. >+ */ >+ public void characters(char[] ch, int start, int length) >+ throws SAXException { >+ stringBuffer.append(ch, start, length); >+ stringContent = true; >+ } > >- /** >- * <b>SAX</b>: Implements >- * {@link org.xml.sax.ext.LexicalHandler#startEntity(String)}. >- */ >- public void startEntity(String name) throws SAXException { >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#ignorableWhitespace(char[],int,int)}. >+ */ >+ public void ignorableWhitespace(char[] ch, int start, int length) >+ throws SAXException { >+ stringBuffer.append(ch, start, length); >+ stringContent = true; >+ } > >- /** >- * <b>SAX</b>: Implements >- * {@link org.xml.sax.ext.LexicalHandler#endEntity(String)}. >- */ >- public void endEntity(String name) throws SAXException { >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ContentHandler#processingInstruction(String,String)}. >+ */ >+ public void processingInstruction(String target, String data) >+ throws SAXException { >+ if (inDTD) >+ return; > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ext.LexicalHandler#startCDATA()}. >- */ >- public void startCDATA() throws SAXException { >- appendStringData(); // Add any collected String Data before CData >- inCDATA = true; >- stringContent = true; // always create CDATA even if empty. >- } >+ appendStringData(); // Add any collected String Data before PI > >- /** >- * <b>SAX</b>: Implements {@link >- * org.xml.sax.ext.LexicalHandler#endCDATA()}. >- */ >- public void endCDATA() throws SAXException { >- appendStringData(); // Add the CDATA section >- inCDATA = false; >- } >+ if (currentNode == null) >+ preInfo.add(new ProcessingInstructionInfo(target, data)); >+ else >+ currentNode.appendChild(document.createProcessingInstruction( >+ target, data)); >+ } > >- /** >- * <b>SAX</b>: Implements >- * {@link org.xml.sax.ext.LexicalHandler#comment(char[],int,int)}. >- */ >- public void comment(char[] ch, int start, int length) throws SAXException { >- if (inDTD) return; >- appendStringData(); >+ // LexicalHandler ///////////////////////////////////////////////////////// > >- String str = new String(ch, start, length); >- if (currentNode == null) { >- preInfo.add(new CommentInfo(str)); >- } else { >- currentNode.appendChild(document.createComment(str)); >- } >- } >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ext.LexicalHandler#startDTD(String,String,String)}. >+ */ >+ public void startDTD(String name, String publicId, String systemId) >+ throws SAXException { >+ appendStringData(); // Add collected string data before entering DTD >+ inDTD = true; >+ } >+ >+ /** >+ * <b>SAX</b>: Implements {@link org.xml.sax.ext.LexicalHandler#endDTD()}. >+ */ >+ public void endDTD() throws SAXException { >+ inDTD = false; >+ } >+ >+ /** >+ * <b>SAX</b>: Implements >+ * {@link org.xml.sax.ext.LexicalHandler#startEntity(String)}. >+ */ >+ public void startEntity(String name) throws SAXException { >+ } >+ >+ /** >+ * <b>SAX</b>: Implements >+ * {@link org.xml.sax.ext.LexicalHandler#endEntity(String)}. >+ */ >+ public void endEntity(String name) throws SAXException { >+ } >+ >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ext.LexicalHandler#startCDATA()}. >+ */ >+ public void startCDATA() throws SAXException { >+ appendStringData(); // Add any collected String Data before CData >+ inCDATA = true; >+ stringContent = true; // always create CDATA even if empty. >+ } >+ >+ /** >+ * <b>SAX</b>: Implements {@link >+ * org.xml.sax.ext.LexicalHandler#endCDATA()}. >+ */ >+ public void endCDATA() throws SAXException { >+ appendStringData(); // Add the CDATA section >+ inCDATA = false; >+ } >+ >+ /** >+ * <b>SAX</b>: Implements >+ * {@link org.xml.sax.ext.LexicalHandler#comment(char[],int,int)}. >+ */ >+ public void comment(char[] ch, int start, int length) throws SAXException { >+ if (inDTD) >+ return; >+ appendStringData(); >+ >+ String str = new String(ch, start, length); >+ if (currentNode == null) { >+ preInfo.add(new CommentInfo(str)); >+ } else { >+ currentNode.appendChild(document.createComment(str)); >+ } >+ } > } >Index: sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java >=================================================================== >--- sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java (revision 549415) >+++ sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java (working copy) >@@ -22,7 +22,11 @@ > import java.awt.Component; > import javax.swing.JDialog; > import javax.swing.JOptionPane; >+ >+import org.apache.batik.swing.JSVGCanvas; >+import org.apache.batik.util.gui.ErrorConsole; > import org.apache.batik.util.gui.JErrorPane; >+import org.apache.batik.util.gui.ErrorConsole.ErrorInfo; > > /** > * One line Class Desc >@@ -53,10 +57,12 @@ > * Displays an error resulting from the specified Exception. > */ > public void displayError(Exception ex) { >- JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(parentComponent, "ERROR"); >- dialog.setModal(false); >- dialog.setVisible(true); >+// JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ // <!FIX ME> Document is null for now, how to get access to it?? >+ ErrorInfo info = new ErrorInfo(ex, "Not available", ErrorConsole.ERROR); >+ console.add(info); >+ ErrorConsole.showDialog(parentComponent); > } > > /** >Index: sources/org/apache/batik/swing/svg/SVGDocumentLoader.java >=================================================================== >--- sources/org/apache/batik/swing/svg/SVGDocumentLoader.java (revision 549415) >+++ sources/org/apache/batik/swing/svg/SVGDocumentLoader.java (working copy) >@@ -73,7 +73,7 @@ > */ > public void run() { > SVGDocumentLoaderEvent evt; >- evt = new SVGDocumentLoaderEvent(this, null); >+ evt = new SVGDocumentLoaderEvent(this, null, null); > try { > fireEvent(startedDispatcher, evt); > if (isHalted()) { >@@ -88,7 +88,7 @@ > return; > } > >- evt = new SVGDocumentLoaderEvent(this, svgDocument); >+ evt = new SVGDocumentLoaderEvent(this, svgDocument, loader.getDocumentDescriptor(svgDocument)); > fireEvent(completedDispatcher, evt); > } catch (InterruptedIOException e) { > fireEvent(cancelledDispatcher, evt); >Index: sources/org/apache/batik/swing/svg/SVGDocumentLoaderEvent.java >=================================================================== >--- sources/org/apache/batik/swing/svg/SVGDocumentLoaderEvent.java (revision 549415) >+++ sources/org/apache/batik/swing/svg/SVGDocumentLoaderEvent.java (working copy) >@@ -20,6 +20,7 @@ > > import java.util.EventObject; > >+import org.apache.batik.dom.util.DocumentDescriptor; > import org.w3c.dom.svg.SVGDocument; > > /** >@@ -37,14 +38,20 @@ > protected SVGDocument svgDocument; > > /** >+ * The document descriptor describing the document >+ */ >+ protected DocumentDescriptor docDescriptor; >+ >+ /** > * Creates a new SVGDocumentLoaderEvent. > * @param source the object that originated the event, ie. the > * SVGDocumentLoader. > * @param doc The associated document. > */ >- public SVGDocumentLoaderEvent(Object source, SVGDocument doc) { >+ public SVGDocumentLoaderEvent(Object source, SVGDocument doc, DocumentDescriptor desc) { > super(source); > svgDocument = doc; >+ docDescriptor = desc; > } > > /** >@@ -54,4 +61,12 @@ > public SVGDocument getSVGDocument() { > return svgDocument; > } >+ >+ /** >+ * Returns the document descriptor for this document, or null >+ * if the document wasn't completely loaded >+ */ >+ public DocumentDescriptor getDocumentDescriptor() { >+ return docDescriptor; >+ } > } >Index: sources/org/apache/batik/swing/JSVGCanvas.java >=================================================================== >--- sources/org/apache/batik/swing/JSVGCanvas.java (revision 549415) >+++ sources/org/apache/batik/swing/JSVGCanvas.java (working copy) >@@ -1,19 +1,19 @@ > /* > >- Licensed to the Apache Software Foundation (ASF) under one or more >- contributor license agreements. See the NOTICE file distributed with >- this work for additional information regarding copyright ownership. >- The ASF licenses this file to You under the Apache License, Version 2.0 >- (the "License"); you may not use this file except in compliance with >- the License. You may obtain a copy of the License at >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at > >- http://www.apache.org/licenses/LICENSE-2.0 >+ http://www.apache.org/licenses/LICENSE-2.0 > >- Unless required by applicable law or agreed to in writing, software >- distributed under the License is distributed on an "AS IS" BASIS, >- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >- See the License for the specific language governing permissions and >- limitations under the License. >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. > > */ > package org.apache.batik.swing; >@@ -57,8 +57,8 @@ > import org.apache.batik.swing.svg.SVGUserAgent; > import org.apache.batik.util.SVGConstants; > import org.apache.batik.util.XMLConstants; >-import org.apache.batik.util.gui.JErrorPane; >- >+import org.apache.batik.util.gui.ErrorConsole; >+import org.apache.batik.util.gui.ErrorConsole.ErrorInfo; > import org.w3c.dom.Element; > import org.w3c.dom.Node; > import org.w3c.dom.events.Event; >@@ -68,1165 +68,1157 @@ > > /** > * This class represents a general-purpose swing SVG component. The >- * <tt>JSVGCanvas</tt> does not provided additional functionalities compared to >- * the <tt>JSVGComponent</tt> but simply provides an API conformed to the >+ * <tt>JSVGCanvas</tt> does not provided additional functionalities compared >+ * to the <tt>JSVGComponent</tt> but simply provides an API conformed to the > * JavaBean specification. The only major change between the > * <tt>JSVGComponent</tt> and this component is that interactors and text > * selection are activated by default. >- * >+ * > * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a> > * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> > * @version $Id$ > */ > public class JSVGCanvas extends JSVGComponent { > >- /** >- * The key for the Action to scroll right. >- */ >- public static final String SCROLL_RIGHT_ACTION = "ScrollRight"; >+ /** >+ * The key for the Action to scroll right. >+ */ >+ public static final String SCROLL_RIGHT_ACTION = "ScrollRight"; > >- /** >- * The key for the Action to scroll left. >- */ >- public static final String SCROLL_LEFT_ACTION = "ScrollLeft"; >+ /** >+ * The key for the Action to scroll left. >+ */ >+ public static final String SCROLL_LEFT_ACTION = "ScrollLeft"; > >- /** >- * The key for the Action to scroll up. >- */ >- public static final String SCROLL_UP_ACTION = "ScrollUp"; >+ /** >+ * The key for the Action to scroll up. >+ */ >+ public static final String SCROLL_UP_ACTION = "ScrollUp"; > >- /** >- * The key for the Action to scroll down. >- */ >- public static final String SCROLL_DOWN_ACTION = "ScrollDown"; >+ /** >+ * The key for the Action to scroll down. >+ */ >+ public static final String SCROLL_DOWN_ACTION = "ScrollDown"; > >- /** >- * The key for the Action to quickly scroll right. >- */ >- public static final String FAST_SCROLL_RIGHT_ACTION = "FastScrollRight"; >+ /** >+ * The key for the Action to quickly scroll right. >+ */ >+ public static final String FAST_SCROLL_RIGHT_ACTION = "FastScrollRight"; > >- /** >- * The key for the Action to quickly scroll left. >- */ >- public static final String FAST_SCROLL_LEFT_ACTION = "FastScrollLeft"; >+ /** >+ * The key for the Action to quickly scroll left. >+ */ >+ public static final String FAST_SCROLL_LEFT_ACTION = "FastScrollLeft"; > >- /** >- * The key for the Action to quickly scroll up. >- */ >- public static final String FAST_SCROLL_UP_ACTION = "FastScrollUp"; >+ /** >+ * The key for the Action to quickly scroll up. >+ */ >+ public static final String FAST_SCROLL_UP_ACTION = "FastScrollUp"; > >- /** >- * The key for the Action to quickly scroll down. >- */ >- public static final String FAST_SCROLL_DOWN_ACTION = "FastScrollDown"; >+ /** >+ * The key for the Action to quickly scroll down. >+ */ >+ public static final String FAST_SCROLL_DOWN_ACTION = "FastScrollDown"; > >- /** >- * The key for the Action to zoom in. >- */ >- public static final String ZOOM_IN_ACTION = "ZoomIn"; >+ /** >+ * The key for the Action to zoom in. >+ */ >+ public static final String ZOOM_IN_ACTION = "ZoomIn"; > >- /** >- * The key for the Action to zoom out. >- */ >- public static final String ZOOM_OUT_ACTION = "ZoomOut"; >+ /** >+ * The key for the Action to zoom out. >+ */ >+ public static final String ZOOM_OUT_ACTION = "ZoomOut"; > >- /** >- * The key for the Action to reset the transform. >- */ >- public static final String RESET_TRANSFORM_ACTION = "ResetTransform"; >+ /** >+ * The key for the Action to reset the transform. >+ */ >+ public static final String RESET_TRANSFORM_ACTION = "ResetTransform"; > >- /** >- * This flag bit indicates whether or not the zoom interactor is >- * enabled. True means the zoom interactor is functional. >- */ >- private boolean isZoomInteractorEnabled = true; >+ /** >+ * This flag bit indicates whether or not the zoom interactor is enabled. >+ * True means the zoom interactor is functional. >+ */ >+ private boolean isZoomInteractorEnabled = true; > >- /** >- * This flag bit indicates whether or not the image zoom interactor is >- * enabled. True means the image zoom interactor is functional. >- */ >- private boolean isImageZoomInteractorEnabled = true; >+ /** >+ * This flag bit indicates whether or not the image zoom interactor is >+ * enabled. True means the image zoom interactor is functional. >+ */ >+ private boolean isImageZoomInteractorEnabled = true; > >- /** >- * This flag bit indicates whether or not the pan interactor is >- * enabled. True means the pan interactor is functional. >- */ >- private boolean isPanInteractorEnabled = true; >+ /** >+ * This flag bit indicates whether or not the pan interactor is enabled. >+ * True means the pan interactor is functional. >+ */ >+ private boolean isPanInteractorEnabled = true; > >- /** >- * This flag bit indicates whether or not the rotate interactor is >- * enabled. True means the rotate interactor is functional. >- */ >- private boolean isRotateInteractorEnabled = true; >+ /** >+ * This flag bit indicates whether or not the rotate interactor is enabled. >+ * True means the rotate interactor is functional. >+ */ >+ private boolean isRotateInteractorEnabled = true; > >- /** >- * This flag bit indicates whether or not the reset transform interactor is >- * enabled. True means the reset transform interactor is functional. >- */ >- private boolean isResetTransformInteractorEnabled = true; >+ /** >+ * This flag bit indicates whether or not the reset transform interactor is >+ * enabled. True means the reset transform interactor is functional. >+ */ >+ private boolean isResetTransformInteractorEnabled = true; > >- /** >- * The <tt>PropertyChangeSupport</tt> used to fire >- * <tt>PropertyChangeEvent</tt>. >- */ >- protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); >+ /** >+ * The <tt>PropertyChangeSupport</tt> used to fire >+ * <tt>PropertyChangeEvent</tt>. >+ */ >+ protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); > >- /** >- * The URI of the current document being displayed. >- */ >- protected String uri; >+ /** >+ * The URI of the current document being displayed. >+ */ >+ protected String uri; > >- /** >- * Keeps track of the last known mouse position over the canvas. >- * This is used for displaying tooltips at the right location. >- */ >- protected LocationListener locationListener = new LocationListener(); >+ /** >+ * Keeps track of the last known mouse position over the canvas. This is >+ * used for displaying tooltips at the right location. >+ */ >+ protected LocationListener locationListener = new LocationListener(); > >- /** >- * Mapping of elements to listeners so they can be removed, >- * if the tooltip is removed. >- */ >- protected Map toolTipMap = null; >- protected EventListener toolTipListener = new ToolTipModifier(); >- protected EventTarget lastTarget = null; >- protected Map toolTipDocs = null; >- /** >- * This is used as the value in the toolTipDocs WeakHashMap. >- * This way we can tell if a document has already been added. >- */ >- protected static final Object MAP_TOKEN = new Object(); >- /** >- * The time of the last tool tip event. >- */ >- protected long lastToolTipEventTimeStamp; >+ /** >+ * Mapping of elements to listeners so they can be removed, if the tooltip >+ * is removed. >+ */ >+ protected Map toolTipMap = null; > >- /** >- * The target for which the last tool tip event was fired. >- */ >- protected EventTarget lastToolTipEventTarget; >+ protected EventListener toolTipListener = new ToolTipModifier(); > >+ protected EventTarget lastTarget = null; > >+ protected Map toolTipDocs = null; > >- /** >- * Creates a new JSVGCanvas. >- */ >- public JSVGCanvas() { >- this(null, true, true); >- addMouseMotionListener(locationListener); >- } >+ /** >+ * This is used as the value in the toolTipDocs WeakHashMap. This way we can >+ * tell if a document has already been added. >+ */ >+ protected static final Object MAP_TOKEN = new Object(); > >- /** >- * Creates a new JSVGCanvas. >- * >- * @param ua a SVGUserAgent instance or null. >- * @param eventsEnabled Whether the GVT tree should be reactive to mouse >- * and key events. >- * @param selectableText Whether the text should be selectable. >- */ >- public JSVGCanvas(SVGUserAgent ua, >- boolean eventsEnabled, >- boolean selectableText) { >+ /** >+ * The time of the last tool tip event. >+ */ >+ protected long lastToolTipEventTimeStamp; > >- super(ua, eventsEnabled, selectableText); >+ /** >+ * The target for which the last tool tip event was fired. >+ */ >+ protected EventTarget lastToolTipEventTarget; > >- setPreferredSize(new Dimension(200, 200)); >- setMinimumSize(new Dimension(100, 100)); >+ /** >+ * Creates a new JSVGCanvas. >+ */ >+ public JSVGCanvas() { >+ this(null, true, true); >+ addMouseMotionListener(locationListener); >+ } > >- List intl = getInteractors(); >- intl.add(zoomInteractor); >- intl.add(imageZoomInteractor); >- intl.add(panInteractor); >- intl.add(rotateInteractor); >- intl.add(resetTransformInteractor); >+ /** >+ * Creates a new JSVGCanvas. >+ * >+ * @param ua >+ * a SVGUserAgent instance or null. >+ * @param eventsEnabled >+ * Whether the GVT tree should be reactive to mouse and key >+ * events. >+ * @param selectableText >+ * Whether the text should be selectable. >+ */ >+ public JSVGCanvas(SVGUserAgent ua, boolean eventsEnabled, >+ boolean selectableText) { > >- installActions(); >+ super(ua, eventsEnabled, selectableText); > >- if (eventsEnabled) { >- addMouseListener(new MouseAdapter() { >- public void mousePressed(MouseEvent evt) { >- requestFocus(); >- } >- }); >+ setPreferredSize(new Dimension(200, 200)); >+ setMinimumSize(new Dimension(100, 100)); > >- installKeyboardActions(); >- } >- addMouseMotionListener(locationListener); >- } >+ List intl = getInteractors(); >+ intl.add(zoomInteractor); >+ intl.add(imageZoomInteractor); >+ intl.add(panInteractor); >+ intl.add(rotateInteractor); >+ intl.add(resetTransformInteractor); > >- /** >- * Builds the ActionMap of this canvas with a set of predefined >- * <tt>Action</tt>s. >- */ >- protected void installActions() { >- ActionMap actionMap = getActionMap(); >+ installActions(); > >- actionMap.put(SCROLL_RIGHT_ACTION, new ScrollRightAction(10)); >- actionMap.put(SCROLL_LEFT_ACTION, new ScrollLeftAction(10)); >- actionMap.put(SCROLL_UP_ACTION, new ScrollUpAction(10)); >- actionMap.put(SCROLL_DOWN_ACTION, new ScrollDownAction(10)); >+ if (eventsEnabled) { >+ addMouseListener(new MouseAdapter() { >+ public void mousePressed(MouseEvent evt) { >+ requestFocus(); >+ } >+ }); > >- actionMap.put(FAST_SCROLL_RIGHT_ACTION, new ScrollRightAction(30)); >- actionMap.put(FAST_SCROLL_LEFT_ACTION, new ScrollLeftAction(30)); >- actionMap.put(FAST_SCROLL_UP_ACTION, new ScrollUpAction(30)); >- actionMap.put(FAST_SCROLL_DOWN_ACTION, new ScrollDownAction(30)); >+ installKeyboardActions(); >+ } >+ addMouseMotionListener(locationListener); >+ } > >- actionMap.put(ZOOM_IN_ACTION, new ZoomInAction()); >- actionMap.put(ZOOM_OUT_ACTION, new ZoomOutAction()); >+ /** >+ * Builds the ActionMap of this canvas with a set of predefined >+ * <tt>Action</tt>s. >+ */ >+ protected void installActions() { >+ ActionMap actionMap = getActionMap(); > >- actionMap.put(RESET_TRANSFORM_ACTION, new ResetTransformAction()); >- } >+ actionMap.put(SCROLL_RIGHT_ACTION, new ScrollRightAction(10)); >+ actionMap.put(SCROLL_LEFT_ACTION, new ScrollLeftAction(10)); >+ actionMap.put(SCROLL_UP_ACTION, new ScrollUpAction(10)); >+ actionMap.put(SCROLL_DOWN_ACTION, new ScrollDownAction(10)); > >- public void setDisableInteractions(boolean b) { >- super.setDisableInteractions(b); >- ActionMap actionMap = getActionMap(); >+ actionMap.put(FAST_SCROLL_RIGHT_ACTION, new ScrollRightAction(30)); >+ actionMap.put(FAST_SCROLL_LEFT_ACTION, new ScrollLeftAction(30)); >+ actionMap.put(FAST_SCROLL_UP_ACTION, new ScrollUpAction(30)); >+ actionMap.put(FAST_SCROLL_DOWN_ACTION, new ScrollDownAction(30)); > >- actionMap.get(SCROLL_RIGHT_ACTION) .setEnabled(!b); >- actionMap.get(SCROLL_LEFT_ACTION) .setEnabled(!b); >- actionMap.get(SCROLL_UP_ACTION) .setEnabled(!b); >- actionMap.get(SCROLL_DOWN_ACTION) .setEnabled(!b); >+ actionMap.put(ZOOM_IN_ACTION, new ZoomInAction()); >+ actionMap.put(ZOOM_OUT_ACTION, new ZoomOutAction()); > >- actionMap.get(FAST_SCROLL_RIGHT_ACTION).setEnabled(!b); >- actionMap.get(FAST_SCROLL_LEFT_ACTION) .setEnabled(!b); >- actionMap.get(FAST_SCROLL_UP_ACTION) .setEnabled(!b); >- actionMap.get(FAST_SCROLL_DOWN_ACTION) .setEnabled(!b); >+ actionMap.put(RESET_TRANSFORM_ACTION, new ResetTransformAction()); >+ } > >- actionMap.get(ZOOM_IN_ACTION) .setEnabled(!b); >- actionMap.get(ZOOM_OUT_ACTION) .setEnabled(!b); >- actionMap.get(RESET_TRANSFORM_ACTION) .setEnabled(!b); >- } >+ public void setDisableInteractions(boolean b) { >+ super.setDisableInteractions(b); >+ ActionMap actionMap = getActionMap(); > >+ actionMap.get(SCROLL_RIGHT_ACTION).setEnabled(!b); >+ actionMap.get(SCROLL_LEFT_ACTION).setEnabled(!b); >+ actionMap.get(SCROLL_UP_ACTION).setEnabled(!b); >+ actionMap.get(SCROLL_DOWN_ACTION).setEnabled(!b); > >- /** >- * Builds the InputMap of this canvas with a set of predefined >- * <tt>Action</tt>s. >- */ >- protected void installKeyboardActions() { >+ actionMap.get(FAST_SCROLL_RIGHT_ACTION).setEnabled(!b); >+ actionMap.get(FAST_SCROLL_LEFT_ACTION).setEnabled(!b); >+ actionMap.get(FAST_SCROLL_UP_ACTION).setEnabled(!b); >+ actionMap.get(FAST_SCROLL_DOWN_ACTION).setEnabled(!b); > >- InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); >- KeyStroke key; >+ actionMap.get(ZOOM_IN_ACTION).setEnabled(!b); >+ actionMap.get(ZOOM_OUT_ACTION).setEnabled(!b); >+ actionMap.get(RESET_TRANSFORM_ACTION).setEnabled(!b); >+ } > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); >- inputMap.put(key, SCROLL_RIGHT_ACTION); >+ /** >+ * Builds the InputMap of this canvas with a set of predefined >+ * <tt>Action</tt>s. >+ */ >+ protected void installKeyboardActions() { > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); >- inputMap.put(key, SCROLL_LEFT_ACTION); >+ InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); >+ KeyStroke key; > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); >- inputMap.put(key, SCROLL_UP_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0); >+ inputMap.put(key, SCROLL_RIGHT_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); >- inputMap.put(key, SCROLL_DOWN_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0); >+ inputMap.put(key, SCROLL_LEFT_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.SHIFT_MASK); >- inputMap.put(key, FAST_SCROLL_RIGHT_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); >+ inputMap.put(key, SCROLL_UP_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.SHIFT_MASK); >- inputMap.put(key, FAST_SCROLL_LEFT_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); >+ inputMap.put(key, SCROLL_DOWN_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.SHIFT_MASK); >- inputMap.put(key, FAST_SCROLL_UP_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.SHIFT_MASK); >+ inputMap.put(key, FAST_SCROLL_RIGHT_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.SHIFT_MASK); >- inputMap.put(key, FAST_SCROLL_DOWN_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.SHIFT_MASK); >+ inputMap.put(key, FAST_SCROLL_LEFT_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK); >- inputMap.put(key, ZOOM_IN_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.SHIFT_MASK); >+ inputMap.put(key, FAST_SCROLL_UP_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK); >- inputMap.put(key, ZOOM_OUT_ACTION); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.SHIFT_MASK); >+ inputMap.put(key, FAST_SCROLL_DOWN_ACTION); > >- key = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK); >- inputMap.put(key, RESET_TRANSFORM_ACTION); >- } >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK); >+ inputMap.put(key, ZOOM_IN_ACTION); > >- /** >- * Adds the specified <tt>PropertyChangeListener</tt>. >- * >- * @param pcl the property change listener to add >- */ >- public void addPropertyChangeListener(PropertyChangeListener pcl) { >- pcs.addPropertyChangeListener(pcl); >- } >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK); >+ inputMap.put(key, ZOOM_OUT_ACTION); > >- /** >- * Removes the specified <tt>PropertyChangeListener</tt>. >- * >- * @param pcl the property change listener to remove >- */ >- public void removePropertyChangeListener(PropertyChangeListener pcl) { >- pcs.removePropertyChangeListener(pcl); >- } >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK); >+ inputMap.put(key, RESET_TRANSFORM_ACTION); >+ } > >- /** >- * Adds the specified <tt>PropertyChangeListener</tt> for the specified >- * property. >- * >- * @param propertyName the name of the property to listen on >- * @param pcl the property change listener to add >- */ >- public void addPropertyChangeListener(String propertyName, >- PropertyChangeListener pcl) { >- pcs.addPropertyChangeListener(propertyName, pcl); >- } >+ /** >+ * Adds the specified <tt>PropertyChangeListener</tt>. >+ * >+ * @param pcl >+ * the property change listener to add >+ */ >+ public void addPropertyChangeListener(PropertyChangeListener pcl) { >+ pcs.addPropertyChangeListener(pcl); >+ } > >- /** >- * Removes the specified <tt>PropertyChangeListener</tt> for the specified >- * property. >- * >- * @param propertyName the name of the property that was listened on >- * @param pcl the property change listener to remove >- */ >- public void removePropertyChangeListener(String propertyName, >- PropertyChangeListener pcl) { >- pcs.removePropertyChangeListener(propertyName, pcl); >- } >+ /** >+ * Removes the specified <tt>PropertyChangeListener</tt>. >+ * >+ * @param pcl >+ * the property change listener to remove >+ */ >+ public void removePropertyChangeListener(PropertyChangeListener pcl) { >+ pcs.removePropertyChangeListener(pcl); >+ } > >- /** >- * Determines whether the zoom interactor is enabled or not. >- */ >- public void setEnableZoomInteractor(boolean b) { >- if (isZoomInteractorEnabled != b) { >- boolean oldValue = isZoomInteractorEnabled; >- isZoomInteractorEnabled = b; >- if (isZoomInteractorEnabled) { >- getInteractors().add(zoomInteractor); >- } else { >- getInteractors().remove(zoomInteractor); >- } >- pcs.firePropertyChange("enableZoomInteractor", oldValue, b); >- } >- } >+ /** >+ * Adds the specified <tt>PropertyChangeListener</tt> for the specified >+ * property. >+ * >+ * @param propertyName >+ * the name of the property to listen on >+ * @param pcl >+ * the property change listener to add >+ */ >+ public void addPropertyChangeListener(String propertyName, >+ PropertyChangeListener pcl) { >+ pcs.addPropertyChangeListener(propertyName, pcl); >+ } > >- /** >- * Returns true if the zoom interactor is enabled, false otherwise. >- */ >- public boolean getEnableZoomInteractor() { >- return isZoomInteractorEnabled; >- } >+ /** >+ * Removes the specified <tt>PropertyChangeListener</tt> for the specified >+ * property. >+ * >+ * @param propertyName >+ * the name of the property that was listened on >+ * @param pcl >+ * the property change listener to remove >+ */ >+ public void removePropertyChangeListener(String propertyName, >+ PropertyChangeListener pcl) { >+ pcs.removePropertyChangeListener(propertyName, pcl); >+ } > >- /** >- * Determines whether the image zoom interactor is enabled or not. >- */ >- public void setEnableImageZoomInteractor(boolean b) { >- if (isImageZoomInteractorEnabled != b) { >- boolean oldValue = isImageZoomInteractorEnabled; >- isImageZoomInteractorEnabled = b; >- if (isImageZoomInteractorEnabled) { >- getInteractors().add(imageZoomInteractor); >- } else { >- getInteractors().remove(imageZoomInteractor); >- } >- pcs.firePropertyChange("enableImageZoomInteractor", oldValue, b); >- } >- } >+ /** >+ * Determines whether the zoom interactor is enabled or not. >+ */ >+ public void setEnableZoomInteractor(boolean b) { >+ if (isZoomInteractorEnabled != b) { >+ boolean oldValue = isZoomInteractorEnabled; >+ isZoomInteractorEnabled = b; >+ if (isZoomInteractorEnabled) { >+ getInteractors().add(zoomInteractor); >+ } else { >+ getInteractors().remove(zoomInteractor); >+ } >+ pcs.firePropertyChange("enableZoomInteractor", oldValue, b); >+ } >+ } > >- /** >- * Returns true if the image zoom interactor is enabled, false otherwise. >- */ >- public boolean getEnableImageZoomInteractor() { >- return isImageZoomInteractorEnabled; >- } >+ /** >+ * Returns true if the zoom interactor is enabled, false otherwise. >+ */ >+ public boolean getEnableZoomInteractor() { >+ return isZoomInteractorEnabled; >+ } > >- /** >- * Determines whether the pan interactor is enabled or not. >- */ >- public void setEnablePanInteractor(boolean b) { >- if (isPanInteractorEnabled != b) { >- boolean oldValue = isPanInteractorEnabled; >- isPanInteractorEnabled = b; >- if (isPanInteractorEnabled) { >- getInteractors().add(panInteractor); >- } else { >- getInteractors().remove(panInteractor); >- } >- pcs.firePropertyChange("enablePanInteractor", oldValue, b); >- } >- } >+ /** >+ * Determines whether the image zoom interactor is enabled or not. >+ */ >+ public void setEnableImageZoomInteractor(boolean b) { >+ if (isImageZoomInteractorEnabled != b) { >+ boolean oldValue = isImageZoomInteractorEnabled; >+ isImageZoomInteractorEnabled = b; >+ if (isImageZoomInteractorEnabled) { >+ getInteractors().add(imageZoomInteractor); >+ } else { >+ getInteractors().remove(imageZoomInteractor); >+ } >+ pcs.firePropertyChange("enableImageZoomInteractor", oldValue, b); >+ } >+ } > >- /** >- * Returns true if the pan interactor is enabled, false otherwise. >- */ >- public boolean getEnablePanInteractor() { >- return isPanInteractorEnabled; >- } >+ /** >+ * Returns true if the image zoom interactor is enabled, false otherwise. >+ */ >+ public boolean getEnableImageZoomInteractor() { >+ return isImageZoomInteractorEnabled; >+ } > >- /** >- * Determines whether the rotate interactor is enabled or not. >- */ >- public void setEnableRotateInteractor(boolean b) { >- if (isRotateInteractorEnabled != b) { >- boolean oldValue = isRotateInteractorEnabled; >- isRotateInteractorEnabled = b; >- if (isRotateInteractorEnabled) { >- getInteractors().add(rotateInteractor); >- } else { >- getInteractors().remove(rotateInteractor); >- } >- pcs.firePropertyChange("enableRotateInteractor", oldValue, b); >- } >- } >+ /** >+ * Determines whether the pan interactor is enabled or not. >+ */ >+ public void setEnablePanInteractor(boolean b) { >+ if (isPanInteractorEnabled != b) { >+ boolean oldValue = isPanInteractorEnabled; >+ isPanInteractorEnabled = b; >+ if (isPanInteractorEnabled) { >+ getInteractors().add(panInteractor); >+ } else { >+ getInteractors().remove(panInteractor); >+ } >+ pcs.firePropertyChange("enablePanInteractor", oldValue, b); >+ } >+ } > >- /** >- * Returns true if the rotate interactor is enabled, false otherwise. >- */ >- public boolean getEnableRotateInteractor() { >- return isRotateInteractorEnabled; >- } >+ /** >+ * Returns true if the pan interactor is enabled, false otherwise. >+ */ >+ public boolean getEnablePanInteractor() { >+ return isPanInteractorEnabled; >+ } > >- /** >- * Determines whether the reset transform interactor is enabled or not. >- */ >- public void setEnableResetTransformInteractor(boolean b) { >- if (isResetTransformInteractorEnabled != b) { >- boolean oldValue = isResetTransformInteractorEnabled; >- isResetTransformInteractorEnabled = b; >- if (isResetTransformInteractorEnabled) { >- getInteractors().add(resetTransformInteractor); >- } else { >- getInteractors().remove(resetTransformInteractor); >- } >- pcs.firePropertyChange("enableResetTransformInteractor", >- oldValue, >- b); >- } >- } >+ /** >+ * Determines whether the rotate interactor is enabled or not. >+ */ >+ public void setEnableRotateInteractor(boolean b) { >+ if (isRotateInteractorEnabled != b) { >+ boolean oldValue = isRotateInteractorEnabled; >+ isRotateInteractorEnabled = b; >+ if (isRotateInteractorEnabled) { >+ getInteractors().add(rotateInteractor); >+ } else { >+ getInteractors().remove(rotateInteractor); >+ } >+ pcs.firePropertyChange("enableRotateInteractor", oldValue, b); >+ } >+ } > >- /** >- * Returns true if the reset transform interactor is enabled, false >- * otherwise. >- */ >- public boolean getEnableResetTransformInteractor() { >- return isResetTransformInteractorEnabled; >- } >+ /** >+ * Returns true if the rotate interactor is enabled, false otherwise. >+ */ >+ public boolean getEnableRotateInteractor() { >+ return isRotateInteractorEnabled; >+ } > >- /** >- * Returns the URI of the current document. >- */ >- public String getURI() { >- return uri; >- } >+ /** >+ * Determines whether the reset transform interactor is enabled or not. >+ */ >+ public void setEnableResetTransformInteractor(boolean b) { >+ if (isResetTransformInteractorEnabled != b) { >+ boolean oldValue = isResetTransformInteractorEnabled; >+ isResetTransformInteractorEnabled = b; >+ if (isResetTransformInteractorEnabled) { >+ getInteractors().add(resetTransformInteractor); >+ } else { >+ getInteractors().remove(resetTransformInteractor); >+ } >+ pcs.firePropertyChange("enableResetTransformInteractor", oldValue, >+ b); >+ } >+ } > >- /** >- * Sets the URI to the specified uri. If the input 'newURI' >- * string is null, then the canvas will display an empty >- * document. >- * >- * @param newURI the new uri of the document to display >- */ >- public void setURI(String newURI) { >- String oldValue = uri; >- this.uri = newURI; >- if (uri != null) { >- loadSVGDocument(uri); >- } else { >- setSVGDocument(null); >- } >+ /** >+ * Returns true if the reset transform interactor is enabled, false >+ * otherwise. >+ */ >+ public boolean getEnableResetTransformInteractor() { >+ return isResetTransformInteractorEnabled; >+ } > >- pcs.firePropertyChange("URI", oldValue, uri); >- } >+ /** >+ * Returns the URI of the current document. >+ */ >+ public String getURI() { >+ return uri; >+ } > >- /** >- * Creates a UserAgent. >- */ >- protected UserAgent createUserAgent() { >- return new CanvasUserAgent(); >- } >+ /** >+ * Sets the URI to the specified uri. If the input 'newURI' string is null, >+ * then the canvas will display an empty document. >+ * >+ * @param newURI >+ * the new uri of the document to display >+ */ >+ public void setURI(String newURI) { >+ String oldValue = uri; >+ this.uri = newURI; >+ if (uri != null) { >+ loadSVGDocument(uri); >+ } else { >+ setSVGDocument(null); >+ } > >- /** >- * Creates an instance of Listener. >- */ >- protected Listener createListener() { >- return new CanvasSVGListener(); >- } >+ pcs.firePropertyChange("URI", oldValue, uri); >+ } > >- /** >- * To hide the listener methods. This class just reset the tooltip. >- */ >- protected class CanvasSVGListener extends ExtendedSVGListener { >+ /** >+ * Creates a UserAgent. >+ */ >+ protected UserAgent createUserAgent() { >+ return new CanvasUserAgent(); >+ } > >- /** >- * Called when the loading of a document was started. >- */ >- public void documentLoadingStarted(SVGDocumentLoaderEvent e) { >- super.documentLoadingStarted(e); >- JSVGCanvas.this.setToolTipText(null); >- } >+ /** >+ * Creates an instance of Listener. >+ */ >+ protected Listener createListener() { >+ return new CanvasSVGListener(); >+ } > >- } >+ /** >+ * To hide the listener methods. This class just reset the tooltip. >+ */ >+ protected class CanvasSVGListener extends ExtendedSVGListener { > >- protected void installSVGDocument(SVGDocument doc) { >- if (toolTipDocs != null) { >- Iterator i = toolTipDocs.keySet().iterator(); >- while (i.hasNext()) { >- SVGDocument ttdoc; >- ttdoc = (SVGDocument)i.next(); >- if (ttdoc == null) continue; >+ /** >+ * Called when the loading of a document was started. >+ */ >+ public void documentLoadingStarted(SVGDocumentLoaderEvent e) { >+ super.documentLoadingStarted(e); >+ JSVGCanvas.this.setToolTipText(null); >+ } > >- NodeEventTarget root; >- root = (NodeEventTarget)ttdoc.getRootElement(); >- if (root == null) continue; >- root.removeEventListenerNS >- (XMLConstants.XML_EVENTS_NAMESPACE_URI, >- SVGConstants.SVG_EVENT_MOUSEOVER, >- toolTipListener, false); >- root.removeEventListenerNS >- (XMLConstants.XML_EVENTS_NAMESPACE_URI, >- SVGConstants.SVG_EVENT_MOUSEOUT, >- toolTipListener, false); >- } >- toolTipDocs = null; >- } >- lastTarget = null; >+ } > >- if (toolTipMap != null) { >- toolTipMap.clear(); >- } >+ protected void installSVGDocument(SVGDocument doc) { >+ if (toolTipDocs != null) { >+ Iterator i = toolTipDocs.keySet().iterator(); >+ while (i.hasNext()) { >+ SVGDocument ttdoc; >+ ttdoc = (SVGDocument) i.next(); >+ if (ttdoc == null) >+ continue; > >- super.installSVGDocument(doc); >- } >+ NodeEventTarget root; >+ root = (NodeEventTarget) ttdoc.getRootElement(); >+ if (root == null) >+ continue; >+ root.removeEventListenerNS( >+ XMLConstants.XML_EVENTS_NAMESPACE_URI, >+ SVGConstants.SVG_EVENT_MOUSEOVER, toolTipListener, >+ false); >+ root >+ .removeEventListenerNS( >+ XMLConstants.XML_EVENTS_NAMESPACE_URI, >+ SVGConstants.SVG_EVENT_MOUSEOUT, >+ toolTipListener, false); >+ } >+ toolTipDocs = null; >+ } >+ lastTarget = null; > >- // ---------------------------------------------------------------------- >- // Actions >- // ---------------------------------------------------------------------- >+ if (toolTipMap != null) { >+ toolTipMap.clear(); >+ } > >- /** >- * A swing action to reset the rendering transform of the canvas. >- */ >- public class ResetTransformAction extends AbstractAction { >- public void actionPerformed(ActionEvent evt) { >- fragmentIdentifier = null; >- resetRenderingTransform(); >- } >- } >+ super.installSVGDocument(doc); >+ } > >- /** >- * A swing action to append an affine transform to the current >- * rendering transform. Before the rendering transform is >- * applied the method translates the center of the display to >- * 0,0 so scale and rotate occur around the middle of >- * the display. >- */ >- public class AffineAction extends AbstractAction { >- AffineTransform at; >- public AffineAction(AffineTransform at) { >- this.at = at; >- } >+ // ---------------------------------------------------------------------- >+ // Actions >+ // ---------------------------------------------------------------------- > >- public void actionPerformed(ActionEvent evt) { >- if (gvtRoot == null) { >- return; >- } >- AffineTransform rat = getRenderingTransform(); >- if (at != null) { >- Dimension dim = getSize(); >- int x = dim.width / 2; >- int y = dim.height / 2; >- AffineTransform t = AffineTransform.getTranslateInstance(x, y); >- t.concatenate(at); >- t.translate(-x, -y); >- t.concatenate(rat); >- setRenderingTransform(t); >- } >- } >- } >+ /** >+ * A swing action to reset the rendering transform of the canvas. >+ */ >+ public class ResetTransformAction extends AbstractAction { >+ public void actionPerformed(ActionEvent evt) { >+ fragmentIdentifier = null; >+ resetRenderingTransform(); >+ } >+ } > >- /** >- * A swing action to apply a zoom factor to the canvas. >- * This can be used to zoom in (scale > 1) and out (scale <1). >- */ >- public class ZoomAction extends AffineAction { >- public ZoomAction(double scale) { >- super(AffineTransform.getScaleInstance(scale, scale)); >- } >- public ZoomAction(double scaleX, double scaleY) { >- super(AffineTransform.getScaleInstance(scaleX, scaleY)); >- } >- } >+ /** >+ * A swing action to append an affine transform to the current rendering >+ * transform. Before the rendering transform is applied the method >+ * translates the center of the display to 0,0 so scale and rotate occur >+ * around the middle of the display. >+ */ >+ public class AffineAction extends AbstractAction { >+ AffineTransform at; > >- /** >- * A swing action to zoom in the canvas. >- */ >- public class ZoomInAction extends ZoomAction { >- ZoomInAction() { super(2); } >- } >+ public AffineAction(AffineTransform at) { >+ this.at = at; >+ } > >- /** >- * A swing action to zoom out the canvas. >- */ >- public class ZoomOutAction extends ZoomAction { >- ZoomOutAction() { super(.5); } >- } >+ public void actionPerformed(ActionEvent evt) { >+ if (gvtRoot == null) { >+ return; >+ } >+ AffineTransform rat = getRenderingTransform(); >+ if (at != null) { >+ Dimension dim = getSize(); >+ int x = dim.width / 2; >+ int y = dim.height / 2; >+ AffineTransform t = AffineTransform.getTranslateInstance(x, y); >+ t.concatenate(at); >+ t.translate(-x, -y); >+ t.concatenate(rat); >+ setRenderingTransform(t); >+ } >+ } >+ } > >- /** >- * A swing action to Rotate the canvas. >- */ >- public class RotateAction extends AffineAction { >- public RotateAction(double theta) { >- super(AffineTransform.getRotateInstance(theta)); >- } >- } >+ /** >+ * A swing action to apply a zoom factor to the canvas. This can be used to >+ * zoom in (scale > 1) and out (scale <1). >+ */ >+ public class ZoomAction extends AffineAction { >+ public ZoomAction(double scale) { >+ super(AffineTransform.getScaleInstance(scale, scale)); >+ } > >- /** >- * A swing action to Pan/scroll the canvas. >- */ >- public class ScrollAction extends AffineAction { >- public ScrollAction(double tx, double ty) { >- super(AffineTransform.getTranslateInstance(tx, ty)); >- } >- } >+ public ZoomAction(double scaleX, double scaleY) { >+ super(AffineTransform.getScaleInstance(scaleX, scaleY)); >+ } >+ } > >- /** >- * A swing action to scroll the canvas to the right, >- * by a fixed amount >- */ >- public class ScrollRightAction extends ScrollAction { >- public ScrollRightAction(int inc) { >- super(-inc, 0); >- } >- } >+ /** >+ * A swing action to zoom in the canvas. >+ */ >+ public class ZoomInAction extends ZoomAction { >+ ZoomInAction() { >+ super(2); >+ } >+ } > >- /** >- * A swing action to scroll the canvas to the left, >- * by a fixed amount >- */ >- public class ScrollLeftAction extends ScrollAction { >- public ScrollLeftAction(int inc) { >- super(inc, 0); >- } >- } >+ /** >+ * A swing action to zoom out the canvas. >+ */ >+ public class ZoomOutAction extends ZoomAction { >+ ZoomOutAction() { >+ super(.5); >+ } >+ } > >- /** >- * A swing action to scroll the canvas up, >- * by a fixed amount >- */ >- public class ScrollUpAction extends ScrollAction { >- public ScrollUpAction(int inc) { >- super(0, inc); >- } >- } >+ /** >+ * A swing action to Rotate the canvas. >+ */ >+ public class RotateAction extends AffineAction { >+ public RotateAction(double theta) { >+ super(AffineTransform.getRotateInstance(theta)); >+ } >+ } > >- /** >- * A swing action to scroll the canvas down, >- * by a fixed amount >- */ >- public class ScrollDownAction extends ScrollAction { >- public ScrollDownAction(int inc) { >- super(0, -inc); >- } >- } >+ /** >+ * A swing action to Pan/scroll the canvas. >+ */ >+ public class ScrollAction extends AffineAction { >+ public ScrollAction(double tx, double ty) { >+ super(AffineTransform.getTranslateInstance(tx, ty)); >+ } >+ } > >- // ---------------------------------------------------------------------- >- // Interactors >- // ---------------------------------------------------------------------- >+ /** >+ * A swing action to scroll the canvas to the right, by a fixed amount >+ */ >+ public class ScrollRightAction extends ScrollAction { >+ public ScrollRightAction(int inc) { >+ super(-inc, 0); >+ } >+ } > >- /** >- * An interactor to perform a zoom. >- * <p>Binding: BUTTON1 + CTRL Key</p> >- */ >- protected Interactor zoomInteractor = new AbstractZoomInteractor() { >- public boolean startInteraction(InputEvent ie) { >- int mods = ie.getModifiers(); >- return >- ie.getID() == MouseEvent.MOUSE_PRESSED && >- (mods & InputEvent.BUTTON1_MASK) != 0 && >- (mods & InputEvent.CTRL_MASK) != 0; >- } >- }; >+ /** >+ * A swing action to scroll the canvas to the left, by a fixed amount >+ */ >+ public class ScrollLeftAction extends ScrollAction { >+ public ScrollLeftAction(int inc) { >+ super(inc, 0); >+ } >+ } > >- /** >- * An interactor to perform a realtime zoom. >- * <p>Binding: BUTTON3 + SHIFT Key</p> >- */ >- protected Interactor imageZoomInteractor >- = new AbstractImageZoomInteractor() { >- public boolean startInteraction(InputEvent ie) { >- int mods = ie.getModifiers(); >- return >- ie.getID() == MouseEvent.MOUSE_PRESSED && >- (mods & InputEvent.BUTTON3_MASK) != 0 && >- (mods & InputEvent.SHIFT_MASK) != 0; >- } >- }; >+ /** >+ * A swing action to scroll the canvas up, by a fixed amount >+ */ >+ public class ScrollUpAction extends ScrollAction { >+ public ScrollUpAction(int inc) { >+ super(0, inc); >+ } >+ } > >- /** >- * An interactor to perform a translation. >- * <p>Binding: BUTTON1 + SHIFT Key</p> >- */ >- protected Interactor panInteractor = new AbstractPanInteractor() { >- public boolean startInteraction(InputEvent ie) { >- int mods = ie.getModifiers(); >- return >- ie.getID() == MouseEvent.MOUSE_PRESSED && >- (mods & InputEvent.BUTTON1_MASK) != 0 && >- (mods & InputEvent.SHIFT_MASK) != 0; >- } >- }; >+ /** >+ * A swing action to scroll the canvas down, by a fixed amount >+ */ >+ public class ScrollDownAction extends ScrollAction { >+ public ScrollDownAction(int inc) { >+ super(0, -inc); >+ } >+ } > >- /** >- * An interactor to perform a rotation. >- * <p>Binding: BUTTON3 + CTRL Key</p> >- */ >- protected Interactor rotateInteractor = new AbstractRotateInteractor() { >- public boolean startInteraction(InputEvent ie) { >- int mods = ie.getModifiers(); >- return >- ie.getID() == MouseEvent.MOUSE_PRESSED && >- (mods & InputEvent.BUTTON3_MASK) != 0 && >- (mods & InputEvent.CTRL_MASK) != 0; >- } >- }; >+ // ---------------------------------------------------------------------- >+ // Interactors >+ // ---------------------------------------------------------------------- > >- /** >- * An interactor to reset the rendering transform. >- * <p>Binding: CTRL+SHIFT+BUTTON3</p> >- */ >- protected Interactor resetTransformInteractor = >- new AbstractResetTransformInteractor() { >- public boolean startInteraction(InputEvent ie) { >- int mods = ie.getModifiers(); >- return >- ie.getID() == MouseEvent.MOUSE_CLICKED && >- (mods & InputEvent.BUTTON3_MASK) != 0 && >- (mods & InputEvent.SHIFT_MASK) != 0 && >- (mods & InputEvent.CTRL_MASK) != 0; >- } >- }; >+ /** >+ * An interactor to perform a zoom. >+ * <p> >+ * Binding: BUTTON1 + CTRL Key >+ * </p> >+ */ >+ protected Interactor zoomInteractor = new AbstractZoomInteractor() { >+ public boolean startInteraction(InputEvent ie) { >+ int mods = ie.getModifiers(); >+ return ie.getID() == MouseEvent.MOUSE_PRESSED >+ && (mods & InputEvent.BUTTON1_MASK) != 0 >+ && (mods & InputEvent.CTRL_MASK) != 0; >+ } >+ }; > >- // ---------------------------------------------------------------------- >- // User agent implementation >- // ---------------------------------------------------------------------- >+ /** >+ * An interactor to perform a realtime zoom. >+ * <p> >+ * Binding: BUTTON3 + SHIFT Key >+ * </p> >+ */ >+ protected Interactor imageZoomInteractor = new AbstractImageZoomInteractor() { >+ public boolean startInteraction(InputEvent ie) { >+ int mods = ie.getModifiers(); >+ return ie.getID() == MouseEvent.MOUSE_PRESSED >+ && (mods & InputEvent.BUTTON3_MASK) != 0 >+ && (mods & InputEvent.SHIFT_MASK) != 0; >+ } >+ }; > >- /** >- * The <tt>CanvasUserAgent</tt> only adds tooltips to the behavior of the >- * default <tt>BridgeUserAgent</tt>. A tooltip will be displayed >- * wheneven the mouse lingers over an element which has a <title> or a >- * <desc> child element. >- */ >- protected class CanvasUserAgent extends BridgeUserAgent >+ /** >+ * An interactor to perform a translation. >+ * <p> >+ * Binding: BUTTON1 + SHIFT Key >+ * </p> >+ */ >+ protected Interactor panInteractor = new AbstractPanInteractor() { >+ public boolean startInteraction(InputEvent ie) { >+ int mods = ie.getModifiers(); >+ return ie.getID() == MouseEvent.MOUSE_PRESSED >+ && (mods & InputEvent.BUTTON1_MASK) != 0 >+ && (mods & InputEvent.SHIFT_MASK) != 0; >+ } >+ }; > >- implements XMLConstants { >+ /** >+ * An interactor to perform a rotation. >+ * <p> >+ * Binding: BUTTON3 + CTRL Key >+ * </p> >+ */ >+ protected Interactor rotateInteractor = new AbstractRotateInteractor() { >+ public boolean startInteraction(InputEvent ie) { >+ int mods = ie.getModifiers(); >+ return ie.getID() == MouseEvent.MOUSE_PRESSED >+ && (mods & InputEvent.BUTTON3_MASK) != 0 >+ && (mods & InputEvent.CTRL_MASK) != 0; >+ } >+ }; > >- final String TOOLTIP_TITLE_ONLY >- = "JSVGCanvas.CanvasUserAgent.ToolTip.titleOnly"; >- final String TOOLTIP_DESC_ONLY >- = "JSVGCanvas.CanvasUserAgent.ToolTip.descOnly"; >- final String TOOLTIP_TITLE_AND_TEXT >- = "JSVGCanvas.CanvasUserAgent.ToolTip.titleAndDesc"; >+ /** >+ * An interactor to reset the rendering transform. >+ * <p> >+ * Binding: CTRL+SHIFT+BUTTON3 >+ * </p> >+ */ >+ protected Interactor resetTransformInteractor = new AbstractResetTransformInteractor() { >+ public boolean startInteraction(InputEvent ie) { >+ int mods = ie.getModifiers(); >+ return ie.getID() == MouseEvent.MOUSE_CLICKED >+ && (mods & InputEvent.BUTTON3_MASK) != 0 >+ && (mods & InputEvent.SHIFT_MASK) != 0 >+ && (mods & InputEvent.CTRL_MASK) != 0; >+ } >+ }; > >- /** >- * The handleElement method builds a tool tip from the >- * content of a <title> element, a <desc> >- * element or both. <br/> >- * Because these elements can appear in any order, here >- * is the algorithm used to build the tool tip:<br /> >- * <ul> >- * <li>If a <title> is passed to <tt>handleElement</tt> >- * the method checks if there is a >desc> peer. If >- * there is one, nothing is done (because the desc will do >- * it). If there in none, the tool tip is set to the value >- * of the <title> element content.</li> >- * <li>If a <desc> is passed to <tt>handleElement</tt> >- * the method checks if there is a <title> peer. If there >- * is one, the content of that peer is pre-pended to the >- * content of the <desc> element.</li> >- * </ul> >- */ >- public void handleElement(Element elt, Object data){ >- super.handleElement(elt, data); >+ // ---------------------------------------------------------------------- >+ // User agent implementation >+ // ---------------------------------------------------------------------- > >- // Don't handle tool tips unless we are interactive. >- if (!isInteractive()) return; >+ /** >+ * The <tt>CanvasUserAgent</tt> only adds tooltips to the behavior of the >+ * default <tt>BridgeUserAgent</tt>. A tooltip will be displayed wheneven >+ * the mouse lingers over an element which has a <title> or a >+ * <desc> child element. >+ */ >+ protected class CanvasUserAgent extends BridgeUserAgent > >- if (!SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) >- return; >+ implements XMLConstants { > >- // Don't handle tool tips for the root SVG element. >- if (elt.getParentNode() == >- elt.getOwnerDocument().getDocumentElement()) { >- return; >- } >+ final String TOOLTIP_TITLE_ONLY = "JSVGCanvas.CanvasUserAgent.ToolTip.titleOnly"; > >- Element parent; >- // When node is removed data is old parent node >- // since we can't get it otherwise. >- if (data instanceof Element) parent = (Element)data; >- else parent = (Element)elt.getParentNode(); >+ final String TOOLTIP_DESC_ONLY = "JSVGCanvas.CanvasUserAgent.ToolTip.descOnly"; > >- Element descPeer = null; >- Element titlePeer = null; >- if (elt.getLocalName().equals(SVGConstants.SVG_TITLE_TAG)) { >- if (data == Boolean.TRUE) >- titlePeer = elt; >- descPeer = getPeerWithTag(parent, >- SVGConstants.SVG_NAMESPACE_URI, >- SVGConstants.SVG_DESC_TAG); >- } else if (elt.getLocalName().equals(SVGConstants.SVG_DESC_TAG)) { >- if (data == Boolean.TRUE) >- descPeer = elt; >- titlePeer = getPeerWithTag(parent, >- SVGConstants.SVG_NAMESPACE_URI, >- SVGConstants.SVG_TITLE_TAG); >- } >+ final String TOOLTIP_TITLE_AND_TEXT = "JSVGCanvas.CanvasUserAgent.ToolTip.titleAndDesc"; > >- String titleTip = null; >- if (titlePeer != null) { >- titlePeer.normalize(); >- if (titlePeer.getFirstChild() != null) >- titleTip = titlePeer.getFirstChild().getNodeValue(); >- } >+ /** >+ * The handleElement method builds a tool tip from the content of a >+ * <title> element, a <desc> element or both. <br/> Because >+ * these elements can appear in any order, here is the algorithm used to >+ * build the tool tip:<br /> >+ * <ul> >+ * <li>If a <title> is passed to <tt>handleElement</tt> the >+ * method checks if there is a >desc> peer. If there is one, >+ * nothing is done (because the desc will do it). If there in none, the >+ * tool tip is set to the value of the <title> element content.</li> >+ * <li>If a <desc> is passed to <tt>handleElement</tt> the >+ * method checks if there is a <title> peer. If there is one, the >+ * content of that peer is pre-pended to the content of the <desc> >+ * element.</li> >+ * </ul> >+ */ >+ public void handleElement(Element elt, Object data) { >+ super.handleElement(elt, data); > >- String descTip = null; >- if (descPeer != null) { >- descPeer.normalize(); >- if (descPeer.getFirstChild() != null) >- descTip = descPeer.getFirstChild().getNodeValue(); >- } >+ // Don't handle tool tips unless we are interactive. >+ if (!isInteractive()) >+ return; > >- final String toolTip; >- if ((titleTip != null) && (titleTip.length() != 0)) { >- if ((descTip != null) && (descTip.length() != 0)) { >- toolTip = Messages.formatMessage >- (TOOLTIP_TITLE_AND_TEXT, >- new Object[] { toFormattedHTML(titleTip), >- toFormattedHTML(descTip)}); >- } else { >- toolTip = Messages.formatMessage >- (TOOLTIP_TITLE_ONLY, >- new Object[]{toFormattedHTML(titleTip)}); >- } >- } else { >- if ((descTip != null) && (descTip.length() != 0)) { >- toolTip = Messages.formatMessage >- (TOOLTIP_DESC_ONLY, >- new Object[]{toFormattedHTML(descTip)}); >- } else { >- toolTip = null; >- } >- } >+ if (!SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) >+ return; > >- if (toolTip == null) { >- removeToolTip(parent); >- return; >- } >+ // Don't handle tool tips for the root SVG element. >+ if (elt.getParentNode() == elt.getOwnerDocument() >+ .getDocumentElement()) { >+ return; >+ } > >- if (lastTarget != parent) { >- setToolTip(parent, toolTip); >- } else { >- // Already has focus check if it already has tip text. >- Object o = null; >- if (toolTipMap != null) { >- o = toolTipMap.get(parent); >- toolTipMap.put(parent, toolTip); >- } >+ Element parent; >+ // When node is removed data is old parent node >+ // since we can't get it otherwise. >+ if (data instanceof Element) >+ parent = (Element) data; >+ else >+ parent = (Element) elt.getParentNode(); > >- if (o != null) { >- // Update components tooltip text now. >- EventQueue.invokeLater(new Runnable() { >- public void run() { >- setToolTipText(toolTip); >- MouseEvent e = new MouseEvent >- (JSVGCanvas.this, >- MouseEvent.MOUSE_MOVED, >- System.currentTimeMillis(), >- 0, >- locationListener.getLastX(), >- locationListener.getLastY(), >- 0, >- false); >- ToolTipManager.sharedInstance().mouseMoved(e); >- } >- }); >- } else { >- EventQueue.invokeLater(new ToolTipRunnable(toolTip)); >- } >- } >- } >+ Element descPeer = null; >+ Element titlePeer = null; >+ if (elt.getLocalName().equals(SVGConstants.SVG_TITLE_TAG)) { >+ if (data == Boolean.TRUE) >+ titlePeer = elt; >+ descPeer = getPeerWithTag(parent, >+ SVGConstants.SVG_NAMESPACE_URI, >+ SVGConstants.SVG_DESC_TAG); >+ } else if (elt.getLocalName().equals(SVGConstants.SVG_DESC_TAG)) { >+ if (data == Boolean.TRUE) >+ descPeer = elt; >+ titlePeer = getPeerWithTag(parent, >+ SVGConstants.SVG_NAMESPACE_URI, >+ SVGConstants.SVG_TITLE_TAG); >+ } > >- /** >- * Converts line breaks to HTML breaks and encodes special entities. >- * Poor way of replacing '<', '>' and '&' in content. >- */ >- public String toFormattedHTML(String str) { >- StringBuffer sb = new StringBuffer(str); >- replace(sb, XML_CHAR_AMP, XML_ENTITY_AMP); // Must go first! >- replace(sb, XML_CHAR_LT, XML_ENTITY_LT); >- replace(sb, XML_CHAR_GT, XML_ENTITY_GT); >- replace(sb, XML_CHAR_QUOT, XML_ENTITY_QUOT); >- // Dont' quote "'" apostrphe since the display doesn't >- // seem to understand it. >- // replace(sb, XML_CHAR_APOS, XML_ENTITY_APOS); >- replace(sb, '\n', "<br>"); >- return sb.toString(); >- } >+ String titleTip = null; >+ if (titlePeer != null) { >+ titlePeer.normalize(); >+ if (titlePeer.getFirstChild() != null) >+ titleTip = titlePeer.getFirstChild().getNodeValue(); >+ } > >- protected void replace(StringBuffer sb, char c, String r) { >- String v = sb.toString(); >- int i = v.length(); >+ String descTip = null; >+ if (descPeer != null) { >+ descPeer.normalize(); >+ if (descPeer.getFirstChild() != null) >+ descTip = descPeer.getFirstChild().getNodeValue(); >+ } > >- while( (i=v.lastIndexOf(c, i-1)) != -1 ) { >- sb.deleteCharAt(i); >- sb.insert(i, r); >- } >- } >+ final String toolTip; >+ if ((titleTip != null) && (titleTip.length() != 0)) { >+ if ((descTip != null) && (descTip.length() != 0)) { >+ toolTip = Messages.formatMessage(TOOLTIP_TITLE_AND_TEXT, >+ new Object[] { toFormattedHTML(titleTip), >+ toFormattedHTML(descTip) }); >+ } else { >+ toolTip = Messages.formatMessage(TOOLTIP_TITLE_ONLY, >+ new Object[] { toFormattedHTML(titleTip) }); >+ } >+ } else { >+ if ((descTip != null) && (descTip.length() != 0)) { >+ toolTip = Messages.formatMessage(TOOLTIP_DESC_ONLY, >+ new Object[] { toFormattedHTML(descTip) }); >+ } else { >+ toolTip = null; >+ } >+ } > >- /** >- * Checks if there is a peer element of a given type. This returns the >- * first occurence of the given type or null if none is found. >- */ >- public Element getPeerWithTag(Element parent, >- String nameSpaceURI, >- String localName) { >+ if (toolTip == null) { >+ removeToolTip(parent); >+ return; >+ } > >- Element p = parent; >- if (p == null) { >- return null; >- } >+ if (lastTarget != parent) { >+ setToolTip(parent, toolTip); >+ } else { >+ // Already has focus check if it already has tip text. >+ Object o = null; >+ if (toolTipMap != null) { >+ o = toolTipMap.get(parent); >+ toolTipMap.put(parent, toolTip); >+ } > >- for (Node n=p.getFirstChild(); n!=null; n = n.getNextSibling()) { >- if (!nameSpaceURI.equals(n.getNamespaceURI())){ >- continue; >- } >- if (!localName.equals(n.getLocalName())){ >- continue; >- } >- if (n.getNodeType() == Node.ELEMENT_NODE) { >- return (Element)n; >- } >- } >- return null; >- } >+ if (o != null) { >+ // Update components tooltip text now. >+ EventQueue.invokeLater(new Runnable() { >+ public void run() { >+ setToolTipText(toolTip); >+ MouseEvent e = new MouseEvent(JSVGCanvas.this, >+ MouseEvent.MOUSE_MOVED, System >+ .currentTimeMillis(), 0, >+ locationListener.getLastX(), >+ locationListener.getLastY(), 0, false); >+ ToolTipManager.sharedInstance().mouseMoved(e); >+ } >+ }); >+ } else { >+ EventQueue.invokeLater(new ToolTipRunnable(toolTip)); >+ } >+ } >+ } > >- /** >- * Returns a boolean defining whether or not there is a peer of >- * <tt>elt</tt> with the given qualified tag. >- */ >- public boolean hasPeerWithTag(Element elt, >- String nameSpaceURI, >- String localName){ >+ /** >+ * Converts line breaks to HTML breaks and encodes special entities. >+ * Poor way of replacing '<', '>' and '&' in content. >+ */ >+ public String toFormattedHTML(String str) { >+ StringBuffer sb = new StringBuffer(str); >+ replace(sb, XML_CHAR_AMP, XML_ENTITY_AMP); // Must go first! >+ replace(sb, XML_CHAR_LT, XML_ENTITY_LT); >+ replace(sb, XML_CHAR_GT, XML_ENTITY_GT); >+ replace(sb, XML_CHAR_QUOT, XML_ENTITY_QUOT); >+ // Dont' quote "'" apostrphe since the display doesn't >+ // seem to understand it. >+ // replace(sb, XML_CHAR_APOS, XML_ENTITY_APOS); >+ replace(sb, '\n', "<br>"); >+ return sb.toString(); >+ } > >- return !(getPeerWithTag(elt, nameSpaceURI, localName) == null); >- } >+ protected void replace(StringBuffer sb, char c, String r) { >+ String v = sb.toString(); >+ int i = v.length(); > >- /** >- * Sets the tool tip on the input element. >- */ >- public void setToolTip(Element elt, String toolTip){ >- if (toolTipMap == null) { >- toolTipMap = new WeakHashMap(); >- } >- if (toolTipDocs == null) { >- toolTipDocs = new WeakHashMap(); >- } >- SVGDocument doc = (SVGDocument)elt.getOwnerDocument(); >- if (toolTipDocs.put(doc, MAP_TOKEN) == null) { >- NodeEventTarget root; >- root = (NodeEventTarget)doc.getRootElement(); >- // On mouseover, it sets the tooltip to the given value >- root.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI, >- SVGConstants.SVG_EVENT_MOUSEOVER, >- toolTipListener, >- false, null); >- // On mouseout, it removes the tooltip >- root.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI, >- SVGConstants.SVG_EVENT_MOUSEOUT, >- toolTipListener, >- false, null); >- } >+ while ((i = v.lastIndexOf(c, i - 1)) != -1) { >+ sb.deleteCharAt(i); >+ sb.insert(i, r); >+ } >+ } > >- toolTipMap.put(elt, toolTip); >+ /** >+ * Checks if there is a peer element of a given type. This returns the >+ * first occurence of the given type or null if none is found. >+ */ >+ public Element getPeerWithTag(Element parent, String nameSpaceURI, >+ String localName) { > >- if (elt == lastTarget) >- EventQueue.invokeLater(new ToolTipRunnable(toolTip)); >- } >+ Element p = parent; >+ if (p == null) { >+ return null; >+ } > >- public void removeToolTip(Element elt) { >- if (toolTipMap != null) >- toolTipMap.remove(elt); >- if (lastTarget == elt) { // clear ToolTip. >- EventQueue.invokeLater(new ToolTipRunnable(null)); >- } >- } >+ for (Node n = p.getFirstChild(); n != null; n = n.getNextSibling()) { >+ if (!nameSpaceURI.equals(n.getNamespaceURI())) { >+ continue; >+ } >+ if (!localName.equals(n.getLocalName())) { >+ continue; >+ } >+ if (n.getNodeType() == Node.ELEMENT_NODE) { >+ return (Element) n; >+ } >+ } >+ return null; >+ } > >- /** >- * Displays an error message in the User Agent interface. >- */ >- public void displayError(String message) { >- if (svgUserAgent != null) { >- super.displayError(message); >- } else { >- JOptionPane pane = >- new JOptionPane(message, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = >- pane.createDialog(JSVGCanvas.this, "ERROR"); >- dialog.setModal(false); >- dialog.setVisible(true); // Safe to be called from any thread >- } >- } >+ /** >+ * Returns a boolean defining whether or not there is a peer of >+ * <tt>elt</tt> with the given qualified tag. >+ */ >+ public boolean hasPeerWithTag(Element elt, String nameSpaceURI, >+ String localName) { > >- /** >- * Displays an error resulting from the specified Exception. >- */ >- public void displayError(Exception ex) { >- if (svgUserAgent != null) { >- super.displayError(ex); >- } else { >- JErrorPane pane = >- new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(JSVGCanvas.this, "ERROR"); >- dialog.setModal(false); >- dialog.setVisible(true); // Safe to be called from any thread >- } >- } >- } >+ return !(getPeerWithTag(elt, nameSpaceURI, localName) == null); >+ } > >- // ---------------------------------------------------------------------- >- // Tooltip >- // ---------------------------------------------------------------------- >+ /** >+ * Sets the tool tip on the input element. >+ */ >+ public void setToolTip(Element elt, String toolTip) { >+ if (toolTipMap == null) { >+ toolTipMap = new WeakHashMap(); >+ } >+ if (toolTipDocs == null) { >+ toolTipDocs = new WeakHashMap(); >+ } >+ SVGDocument doc = (SVGDocument) elt.getOwnerDocument(); >+ if (toolTipDocs.put(doc, MAP_TOKEN) == null) { >+ NodeEventTarget root; >+ root = (NodeEventTarget) doc.getRootElement(); >+ // On mouseover, it sets the tooltip to the given value >+ root.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI, >+ SVGConstants.SVG_EVENT_MOUSEOVER, toolTipListener, >+ false, null); >+ // On mouseout, it removes the tooltip >+ root.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI, >+ SVGConstants.SVG_EVENT_MOUSEOUT, toolTipListener, >+ false, null); >+ } > >- /** >- * Sets the time and element of the last tool tip event handled. >- */ >- public void setLastToolTipEvent(long t, EventTarget et) { >- lastToolTipEventTimeStamp = t; >- lastToolTipEventTarget = et; >- } >+ toolTipMap.put(elt, toolTip); > >- /** >- * 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; >- } >+ if (elt == lastTarget) >+ EventQueue.invokeLater(new ToolTipRunnable(toolTip)); >+ } > >- /** >- * Helper class. Simply keeps track of the last known mouse >- * position over the canvas. >- */ >- protected class LocationListener extends MouseMotionAdapter { >+ public void removeToolTip(Element elt) { >+ if (toolTipMap != null) >+ toolTipMap.remove(elt); >+ if (lastTarget == elt) { // clear ToolTip. >+ EventQueue.invokeLater(new ToolTipRunnable(null)); >+ } >+ } > >- protected int lastX, lastY; >+ /** >+ * Displays an error message in the User Agent interface. >+ */ >+ public void displayError(String message) { >+ if (svgUserAgent != null) { >+ super.displayError(message); >+ } else { >+ JOptionPane pane = new JOptionPane(message, >+ JOptionPane.ERROR_MESSAGE); >+ JDialog dialog = pane.createDialog(JSVGCanvas.this, "ERROR"); >+ dialog.setModal(false); >+ dialog.setVisible(true); // Safe to be called from any thread >+ } >+ } > >- public LocationListener () { >- lastX = 0; lastY = 0; >- } >+ /** >+ * Displays an error resulting from the specified Exception. >+ */ >+ public void displayError(Exception ex) { >+ if (svgUserAgent != null) { >+ super.displayError(ex); >+ } else { >+ // JErrorPane pane = >+ // new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ ErrorInfo info = new ErrorInfo(ex, getURI(), >+ ErrorConsole.ERROR); >+ console.add(info); >+ ErrorConsole.showDialog(JSVGCanvas.this); >+ } >+ } >+ } > >- public void mouseMoved(MouseEvent evt) { >- lastX = evt.getX(); >- lastY = evt.getY(); >- } >+ // ---------------------------------------------------------------------- >+ // Tooltip >+ // ---------------------------------------------------------------------- > >- public int getLastX() { >- return lastX; >- } >+ /** >+ * Sets the time and element of the last tool tip event handled. >+ */ >+ public void setLastToolTipEvent(long t, EventTarget et) { >+ lastToolTipEventTimeStamp = t; >+ lastToolTipEventTarget = et; >+ } > >- public int getLastY() { >- return lastY; >- } >- } >+ /** >+ * 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; >+ } > >- /** >- * Sets a specific tooltip on the JSVGCanvas when a given event occurs. >- * This listener is used in the handleElement method to set, remove or >- * modify the JSVGCanvas tooltip on mouseover and on mouseout.<br/> >- * >- * Because we are on a single <tt>JComponent</tt> we trigger an artificial >- * <tt>MouseEvent</tt> when the toolTip is set to a non-null value, so as >- * to make sure it will show after the <tt>ToolTipManager</tt>'s default >- * delay. >- */ >- protected class ToolTipModifier implements EventListener { >- /** >- * The CanvasUserAgent used to track the last tool tip event. >- */ >- protected CanvasUserAgent canvasUserAgent; >+ /** >+ * Helper class. Simply keeps track of the last known mouse position over >+ * the canvas. >+ */ >+ protected class LocationListener extends MouseMotionAdapter { > >- /** >- * Creates a new ToolTipModifier object. >- */ >- public ToolTipModifier() { >- } >+ protected int lastX, lastY; > >- 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 (matchLastToolTipEvent(evt.getTimeStamp(), evt.getTarget())) { >- return; >- } >- setLastToolTipEvent(evt.getTimeStamp(), evt.getTarget()); >- EventTarget prevLastTarget = lastTarget; >- if (SVGConstants.SVG_EVENT_MOUSEOVER.equals(evt.getType())) { >- lastTarget = evt.getTarget(); >- } else if (SVGConstants.SVG_EVENT_MOUSEOUT.equals(evt.getType())) { >- // related target is one it is entering or null. >- org.w3c.dom.events.MouseEvent mouseEvt; >- mouseEvt = ((org.w3c.dom.events.MouseEvent)evt); >- lastTarget = mouseEvt.getRelatedTarget(); >- } >+ public LocationListener() { >+ lastX = 0; >+ lastY = 0; >+ } > >- if (toolTipMap != null) { >- Element e = (Element)lastTarget; >- Object o = null; >- while (e != null) { >- // Search the parents of the current node for ToolTips. >- o = toolTipMap.get(e); >- if (o != null) { >- break; >- } >- e = CSSEngine.getParentCSSStylableElement(e); >- } >- final String theToolTip = (String)o; >- if (prevLastTarget != lastTarget) >- EventQueue.invokeLater(new ToolTipRunnable(theToolTip)); >- } >- } >- } >+ public void mouseMoved(MouseEvent evt) { >+ lastX = evt.getX(); >+ lastY = evt.getY(); >+ } > >- protected class ToolTipRunnable implements Runnable { >- String theToolTip; >- public ToolTipRunnable(String toolTip) { >- this.theToolTip = toolTip; >- } >+ public int getLastX() { >+ return lastX; >+ } > >- public void run() { >- setToolTipText(theToolTip); >+ public int getLastY() { >+ return lastY; >+ } >+ } > >- MouseEvent e; >- if (theToolTip != null) { >- e = new MouseEvent >- (JSVGCanvas.this, >- MouseEvent.MOUSE_ENTERED, >- System.currentTimeMillis(), >- 0, >- locationListener.getLastX(), >- locationListener.getLastY(), >- 0, >- false); >- ToolTipManager.sharedInstance().mouseEntered(e); >- e = new MouseEvent >- (JSVGCanvas.this, >- MouseEvent.MOUSE_MOVED, >- System.currentTimeMillis(), >- 0, >- locationListener.getLastX(), >- locationListener.getLastY(), >- 0, >- false); >- ToolTipManager.sharedInstance().mouseMoved(e); >- } else { >- e = new MouseEvent >- (JSVGCanvas.this, >- MouseEvent.MOUSE_MOVED, >- System.currentTimeMillis(), >- 0, >- locationListener.getLastX(), >- locationListener.getLastY(), >- 0, >- false); >- ToolTipManager.sharedInstance().mouseMoved(e); >- } >- } >- } >+ /** >+ * Sets a specific tooltip on the JSVGCanvas when a given event occurs. This >+ * listener is used in the handleElement method to set, remove or modify the >+ * JSVGCanvas tooltip on mouseover and on mouseout.<br/> >+ * >+ * Because we are on a single <tt>JComponent</tt> we trigger an artificial >+ * <tt>MouseEvent</tt> when the toolTip is set to a non-null value, so as >+ * to make sure it will show after the <tt>ToolTipManager</tt>'s default >+ * delay. >+ */ >+ protected class ToolTipModifier implements EventListener { >+ /** >+ * The CanvasUserAgent used to track the last tool tip event. >+ */ >+ protected CanvasUserAgent canvasUserAgent; >+ >+ /** >+ * Creates a new ToolTipModifier object. >+ */ >+ public ToolTipModifier() { >+ } >+ >+ 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 (matchLastToolTipEvent(evt.getTimeStamp(), evt.getTarget())) { >+ return; >+ } >+ setLastToolTipEvent(evt.getTimeStamp(), evt.getTarget()); >+ EventTarget prevLastTarget = lastTarget; >+ if (SVGConstants.SVG_EVENT_MOUSEOVER.equals(evt.getType())) { >+ lastTarget = evt.getTarget(); >+ } else if (SVGConstants.SVG_EVENT_MOUSEOUT.equals(evt.getType())) { >+ // related target is one it is entering or null. >+ org.w3c.dom.events.MouseEvent mouseEvt; >+ mouseEvt = ((org.w3c.dom.events.MouseEvent) evt); >+ lastTarget = mouseEvt.getRelatedTarget(); >+ } >+ >+ if (toolTipMap != null) { >+ Element e = (Element) lastTarget; >+ Object o = null; >+ while (e != null) { >+ // Search the parents of the current node for ToolTips. >+ o = toolTipMap.get(e); >+ if (o != null) { >+ break; >+ } >+ e = CSSEngine.getParentCSSStylableElement(e); >+ } >+ final String theToolTip = (String) o; >+ if (prevLastTarget != lastTarget) >+ EventQueue.invokeLater(new ToolTipRunnable(theToolTip)); >+ } >+ } >+ } >+ >+ protected class ToolTipRunnable implements Runnable { >+ String theToolTip; >+ >+ public ToolTipRunnable(String toolTip) { >+ this.theToolTip = toolTip; >+ } >+ >+ public void run() { >+ setToolTipText(theToolTip); >+ >+ MouseEvent e; >+ if (theToolTip != null) { >+ e = new MouseEvent(JSVGCanvas.this, MouseEvent.MOUSE_ENTERED, >+ System.currentTimeMillis(), 0, locationListener >+ .getLastX(), locationListener.getLastY(), 0, >+ false); >+ ToolTipManager.sharedInstance().mouseEntered(e); >+ e = new MouseEvent(JSVGCanvas.this, MouseEvent.MOUSE_MOVED, >+ System.currentTimeMillis(), 0, locationListener >+ .getLastX(), locationListener.getLastY(), 0, >+ false); >+ ToolTipManager.sharedInstance().mouseMoved(e); >+ } else { >+ e = new MouseEvent(JSVGCanvas.this, MouseEvent.MOUSE_MOVED, >+ System.currentTimeMillis(), 0, locationListener >+ .getLastX(), locationListener.getLastY(), 0, >+ false); >+ ToolTipManager.sharedInstance().mouseMoved(e); >+ } >+ } >+ } > } >Index: sources/org/apache/batik/bridge/SVGShapeElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGShapeElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGShapeElementBridge.java (working copy) >@@ -19,6 +19,8 @@ > package org.apache.batik.bridge; > > import java.awt.RenderingHints; >+import java.awt.Shape; >+import java.awt.geom.Area; > > import org.apache.batik.css.engine.CSSEngineEvent; > import org.apache.batik.css.engine.SVGCSSEngine; >@@ -35,6 +37,11 @@ > */ > public abstract class SVGShapeElementBridge extends AbstractGraphicsNodeBridge { > >+ /** >+ * >+ */ >+ protected static Shape nullShape = new Area(); >+ > /** > * Constructs a new bridge for SVG shapes. > */ >Index: sources/org/apache/batik/bridge/SVGLineElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGLineElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGLineElementBridge.java (working copy) >@@ -117,7 +117,12 @@ > > shapeNode.setShape(new Line2D.Float(x1, y1, x2, y2)); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/SVGPolylineElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGPolylineElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGPolylineElementBridge.java (working copy) >@@ -98,7 +98,12 @@ > shapeNode.setShape(app.getShape()); > } > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/DocumentLoader.java >=================================================================== >--- sources/org/apache/batik/bridge/DocumentLoader.java (revision 549415) >+++ sources/org/apache/batik/bridge/DocumentLoader.java (working copy) >@@ -18,15 +18,14 @@ > */ > package org.apache.batik.bridge; > >+import java.io.IOException; > import java.io.InputStream; >-import java.io.IOException; > import java.util.HashMap; > > import org.apache.batik.dom.svg.SAXSVGDocumentFactory; > import org.apache.batik.dom.svg.SVGDocumentFactory; > import org.apache.batik.dom.util.DocumentDescriptor; > import org.apache.batik.util.CleanerThread; >- > import org.w3c.dom.Document; > import org.w3c.dom.Element; > import org.w3c.dom.svg.SVGDocument; >@@ -104,7 +103,6 @@ > return ret; > > SVGDocument document = documentFactory.createSVGDocument(uri); >- > DocumentDescriptor desc = documentFactory.getDocumentDescriptor(); > DocumentState state = new DocumentState(uri, document, desc); > synchronized (cacheMap) { >@@ -176,6 +174,25 @@ > } > > /** >+ * Returns the document descriptor of the last loaded document >+ * >+ * @return the document descriptor of the last loaded document, or >+ * null if no document has been loaded. >+ */ >+ public DocumentDescriptor getDocumentDescriptor(SVGDocument doc) { >+ String uri = doc.getURL(); >+ DocumentState state; >+ synchronized (cacheMap) { >+ state = (DocumentState)cacheMap.get(uri); >+ } >+ if (state == null) { >+ return null; >+ } else { >+ return state.desc; >+ } >+ } >+ >+ /** > * A simple class that contains a Document and its number of nodes. > */ > private class DocumentState extends CleanerThread.SoftReferenceCleared { >Index: sources/org/apache/batik/bridge/SVGCircleElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGCircleElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGCircleElementBridge.java (working copy) >@@ -90,7 +90,12 @@ > float w = r * 2; > shapeNode.setShape(new Ellipse2D.Float(x, y, w, w)); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/SVGPolygonElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGPolygonElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGPolygonElementBridge.java (working copy) >@@ -20,6 +20,7 @@ > > import java.awt.Shape; > import java.awt.geom.GeneralPath; >+import java.awt.geom.Rectangle2D; > > import org.apache.batik.css.engine.SVGCSSEngine; > import org.apache.batik.dom.svg.AnimatedLiveAttributeValue; >@@ -98,7 +99,12 @@ > shapeNode.setShape(app.getShape()); > } > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/SVGEllipseElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGEllipseElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGEllipseElementBridge.java (working copy) >@@ -93,7 +93,12 @@ > shapeNode.setShape(new Ellipse2D.Float(cx - rx, cy - ry, > rx * 2, ry * 2)); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/SVGRectElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGRectElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGRectElementBridge.java (working copy) >@@ -28,7 +28,6 @@ > import org.apache.batik.dom.svg.SVGOMRectElement; > import org.apache.batik.gvt.ShapeNode; > import org.apache.batik.gvt.ShapePainter; >- > import org.w3c.dom.Element; > > /** >@@ -116,7 +115,12 @@ > } > shapeNode.setShape(shape); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } > } > >Index: sources/org/apache/batik/bridge/SVGPathElementBridge.java >=================================================================== >--- sources/org/apache/batik/bridge/SVGPathElementBridge.java (revision 549415) >+++ sources/org/apache/batik/bridge/SVGPathElementBridge.java (working copy) >@@ -92,7 +92,12 @@ > app.setWindingRule(CSSUtilities.convertFillRule(e)); > SVGAnimatedPathDataSupport.handlePathSegList(p, app); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(nullShape); >+ } > } finally { > shapeNode.setShape(app.getShape()); > } >Index: sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java >=================================================================== >--- sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (revision 549415) >+++ sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (working copy) >@@ -1,19 +1,19 @@ > /* > >- Licensed to the Apache Software Foundation (ASF) under one or more >- contributor license agreements. See the NOTICE file distributed with >- this work for additional information regarding copyright ownership. >- The ASF licenses this file to You under the Apache License, Version 2.0 >- (the "License"); you may not use this file except in compliance with >- the License. You may obtain a copy of the License at >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at > >- http://www.apache.org/licenses/LICENSE-2.0 >+ http://www.apache.org/licenses/LICENSE-2.0 > >- Unless required by applicable law or agreed to in writing, software >- distributed under the License is distributed on an "AS IS" BASIS, >- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >- See the License for the specific language governing permissions and >- limitations under the License. >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. > > */ > package org.apache.batik.apps.svgbrowser; >@@ -25,7 +25,6 @@ > import java.awt.Event; > import java.awt.EventQueue; > import java.awt.FileDialog; >-import java.awt.Font; > import java.awt.Graphics2D; > import java.awt.Rectangle; > import java.awt.Toolkit; >@@ -44,11 +43,13 @@ > import java.awt.image.BufferedImage; > import java.awt.print.PrinterException; > import java.io.BufferedOutputStream; >+import java.io.BufferedReader; > import java.io.File; >+import java.io.FileOutputStream; > import java.io.FilenameFilter; >-import java.io.FileOutputStream; > import java.io.IOException; > import java.io.InputStream; >+import java.io.InputStreamReader; > import java.io.OutputStream; > import java.io.OutputStreamWriter; > import java.io.Reader; >@@ -70,6 +71,7 @@ > import javax.swing.Action; > import javax.swing.BorderFactory; > import javax.swing.ButtonGroup; >+import javax.swing.ImageIcon; > import javax.swing.JComponent; > import javax.swing.JDialog; > import javax.swing.JFileChooser; >@@ -79,15 +81,12 @@ > import javax.swing.JOptionPane; > import javax.swing.JPanel; > import javax.swing.JRadioButtonMenuItem; >-import javax.swing.JScrollPane; >-import javax.swing.JTextArea; > import javax.swing.JToolBar; > import javax.swing.JWindow; > import javax.swing.KeyStroke; > import javax.swing.filechooser.FileFilter; >-import javax.swing.text.Document; >-import javax.swing.text.PlainDocument; > >+import org.apache.batik.apps.svgbrowser.srcview.SourceViewFrame; > import org.apache.batik.bridge.DefaultExternalResourceSecurity; > import org.apache.batik.bridge.DefaultScriptSecurity; > import org.apache.batik.bridge.EmbededExternalResourceSecurity; >@@ -102,9 +101,11 @@ > import org.apache.batik.bridge.UpdateManagerEvent; > import org.apache.batik.bridge.UpdateManagerListener; > import org.apache.batik.dom.StyleSheetProcessingInstruction; >+import org.apache.batik.dom.svg.LiveAttributeException; > import org.apache.batik.dom.svg.SVGOMDocument; >+import org.apache.batik.dom.util.DOMUtilities; >+import org.apache.batik.dom.util.DocumentDescriptor; > import org.apache.batik.dom.util.HashTable; >-import org.apache.batik.dom.util.DOMUtilities; > import org.apache.batik.ext.swing.JAffineTransformChooser; > import org.apache.batik.swing.JSVGCanvas; > import org.apache.batik.swing.gvt.GVTTreeRendererEvent; >@@ -129,14 +130,17 @@ > import org.apache.batik.transcoder.svg2svg.SVGTranscoder; > import org.apache.batik.util.ParsedURL; > import org.apache.batik.util.Platform; >+import org.apache.batik.util.SVGConstants; > import org.apache.batik.util.Service; >-import org.apache.batik.util.SVGConstants; > import org.apache.batik.util.XMLConstants; > import org.apache.batik.util.gui.DOMViewer; >-import org.apache.batik.util.gui.JErrorPane; >+import org.apache.batik.util.gui.ErrorConsole; > import org.apache.batik.util.gui.LocationBar; > import org.apache.batik.util.gui.MemoryMonitor; >+import org.apache.batik.util.gui.TimelineViewer; > import org.apache.batik.util.gui.URIChooser; >+import org.apache.batik.util.gui.ErrorConsole.ErrorInfo; >+import org.apache.batik.util.gui.ErrorConsole.AttributeErrorInfo; > import org.apache.batik.util.gui.resource.ActionMap; > import org.apache.batik.util.gui.resource.JComponentModifier; > import org.apache.batik.util.gui.resource.MenuFactory; >@@ -151,2936 +155,3127 @@ > > /** > * This class represents a SVG viewer swing frame. >- * >+ * > * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> > * @version $Id$ > */ >-public class JSVGViewerFrame >- extends JFrame >- implements ActionMap, >- SVGDocumentLoaderListener, >- GVTTreeBuilderListener, >- SVGLoadEventDispatcherListener, >- GVTTreeRendererListener, >- LinkActivationListener, >- UpdateManagerListener { >+public class JSVGViewerFrame extends JFrame implements ActionMap, >+ SVGDocumentLoaderListener, GVTTreeBuilderListener, >+ SVGLoadEventDispatcherListener, GVTTreeRendererListener, >+ LinkActivationListener, UpdateManagerListener { > >- private static String EOL; >- static { >- try { >- EOL = System.getProperty("line.separator", "\n"); >- } catch (SecurityException e) { >- EOL = "\n"; >- } >- } >+ private static String EOL; >+ static { >+ try { >+ EOL = System.getProperty("line.separator", "\n"); >+ } catch (SecurityException e) { >+ EOL = "\n"; >+ } >+ } > >- /** >- * Kind of ugly, but we need to know if we are running before >- * or after 1.4... >- */ >- protected static boolean priorJDK1_4 = true; >+ /** >+ * Kind of ugly, but we need to know if we are running before or after >+ * 1.4... >+ */ >+ protected static boolean priorJDK1_4 = true; > >- /** >- * If the following class can be found (it appeared in JDK 1.4), >- * then we know we are post JDK 1.4. >- */ >- protected static final String JDK_1_4_PRESENCE_TEST_CLASS >- = "java.util.logging.LoggingPermission"; >+ /** >+ * If the following class can be found (it appeared in JDK 1.4), then we >+ * know we are post JDK 1.4. >+ */ >+ protected static final String JDK_1_4_PRESENCE_TEST_CLASS = "java.util.logging.LoggingPermission"; > >- static { >- try { >- Class.forName(JDK_1_4_PRESENCE_TEST_CLASS); >- priorJDK1_4 = false; >- } catch (ClassNotFoundException e) { >- } >- } >+ static { >+ try { >+ Class.forName(JDK_1_4_PRESENCE_TEST_CLASS); >+ priorJDK1_4 = false; >+ } catch (ClassNotFoundException e) { >+ } >+ } > >- /** >- * The gui resources file name >- */ >- public static final String RESOURCES = >- "org.apache.batik.apps.svgbrowser.resources.GUI"; >+ /** >+ * The gui resources file name >+ */ >+ public static final String RESOURCES = "org.apache.batik.apps.svgbrowser.resources.GUI"; > >- // The actions names. >- public static final String ABOUT_ACTION = "AboutAction"; >- public static final String OPEN_ACTION = "OpenAction"; >- public static final String OPEN_LOCATION_ACTION = "OpenLocationAction"; >- public static final String NEW_WINDOW_ACTION = "NewWindowAction"; >- public static final String RELOAD_ACTION = "ReloadAction"; >- public static final String SAVE_AS_ACTION = "SaveAsAction"; >- public static final String BACK_ACTION = "BackAction"; >- public static final String FORWARD_ACTION = "ForwardAction"; >- public static final String FULL_SCREEN_ACTION = "FullScreenAction"; >- public static final String PRINT_ACTION = "PrintAction"; >- public static final String EXPORT_AS_JPG_ACTION = "ExportAsJPGAction"; >- public static final String EXPORT_AS_PNG_ACTION = "ExportAsPNGAction"; >- public static final String EXPORT_AS_TIFF_ACTION = "ExportAsTIFFAction"; >- public static final String PREFERENCES_ACTION = "PreferencesAction"; >- public static final String CLOSE_ACTION = "CloseAction"; >- public static final String VIEW_SOURCE_ACTION = "ViewSourceAction"; >- public static final String EXIT_ACTION = "ExitAction"; >- public static final String RESET_TRANSFORM_ACTION = "ResetTransformAction"; >- public static final String ZOOM_IN_ACTION = "ZoomInAction"; >- public static final String ZOOM_OUT_ACTION = "ZoomOutAction"; >- public static final String PREVIOUS_TRANSFORM_ACTION = "PreviousTransformAction"; >- public static final String NEXT_TRANSFORM_ACTION = "NextTransformAction"; >- public static final String USE_STYLESHEET_ACTION = "UseStylesheetAction"; >- public static final String PLAY_ACTION = "PlayAction"; >- public static final String PAUSE_ACTION = "PauseAction"; >- public static final String STOP_ACTION = "StopAction"; >- public static final String MONITOR_ACTION = "MonitorAction"; >- public static final String DOM_VIEWER_ACTION = "DOMViewerAction"; >- public static final String SET_TRANSFORM_ACTION = "SetTransformAction"; >- public static final String FIND_DIALOG_ACTION = "FindDialogAction"; >- public static final String THUMBNAIL_DIALOG_ACTION = "ThumbnailDialogAction"; >- public static final String FLUSH_ACTION = "FlushAction"; >- public static final String TOGGLE_DEBUGGER_ACTION = "ToggleDebuggerAction"; >+ // The actions names. >+ public static final String ABOUT_ACTION = "AboutAction"; > >- /** >- * The cursor indicating that an operation is pending. >- */ >- public static final Cursor WAIT_CURSOR = >- new Cursor(Cursor.WAIT_CURSOR); >+ public static final String OPEN_ACTION = "OpenAction"; > >- /** >- * The default cursor. >- */ >- public static final Cursor DEFAULT_CURSOR = >- new Cursor(Cursor.DEFAULT_CURSOR); >+ public static final String OPEN_LOCATION_ACTION = "OpenLocationAction"; > >- /** >- * Name for the os-name property >- */ >- public static final String PROPERTY_OS_NAME >- = Resources.getString("JSVGViewerFrame.property.os.name"); >+ public static final String NEW_WINDOW_ACTION = "NewWindowAction"; > >- /** >- * Name for the os.name default >- */ >- public static final String PROPERTY_OS_NAME_DEFAULT >- = Resources.getString("JSVGViewerFrame.property.os.name.default"); >+ public static final String RELOAD_ACTION = "ReloadAction"; > >- /** >- * Name for the os.name property prefix we are looking >- * for in OpenAction to work around JFileChooser bug >- */ >- public static final String PROPERTY_OS_WINDOWS_PREFIX >- = Resources.getString("JSVGViewerFrame.property.os.windows.prefix"); >+ public static final String SAVE_AS_ACTION = "SaveAsAction"; > >- /** >- * Resource string name for the Open dialog. >- */ >- protected static final String OPEN_TITLE = "Open.title"; >+ public static final String BACK_ACTION = "BackAction"; > >- /** >- * The input handlers >- */ >- protected static Vector handlers; >+ public static final String FORWARD_ACTION = "ForwardAction"; > >- /** >- * The default input handler >- */ >- protected static SquiggleInputHandler defaultHandler = new SVGInputHandler(); >+ public static final String FULL_SCREEN_ACTION = "FullScreenAction"; > >- /** >- * The resource bundle >- */ >- protected static ResourceBundle bundle; >+ public static final String PRINT_ACTION = "PrintAction"; > >- /** >- * The resource manager >- */ >- protected static ResourceManager resources; >- static { >- bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >- resources = new ResourceManager(bundle); >- } >+ public static final String EXPORT_AS_JPG_ACTION = "ExportAsJPGAction"; > >- /** >- * The current application. >- */ >- protected Application application; >+ public static final String EXPORT_AS_PNG_ACTION = "ExportAsPNGAction"; > >- /** >- * The JSVGCanvas. >- */ >- protected Canvas svgCanvas; >+ public static final String EXPORT_AS_TIFF_ACTION = "ExportAsTIFFAction"; > >- /** >- * An extension of JSVGCanvas that exposes the Rhino interpreter. >- */ >- protected static class Canvas extends JSVGCanvas { >+ public static final String PREFERENCES_ACTION = "PreferencesAction"; > >- /** >- * Creates a new Canvas. >- */ >- public Canvas(SVGUserAgent ua, boolean eventsEnabled, >- boolean selectableText) { >- super(ua, eventsEnabled, selectableText); >- } >+ public static final String CLOSE_ACTION = "CloseAction"; > >- /** >- * Returns the Rhino interpreter for this canvas. >- */ >- public Object getRhinoInterpreter() { >- if (bridgeContext == null) { >- return null; >- } >- return bridgeContext.getInterpreter("text/ecmascript"); >- } >- } >+ public static final String VIEW_SOURCE_ACTION = "ViewSourceAction"; > >- /** >- * The panel where the svgCanvas is displayed >- */ >- protected JPanel svgCanvasPanel; >+ public static final String EXIT_ACTION = "ExitAction"; > >- /** >- * A window used for full screen display >- */ >- protected JWindow window; >+ public static final String RESET_TRANSFORM_ACTION = "ResetTransformAction"; > >- /** >- * The memory monitor frame. >- */ >- protected static JFrame memoryMonitorFrame; >+ public static final String ZOOM_IN_ACTION = "ZoomInAction"; > >- /** >- * The current path. >- */ >- protected File currentPath = new File(""); >+ public static final String ZOOM_OUT_ACTION = "ZoomOutAction"; > >- /** >- * The current export path. >- */ >- protected File currentSavePath = new File(""); >+ public static final String PREVIOUS_TRANSFORM_ACTION = "PreviousTransformAction"; > >- /** >- * The back action >- */ >- protected BackAction backAction = new BackAction(); >+ public static final String NEXT_TRANSFORM_ACTION = "NextTransformAction"; > >- /** >- * The forward action >- */ >- protected ForwardAction forwardAction = new ForwardAction(); >+ public static final String USE_STYLESHEET_ACTION = "UseStylesheetAction"; > >- /** >- * The play action >- */ >- protected PlayAction playAction = new PlayAction(); >+ public static final String PLAY_ACTION = "PlayAction"; > >- /** >- * The pause action >- */ >- protected PauseAction pauseAction = new PauseAction(); >+ public static final String PAUSE_ACTION = "PauseAction"; > >- /** >- * The stop action >- */ >- protected StopAction stopAction = new StopAction(); >+ public static final String STOP_ACTION = "StopAction"; > >- /** >- * The previous transform action >- */ >- protected PreviousTransformAction previousTransformAction = >- new PreviousTransformAction(); >+ public static final String MONITOR_ACTION = "MonitorAction"; > >- /** >- * The next transform action >- */ >- protected NextTransformAction nextTransformAction = >- new NextTransformAction(); >+ public static final String DOM_VIEWER_ACTION = "DOMViewerAction"; > >- /** >- * The use (author) stylesheet action >- */ >- protected UseStylesheetAction useStylesheetAction = >- new UseStylesheetAction(); >+ public static final String TIMELINE_VIEWER_ACTION = "TimelineViewerAction"; > >- /** >- * The debug flag. >- */ >- protected boolean debug; >+ public static final String SET_TRANSFORM_ACTION = "SetTransformAction"; > >- /** >- * The auto adjust flag. >- */ >- protected boolean autoAdjust = true; >+ public static final String FIND_DIALOG_ACTION = "FindDialogAction"; > >- /** >- * Whether the update manager was stopped. >- */ >- protected boolean managerStopped; >+ public static final String THUMBNAIL_DIALOG_ACTION = "ThumbnailDialogAction"; > >- /** >- * The SVG user agent. >- */ >- protected SVGUserAgent userAgent = new UserAgent(); >+ public static final String FLUSH_ACTION = "FlushAction"; > >- /** >- * The current document. >- */ >- protected SVGDocument svgDocument; >+ public static final String TOGGLE_DEBUGGER_ACTION = "ToggleDebuggerAction"; > >- /** >- * The URI chooser. >- */ >- protected URIChooser uriChooser; >+ /** >+ * The cursor indicating that an operation is pending. >+ */ >+ public static final Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR); > >- /** >- * The DOM viewer. >- */ >- protected DOMViewer domViewer; >+ /** >+ * The default cursor. >+ */ >+ public static final Cursor DEFAULT_CURSOR = new Cursor( >+ Cursor.DEFAULT_CURSOR); > >- /** >- * The Find dialog. >- */ >- protected FindDialog findDialog; >+ /** >+ * Name for the os-name property >+ */ >+ public static final String PROPERTY_OS_NAME = Resources >+ .getString("JSVGViewerFrame.property.os.name"); > >- /** >- * The Find dialog. >- */ >- protected ThumbnailDialog thumbnailDialog; >+ /** >+ * Name for the os.name default >+ */ >+ public static final String PROPERTY_OS_NAME_DEFAULT = Resources >+ .getString("JSVGViewerFrame.property.os.name.default"); > >- /** >- * The transform dialog >- */ >- protected JAffineTransformChooser.Dialog transformDialog; >+ /** >+ * Name for the os.name property prefix we are looking for in OpenAction to >+ * work around JFileChooser bug >+ */ >+ public static final String PROPERTY_OS_WINDOWS_PREFIX = Resources >+ .getString("JSVGViewerFrame.property.os.windows.prefix"); > >- /** >- * The location bar. >- */ >- protected LocationBar locationBar; >+ /** >+ * Resource string name for the Open dialog. >+ */ >+ protected static final String OPEN_TITLE = "Open.title"; > >- /** >- * The status bar. >- */ >- protected StatusBar statusBar; >+ /** >+ * The input handlers >+ */ >+ protected static Vector handlers; > >- /** >- * The initial frame title. >- */ >- protected String title; >+ /** >+ * The default input handler >+ */ >+ protected static SquiggleInputHandler defaultHandler = new SVGInputHandler(); > >- /** >- * The local history. >- */ >- protected LocalHistory localHistory; >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; > >- /** >- * The transform history. >- */ >- protected TransformHistory transformHistory = new TransformHistory(); >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } > >- /** >- * The alternate style-sheet title. >- */ >- protected String alternateStyleSheet; >+ /** >+ * The current application. >+ */ >+ protected Application application; > >- /** >- * The debugger object. >- */ >- protected Debugger debugger; >+ /** >+ * The JSVGCanvas. >+ */ >+ protected Canvas svgCanvas; > >- /** >- * Creates a new SVG viewer frame. >- */ >- public JSVGViewerFrame(Application app) { >- application = app; >+ /** >+ * An extension of JSVGCanvas that exposes the Rhino interpreter. >+ */ >+ protected static class Canvas extends JSVGCanvas { > >- addWindowListener(new WindowAdapter() { >- public void windowClosing(WindowEvent e) { >- application.closeJSVGViewerFrame(JSVGViewerFrame.this); >- } >- }); >+ /** >+ * Creates a new Canvas. >+ */ >+ public Canvas(SVGUserAgent ua, boolean eventsEnabled, >+ boolean selectableText) { >+ super(ua, eventsEnabled, selectableText); >+ } > >- // >- // Set the frame's maximum size so that content >- // bigger than the screen does not cause the creation >- // of unnecessary large images. >- // >- svgCanvas = new Canvas(userAgent, true, true) { >- Dimension screenSize; >+ /** >+ * Returns the Rhino interpreter for this canvas. >+ */ >+ public Object getRhinoInterpreter() { >+ if (bridgeContext == null) { >+ return null; >+ } >+ return bridgeContext.getInterpreter("text/ecmascript"); >+ } >+ } > >- { >- screenSize = Toolkit.getDefaultToolkit().getScreenSize(); >- setMaximumSize(screenSize); >- } >+ /** >+ * The panel where the svgCanvas is displayed >+ */ >+ protected JPanel svgCanvasPanel; > >- public Dimension getPreferredSize(){ >- Dimension s = super.getPreferredSize(); >- if (s.width > screenSize.width) s.width =screenSize.width; >- if (s.height > screenSize.height) s.height = screenSize.height; >- return s; >- } >+ /** >+ * A window used for full screen display >+ */ >+ protected JWindow window; > >+ /** >+ * The memory monitor frame. >+ */ >+ protected static JFrame memoryMonitorFrame; > >- /** >- * This method is called when the component knows the desired >- * size of the window (based on width/height of outermost SVG >- * element). We override it to immediately pack this frame. >- */ >- public void setMySize(Dimension d) { >- setPreferredSize(d); >- invalidate(); >- if (JSVGViewerFrame.this.autoAdjust) { >- Platform.unmaximize(JSVGViewerFrame.this); >- JSVGViewerFrame.this.pack(); >- } >- } >+ /** >+ * The current path. >+ */ >+ protected File currentPath = new File(""); > >- public void setDisableInteractions(boolean b) { >- super.setDisableInteractions(b); >+ /** >+ * The current export path. >+ */ >+ protected File currentSavePath = new File(""); > >- // Disable/Enable all our different ways to adjust the >- // rendering transform (menus, toolbar, thumbnail, keyboard). >+ /** >+ * The back action >+ */ >+ protected BackAction backAction = new BackAction(); > >- ((Action)listeners.get(SET_TRANSFORM_ACTION)) .setEnabled(!b); >+ /** >+ * The forward action >+ */ >+ protected ForwardAction forwardAction = new ForwardAction(); > >- if (thumbnailDialog != null) >- thumbnailDialog.setInteractionEnabled(!b); >- } >- }; >+ /** >+ * The play action >+ */ >+ protected PlayAction playAction = new PlayAction(); > >- javax.swing.ActionMap map = svgCanvas.getActionMap(); >- map.put(FULL_SCREEN_ACTION, new FullScreenAction()); >- javax.swing.InputMap imap = svgCanvas.getInputMap(JComponent.WHEN_FOCUSED); >- KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0); >- imap.put(key, FULL_SCREEN_ACTION); >+ /** >+ * The pause action >+ */ >+ protected PauseAction pauseAction = new PauseAction(); > >- svgCanvas.setDoubleBufferedRendering(true); >+ /** >+ * The stop action >+ */ >+ protected StopAction stopAction = new StopAction(); > >- listeners.put(ABOUT_ACTION, new AboutAction()); >- listeners.put(OPEN_ACTION, new OpenAction()); >- listeners.put(OPEN_LOCATION_ACTION, new OpenLocationAction()); >- listeners.put(NEW_WINDOW_ACTION, new NewWindowAction()); >- listeners.put(RELOAD_ACTION, new ReloadAction()); >- listeners.put(SAVE_AS_ACTION, new SaveAsAction()); >- listeners.put(BACK_ACTION, backAction); >- listeners.put(FORWARD_ACTION, forwardAction); >- listeners.put(PRINT_ACTION, new PrintAction()); >- listeners.put(EXPORT_AS_JPG_ACTION, new ExportAsJPGAction()); >- listeners.put(EXPORT_AS_PNG_ACTION, new ExportAsPNGAction()); >- listeners.put(EXPORT_AS_TIFF_ACTION, new ExportAsTIFFAction()); >- listeners.put(PREFERENCES_ACTION, new PreferencesAction()); >- listeners.put(CLOSE_ACTION, new CloseAction()); >- listeners.put(EXIT_ACTION, application.createExitAction(this)); >- listeners.put(VIEW_SOURCE_ACTION, new ViewSourceAction()); >+ /** >+ * The previous transform action >+ */ >+ protected PreviousTransformAction previousTransformAction = new PreviousTransformAction(); > >- javax.swing.ActionMap cMap = svgCanvas.getActionMap(); >- listeners.put(RESET_TRANSFORM_ACTION, >- cMap.get(JSVGCanvas.RESET_TRANSFORM_ACTION)); >- listeners.put(ZOOM_IN_ACTION, >- cMap.get(JSVGCanvas.ZOOM_IN_ACTION)); >- listeners.put(ZOOM_OUT_ACTION, >- cMap.get(JSVGCanvas.ZOOM_OUT_ACTION)); >+ /** >+ * The next transform action >+ */ >+ protected NextTransformAction nextTransformAction = new NextTransformAction(); > >- listeners.put(PREVIOUS_TRANSFORM_ACTION, previousTransformAction); >- key = KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK); >- imap.put(key, previousTransformAction); >+ /** >+ * The use (author) stylesheet action >+ */ >+ protected UseStylesheetAction useStylesheetAction = new UseStylesheetAction(); > >- listeners.put(NEXT_TRANSFORM_ACTION, nextTransformAction); >- key = KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_MASK); >- imap.put(key, nextTransformAction); >+ /** >+ * The debug flag. >+ */ >+ protected boolean debug; > >- listeners.put(USE_STYLESHEET_ACTION, useStylesheetAction); >- listeners.put(PLAY_ACTION, playAction); >- listeners.put(PAUSE_ACTION, pauseAction); >- listeners.put(STOP_ACTION, stopAction); >- listeners.put(MONITOR_ACTION, new MonitorAction()); >- listeners.put(DOM_VIEWER_ACTION, new DOMViewerAction()); >- listeners.put(SET_TRANSFORM_ACTION, new SetTransformAction()); >- listeners.put(FIND_DIALOG_ACTION, new FindDialogAction()); >- listeners.put(THUMBNAIL_DIALOG_ACTION, new ThumbnailDialogAction()); >- listeners.put(FLUSH_ACTION, new FlushAction()); >- listeners.put(TOGGLE_DEBUGGER_ACTION, new ToggleDebuggerAction()); >+ /** >+ * The auto adjust flag. >+ */ >+ protected boolean autoAdjust = true; > >- JPanel p = null; >- try { >- // Create the menu >- MenuFactory mf = new MenuFactory(bundle, this); >- JMenuBar mb = >- mf.createJMenuBar("MenuBar", application.getUISpecialization()); >- setJMenuBar(mb); >+ /** >+ * Whether the update manager was stopped. >+ */ >+ protected boolean managerStopped; > >- localHistory = new LocalHistory(mb, this); >+ /** >+ * The SVG user agent. >+ */ >+ protected SVGUserAgent userAgent = new UserAgent(); > >- String[] uri = application.getVisitedURIs(); >- for (int i=0; i<uri.length; i++) { >- if (uri[i] != null && !"".equals(uri[i])) { >- localHistory.update(uri[i]); >- } >- } >- p = new JPanel(new BorderLayout()); >+ /** >+ * The current document. >+ */ >+ protected SVGDocument svgDocument; > >- // Create the toolbar >- ToolBarFactory tbf = new ToolBarFactory(bundle, this); >- JToolBar tb = tbf.createJToolBar("ToolBar"); >- tb.setFloatable(false); >- getContentPane().add(p, BorderLayout.NORTH); >- p.add(tb, BorderLayout.NORTH); >- p.add(new javax.swing.JSeparator(), BorderLayout.CENTER); >- p.add(locationBar = new LocationBar(), BorderLayout.SOUTH); >- locationBar.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); >+ /** >+ * The descriptor associated with the current document. >+ */ >+ protected DocumentDescriptor docDescriptor; > >- } catch (MissingResourceException e) { >- System.out.println(e.getMessage()); >- System.exit(0); >- } >+ /** >+ * Document text, stored when the document is loaded >+ */ >+ protected String docText; > >- svgCanvasPanel = new JPanel(new BorderLayout()); >- svgCanvasPanel.setBorder(BorderFactory.createEtchedBorder()); >+ /** >+ * The URI chooser. >+ */ >+ protected URIChooser uriChooser; > >- svgCanvasPanel.add(svgCanvas, BorderLayout.CENTER); >- p = new JPanel(new BorderLayout()); >- p.add(svgCanvasPanel, BorderLayout.CENTER); >- p.add(statusBar = new StatusBar(), BorderLayout.SOUTH); >+ /** >+ * The DOM viewer. >+ */ >+ protected DOMViewer domViewer; > >- getContentPane().add(p, BorderLayout.CENTER); >+ /** >+ * The Timeline viewer. >+ */ >+ protected TimelineViewer timelineViewer; > >- svgCanvas.addSVGDocumentLoaderListener(this); >- svgCanvas.addGVTTreeBuilderListener(this); >- svgCanvas.addSVGLoadEventDispatcherListener(this); >- svgCanvas.addGVTTreeRendererListener(this); >- svgCanvas.addLinkActivationListener(this); >- svgCanvas.addUpdateManagerListener(this); >+ /** >+ * The Find dialog. >+ */ >+ protected FindDialog findDialog; > >- svgCanvas.addMouseMotionListener(new MouseMotionAdapter() { >- public void mouseMoved(MouseEvent e) { >- if (svgDocument == null) { >- statusBar.setXPosition(e.getX()); >- statusBar.setYPosition(e.getY()); >- } else { >- try { >- AffineTransform at; >- at = svgCanvas.getViewBoxTransform(); >- if (at != null) { >- at = at.createInverse(); >- Point2D p2d = >- at.transform(new Point2D.Float(e.getX(), e.getY()), >- null); >- statusBar.setXPosition((float)p2d.getX()); >- statusBar.setYPosition((float)p2d.getY()); >- return; >- } >- } catch (NoninvertibleTransformException ex) { >- } >- statusBar.setXPosition(e.getX()); >- statusBar.setYPosition(e.getY()); >- } >- } >- }); >- svgCanvas.addMouseListener(new MouseAdapter() { >- public void mouseExited(MouseEvent e) { >- Dimension dim = svgCanvas.getSize(); >- if (svgDocument == null) { >- statusBar.setWidth(dim.width); >- statusBar.setHeight(dim.height); >- } else { >- try { >- AffineTransform at; >- at = svgCanvas.getViewBoxTransform(); >- if (at != null) { >- at = at.createInverse(); >- Point2D o = >- at.transform(new Point2D.Float(0, 0), >- null); >- Point2D p2d = >- at.transform(new Point2D.Float(dim.width, >- dim.height), >- null); >- statusBar.setWidth((float)(p2d.getX() - o.getX())); >- statusBar.setHeight((float)(p2d.getY() - o.getY())); >- return; >- } >- } catch (NoninvertibleTransformException ex) { >- } >- statusBar.setWidth(dim.width); >- statusBar.setHeight(dim.height); >- } >- } >- }); >- svgCanvas.addComponentListener(new ComponentAdapter() { >- public void componentResized(ComponentEvent e) { >- Dimension dim = svgCanvas.getSize(); >- if (svgDocument == null) { >- statusBar.setWidth(dim.width); >- statusBar.setHeight(dim.height); >- } else { >- try { >- AffineTransform at; >- at = svgCanvas.getViewBoxTransform(); >- if (at != null) { >- at = at.createInverse(); >- Point2D o = >- at.transform(new Point2D.Float(0, 0), >- null); >- Point2D p2d = >- at.transform(new Point2D.Float(dim.width, >- dim.height), >- null); >- statusBar.setWidth((float)(p2d.getX() - o.getX())); >- statusBar.setHeight((float)(p2d.getY() - o.getY())); >- return; >- } >- } catch (NoninvertibleTransformException ex) { >- } >- statusBar.setWidth(dim.width); >- statusBar.setHeight(dim.height); >- } >- } >- }); >+ /** >+ * The Find dialog. >+ */ >+ protected ThumbnailDialog thumbnailDialog; > >- locationBar.addActionListener(new AbstractAction() { >- public void actionPerformed(ActionEvent e) { >- String st = locationBar.getText().trim(); >- int i = st.indexOf( '#' ); >- String t = ""; >- if (i != -1) { >- t = st.substring(i + 1); >- st = st.substring(0, i); >- } >+ /** >+ * The transform dialog >+ */ >+ protected JAffineTransformChooser.Dialog transformDialog; > >- if (st.equals("")) >- return; >+ /** >+ * The location bar. >+ */ >+ protected LocationBar locationBar; > >- try{ >- File f = new File(st); >- if (f.exists()) { >- if (f.isDirectory()) { >- return; >- } else { >- try { >- st = f.getCanonicalPath(); >- if (st.startsWith("/")) { >- st = "file:" + st; >- } else { >- st = "file:/" + st; >- } >- } catch (IOException ex) { >- } >- } >- } >- }catch(SecurityException se){ >- // Could not patch the file URI for security >- // reasons (e.g., when run as an unsigned >- // JavaWebStart jar): file access is not >- // allowed. Loading will fail, but there is >- // nothing more to do at this point. >- } >+ /** >+ * The status bar. >+ */ >+ protected StatusBar statusBar; > >- String fi = svgCanvas.getFragmentIdentifier(); >- if (svgDocument != null) { >- ParsedURL docPURL >- = new ParsedURL(svgDocument.getURL()); >- ParsedURL purl = new ParsedURL(docPURL, st); >- fi = (fi == null) ? "" : fi; >- if (docPURL.equals(purl) && t.equals(fi)) { >- return; >- } >- } >- if (t.length() != 0) { >- st += '#' + t; >- } >- locationBar.setText(st); >- locationBar.addToHistory(st); >- showSVGDocument(st); >- } >- }); >- } >+ /** >+ * The initial frame title. >+ */ >+ protected String title; > >- /** >- * Call dispose on canvas as well. >- */ >- public void dispose() { >- hideDebugger(); >- svgCanvas.dispose(); >- super.dispose(); >- } >+ /** >+ * The local history. >+ */ >+ protected LocalHistory localHistory; > >- /** >- * Whether to show the debug traces. >- */ >- public void setDebug(boolean b) { >- debug = b; >- } >+ /** >+ * The transform history. >+ */ >+ protected TransformHistory transformHistory = new TransformHistory(); > >- /** >- * Whether to auto adjust the canvas to the size of the document. >- */ >- public void setAutoAdjust(boolean b) { >- autoAdjust = b; >- } >+ /** >+ * The alternate style-sheet title. >+ */ >+ protected String alternateStyleSheet; > >- /** >- * Returns the main JSVGCanvas of this frame. >- */ >- public JSVGCanvas getJSVGCanvas() { >- return svgCanvas; >- } >+ /** >+ * The debugger object. >+ */ >+ protected Debugger debugger; > >- /** >- * Needed to work-around JFileChooser bug with abstract Files >- */ >- private static File makeAbsolute(File f){ >- if(!f.isAbsolute()){ >- return f.getAbsoluteFile(); >- } >- return f; >- } >+ /** >+ * Creates a new SVG viewer frame. >+ */ >+ public JSVGViewerFrame(Application app) { >+ application = app; > >- /** >- * Shows the Rhino debugger. >- */ >- public void showDebugger() { >- if (debugger == null && Debugger.isPresent) { >- debugger = new Debugger(this, locationBar.getText()); >- debugger.initialize(); >- } >- } >+ addWindowListener(new WindowAdapter() { >+ public void windowClosing(WindowEvent e) { >+ application.closeJSVGViewerFrame(JSVGViewerFrame.this); >+ } >+ }); > >- /** >- * Hides and destroys the Rhino debugger. >- */ >- public void hideDebugger() { >- if (debugger != null) { >- debugger.clearAllBreakpoints(); >- debugger.go(); >- debugger.dispose(); >- debugger = null; >- } >- } >+ // >+ // Set the frame's maximum size so that content >+ // bigger than the screen does not cause the creation >+ // of unnecessary large images. >+ // >+ svgCanvas = new Canvas(userAgent, true, true) { >+ Dimension screenSize; > >- /** >- * Rhino debugger class. >- */ >- protected static class Debugger { >+ { >+ screenSize = Toolkit.getDefaultToolkit().getScreenSize(); >+ setMaximumSize(screenSize); >+ } > >- /** >- * Whether the Rhino debugger classes are present. >- */ >- protected static boolean isPresent; >+ public Dimension getPreferredSize() { >+ Dimension s = super.getPreferredSize(); >+ if (s.width > screenSize.width) >+ s.width = screenSize.width; >+ if (s.height > screenSize.height) >+ s.height = screenSize.height; >+ return s; >+ } > >- /** >- * The Rhino debugger class. >- */ >- protected static Class debuggerClass; >+ /** >+ * This method is called when the component knows the desired size >+ * of the window (based on width/height of outermost SVG element). >+ * We override it to immediately pack this frame. >+ */ >+ public void setMySize(Dimension d) { >+ setPreferredSize(d); >+ invalidate(); >+ if (JSVGViewerFrame.this.autoAdjust) { >+ Platform.unmaximize(JSVGViewerFrame.this); >+ JSVGViewerFrame.this.pack(); >+ } >+ } > >- /** >- * The Rhino ContextFactory class. >- */ >- protected static Class contextFactoryClass; >+ public void setDisableInteractions(boolean b) { >+ super.setDisableInteractions(b); > >- // Indexes into the debuggerMethods array. >- protected static final int CLEAR_ALL_BREAKPOINTS_METHOD = 0; >- protected static final int GO_METHOD = 1; >- protected static final int SET_EXIT_ACTION_METHOD = 2; >- protected static final int ATTACH_TO_METHOD = 3; >- protected static final int DETACH_METHOD = 4; >- protected static final int DISPOSE_METHOD = 5; >- protected static final int GET_DEBUG_FRAME_METHOD = 6; >+ // Disable/Enable all our different ways to adjust the >+ // rendering transform (menus, toolbar, thumbnail, keyboard). > >- /** >- * Rhino debugger class constructor. >- */ >- protected static Constructor debuggerConstructor; >+ ((Action) listeners.get(SET_TRANSFORM_ACTION)).setEnabled(!b); > >- /** >- * Rhino debugger class methods. >- */ >- protected static Method[] debuggerMethods; >+ if (thumbnailDialog != null) >+ thumbnailDialog.setInteractionEnabled(!b); >+ } >+ }; > >- /** >- * The RhinoInterpreter class. >- */ >- protected static Class rhinoInterpreterClass; >+ javax.swing.ActionMap map = svgCanvas.getActionMap(); >+ map.put(FULL_SCREEN_ACTION, new FullScreenAction()); >+ javax.swing.InputMap imap = svgCanvas >+ .getInputMap(JComponent.WHEN_FOCUSED); >+ KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0); >+ imap.put(key, FULL_SCREEN_ACTION); > >- /** >- * The {@code getContextFactory} method on the {@link >- * org.apache.batik.script.rhino.RhinoInterpreter} class. >- */ >- protected static Method getContextFactoryMethod; >+ svgCanvas.setDoubleBufferedRendering(true); > >- static { >- try { >- Class dc = >- Class.forName("org.mozilla.javascript.tools.debugger.Main"); >- Class cfc = >- Class.forName("org.mozilla.javascript.ContextFactory"); >- rhinoInterpreterClass = Class.forName >- ("org.apache.batik.script.rhino.RhinoInterpreter"); >- debuggerConstructor = >- dc.getConstructor(new Class[] { String.class }); >- debuggerMethods = new Method[] { >- dc.getMethod("clearAllBreakpoints", (Class[]) null), >- dc.getMethod("go", (Class[]) null), >- dc.getMethod("setExitAction", new Class[] {Runnable.class}), >- dc.getMethod("attachTo", new Class[] { cfc }), >- dc.getMethod("detach", (Class[]) null), >- dc.getMethod("dispose", (Class[]) null), >- dc.getMethod("getDebugFrame", (Class[]) null) >- }; >- getContextFactoryMethod = >- rhinoInterpreterClass.getMethod("getContextFactory", >- (Class[]) null); >- debuggerClass = dc; >- isPresent = true; >- } catch (ClassNotFoundException cnfe) { >- } catch (NoSuchMethodException nsme) { >- } catch (SecurityException se) { >- } >- } >+ listeners.put(ABOUT_ACTION, new AboutAction()); >+ listeners.put(OPEN_ACTION, new OpenAction()); >+ listeners.put(OPEN_LOCATION_ACTION, new OpenLocationAction()); >+ listeners.put(NEW_WINDOW_ACTION, new NewWindowAction()); >+ listeners.put(RELOAD_ACTION, new ReloadAction()); >+ listeners.put(SAVE_AS_ACTION, new SaveAsAction()); >+ listeners.put(BACK_ACTION, backAction); >+ listeners.put(FORWARD_ACTION, forwardAction); >+ listeners.put(PRINT_ACTION, new PrintAction()); >+ listeners.put(EXPORT_AS_JPG_ACTION, new ExportAsJPGAction()); >+ listeners.put(EXPORT_AS_PNG_ACTION, new ExportAsPNGAction()); >+ listeners.put(EXPORT_AS_TIFF_ACTION, new ExportAsTIFFAction()); >+ listeners.put(PREFERENCES_ACTION, new PreferencesAction()); >+ listeners.put(CLOSE_ACTION, new CloseAction()); >+ listeners.put(EXIT_ACTION, application.createExitAction(this)); >+ listeners.put(VIEW_SOURCE_ACTION, new ViewSourceAction()); > >- /** >- * The Rhino debugger instance. >- */ >- protected Object debuggerInstance; >+ javax.swing.ActionMap cMap = svgCanvas.getActionMap(); >+ listeners.put(RESET_TRANSFORM_ACTION, cMap >+ .get(JSVGCanvas.RESET_TRANSFORM_ACTION)); >+ listeners.put(ZOOM_IN_ACTION, cMap.get(JSVGCanvas.ZOOM_IN_ACTION)); >+ listeners.put(ZOOM_OUT_ACTION, cMap.get(JSVGCanvas.ZOOM_OUT_ACTION)); > >- /** >- * The JSVGViewerFrame. >- */ >- protected JSVGViewerFrame svgFrame; >+ listeners.put(PREVIOUS_TRANSFORM_ACTION, previousTransformAction); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK); >+ imap.put(key, previousTransformAction); > >- /** >- * Creates a new Debugger. >- */ >- public Debugger(JSVGViewerFrame frame, String url) { >- svgFrame = frame; >- try { >- debuggerInstance = debuggerConstructor.newInstance >- (new Object[] { "JavaScript Debugger - " + url }); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } catch (InvocationTargetException ite) { >- ite.printStackTrace(); >- throw new RuntimeException(ite.getMessage()); >- } catch (InstantiationException ie) { >- throw new RuntimeException(ie.getMessage()); >- } >- } >+ listeners.put(NEXT_TRANSFORM_ACTION, nextTransformAction); >+ key = KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_MASK); >+ imap.put(key, nextTransformAction); > >- /** >- * Sets the document URL to use in the window title. >- */ >- public void setDocumentURL(String url) { >- getDebugFrame().setTitle("JavaScript Debugger - " + url); >- } >+ listeners.put(USE_STYLESHEET_ACTION, useStylesheetAction); >+ listeners.put(PLAY_ACTION, playAction); >+ listeners.put(PAUSE_ACTION, pauseAction); >+ listeners.put(STOP_ACTION, stopAction); >+ listeners.put(MONITOR_ACTION, new MonitorAction()); >+ listeners.put(DOM_VIEWER_ACTION, new DOMViewerAction()); >+ listeners.put(TIMELINE_VIEWER_ACTION, new TimelineViewerAction()); >+ listeners.put(SET_TRANSFORM_ACTION, new SetTransformAction()); >+ listeners.put(FIND_DIALOG_ACTION, new FindDialogAction()); >+ listeners.put(THUMBNAIL_DIALOG_ACTION, new ThumbnailDialogAction()); >+ listeners.put(FLUSH_ACTION, new FlushAction()); >+ listeners.put(TOGGLE_DEBUGGER_ACTION, new ToggleDebuggerAction()); > >- /** >- * Initializes the debugger by massaging the GUI and attaching it >- * to the Rhino interpreter's {@link >- * org.mozilla.javascript.ContextFactory}. >- */ >- public void initialize() { >- // Customize the menubar a bit, disable menu >- // items that can't be used and change 'Exit' to 'Close'. >- JFrame debugGui = getDebugFrame(); >- JMenuBar menuBar = debugGui.getJMenuBar(); >- JMenu menu = menuBar.getMenu(0); >- menu.getItem(0).setEnabled(false); // Open... >- menu.getItem(1).setEnabled(false); // Run... >- menu.getItem(3).setText >- (Resources.getString("Close.text")); // Exit -> "Close" >- menu.getItem(3).setAccelerator >- (KeyStroke.getKeyStroke(KeyEvent.VK_W, Event.CTRL_MASK)); >+ JPanel p = null; >+ try { >+ // Create the menu >+ MenuFactory mf = new MenuFactory(bundle, this); >+ JMenuBar mb = mf.createJMenuBar("MenuBar", application >+ .getUISpecialization()); >+ setJMenuBar(mb); > >- debugGui.setSize(600, 460); >- debugGui.pack(); >- setExitAction(new Runnable() { >- public void run() { >- svgFrame.hideDebugger(); >- }}); >- WindowAdapter wa = new WindowAdapter() { >- public void windowClosing(WindowEvent e) { >- svgFrame.hideDebugger(); >- }}; >- debugGui.addWindowListener(wa); >- debugGui.setVisible(true); >- attach(); >- } >+ localHistory = new LocalHistory(mb, this); > >- /** >- * Attaches the debugger to the canvas' current interpreter. >- */ >- public void attach() { >- Object interpreter = svgFrame.svgCanvas.getRhinoInterpreter(); >- if (interpreter != null) { >- attachTo(getContextFactory(interpreter)); >- } >- } >+ String[] uri = application.getVisitedURIs(); >+ for (int i = 0; i < uri.length; i++) { >+ if (uri[i] != null && !"".equals(uri[i])) { >+ localHistory.update(uri[i]); >+ } >+ } >+ p = new JPanel(new BorderLayout()); > >- /** >- * Calls {@code getDebugFrame} on {@link #debuggerInstance}. >- */ >- protected JFrame getDebugFrame() { >- try { >- return (JFrame) debuggerMethods[GET_DEBUG_FRAME_METHOD].invoke >- (debuggerInstance, (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ // Create the toolbar >+ ToolBarFactory tbf = new ToolBarFactory(bundle, this); >+ JToolBar tb = tbf.createJToolBar("ToolBar"); >+ tb.setFloatable(false); >+ getContentPane().add(p, BorderLayout.NORTH); >+ p.add(tb, BorderLayout.NORTH); >+ p.add(new javax.swing.JSeparator(), BorderLayout.CENTER); >+ p.add(locationBar = new LocationBar(), BorderLayout.SOUTH); >+ locationBar.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); > >- /** >- * Calls {@code setExitAction} on {@link #debuggerInstance}. >- */ >- protected void setExitAction(Runnable r) { >- try { >- debuggerMethods[SET_EXIT_ACTION_METHOD].invoke >- (debuggerInstance, new Object[] { r }); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ } catch (MissingResourceException e) { >+ System.out.println(e.getMessage()); >+ System.exit(0); >+ } > >- /** >- * Calls {@code attachTo} on {@link #debuggerInstance}. >- */ >- public void attachTo(Object contextFactory) { >- try { >- debuggerMethods[ATTACH_TO_METHOD].invoke >- (debuggerInstance, new Object[] { contextFactory }); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ svgCanvasPanel = new JPanel(new BorderLayout()); >+ svgCanvasPanel.setBorder(BorderFactory.createEtchedBorder()); > >- /** >- * Calls {@code detach} on {@link #debuggerInstance}. >- */ >- public void detach() { >- try { >- debuggerMethods[DETACH_METHOD].invoke(debuggerInstance, >- (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ svgCanvasPanel.add(svgCanvas, BorderLayout.CENTER); >+ p = new JPanel(new BorderLayout()); >+ p.add(svgCanvasPanel, BorderLayout.CENTER); >+ p.add(statusBar = new StatusBar(), BorderLayout.SOUTH); > >- /** >- * Calls {@code go} on {@link #debuggerInstance}. >- */ >- public void go() { >- try { >- debuggerMethods[GO_METHOD].invoke(debuggerInstance, >- (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ getContentPane().add(p, BorderLayout.CENTER); > >- /** >- * Calls {@code clearAllBreakpoints} on {@link #debuggerInstance}. >- */ >- public void clearAllBreakpoints() { >- try { >- debuggerMethods[CLEAR_ALL_BREAKPOINTS_METHOD].invoke >- (debuggerInstance, (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ svgCanvas.addSVGDocumentLoaderListener(this); >+ svgCanvas.addGVTTreeBuilderListener(this); >+ svgCanvas.addSVGLoadEventDispatcherListener(this); >+ svgCanvas.addGVTTreeRendererListener(this); >+ svgCanvas.addLinkActivationListener(this); >+ svgCanvas.addUpdateManagerListener(this); > >- /** >- * Calls {@code dispose} on {@link #debuggerInstance}. >- */ >- public void dispose() { >- try { >- debuggerMethods[DISPOSE_METHOD].invoke(debuggerInstance, >- (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >+ svgCanvas.addMouseMotionListener(new MouseMotionAdapter() { >+ public void mouseMoved(MouseEvent e) { >+ if (svgDocument == null) { >+ statusBar.setXPosition(e.getX()); >+ statusBar.setYPosition(e.getY()); >+ } else { >+ try { >+ AffineTransform at; >+ at = svgCanvas.getViewBoxTransform(); >+ if (at != null) { >+ at = at.createInverse(); >+ Point2D p2d = at.transform(new Point2D.Float(e >+ .getX(), e.getY()), null); >+ statusBar.setXPosition((float) p2d.getX()); >+ statusBar.setYPosition((float) p2d.getY()); >+ return; >+ } >+ } catch (NoninvertibleTransformException ex) { >+ } >+ statusBar.setXPosition(e.getX()); >+ statusBar.setYPosition(e.getY()); >+ } >+ } >+ }); >+ svgCanvas.addMouseListener(new MouseAdapter() { >+ public void mouseExited(MouseEvent e) { >+ Dimension dim = svgCanvas.getSize(); >+ if (svgDocument == null) { >+ statusBar.setWidth(dim.width); >+ statusBar.setHeight(dim.height); >+ } else { >+ try { >+ AffineTransform at; >+ at = svgCanvas.getViewBoxTransform(); >+ if (at != null) { >+ at = at.createInverse(); >+ Point2D o = at.transform(new Point2D.Float(0, 0), >+ null); >+ Point2D p2d = at.transform(new Point2D.Float( >+ dim.width, dim.height), null); >+ statusBar.setWidth((float) (p2d.getX() - o.getX())); >+ statusBar >+ .setHeight((float) (p2d.getY() - o.getY())); >+ return; >+ } >+ } catch (NoninvertibleTransformException ex) { >+ } >+ statusBar.setWidth(dim.width); >+ statusBar.setHeight(dim.height); >+ } >+ } >+ }); >+ svgCanvas.addComponentListener(new ComponentAdapter() { >+ public void componentResized(ComponentEvent e) { >+ Dimension dim = svgCanvas.getSize(); >+ if (svgDocument == null) { >+ statusBar.setWidth(dim.width); >+ statusBar.setHeight(dim.height); >+ } else { >+ try { >+ AffineTransform at; >+ at = svgCanvas.getViewBoxTransform(); >+ if (at != null) { >+ at = at.createInverse(); >+ Point2D o = at.transform(new Point2D.Float(0, 0), >+ null); >+ Point2D p2d = at.transform(new Point2D.Float( >+ dim.width, dim.height), null); >+ statusBar.setWidth((float) (p2d.getX() - o.getX())); >+ statusBar >+ .setHeight((float) (p2d.getY() - o.getY())); >+ return; >+ } >+ } catch (NoninvertibleTransformException ex) { >+ } >+ statusBar.setWidth(dim.width); >+ statusBar.setHeight(dim.height); >+ } >+ } >+ }); > >- /** >- * Calls {@code getContextFactory} on the given instance of >- * {@link org.apache.batik.script.rhino.RhinoInterpreter}. >- */ >- protected Object getContextFactory(Object rhinoInterpreter) { >- try { >- return getContextFactoryMethod.invoke(rhinoInterpreter, >- (Object[]) null); >- } catch (InvocationTargetException ite) { >- throw new RuntimeException(ite.getMessage()); >- } catch (IllegalAccessException iae) { >- throw new RuntimeException(iae.getMessage()); >- } >- } >- } >+ locationBar.addActionListener(new AbstractAction() { >+ public void actionPerformed(ActionEvent e) { >+ String st = locationBar.getText().trim(); >+ int i = st.indexOf('#'); >+ String t = ""; >+ if (i != -1) { >+ t = st.substring(i + 1); >+ st = st.substring(0, i); >+ } > >- /** >- * To show the about dialog >- */ >- public class AboutAction extends AbstractAction { >- public AboutAction(){ >- } >+ if (st.equals("")) >+ return; > >- public void actionPerformed(ActionEvent e){ >- AboutDialog dlg = new AboutDialog(JSVGViewerFrame.this); >- // Work around pack() bug on some platforms >- dlg.setSize(dlg.getPreferredSize()); >- dlg.setLocationRelativeTo(JSVGViewerFrame.this); >- dlg.setVisible(true); >- dlg.toFront(); >- } >- } >+ try { >+ File f = new File(st); >+ if (f.exists()) { >+ if (f.isDirectory()) { >+ return; >+ } else { >+ try { >+ st = f.getCanonicalPath(); >+ if (st.startsWith("/")) { >+ st = "file:" + st; >+ } else { >+ st = "file:/" + st; >+ } >+ } catch (IOException ex) { >+ } >+ } >+ } >+ } catch (SecurityException se) { >+ // Could not patch the file URI for security >+ // reasons (e.g., when run as an unsigned >+ // JavaWebStart jar): file access is not >+ // allowed. Loading will fail, but there is >+ // nothing more to do at this point. >+ } > >- /** >- * To open a new file. >- */ >- public class OpenAction extends AbstractAction { >+ String fi = svgCanvas.getFragmentIdentifier(); >+ if (svgDocument != null) { >+ ParsedURL docPURL = new ParsedURL(svgDocument.getURL()); >+ ParsedURL purl = new ParsedURL(docPURL, st); >+ fi = (fi == null) ? "" : fi; >+ if (docPURL.equals(purl) && t.equals(fi)) { >+ return; >+ } >+ } >+ if (t.length() != 0) { >+ st += '#' + t; >+ } >+ locationBar.setText(st); >+ locationBar.addToHistory(st); >+ showSVGDocument(st); >+ } >+ }); >+ } > >- public OpenAction() { >- } >- public void actionPerformed(ActionEvent e) { >- File f = null; >- if (Platform.isOSX) { >- FileDialog fileDialog = >- new FileDialog(JSVGViewerFrame.this, >- Resources.getString(OPEN_TITLE)); >- fileDialog.setFilenameFilter(new FilenameFilter() { >- public boolean accept(File dir, String name) { >- Iterator iter = getHandlers().iterator(); >- while (iter.hasNext()) { >- SquiggleInputHandler handler >- = (SquiggleInputHandler)iter.next(); >- if (handler.accept(new File(dir, name))) { >- return true; >- } >- } >- return false; >- } >- }); >- fileDialog.setVisible(true); >- String filename = fileDialog.getFile(); >- if (fileDialog != null) { >- String dirname = fileDialog.getDirectory(); >- f = new File(dirname, filename); >- } >- } else { >- JFileChooser fileChooser = null; >+ /** >+ * Call dispose on canvas as well. >+ */ >+ public void dispose() { >+ hideDebugger(); >+ svgCanvas.dispose(); >+ super.dispose(); >+ } > >- // Apply work around Windows problem when security is enabled, >- // and when prior to JDK 1.4. >- String os = System.getProperty(PROPERTY_OS_NAME, PROPERTY_OS_NAME_DEFAULT); >- SecurityManager sm = System.getSecurityManager(); >+ /** >+ * Whether to show the debug traces. >+ */ >+ public void setDebug(boolean b) { >+ debug = b; >+ } > >- if ( priorJDK1_4 && sm != null && os.indexOf(PROPERTY_OS_WINDOWS_PREFIX) != -1 ){ >- fileChooser = new JFileChooser(makeAbsolute(currentPath), >- new WindowsAltFileSystemView()); >- } else { >- fileChooser = new JFileChooser(makeAbsolute(currentPath)); >- } >+ /** >+ * Whether to auto adjust the canvas to the size of the document. >+ */ >+ public void setAutoAdjust(boolean b) { >+ autoAdjust = b; >+ } > >- fileChooser.setFileHidingEnabled(false); >- fileChooser.setFileSelectionMode >- (JFileChooser.FILES_ONLY); >+ /** >+ * Returns the main JSVGCanvas of this frame. >+ */ >+ public JSVGCanvas getJSVGCanvas() { >+ return svgCanvas; >+ } > >- // >- // Add file filters from the handlers map >- // >- Iterator iter = getHandlers().iterator(); >- while (iter.hasNext()) { >- SquiggleInputHandler handler >- = (SquiggleInputHandler)iter.next(); >- fileChooser.addChoosableFileFilter >- (new SquiggleInputHandlerFilter(handler)); >- } >+ /** >+ * Needed to work-around JFileChooser bug with abstract Files >+ */ >+ private static File makeAbsolute(File f) { >+ if (!f.isAbsolute()) { >+ return f.getAbsoluteFile(); >+ } >+ return f; >+ } > >- int choice = fileChooser.showOpenDialog(JSVGViewerFrame.this); >- if (choice == JFileChooser.APPROVE_OPTION) { >- f = fileChooser.getSelectedFile(); >- currentPath = f; >- } >- } >+ /** >+ * Shows the Rhino debugger. >+ */ >+ public void showDebugger() { >+ if (debugger == null && Debugger.isPresent) { >+ debugger = new Debugger(this, locationBar.getText()); >+ debugger.initialize(); >+ } >+ } > >- if (f != null) { >- try { >- String furl = f.toURL().toString(); >- showSVGDocument(furl); >- } catch (MalformedURLException ex) { >- if (userAgent != null) { >- userAgent.displayError(ex); >- } >- } >- } >- } >- } >+ /** >+ * Hides and destroys the Rhino debugger. >+ */ >+ public void hideDebugger() { >+ if (debugger != null) { >+ debugger.clearAllBreakpoints(); >+ debugger.go(); >+ debugger.dispose(); >+ debugger = null; >+ } >+ } > >- /** >- * Shows the given document into the viewer frame >- */ >- public void showSVGDocument(String uri){ >- try { >- ParsedURL purl = new ParsedURL(uri); >- SquiggleInputHandler >- handler = getInputHandler(purl); >+ /** >+ * Rhino debugger class. >+ */ >+ protected static class Debugger { > >- handler.handle(purl, >- JSVGViewerFrame.this); >- } catch (Exception e) { >- if (userAgent != null) { >- userAgent.displayError(e); >- } >- } >+ /** >+ * Whether the Rhino debugger classes are present. >+ */ >+ protected static boolean isPresent; > >- } >+ /** >+ * The Rhino debugger class. >+ */ >+ protected static Class debuggerClass; > >- /** >- * Returns the input handler for the given URI >- */ >- public SquiggleInputHandler getInputHandler(ParsedURL purl) throws IOException { >- Iterator iter = getHandlers().iterator(); >- SquiggleInputHandler handler = null; >+ /** >+ * The Rhino ContextFactory class. >+ */ >+ protected static Class contextFactoryClass; > >- while (iter.hasNext()) { >- SquiggleInputHandler curHandler = >- (SquiggleInputHandler)iter.next(); >- if (curHandler.accept(purl)) { >- handler = curHandler; >- break; >- } >- } >+ // Indexes into the debuggerMethods array. >+ protected static final int CLEAR_ALL_BREAKPOINTS_METHOD = 0; > >- // No handler found, use the default one. >- if (handler == null) { >- handler = defaultHandler; >- } >+ protected static final int GO_METHOD = 1; > >- return handler; >- } >+ protected static final int SET_EXIT_ACTION_METHOD = 2; > >+ protected static final int ATTACH_TO_METHOD = 3; > >- /** >- * Returns the list of input file handler. >- */ >- protected static Vector getHandlers() { >- if (handlers != null) { >- return handlers; >- } >+ protected static final int DETACH_METHOD = 4; > >- handlers = new Vector(); >- registerHandler(new SVGInputHandler()); >+ protected static final int DISPOSE_METHOD = 5; > >- Iterator iter = Service.providers(SquiggleInputHandler.class); >- while (iter.hasNext()) { >- SquiggleInputHandler handler >- = (SquiggleInputHandler)iter.next(); >+ protected static final int GET_DEBUG_FRAME_METHOD = 6; > >- registerHandler(handler); >- } >+ /** >+ * Rhino debugger class constructor. >+ */ >+ protected static Constructor debuggerConstructor; > >- return handlers; >- } >+ /** >+ * Rhino debugger class methods. >+ */ >+ protected static Method[] debuggerMethods; > >- /** >- * Registers an input file handler by adding it to the handlers map. >- * @param handler the new input handler to register. >- */ >- public static synchronized >- void registerHandler(SquiggleInputHandler handler) { >- Vector handlers = getHandlers(); >- handlers.addElement(handler); >- } >+ /** >+ * The RhinoInterpreter class. >+ */ >+ protected static Class rhinoInterpreterClass; > >- /** >- * To open a new document. >- */ >- public class OpenLocationAction extends AbstractAction { >- public OpenLocationAction() {} >- public void actionPerformed(ActionEvent e) { >- if (uriChooser == null) { >- uriChooser = new URIChooser(JSVGViewerFrame.this); >- uriChooser.setFileFilter(new SVGFileFilter()); >- uriChooser.pack(); >- Rectangle fr = getBounds(); >- Dimension sd = uriChooser.getSize(); >- uriChooser.setLocation(fr.x + (fr.width - sd.width) / 2, >- fr.y + (fr.height - sd.height) / 2); >- } >- if (uriChooser.showDialog() == URIChooser.OK_OPTION) { >- String s = uriChooser.getText(); >- if (s == null) return; >- int i = s.indexOf( '#' ); >- String t = ""; >- if (i != -1) { >- t = s.substring(i + 1); >- s = s.substring(0, i); >- } >- if (!s.equals("")) { >- File f = new File(s); >- if (f.exists()) { >- if (f.isDirectory()) { >- s = null; >- } else { >- try { >- s = f.getCanonicalPath(); >- if (s.startsWith("/")) { >- s = "file:" + s; >- } else { >- s = "file:/" + s; >- } >- } catch (IOException ex) { >- } >- } >- } >- if (s != null) { >- if (svgDocument != null) { >- ParsedURL docPURL >- = new ParsedURL(svgDocument.getURL()); >- ParsedURL purl = new ParsedURL(docPURL, s); >- String fi = svgCanvas.getFragmentIdentifier(); >- if (docPURL.equals(purl) && t.equals(fi)) { >- return; >- } >- } >- if (t.length() != 0) { >- s += '#' + t; >- } >+ /** >+ * The {@code getContextFactory} method on the {@link >+ * org.apache.batik.script.rhino.RhinoInterpreter} class. >+ */ >+ protected static Method getContextFactoryMethod; > >- showSVGDocument(s); >- } >- } >- } >- } >- } >+ static { >+ try { >+ Class dc = Class >+ .forName("org.mozilla.javascript.tools.debugger.Main"); >+ Class cfc = Class >+ .forName("org.mozilla.javascript.ContextFactory"); >+ rhinoInterpreterClass = Class >+ .forName("org.apache.batik.script.rhino.RhinoInterpreter"); >+ debuggerConstructor = dc >+ .getConstructor(new Class[] { String.class }); >+ debuggerMethods = new Method[] { >+ dc.getMethod("clearAllBreakpoints", (Class[]) null), >+ dc.getMethod("go", (Class[]) null), >+ dc.getMethod("setExitAction", >+ new Class[] { Runnable.class }), >+ dc.getMethod("attachTo", new Class[] { cfc }), >+ dc.getMethod("detach", (Class[]) null), >+ dc.getMethod("dispose", (Class[]) null), >+ dc.getMethod("getDebugFrame", (Class[]) null) }; >+ getContextFactoryMethod = rhinoInterpreterClass.getMethod( >+ "getContextFactory", (Class[]) null); >+ debuggerClass = dc; >+ isPresent = true; >+ } catch (ClassNotFoundException cnfe) { >+ } catch (NoSuchMethodException nsme) { >+ } catch (SecurityException se) { >+ } >+ } > >- /** >- * To open a new window. >- */ >- public class NewWindowAction extends AbstractAction { >- public NewWindowAction() {} >- public void actionPerformed(ActionEvent e) { >- JSVGViewerFrame vf = application.createAndShowJSVGViewerFrame(); >+ /** >+ * The Rhino debugger instance. >+ */ >+ protected Object debuggerInstance; > >- // Copy the current settings to the new window. >- vf.autoAdjust = autoAdjust; >- vf.debug = debug; >- vf.svgCanvas.setProgressivePaint(svgCanvas.getProgressivePaint()); >- vf.svgCanvas.setDoubleBufferedRendering >- (svgCanvas.getDoubleBufferedRendering()); >- } >- } >+ /** >+ * The JSVGViewerFrame. >+ */ >+ protected JSVGViewerFrame svgFrame; > >- /** >- * To show the preferences. >- */ >- public class PreferencesAction extends AbstractAction { >- public PreferencesAction() {} >- public void actionPerformed(ActionEvent e) { >- application.showPreferenceDialog(JSVGViewerFrame.this); >- } >- } >+ /** >+ * Creates a new Debugger. >+ */ >+ public Debugger(JSVGViewerFrame frame, String url) { >+ svgFrame = frame; >+ try { >+ debuggerInstance = debuggerConstructor >+ .newInstance(new Object[] { "JavaScript Debugger - " >+ + url }); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } catch (InvocationTargetException ite) { >+ ite.printStackTrace(); >+ throw new RuntimeException(ite.getMessage()); >+ } catch (InstantiationException ie) { >+ throw new RuntimeException(ie.getMessage()); >+ } >+ } > >- /** >- * To close the last document. >- */ >- public class CloseAction extends AbstractAction { >- public CloseAction() {} >- public void actionPerformed(ActionEvent e) { >- application.closeJSVGViewerFrame(JSVGViewerFrame.this); >- } >- } >+ /** >+ * Sets the document URL to use in the window title. >+ */ >+ public void setDocumentURL(String url) { >+ getDebugFrame().setTitle("JavaScript Debugger - " + url); >+ } > >- /** >- * To reload the current document. >- */ >- public class ReloadAction extends AbstractAction { >- public ReloadAction() {} >- public void actionPerformed(ActionEvent e) { >- if ((e.getModifiers() & ActionEvent.SHIFT_MASK) == 1) { >- svgCanvas.flushImageCache(); >- } >- if (svgDocument != null) { >- localHistory.reload(); >- } >- } >- } >+ /** >+ * Initializes the debugger by massaging the GUI and attaching it to the >+ * Rhino interpreter's {@link org.mozilla.javascript.ContextFactory}. >+ */ >+ public void initialize() { >+ // Customize the menubar a bit, disable menu >+ // items that can't be used and change 'Exit' to 'Close'. >+ JFrame debugGui = getDebugFrame(); >+ JMenuBar menuBar = debugGui.getJMenuBar(); >+ JMenu menu = menuBar.getMenu(0); >+ menu.getItem(0).setEnabled(false); // Open... >+ menu.getItem(1).setEnabled(false); // Run... >+ menu.getItem(3).setText(Resources.getString("Close.text")); // Exit >+ // -> >+ // "Close" >+ menu.getItem(3).setAccelerator( >+ KeyStroke.getKeyStroke(KeyEvent.VK_W, Event.CTRL_MASK)); > >- /** >- * To go back to the previous document >- */ >- public class BackAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public BackAction() {} >- public void actionPerformed(ActionEvent e) { >- if (localHistory.canGoBack()) { >- localHistory.back(); >- } >- } >+ debugGui.setSize(600, 460); >+ debugGui.pack(); >+ setExitAction(new Runnable() { >+ public void run() { >+ svgFrame.hideDebugger(); >+ } >+ }); >+ WindowAdapter wa = new WindowAdapter() { >+ public void windowClosing(WindowEvent e) { >+ svgFrame.hideDebugger(); >+ } >+ }; >+ debugGui.addWindowListener(wa); >+ debugGui.setVisible(true); >+ attach(); >+ } > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ /** >+ * Attaches the debugger to the canvas' current interpreter. >+ */ >+ public void attach() { >+ Object interpreter = svgFrame.svgCanvas.getRhinoInterpreter(); >+ if (interpreter != null) { >+ attachTo(getContextFactory(interpreter)); >+ } >+ } > >- protected void update() { >- boolean b = localHistory.canGoBack(); >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(b); >- } >- } >- } >+ /** >+ * Calls {@code getDebugFrame} on {@link #debuggerInstance}. >+ */ >+ protected JFrame getDebugFrame() { >+ try { >+ return (JFrame) debuggerMethods[GET_DEBUG_FRAME_METHOD].invoke( >+ debuggerInstance, (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- /** >- * To go forward to the next document >- */ >- public class ForwardAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public ForwardAction() {} >- public void actionPerformed(ActionEvent e) { >- if (localHistory.canGoForward()) { >- localHistory.forward(); >- } >- } >+ /** >+ * Calls {@code setExitAction} on {@link #debuggerInstance}. >+ */ >+ protected void setExitAction(Runnable r) { >+ try { >+ debuggerMethods[SET_EXIT_ACTION_METHOD].invoke( >+ debuggerInstance, new Object[] { r }); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ /** >+ * Calls {@code attachTo} on {@link #debuggerInstance}. >+ */ >+ public void attachTo(Object contextFactory) { >+ try { >+ debuggerMethods[ATTACH_TO_METHOD].invoke(debuggerInstance, >+ new Object[] { contextFactory }); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- protected void update() { >- boolean b = localHistory.canGoForward(); >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(b); >- } >- } >- } >+ /** >+ * Calls {@code detach} on {@link #debuggerInstance}. >+ */ >+ public void detach() { >+ try { >+ debuggerMethods[DETACH_METHOD].invoke(debuggerInstance, >+ (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- /** >- * To print the current document. >- */ >- public class PrintAction extends AbstractAction { >- public PrintAction() {} >- public void actionPerformed(ActionEvent e) { >- if (svgDocument != null) { >- final SVGDocument doc = svgDocument; >- new Thread() { >- public void run(){ >- String uri = doc.getURL(); >- String fragment = svgCanvas.getFragmentIdentifier(); >- if (fragment != null) { >- uri += '#' +fragment; >- } >+ /** >+ * Calls {@code go} on {@link #debuggerInstance}. >+ */ >+ public void go() { >+ try { >+ debuggerMethods[GO_METHOD].invoke(debuggerInstance, >+ (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- // >- // Build a PrintTranscoder to handle printing >- // of the svgDocument object >- // >- PrintTranscoder pt = new PrintTranscoder(); >+ /** >+ * Calls {@code clearAllBreakpoints} on {@link #debuggerInstance}. >+ */ >+ public void clearAllBreakpoints() { >+ try { >+ debuggerMethods[CLEAR_ALL_BREAKPOINTS_METHOD].invoke( >+ debuggerInstance, (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- // >- // Set transcoding hints >- // >- if (application.getXMLParserClassName() != null) { >- pt.addTranscodingHint >- (JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >- application.getXMLParserClassName()); >- } >+ /** >+ * Calls {@code dispose} on {@link #debuggerInstance}. >+ */ >+ public void dispose() { >+ try { >+ debuggerMethods[DISPOSE_METHOD].invoke(debuggerInstance, >+ (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } > >- pt.addTranscodingHint(PrintTranscoder.KEY_SHOW_PAGE_DIALOG, >- Boolean.TRUE); >+ /** >+ * Calls {@code getContextFactory} on the given instance of >+ * {@link org.apache.batik.script.rhino.RhinoInterpreter}. >+ */ >+ protected Object getContextFactory(Object rhinoInterpreter) { >+ try { >+ return getContextFactoryMethod.invoke(rhinoInterpreter, >+ (Object[]) null); >+ } catch (InvocationTargetException ite) { >+ throw new RuntimeException(ite.getMessage()); >+ } catch (IllegalAccessException iae) { >+ throw new RuntimeException(iae.getMessage()); >+ } >+ } >+ } > >+ /** >+ * To show the about dialog >+ */ >+ public class AboutAction extends AbstractAction { >+ public AboutAction() { >+ } > >- pt.addTranscodingHint(PrintTranscoder.KEY_SHOW_PRINTER_DIALOG, >- Boolean.TRUE); >+ public void actionPerformed(ActionEvent e) { >+ AboutDialog dlg = new AboutDialog(JSVGViewerFrame.this); >+ // Work around pack() bug on some platforms >+ dlg.setSize(dlg.getPreferredSize()); >+ dlg.setLocationRelativeTo(JSVGViewerFrame.this); >+ dlg.setVisible(true); >+ dlg.toFront(); >+ } >+ } > >- // >- // Do transcoding now >- // >- pt.transcode(new TranscoderInput(uri), null); >+ /** >+ * To open a new file. >+ */ >+ public class OpenAction extends AbstractAction { > >- // >- // Print >- // >- try { >- pt.print(); >- } catch (PrinterException ex) { >- userAgent.displayError(ex); >- } >- } >- }.start(); >- } >- } >- } >+ public OpenAction() { >+ } > >- /** >- * To save the current document as SVG. >- */ >- public class SaveAsAction extends AbstractAction { >- public SaveAsAction() {} >+ public void actionPerformed(ActionEvent e) { >+ File f = null; >+ if (Platform.isOSX) { >+ FileDialog fileDialog = new FileDialog(JSVGViewerFrame.this, >+ Resources.getString(OPEN_TITLE)); >+ fileDialog.setFilenameFilter(new FilenameFilter() { >+ public boolean accept(File dir, String name) { >+ Iterator iter = getHandlers().iterator(); >+ while (iter.hasNext()) { >+ SquiggleInputHandler handler = (SquiggleInputHandler) iter >+ .next(); >+ if (handler.accept(new File(dir, name))) { >+ return true; >+ } >+ } >+ return false; >+ } >+ }); >+ fileDialog.setVisible(true); >+ String filename = fileDialog.getFile(); >+ if (fileDialog != null) { >+ String dirname = fileDialog.getDirectory(); >+ f = new File(dirname, filename); >+ } >+ } else { >+ JFileChooser fileChooser = null; > >- public void actionPerformed(ActionEvent e) { >- JFileChooser fileChooser; >- fileChooser = new JFileChooser(makeAbsolute(currentSavePath)); >- fileChooser.setDialogTitle(resources.getString("SaveAs.title")); >- fileChooser.setFileHidingEnabled(false); >- fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >- fileChooser.addChoosableFileFilter(new ImageFileFilter(".svg")); >+ // Apply work around Windows problem when security is enabled, >+ // and when prior to JDK 1.4. >+ String os = System.getProperty(PROPERTY_OS_NAME, >+ PROPERTY_OS_NAME_DEFAULT); >+ SecurityManager sm = System.getSecurityManager(); > >- int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >- if (choice != JFileChooser.APPROVE_OPTION) >- return; >+ if (priorJDK1_4 && sm != null >+ && os.indexOf(PROPERTY_OS_WINDOWS_PREFIX) != -1) { >+ fileChooser = new JFileChooser(makeAbsolute(currentPath), >+ new WindowsAltFileSystemView()); >+ } else { >+ fileChooser = new JFileChooser(makeAbsolute(currentPath)); >+ } > >- final File f = fileChooser.getSelectedFile(); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); > >- SVGOptionPanel sop; >- sop = SVGOptionPanel.showDialog(JSVGViewerFrame.this); >+ // >+ // Add file filters from the handlers map >+ // >+ Iterator iter = getHandlers().iterator(); >+ while (iter.hasNext()) { >+ SquiggleInputHandler handler = (SquiggleInputHandler) iter >+ .next(); >+ fileChooser >+ .addChoosableFileFilter(new SquiggleInputHandlerFilter( >+ handler)); >+ } > >- final boolean useXMLBase = sop.getUseXMLBase(); >- final boolean prettyPrint = sop.getPrettyPrint(); >- sop = null; >+ int choice = fileChooser.showOpenDialog(JSVGViewerFrame.this); >+ if (choice == JFileChooser.APPROVE_OPTION) { >+ f = fileChooser.getSelectedFile(); >+ currentPath = f; >+ } >+ } > >- final SVGDocument svgDoc = svgCanvas.getSVGDocument(); >- if (svgDoc == null) return; >+ if (f != null) { >+ try { >+ String furl = f.toURL().toString(); >+ showSVGDocument(furl); >+ } catch (MalformedURLException ex) { >+ if (userAgent != null) { >+ userAgent.displayError(ex); >+ } >+ } >+ } >+ } >+ } > >- statusBar.setMessage(resources.getString("Message.saveAs")); >- currentSavePath = f; >- OutputStreamWriter w = null; >- try { >- OutputStream tos = null; >- tos = new FileOutputStream(f); >- tos = new BufferedOutputStream(tos); >- w = new OutputStreamWriter(tos, "utf-8"); >- } catch (Exception ex) { >- userAgent.displayError(ex); >- return; >- } >+ /** >+ * Shows the given document into the viewer frame >+ */ >+ public void showSVGDocument(String uri) { >+ try { >+ ParsedURL purl = new ParsedURL(uri); >+ SquiggleInputHandler handler = getInputHandler(purl); > >- final OutputStreamWriter writer = w; >+ handler.handle(purl, JSVGViewerFrame.this); >+ } catch (Exception e) { >+ if (userAgent != null) { >+ userAgent.displayError(e); >+ } >+ } > >- final Runnable doneRun = new Runnable() { >- public void run() { >- String doneStr = resources.getString("Message.done"); >- statusBar.setMessage(doneStr); >- } >- }; >- Runnable r = new Runnable() { >- public void run() { >- try { >- // Write standard XML header. >- writer.write >- ("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); >- writer.write (EOL); >+ } > >- Node fc = svgDoc.getFirstChild(); >- if (fc.getNodeType() != Node.DOCUMENT_TYPE_NODE) { >- // Not DT node in Document, so >- // provide Document Type dec. >- writer.write ("<!DOCTYPE svg PUBLIC '"); >- writer.write (SVGConstants.SVG_PUBLIC_ID); >- writer.write ("' '"); >- writer.write (SVGConstants.SVG_SYSTEM_ID); >- writer.write ("'>"); >- writer.write (EOL); >- writer.write (EOL); >- } >- Element root = svgDoc.getRootElement(); >- boolean doXMLBase = useXMLBase; >- if (root.hasAttributeNS >- (XMLConstants.XML_NAMESPACE_URI, "base")) >- doXMLBase = false; >+ /** >+ * Returns the input handler for the given URI >+ */ >+ public SquiggleInputHandler getInputHandler(ParsedURL purl) >+ throws IOException { >+ Iterator iter = getHandlers().iterator(); >+ SquiggleInputHandler handler = null; > >- if (doXMLBase) { >- root.setAttributeNS >- (XMLConstants.XML_NAMESPACE_URI, >- "xml:base", >- svgDoc.getURL()); >- } >+ while (iter.hasNext()) { >+ SquiggleInputHandler curHandler = (SquiggleInputHandler) iter >+ .next(); >+ if (curHandler.accept(purl)) { >+ handler = curHandler; >+ break; >+ } >+ } > >- if (prettyPrint) { >- SVGTranscoder trans = new SVGTranscoder(); >- trans.transcode(new TranscoderInput(svgDoc), >- new TranscoderOutput(writer)); >- } else { >- DOMUtilities.writeDocument(svgDoc, writer); >- } >+ // No handler found, use the default one. >+ if (handler == null) { >+ handler = defaultHandler; >+ } > >- writer.close(); >+ return handler; >+ } > >- if (doXMLBase) >- root.removeAttributeNS >- (XMLConstants.XML_NAMESPACE_URI, >- "xml:base"); >+ /** >+ * Returns the list of input file handler. >+ */ >+ protected static Vector getHandlers() { >+ if (handlers != null) { >+ return handlers; >+ } > >- if (EventQueue.isDispatchThread()) { >- doneRun.run(); >- } else { >- EventQueue.invokeLater(doneRun); >- } >- } catch (Exception ex) { >- userAgent.displayError(ex); >- } >- } >- }; >+ handlers = new Vector(); >+ registerHandler(new SVGInputHandler()); > >- UpdateManager um = svgCanvas.getUpdateManager(); >- if ((um != null) && (um.isRunning())) { >- um.getUpdateRunnableQueue().invokeLater(r); >- } else { >- r.run(); >- } >- } >- } >+ Iterator iter = Service.providers(SquiggleInputHandler.class); >+ while (iter.hasNext()) { >+ SquiggleInputHandler handler = (SquiggleInputHandler) iter.next(); > >- /** >- * To save the current document as JPG. >- */ >- public class ExportAsJPGAction extends AbstractAction { >- public ExportAsJPGAction() {} >- public void actionPerformed(ActionEvent e) { >- JFileChooser fileChooser = >- new JFileChooser(makeAbsolute(currentSavePath)); >- fileChooser.setDialogTitle(resources.getString("ExportAsJPG.title")); >- fileChooser.setFileHidingEnabled(false); >- fileChooser.setFileSelectionMode >- (JFileChooser.FILES_ONLY); >- fileChooser.addChoosableFileFilter(new ImageFileFilter(".jpg")); >+ registerHandler(handler); >+ } > >- int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >- if (choice == JFileChooser.APPROVE_OPTION) { >- float quality = >- JPEGOptionPanel.showDialog(JSVGViewerFrame.this); >+ return handlers; >+ } > >- final File f = fileChooser.getSelectedFile(); >- BufferedImage buffer = svgCanvas.getOffScreen(); >- if (buffer != null) { >- statusBar.setMessage >- (resources.getString("Message.exportAsJPG")); >+ /** >+ * Registers an input file handler by adding it to the handlers map. >+ * >+ * @param handler >+ * the new input handler to register. >+ */ >+ public static synchronized void registerHandler(SquiggleInputHandler handler) { >+ Vector handlers = getHandlers(); >+ handlers.addElement(handler); >+ } > >- // create a BufferedImage of the appropriate type >- int w = buffer.getWidth(); >- int h = buffer.getHeight(); >- final ImageTranscoder trans = new JPEGTranscoder(); >- if (application.getXMLParserClassName() != null) { >- trans.addTranscodingHint >- (JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >- application.getXMLParserClassName()); >- } >- trans.addTranscodingHint >- (JPEGTranscoder.KEY_QUALITY, new Float(quality)); >+ /** >+ * To open a new document. >+ */ >+ public class OpenLocationAction extends AbstractAction { >+ public OpenLocationAction() { >+ } > >- final BufferedImage img = trans.createImage(w, h); >+ public void actionPerformed(ActionEvent e) { >+ if (uriChooser == null) { >+ uriChooser = new URIChooser(JSVGViewerFrame.this); >+ uriChooser.setFileFilter(new SVGFileFilter()); >+ uriChooser.pack(); >+ Rectangle fr = getBounds(); >+ Dimension sd = uriChooser.getSize(); >+ uriChooser.setLocation(fr.x + (fr.width - sd.width) / 2, fr.y >+ + (fr.height - sd.height) / 2); >+ } >+ if (uriChooser.showDialog() == URIChooser.OK_OPTION) { >+ String s = uriChooser.getText(); >+ if (s == null) >+ return; >+ int i = s.indexOf('#'); >+ String t = ""; >+ if (i != -1) { >+ t = s.substring(i + 1); >+ s = s.substring(0, i); >+ } >+ if (!s.equals("")) { >+ File f = new File(s); >+ if (f.exists()) { >+ if (f.isDirectory()) { >+ s = null; >+ } else { >+ try { >+ s = f.getCanonicalPath(); >+ if (s.startsWith("/")) { >+ s = "file:" + s; >+ } else { >+ s = "file:/" + s; >+ } >+ } catch (IOException ex) { >+ } >+ } >+ } >+ if (s != null) { >+ if (svgDocument != null) { >+ ParsedURL docPURL = new ParsedURL(svgDocument >+ .getURL()); >+ ParsedURL purl = new ParsedURL(docPURL, s); >+ String fi = svgCanvas.getFragmentIdentifier(); >+ if (docPURL.equals(purl) && t.equals(fi)) { >+ return; >+ } >+ } >+ if (t.length() != 0) { >+ s += '#' + t; >+ } > >- // paint the buffer to the image >- Graphics2D g2d = img.createGraphics(); >- g2d.setColor(Color.white); >- g2d.fillRect(0, 0, w, h); >- g2d.drawImage(buffer, null, 0, 0); >- new Thread() { >- public void run() { >- try { >- currentSavePath = f; >- OutputStream ostream = >- new BufferedOutputStream(new FileOutputStream(f)); >- trans.writeImage(img, new TranscoderOutput(ostream)); >- ostream.close(); >- } catch (Exception ex) { } >- statusBar.setMessage >- (resources.getString("Message.done")); >- } >- }.start(); >- } >- } >- } >- } >+ showSVGDocument(s); >+ } >+ } >+ } >+ } >+ } > >- /** >- * To save the current document as PNG. >- */ >- public class ExportAsPNGAction extends AbstractAction { >- public ExportAsPNGAction() {} >- public void actionPerformed(ActionEvent e) { >- JFileChooser fileChooser = >- new JFileChooser(makeAbsolute(currentSavePath)); >- fileChooser.setDialogTitle(resources.getString("ExportAsPNG.title")); >- fileChooser.setFileHidingEnabled(false); >- fileChooser.setFileSelectionMode >- (JFileChooser.FILES_ONLY); >- fileChooser.addChoosableFileFilter(new ImageFileFilter(".png")); >+ /** >+ * To open a new window. >+ */ >+ public class NewWindowAction extends AbstractAction { >+ public NewWindowAction() { >+ } > >- int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >- if (choice == JFileChooser.APPROVE_OPTION) { >+ public void actionPerformed(ActionEvent e) { >+ JSVGViewerFrame vf = application.createAndShowJSVGViewerFrame(); > >- // Start: By Jun Inamori (jun@oop-reserch.com) >- boolean isIndexed = PNGOptionPanel.showDialog(JSVGViewerFrame.this); >- // End: By Jun Inamori (jun@oop-reserch.com) >+ // Copy the current settings to the new window. >+ vf.autoAdjust = autoAdjust; >+ vf.debug = debug; >+ vf.svgCanvas.setProgressivePaint(svgCanvas.getProgressivePaint()); >+ vf.svgCanvas.setDoubleBufferedRendering(svgCanvas >+ .getDoubleBufferedRendering()); >+ } >+ } > >- final File f = fileChooser.getSelectedFile(); >- BufferedImage buffer = svgCanvas.getOffScreen(); >- if (buffer != null) { >- statusBar.setMessage >- (resources.getString("Message.exportAsPNG")); >+ /** >+ * To show the preferences. >+ */ >+ public class PreferencesAction extends AbstractAction { >+ public PreferencesAction() { >+ } > >- // create a BufferedImage of the appropriate type >- int w = buffer.getWidth(); >- int h = buffer.getHeight(); >- final ImageTranscoder trans = new PNGTranscoder(); >- if (application.getXMLParserClassName() != null) { >- trans.addTranscodingHint >- (JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >- application.getXMLParserClassName()); >- } >- trans.addTranscodingHint(PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE, >- Boolean.TRUE ); >+ public void actionPerformed(ActionEvent e) { >+ application.showPreferenceDialog(JSVGViewerFrame.this); >+ } >+ } > >- // Start: By Jun Inamori >- if(isIndexed){ >- trans.addTranscodingHint(PNGTranscoder.KEY_INDEXED,new Integer(256)); >- } >- // End: By Jun Inamori >+ /** >+ * To close the last document. >+ */ >+ public class CloseAction extends AbstractAction { >+ public CloseAction() { >+ } > >- final BufferedImage img = trans.createImage(w, h); >+ public void actionPerformed(ActionEvent e) { >+ application.closeJSVGViewerFrame(JSVGViewerFrame.this); >+ } >+ } > >- // paint the buffer to the image >- Graphics2D g2d = img.createGraphics(); >- g2d.drawImage(buffer, null, 0, 0); >- new Thread() { >- public void run() { >- try { >- currentSavePath = f; >- OutputStream ostream = >- new BufferedOutputStream(new FileOutputStream(f)); >- trans.writeImage(img, >- new TranscoderOutput(ostream)); >- ostream.close(); >- } catch (Exception ex) {} >- statusBar.setMessage >- (resources.getString("Message.done")); >- } >- }.start(); >- } >- } >- } >- } >+ /** >+ * To reload the current document. >+ */ >+ public class ReloadAction extends AbstractAction { >+ public ReloadAction() { >+ } > >- /** >- * To save the current document as TIFF. >- */ >- public class ExportAsTIFFAction extends AbstractAction { >- public ExportAsTIFFAction() {} >- public void actionPerformed(ActionEvent e) { >- JFileChooser fileChooser = >- new JFileChooser(makeAbsolute(currentSavePath)); >- fileChooser.setDialogTitle(resources.getString("ExportAsTIFF.title")); >- fileChooser.setFileHidingEnabled(false); >- fileChooser.setFileSelectionMode >- (JFileChooser.FILES_ONLY); >- fileChooser.addChoosableFileFilter(new ImageFileFilter(".tiff")); >+ public void actionPerformed(ActionEvent e) { >+ if ((e.getModifiers() & ActionEvent.SHIFT_MASK) == 1) { >+ svgCanvas.flushImageCache(); >+ } >+ if (svgDocument != null) { >+ localHistory.reload(); >+ } >+ } >+ } > >- int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >- if (choice == JFileChooser.APPROVE_OPTION) { >- final File f = fileChooser.getSelectedFile(); >- BufferedImage buffer = svgCanvas.getOffScreen(); >- if (buffer != null) { >- statusBar.setMessage >- (resources.getString("Message.exportAsTIFF")); >+ /** >+ * To go back to the previous document >+ */ >+ public class BackAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- // create a BufferedImage of the appropriate type >- int w = buffer.getWidth(); >- int h = buffer.getHeight(); >- final ImageTranscoder trans = new TIFFTranscoder(); >- if (application.getXMLParserClassName() != null) { >- trans.addTranscodingHint >- (JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >- application.getXMLParserClassName()); >- } >- final BufferedImage img = trans.createImage(w, h); >+ public BackAction() { >+ } > >- // paint the buffer to the image >- Graphics2D g2d = img.createGraphics(); >- g2d.drawImage(buffer, null, 0, 0); >- new Thread() { >- public void run() { >- try { >- currentSavePath = f; >- OutputStream ostream = new BufferedOutputStream >- (new FileOutputStream(f)); >- trans.writeImage >- (img, new TranscoderOutput(ostream)); >- ostream.close(); >- } catch (Exception ex) {} >- statusBar.setMessage >- (resources.getString("Message.done")); >- } >- }.start(); >- } >- } >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ if (localHistory.canGoBack()) { >+ localHistory.back(); >+ } >+ } > >- /** >- * To view the source of the current document. >- */ >- public class ViewSourceAction extends AbstractAction { >- public ViewSourceAction() {} >- public void actionPerformed(ActionEvent e) { >- if (svgDocument == null) { >- return; >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- final ParsedURL u = new ParsedURL(svgDocument.getURL()); >+ protected void update() { >+ boolean b = localHistory.canGoBack(); >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(b); >+ } >+ } >+ } > >- final JFrame fr = new JFrame(u.toString()); >- fr.setSize(resources.getInteger("ViewSource.width"), >- resources.getInteger("ViewSource.height")); >- final JTextArea ta = new JTextArea(); >- ta.setLineWrap(true); >- ta.setFont(new Font("monospaced", Font.PLAIN, 12)); >+ /** >+ * To go forward to the next document >+ */ >+ public class ForwardAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- JScrollPane scroll = new JScrollPane(); >- scroll.getViewport().add(ta); >- scroll.setVerticalScrollBarPolicy >- (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); >- fr.getContentPane().add(scroll, BorderLayout.CENTER); >+ public ForwardAction() { >+ } > >- new Thread() { >- public void run() { >- char [] buffer = new char[4096]; >+ public void actionPerformed(ActionEvent e) { >+ if (localHistory.canGoForward()) { >+ localHistory.forward(); >+ } >+ } > >- try { >- Document doc = new PlainDocument(); >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- ParsedURL purl = new ParsedURL(svgDocument.getURL()); >- InputStream is >- = u.openStream(getInputHandler(purl). >- getHandledMimeTypes()); >- // u.openStream(MimeTypeConstants.MIME_TYPES_SVG); >+ protected void update() { >+ boolean b = localHistory.canGoForward(); >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(b); >+ } >+ } >+ } > >- Reader in = XMLUtilities.createXMLDocumentReader(is); >- int len; >- while ((len=in.read(buffer, 0, buffer.length)) != -1) { >- doc.insertString(doc.getLength(), >- new String(buffer, 0, len), null); >- } >+ /** >+ * To print the current document. >+ */ >+ public class PrintAction extends AbstractAction { >+ public PrintAction() { >+ } > >- ta.setDocument(doc); >- ta.setEditable(false); >- ta.setBackground(Color.white); >- fr.setVisible(true); >- } catch (Exception ex) { >- userAgent.displayError(ex); >- } >- } >- }.start(); >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ if (svgDocument != null) { >+ final SVGDocument doc = svgDocument; >+ new Thread() { >+ public void run() { >+ String uri = doc.getURL(); >+ String fragment = svgCanvas.getFragmentIdentifier(); >+ if (fragment != null) { >+ uri += '#' + fragment; >+ } > >- /** >- * To flush image cache (purely for debugging purposes) >- */ >- public class FlushAction extends AbstractAction { >- public FlushAction() {} >- public void actionPerformed(ActionEvent e) { >- svgCanvas.flush(); >- // Force redraw... >- svgCanvas.setRenderingTransform(svgCanvas.getRenderingTransform()); >- } >- } >+ // >+ // Build a PrintTranscoder to handle printing >+ // of the svgDocument object >+ // >+ PrintTranscoder pt = new PrintTranscoder(); > >- /** >- * To toggle visiblity of JavaScript Debugger. >- */ >- public class ToggleDebuggerAction extends AbstractAction { >- public ToggleDebuggerAction() { >- super("Toggle Debugger Action"); >- } >+ // >+ // Set transcoding hints >+ // >+ if (application.getXMLParserClassName() != null) { >+ pt.addTranscodingHint( >+ JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >+ application.getXMLParserClassName()); >+ } > >- public void actionPerformed(ActionEvent e) { >- if (debugger == null) { >- showDebugger(); >- } else { >- hideDebugger(); >- } >- } >- } >+ pt.addTranscodingHint( >+ PrintTranscoder.KEY_SHOW_PAGE_DIALOG, >+ Boolean.TRUE); > >- /** >- * To go back to the previous transform >- */ >- public class PreviousTransformAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public PreviousTransformAction() {} >- public void actionPerformed(ActionEvent e) { >- if (transformHistory.canGoBack()) { >- transformHistory.back(); >- update(); >- nextTransformAction.update(); >- svgCanvas.setRenderingTransform(transformHistory.currentTransform()); >- } >- } >+ pt.addTranscodingHint( >+ PrintTranscoder.KEY_SHOW_PRINTER_DIALOG, >+ Boolean.TRUE); > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ // >+ // Do transcoding now >+ // >+ pt.transcode(new TranscoderInput(uri), null); > >- protected void update() { >- boolean b = transformHistory.canGoBack(); >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(b); >- } >- } >- } >+ // >+ // Print >+ // >+ try { >+ pt.print(); >+ } catch (PrinterException ex) { >+ userAgent.displayError(ex); >+ } >+ } >+ }.start(); >+ } >+ } >+ } > >- /** >- * To go forward to the next transform >- */ >- public class NextTransformAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public NextTransformAction() {} >- public void actionPerformed(ActionEvent e) { >- if (transformHistory.canGoForward()) { >- transformHistory.forward(); >- update(); >- previousTransformAction.update(); >- svgCanvas.setRenderingTransform(transformHistory.currentTransform()); >- } >- } >+ /** >+ * To save the current document as SVG. >+ */ >+ public class SaveAsAction extends AbstractAction { >+ public SaveAsAction() { >+ } > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ public void actionPerformed(ActionEvent e) { >+ JFileChooser fileChooser; >+ fileChooser = new JFileChooser(makeAbsolute(currentSavePath)); >+ fileChooser.setDialogTitle(resources.getString("SaveAs.title")); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >+ fileChooser.addChoosableFileFilter(new ImageFileFilter(".svg")); > >- protected void update() { >- boolean b = transformHistory.canGoForward(); >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(b); >- } >- } >- } >+ int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >+ if (choice != JFileChooser.APPROVE_OPTION) >+ return; > >- /** >- * To apply the selected author stylesheet >- */ >- public class UseStylesheetAction extends AbstractAction >- implements JComponentModifier { >+ final File f = fileChooser.getSelectedFile(); > >- List components = new LinkedList(); >+ SVGOptionPanel sop; >+ sop = SVGOptionPanel.showDialog(JSVGViewerFrame.this); > >- public UseStylesheetAction() {} >+ final boolean useXMLBase = sop.getUseXMLBase(); >+ final boolean prettyPrint = sop.getPrettyPrint(); >+ sop = null; > >- public void actionPerformed(ActionEvent e) { >- } >+ final SVGDocument svgDoc = svgCanvas.getSVGDocument(); >+ if (svgDoc == null) >+ return; > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ statusBar.setMessage(resources.getString("Message.saveAs")); >+ currentSavePath = f; >+ OutputStreamWriter w = null; >+ try { >+ OutputStream tos = null; >+ tos = new FileOutputStream(f); >+ tos = new BufferedOutputStream(tos); >+ w = new OutputStreamWriter(tos, "utf-8"); >+ } catch (Exception ex) { >+ userAgent.displayError(ex); >+ return; >+ } > >- protected void update() { >- alternateStyleSheet = null; >- Iterator it = components.iterator(); >- SVGDocument doc = svgCanvas.getSVGDocument(); >- while (it.hasNext()) { >- JComponent stylesheetMenu = (JComponent)it.next(); >- stylesheetMenu.removeAll(); >- stylesheetMenu.setEnabled(false); >+ final OutputStreamWriter writer = w; > >- ButtonGroup buttonGroup = new ButtonGroup(); >+ final Runnable doneRun = new Runnable() { >+ public void run() { >+ String doneStr = resources.getString("Message.done"); >+ statusBar.setMessage(doneStr); >+ } >+ }; >+ Runnable r = new Runnable() { >+ public void run() { >+ try { >+ // Write standard XML header. >+ writer >+ .write("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); >+ writer.write(EOL); > >- for (Node n = doc.getFirstChild(); >- n != null && n.getNodeType() != Node.ELEMENT_NODE; >- n = n.getNextSibling()) { >- if (n instanceof StyleSheetProcessingInstruction) { >- StyleSheetProcessingInstruction sspi; >- sspi = (StyleSheetProcessingInstruction)n; >- HashTable attrs = sspi.getPseudoAttributes(); >- final String title = (String)attrs.get("title"); >- String alt = (String)attrs.get("alternate"); >- if (title != null && "yes".equals(alt)) { >- JRadioButtonMenuItem button; >- button = new JRadioButtonMenuItem(title); >+ Node fc = svgDoc.getFirstChild(); >+ if (fc.getNodeType() != Node.DOCUMENT_TYPE_NODE) { >+ // Not DT node in Document, so >+ // provide Document Type dec. >+ writer.write("<!DOCTYPE svg PUBLIC '"); >+ writer.write(SVGConstants.SVG_PUBLIC_ID); >+ writer.write("' '"); >+ writer.write(SVGConstants.SVG_SYSTEM_ID); >+ writer.write("'>"); >+ writer.write(EOL); >+ writer.write(EOL); >+ } >+ Element root = svgDoc.getRootElement(); >+ boolean doXMLBase = useXMLBase; >+ if (root.hasAttributeNS(XMLConstants.XML_NAMESPACE_URI, >+ "base")) >+ doXMLBase = false; > >- button.addActionListener >- (new java.awt.event.ActionListener() { >- public void actionPerformed(ActionEvent e) { >- SVGOMDocument doc; >- doc = (SVGOMDocument)svgCanvas.getSVGDocument(); >- doc.clearViewCSS(); >- alternateStyleSheet = title; >- svgCanvas.setSVGDocument(doc); >- } >- }); >+ if (doXMLBase) { >+ root.setAttributeNS(XMLConstants.XML_NAMESPACE_URI, >+ "xml:base", svgDoc.getURL()); >+ } > >- buttonGroup.add(button); >- stylesheetMenu.add(button); >- stylesheetMenu.setEnabled(true); >- } >- } >- } >- } >- } >- } >+ if (prettyPrint) { >+ SVGTranscoder trans = new SVGTranscoder(); >+ trans.transcode(new TranscoderInput(svgDoc), >+ new TranscoderOutput(writer)); >+ } else { >+ DOMUtilities.writeDocument(svgDoc, writer); >+ } > >- /** >- * To restart after a pause. >- */ >- public class PlayAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public PlayAction() {} >- public void actionPerformed(ActionEvent e) { >- svgCanvas.resumeProcessing(); >- } >+ writer.close(); > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ if (doXMLBase) >+ root.removeAttributeNS( >+ XMLConstants.XML_NAMESPACE_URI, "xml:base"); > >- public void update(boolean enabled) { >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(enabled); >- } >- } >- } >+ if (EventQueue.isDispatchThread()) { >+ doneRun.run(); >+ } else { >+ EventQueue.invokeLater(doneRun); >+ } >+ } catch (Exception ex) { >+ userAgent.displayError(ex); >+ } >+ } >+ }; > >- /** >- * To pause a document. >- */ >- public class PauseAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public PauseAction() {} >- public void actionPerformed(ActionEvent e) { >- svgCanvas.suspendProcessing(); >- } >+ UpdateManager um = svgCanvas.getUpdateManager(); >+ if ((um != null) && (um.isRunning())) { >+ um.getUpdateRunnableQueue().invokeLater(r); >+ } else { >+ r.run(); >+ } >+ } >+ } > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ /** >+ * To save the current document as JPG. >+ */ >+ public class ExportAsJPGAction extends AbstractAction { >+ public ExportAsJPGAction() { >+ } > >- public void update(boolean enabled) { >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(enabled); >- } >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ JFileChooser fileChooser = new JFileChooser( >+ makeAbsolute(currentSavePath)); >+ fileChooser >+ .setDialogTitle(resources.getString("ExportAsJPG.title")); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >+ fileChooser.addChoosableFileFilter(new ImageFileFilter(".jpg")); > >- /** >- * To stop the current processing. >- */ >- public class StopAction extends AbstractAction >- implements JComponentModifier { >- List components = new LinkedList(); >- public StopAction() {} >- public void actionPerformed(ActionEvent e) { >- svgCanvas.stopProcessing(); >- } >+ int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >+ if (choice == JFileChooser.APPROVE_OPTION) { >+ float quality = JPEGOptionPanel >+ .showDialog(JSVGViewerFrame.this); > >- public void addJComponent(JComponent c) { >- components.add(c); >- c.setEnabled(false); >- } >+ final File f = fileChooser.getSelectedFile(); >+ BufferedImage buffer = svgCanvas.getOffScreen(); >+ if (buffer != null) { >+ statusBar.setMessage(resources >+ .getString("Message.exportAsJPG")); > >- public void update(boolean enabled) { >- Iterator it = components.iterator(); >- while (it.hasNext()) { >- ((JComponent)it.next()).setEnabled(enabled); >- } >- } >- } >+ // create a BufferedImage of the appropriate type >+ int w = buffer.getWidth(); >+ int h = buffer.getHeight(); >+ final ImageTranscoder trans = new JPEGTranscoder(); >+ if (application.getXMLParserClassName() != null) { >+ trans.addTranscodingHint( >+ JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >+ application.getXMLParserClassName()); >+ } >+ trans.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, >+ new Float(quality)); > >- /** >- * To show the set transform dialog >- */ >- public class SetTransformAction extends AbstractAction { >- public SetTransformAction(){} >- public void actionPerformed(ActionEvent e){ >- if (transformDialog == null){ >- transformDialog >- = JAffineTransformChooser.createDialog >- (JSVGViewerFrame.this, >- resources.getString("SetTransform.title")); >- } >+ final BufferedImage img = trans.createImage(w, h); > >- AffineTransform txf = transformDialog.showDialog(); >- if(txf != null){ >- AffineTransform at = svgCanvas.getRenderingTransform(); >- if(at == null){ >- at = new AffineTransform(); >- } >+ // paint the buffer to the image >+ Graphics2D g2d = img.createGraphics(); >+ g2d.setColor(Color.white); >+ g2d.fillRect(0, 0, w, h); >+ g2d.drawImage(buffer, null, 0, 0); >+ new Thread() { >+ public void run() { >+ try { >+ currentSavePath = f; >+ OutputStream ostream = new BufferedOutputStream( >+ new FileOutputStream(f)); >+ trans.writeImage(img, new TranscoderOutput( >+ ostream)); >+ ostream.close(); >+ } catch (Exception ex) { >+ } >+ statusBar.setMessage(resources >+ .getString("Message.done")); >+ } >+ }.start(); >+ } >+ } >+ } >+ } > >- txf.concatenate(at); >- svgCanvas.setRenderingTransform(txf); >- } >- } >- } >+ /** >+ * To save the current document as PNG. >+ */ >+ public class ExportAsPNGAction extends AbstractAction { >+ public ExportAsPNGAction() { >+ } > >- /** >- * To display the memory monitor. >- */ >- public class MonitorAction extends AbstractAction { >- public MonitorAction() {} >- public void actionPerformed(ActionEvent e) { >- if (memoryMonitorFrame == null) { >- memoryMonitorFrame = new MemoryMonitor(); >- Rectangle fr = getBounds(); >- Dimension md = memoryMonitorFrame.getSize(); >- memoryMonitorFrame.setLocation(fr.x + (fr.width - md.width) / 2, >- fr.y + (fr.height - md.height) / 2); >- } >- memoryMonitorFrame.setVisible(true); >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ JFileChooser fileChooser = new JFileChooser( >+ makeAbsolute(currentSavePath)); >+ fileChooser >+ .setDialogTitle(resources.getString("ExportAsPNG.title")); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >+ fileChooser.addChoosableFileFilter(new ImageFileFilter(".png")); > >- /** >- * To display the Find dialog >- */ >- public class FindDialogAction extends AbstractAction { >- public FindDialogAction() {} >- public void actionPerformed(ActionEvent e) { >- if (findDialog == null) { >- findDialog = new FindDialog(JSVGViewerFrame.this, svgCanvas); >- findDialog.setGraphicsNode(svgCanvas.getGraphicsNode()); >- findDialog.pack(); >- Rectangle fr = getBounds(); >- Dimension td = findDialog.getSize(); >- findDialog.setLocation(fr.x + (fr.width - td.width) / 2, >- fr.y + (fr.height - td.height) / 2); >- } >- findDialog.setVisible(true); >- } >- } >+ int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >+ if (choice == JFileChooser.APPROVE_OPTION) { > >- /** >- * To display the Thumbnail dialog >- */ >- public class ThumbnailDialogAction extends AbstractAction { >- public ThumbnailDialogAction() {} >- public void actionPerformed(ActionEvent e) { >- if (thumbnailDialog == null) { >- thumbnailDialog >- = new ThumbnailDialog(JSVGViewerFrame.this, svgCanvas); >- thumbnailDialog.pack(); >- Rectangle fr = getBounds(); >- Dimension td = thumbnailDialog.getSize(); >- thumbnailDialog.setLocation(fr.x + (fr.width - td.width) / 2, >- fr.y + (fr.height - td.height) / 2); >- } >- thumbnailDialog.setInteractionEnabled >- (!svgCanvas.getDisableInteractions()); >- thumbnailDialog.setVisible(true); >- } >- } >+ // Start: By Jun Inamori (jun@oop-reserch.com) >+ boolean isIndexed = PNGOptionPanel >+ .showDialog(JSVGViewerFrame.this); >+ // End: By Jun Inamori (jun@oop-reserch.com) > >- /** >- * To display the document full screen >- */ >- public class FullScreenAction extends AbstractAction { >- public FullScreenAction() {} >+ final File f = fileChooser.getSelectedFile(); >+ BufferedImage buffer = svgCanvas.getOffScreen(); >+ if (buffer != null) { >+ statusBar.setMessage(resources >+ .getString("Message.exportAsPNG")); > >- public void actionPerformed(ActionEvent e) { >- if (window == null || !window.isVisible()) { >- if (window == null) { >- window = new JWindow(JSVGViewerFrame.this); >- Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); >- window.setSize(size); >- } >- // Go to full screen in JWindow) >- svgCanvas.getParent().remove(svgCanvas); >- window.getContentPane().add(svgCanvas); >- window.setVisible(true); >- window.toFront(); >- svgCanvas.requestFocus(); >- } else { >- // Go back to JSVGViewerFrame display >- svgCanvas.getParent().remove(svgCanvas); >- svgCanvasPanel.add(svgCanvas, BorderLayout.CENTER); >- window.setVisible(false); >- } >- } >- } >+ // create a BufferedImage of the appropriate type >+ int w = buffer.getWidth(); >+ int h = buffer.getHeight(); >+ final ImageTranscoder trans = new PNGTranscoder(); >+ if (application.getXMLParserClassName() != null) { >+ trans.addTranscodingHint( >+ JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >+ application.getXMLParserClassName()); >+ } >+ trans.addTranscodingHint( >+ PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE, >+ Boolean.TRUE); > >- /** >- * To display the DOM viewer of the document >- */ >- public class DOMViewerAction extends AbstractAction { >- public DOMViewerAction() {} >- public void actionPerformed(ActionEvent e) { >- if (domViewer == null) { >- domViewer = new DOMViewer(); >- if (svgDocument != null) { >- domViewer.setDocument(svgDocument, >- (ViewCSS)svgDocument.getDocumentElement()); >- } >- Rectangle fr = getBounds(); >- Dimension td = domViewer.getSize(); >- domViewer.setLocation(fr.x + (fr.width - td.width) / 2, >- fr.y + (fr.height - td.height) / 2); >- } >- domViewer.setVisible(true); >- } >- } >+ // Start: By Jun Inamori >+ if (isIndexed) { >+ trans.addTranscodingHint(PNGTranscoder.KEY_INDEXED, >+ new Integer(256)); >+ } >+ // End: By Jun Inamori > >- // ActionMap ///////////////////////////////////////////////////// >+ final BufferedImage img = trans.createImage(w, h); > >- /** >- * The map that contains the action listeners >- */ >- protected Map listeners = new HashMap(); >+ // paint the buffer to the image >+ Graphics2D g2d = img.createGraphics(); >+ g2d.drawImage(buffer, null, 0, 0); >+ new Thread() { >+ public void run() { >+ try { >+ currentSavePath = f; >+ OutputStream ostream = new BufferedOutputStream( >+ new FileOutputStream(f)); >+ trans.writeImage(img, new TranscoderOutput( >+ ostream)); >+ ostream.close(); >+ } catch (Exception ex) { >+ } >+ statusBar.setMessage(resources >+ .getString("Message.done")); >+ } >+ }.start(); >+ } >+ } >+ } >+ } > >- /** >- * Returns the action associated with the given string >- * or null on error >- * @param key the key mapped with the action to get >- * @throws MissingListenerException if the action is not found >- */ >- public Action getAction(String key) throws MissingListenerException { >- Action result = (Action)listeners.get(key); >- //if (result == null) { >- //result = canvas.getAction(key); >- //} >- if (result == null) { >- throw new MissingListenerException("Can't find action.", RESOURCES, key); >- } >- return result; >- } >+ /** >+ * To save the current document as TIFF. >+ */ >+ public class ExportAsTIFFAction extends AbstractAction { >+ public ExportAsTIFFAction() { >+ } > >- // SVGDocumentLoaderListener /////////////////////////////////////////// >+ public void actionPerformed(ActionEvent e) { >+ JFileChooser fileChooser = new JFileChooser( >+ makeAbsolute(currentSavePath)); >+ fileChooser.setDialogTitle(resources >+ .getString("ExportAsTIFF.title")); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >+ fileChooser.addChoosableFileFilter(new ImageFileFilter(".tiff")); > >- long time; // For debug. >+ int choice = fileChooser.showSaveDialog(JSVGViewerFrame.this); >+ if (choice == JFileChooser.APPROVE_OPTION) { >+ final File f = fileChooser.getSelectedFile(); >+ BufferedImage buffer = svgCanvas.getOffScreen(); >+ if (buffer != null) { >+ statusBar.setMessage(resources >+ .getString("Message.exportAsTIFF")); > >- /** >- * Called when the loading of a document was started. >- */ >- public void documentLoadingStarted(SVGDocumentLoaderEvent e) { >- String msg = resources.getString("Message.documentLoad"); >- if (debug) { >- System.out.println(msg); >- time = System.currentTimeMillis(); >- } >- statusBar.setMainMessage(msg); >- stopAction.update(true); >- svgCanvas.setCursor(WAIT_CURSOR); >- } >+ // create a BufferedImage of the appropriate type >+ int w = buffer.getWidth(); >+ int h = buffer.getHeight(); >+ final ImageTranscoder trans = new TIFFTranscoder(); >+ if (application.getXMLParserClassName() != null) { >+ trans.addTranscodingHint( >+ JPEGTranscoder.KEY_XML_PARSER_CLASSNAME, >+ application.getXMLParserClassName()); >+ } >+ final BufferedImage img = trans.createImage(w, h); > >+ // paint the buffer to the image >+ Graphics2D g2d = img.createGraphics(); >+ g2d.drawImage(buffer, null, 0, 0); >+ new Thread() { >+ public void run() { >+ try { >+ currentSavePath = f; >+ OutputStream ostream = new BufferedOutputStream( >+ new FileOutputStream(f)); >+ trans.writeImage(img, new TranscoderOutput( >+ ostream)); >+ ostream.close(); >+ } catch (Exception ex) { >+ } >+ statusBar.setMessage(resources >+ .getString("Message.done")); >+ } >+ }.start(); >+ } >+ } >+ } >+ } > >- /** >- * Called when the loading of a document was completed. >- */ >- public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { >- if (debug) { >- System.out.print(resources.getString("Message.documentLoadTime")); >- System.out.println((System.currentTimeMillis() - time) + " ms"); >- } >+ /** >+ * To view the source of the current document. >+ */ >+ public class ViewSourceAction extends AbstractAction { >+ >+ protected SourceViewFrame sourceViewFrame; >+ >+ protected Thread displayThread; >+ >+ public ViewSourceAction() { >+ } > >- setSVGDocument(e.getSVGDocument(), >- e.getSVGDocument().getURL(), >- e.getSVGDocument().getTitle()); >- } >+ public void actionPerformed(ActionEvent e) { >+ if (svgDocument == null) { >+ return; >+ } > >- /** >- * Forces the viewer frame to show the input SVGDocument >- */ >- public void setSVGDocument(SVGDocument svgDocument, >- String svgDocumentURL, >- String svgDocumentTitle) { >- this.svgDocument = svgDocument; >+ final ParsedURL u = new ParsedURL(svgDocument.getURL()); > >- if (domViewer != null) { >- if(domViewer.isVisible() && svgDocument != null) { >- domViewer.setDocument(svgDocument, >- (ViewCSS)svgDocument.getDocumentElement()); >- } else { >- domViewer.dispose(); >- domViewer = null; >- } >- } >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- String s = svgDocumentURL; >- locationBar.setText(s); >- if (debugger != null) { >- debugger.detach(); >- debugger.setDocumentURL(s); >- } >- if (title == null) { >- title = getTitle(); >- } >+ sourceViewFrame = new SourceViewFrame(application, userAgent); >+ displayThread = new Thread() { >+ public void run() { >+// char[] buffer = new char[4096]; > >- String dt = svgDocumentTitle; >- if (dt.length() != 0) { >- setTitle(title + ": " + dt); >- } else { >- int i = s.lastIndexOf("/"); >- if (i == -1) >- i = s.lastIndexOf("\\"); >- if (i == -1) { >- setTitle(title + ": " + s); >- } else { >- setTitle(title + ": " + s.substring(i + 1)); >- } >- } >+ try { >+ StringBuilder sb = new StringBuilder(); > >- localHistory.update(s); >- application.addVisitedURI(s); >- backAction.update(); >- forwardAction.update(); >+ ParsedURL purl = new ParsedURL(svgDocument.getURL()); >+ InputStream is = u.openStream(getInputHandler(purl) >+ .getHandledMimeTypes()); >+ // u.openStream(MimeTypeConstants.MIME_TYPES_SVG); > >- transformHistory = new TransformHistory(); >- previousTransformAction.update(); >- nextTransformAction.update(); >+// Reader in = XMLUtilities.createXMLDocumentReader(is); >+// int len; >+// while ((len = in.read(buffer, 0, buffer.length)) != -1) { >+// sb.append(new String(buffer, 0, len)); >+// } > >- useStylesheetAction.update(); >- } >+ BufferedReader reader = new BufferedReader( >+ new InputStreamReader(is)); >+ String line; > >- /** >- * Called when the loading of a document was cancelled. >- */ >- public void documentLoadingCancelled(SVGDocumentLoaderEvent e) { >- String msg = resources.getString("Message.documentCancelled"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- } >+ while ((line = reader.readLine()) != null) { >+ sb.append(line + "\n"); >+ } >+ >+ sourceViewFrame.setText(sb.toString()); >+ sourceViewFrame.setTitle(u.toString()); >+ ImageIcon icon = new ImageIcon(getClass().getResource( >+ resources.getString("ViewSource.frameicon"))); >+ sourceViewFrame.setIconImage(icon.getImage()); >+ sourceViewFrame.setSize(resources.getInteger("ViewSource.width"), >+ resources.getInteger("ViewSource.height")); >+ sourceViewFrame.setVisible(true); >+ } catch (Exception ex) { >+ userAgent.displayError(ex); >+ } >+ } >+ }; >+ displayThread.start(); >+ } >+ >+ public SourceViewFrame getSourceViewFrame() { >+ return sourceViewFrame; >+ } >+ >+ public Thread getDisplayThread() { >+ return displayThread; >+ } >+ } > >- /** >- * Called when the loading of a document has failed. >- */ >- public void documentLoadingFailed(SVGDocumentLoaderEvent e) { >- String msg = resources.getString("Message.documentFailed"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- } >+ /** >+ * To flush image cache (purely for debugging purposes) >+ */ >+ public class FlushAction extends AbstractAction { >+ public FlushAction() { >+ } > >- // GVTTreeBuilderListener ////////////////////////////////////////////// >+ public void actionPerformed(ActionEvent e) { >+ svgCanvas.flush(); >+ // Force redraw... >+ svgCanvas.setRenderingTransform(svgCanvas.getRenderingTransform()); >+ } >+ } > >- /** >- * Called when a build started. >- * The data of the event is initialized to the old document. >- */ >- public void gvtBuildStarted(GVTTreeBuilderEvent e) { >- String msg = resources.getString("Message.treeBuild"); >- if (debug) { >- System.out.println(msg); >- time = System.currentTimeMillis(); >- } >- statusBar.setMainMessage(msg); >- stopAction.update(true); >- svgCanvas.setCursor(WAIT_CURSOR); >- } >+ /** >+ * To toggle visiblity of JavaScript Debugger. >+ */ >+ public class ToggleDebuggerAction extends AbstractAction { >+ public ToggleDebuggerAction() { >+ super("Toggle Debugger Action"); >+ } > >- /** >- * Called when a build was completed. >- */ >- public void gvtBuildCompleted(GVTTreeBuilderEvent e) { >- if (debug) { >- System.out.print(resources.getString("Message.treeBuildTime")); >- System.out.println((System.currentTimeMillis() - time) + " ms"); >- } >- if (findDialog != null) { >- if(findDialog.isVisible()) { >- findDialog.setGraphicsNode(svgCanvas.getGraphicsNode()); >- } else { >- findDialog.dispose(); >- findDialog = null; >- } >- } >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- svgCanvas.setSelectionOverlayXORMode >- (application.isSelectionOverlayXORMode()); >- svgCanvas.requestFocus(); // request focus when load completes. >- if (debugger != null) { >- debugger.attach(); >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ if (debugger == null) { >+ showDebugger(); >+ } else { >+ hideDebugger(); >+ } >+ } >+ } > >- /** >- * Called when a build was cancelled. >- */ >- public void gvtBuildCancelled(GVTTreeBuilderEvent e) { >- String msg = resources.getString("Message.treeCancelled"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- svgCanvas.setSelectionOverlayXORMode >- (application.isSelectionOverlayXORMode()); >- } >+ /** >+ * To go back to the previous transform >+ */ >+ public class PreviousTransformAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- /** >- * Called when a build failed. >- */ >- public void gvtBuildFailed(GVTTreeBuilderEvent e) { >- String msg = resources.getString("Message.treeFailed"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- stopAction.update(false); >- svgCanvas.setCursor(DEFAULT_CURSOR); >- svgCanvas.setSelectionOverlayXORMode >- (application.isSelectionOverlayXORMode()); >- if (autoAdjust) { >- pack(); >- } >- } >+ public PreviousTransformAction() { >+ } > >- // SVGLoadEventDispatcherListener ////////////////////////////////////// >+ public void actionPerformed(ActionEvent e) { >+ if (transformHistory.canGoBack()) { >+ transformHistory.back(); >+ update(); >+ nextTransformAction.update(); >+ svgCanvas.setRenderingTransform(transformHistory >+ .currentTransform()); >+ } >+ } > >- /** >- * Called when a onload event dispatch started. >- */ >- public void svgLoadEventDispatchStarted(SVGLoadEventDispatcherEvent e) { >- String msg = resources.getString("Message.onload"); >- if (debug) { >- System.out.println(msg); >- time = System.currentTimeMillis(); >- } >- stopAction.update(true); >- statusBar.setMainMessage(msg); >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Called when a onload event dispatch was completed. >- */ >- public void svgLoadEventDispatchCompleted(SVGLoadEventDispatcherEvent e) { >- if (debug) { >- System.out.print(resources.getString("Message.onloadTime")); >- System.out.println((System.currentTimeMillis() - time) + " ms"); >- } >- stopAction.update(false); >- statusBar.setMainMessage(""); >- statusBar.setMessage(resources.getString("Message.done")); >- } >+ protected void update() { >+ boolean b = transformHistory.canGoBack(); >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(b); >+ } >+ } >+ } > >- /** >- * Called when a onload event dispatch was cancelled. >- */ >- public void svgLoadEventDispatchCancelled(SVGLoadEventDispatcherEvent e) { >- String msg = resources.getString("Message.onloadCancelled"); >- if (debug) { >- System.out.println(msg); >- } >- stopAction.update(false); >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- } >+ /** >+ * To go forward to the next transform >+ */ >+ public class NextTransformAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- /** >- * Called when a onload event dispatch failed. >- */ >- public void svgLoadEventDispatchFailed(SVGLoadEventDispatcherEvent e) { >- String msg = resources.getString("Message.onloadFailed"); >- if (debug) { >- System.out.println(msg); >- } >- stopAction.update(false); >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- } >+ public NextTransformAction() { >+ } > >- // GVTTreeRendererListener ///////////////////////////////////////////// >+ public void actionPerformed(ActionEvent e) { >+ if (transformHistory.canGoForward()) { >+ transformHistory.forward(); >+ update(); >+ previousTransformAction.update(); >+ svgCanvas.setRenderingTransform(transformHistory >+ .currentTransform()); >+ } >+ } > >- /** >- * Called when a rendering is in its preparing phase. >- */ >- public void gvtRenderingPrepare(GVTTreeRendererEvent e) { >- if (debug) { >- String msg = resources.getString("Message.treeRenderingPrep"); >- System.out.println(msg); >- time = System.currentTimeMillis(); >- } >- stopAction.update(true); >- svgCanvas.setCursor(WAIT_CURSOR); >- statusBar.setMainMessage(resources.getString("Message.treeRendering")); >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Called when a rendering started. >- */ >- public void gvtRenderingStarted(GVTTreeRendererEvent e) { >- if (debug) { >- String msg = resources.getString("Message.treeRenderingPrepTime"); >- System.out.print(msg); >- System.out.println((System.currentTimeMillis() - time) + " ms"); >- time = System.currentTimeMillis(); >- msg = resources.getString("Message.treeRenderingStart"); >- System.out.println(msg); >- } >- // Do nothing >- } >+ protected void update() { >+ boolean b = transformHistory.canGoForward(); >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(b); >+ } >+ } >+ } > >- /** >- * Called when a rendering was completed. >- */ >- public void gvtRenderingCompleted(GVTTreeRendererEvent e) { >- if (debug) { >- String msg = resources.getString("Message.treeRenderingTime"); >- System.out.print(msg); >- System.out.println((System.currentTimeMillis() - time) + " ms"); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(resources.getString("Message.done")); >- if (!svgCanvas.isDynamic() || managerStopped) { >- stopAction.update(false); >- } >- svgCanvas.setCursor(DEFAULT_CURSOR); >+ /** >+ * To apply the selected author stylesheet >+ */ >+ public class UseStylesheetAction extends AbstractAction implements >+ JComponentModifier { > >- transformHistory.update(svgCanvas.getRenderingTransform()); >- previousTransformAction.update(); >- nextTransformAction.update(); >- } >+ List components = new LinkedList(); > >- /** >- * Called when a rendering was cancelled. >- */ >- public void gvtRenderingCancelled(GVTTreeRendererEvent e) { >- String msg = resources.getString("Message.treeRenderingCancelled"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- if (!svgCanvas.isDynamic()) { >- stopAction.update(false); >- } >- svgCanvas.setCursor(DEFAULT_CURSOR); >- } >+ public UseStylesheetAction() { >+ } > >- /** >- * Called when a rendering failed. >- */ >- public void gvtRenderingFailed(GVTTreeRendererEvent e) { >- String msg = resources.getString("Message.treeRenderingFailed"); >- if (debug) { >- System.out.println(msg); >- } >- statusBar.setMainMessage(""); >- statusBar.setMessage(msg); >- if (!svgCanvas.isDynamic()) { >- stopAction.update(false); >- } >- svgCanvas.setCursor(DEFAULT_CURSOR); >- } >+ public void actionPerformed(ActionEvent e) { >+ } > >- // LinkActivationListener ///////////////////////////////////////// >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Called when a link was activated. >- */ >- public void linkActivated(LinkActivationEvent e) { >- String s = e.getReferencedURI(); >- if (svgDocument != null) { >- ParsedURL docURL = new ParsedURL(svgDocument.getURL()); >- ParsedURL url = new ParsedURL(docURL, s); >- if (!url.sameFile(docURL)) { >- return; >- } >+ protected void update() { >+ alternateStyleSheet = null; >+ Iterator it = components.iterator(); >+ SVGDocument doc = svgCanvas.getSVGDocument(); >+ while (it.hasNext()) { >+ JComponent stylesheetMenu = (JComponent) it.next(); >+ stylesheetMenu.removeAll(); >+ stylesheetMenu.setEnabled(false); > >- if (s.indexOf( '#' ) != -1) { >- localHistory.update(s); >- locationBar.setText(s); >- if (debugger != null) { >- debugger.detach(); >- debugger.setDocumentURL(s); >- } >- application.addVisitedURI(s); >- backAction.update(); >- forwardAction.update(); >+ ButtonGroup buttonGroup = new ButtonGroup(); > >- transformHistory = new TransformHistory(); >- previousTransformAction.update(); >- nextTransformAction.update(); >- } >- } >- } >+ for (Node n = doc.getFirstChild(); n != null >+ && n.getNodeType() != Node.ELEMENT_NODE; n = n >+ .getNextSibling()) { >+ if (n instanceof StyleSheetProcessingInstruction) { >+ StyleSheetProcessingInstruction sspi; >+ sspi = (StyleSheetProcessingInstruction) n; >+ HashTable attrs = sspi.getPseudoAttributes(); >+ final String title = (String) attrs.get("title"); >+ String alt = (String) attrs.get("alternate"); >+ if (title != null && "yes".equals(alt)) { >+ JRadioButtonMenuItem button; >+ button = new JRadioButtonMenuItem(title); > >- // UpdateManagerListener //////////////////////////////////////////////// >+ button >+ .addActionListener(new java.awt.event.ActionListener() { >+ public void actionPerformed( >+ ActionEvent e) { >+ SVGOMDocument doc; >+ doc = (SVGOMDocument) svgCanvas >+ .getSVGDocument(); >+ doc.clearViewCSS(); >+ alternateStyleSheet = title; >+ svgCanvas.setSVGDocument(doc); >+ } >+ }); > >- /** >- * Called when the manager was started. >- */ >- public void managerStarted(UpdateManagerEvent e) { >- if (debug) { >- String msg = resources.getString("Message.updateManagerStarted"); >- System.out.println(msg); >- } >- managerStopped = false; >- playAction.update(false); >- pauseAction.update(true); >- stopAction.update(true); >- } >+ buttonGroup.add(button); >+ stylesheetMenu.add(button); >+ stylesheetMenu.setEnabled(true); >+ } >+ } >+ } >+ } >+ } >+ } > >- /** >- * Called when the manager was suspended. >- */ >- public void managerSuspended(UpdateManagerEvent e) { >- if (debug) { >- String msg = resources.getString("Message.updateManagerSuspended"); >- System.out.println(msg); >- } >- playAction.update(true); >- pauseAction.update(false); >- } >+ /** >+ * To restart after a pause. >+ */ >+ public class PlayAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- /** >- * Called when the manager was resumed. >- */ >- public void managerResumed(UpdateManagerEvent e) { >- if (debug) { >- String msg = resources.getString("Message.updateManagerResumed"); >- System.out.println(msg); >- } >- playAction.update(false); >- pauseAction.update(true); >- } >+ public PlayAction() { >+ } > >- /** >- * Called when the manager was stopped. >- */ >- public void managerStopped(UpdateManagerEvent e) { >- if (debug) { >- String msg = resources.getString("Message.updateManagerStopped"); >- System.out.println(msg); >- } >- managerStopped = true; >- playAction.update(false); >- pauseAction.update(false); >- stopAction.update(false); >- } >+ public void actionPerformed(ActionEvent e) { >+ svgCanvas.resumeProcessing(); >+ } > >- /** >- * Called when an update started. >- */ >- public void updateStarted(final UpdateManagerEvent e) { >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Called when an update was completed. >- */ >- public void updateCompleted(final UpdateManagerEvent e) { >- } >+ public void update(boolean enabled) { >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(enabled); >+ } >+ } >+ } > >- /** >- * Called when an update failed. >- */ >- public void updateFailed(UpdateManagerEvent e) { >- } >+ /** >+ * To pause a document. >+ */ >+ public class PauseAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- /** >- * This class implements a SVG user agent. >- */ >- protected class UserAgent implements SVGUserAgent { >+ public PauseAction() { >+ } > >- /** >- * Creates a new SVGUserAgent. >- */ >- protected UserAgent() { >- } >+ public void actionPerformed(ActionEvent e) { >+ svgCanvas.suspendProcessing(); >+ } > >- /** >- * Displays an error message. >- */ >- public void displayError(String message) { >- if (debug) { >- System.err.println(message); >- } >- JOptionPane pane = >- new JOptionPane(message, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(JSVGViewerFrame.this, "ERROR"); >- dialog.setModal(false); >- dialog.setVisible(true); >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Displays an error resulting from the specified Exception. >- */ >- public void displayError(Exception ex) { >- if (debug) { >- ex.printStackTrace(); >- } >- JErrorPane pane = >- new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(JSVGViewerFrame.this, "ERROR"); >- dialog.setModal(false); >- dialog.setVisible(true); >- } >+ public void update(boolean enabled) { >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(enabled); >+ } >+ } >+ } > >- /** >- * Displays a message in the User Agent interface. >- * The given message is typically displayed in a status bar. >- */ >- public void displayMessage(String message) { >- statusBar.setMessage(message); >- } >+ /** >+ * To stop the current processing. >+ */ >+ public class StopAction extends AbstractAction implements >+ JComponentModifier { >+ List components = new LinkedList(); > >- /** >- * Shows an alert dialog box. >- */ >- public void showAlert(String message) { >- svgCanvas.showAlert(message); >- } >+ public StopAction() { >+ } > >- /** >- * Shows a prompt dialog box. >- */ >- public String showPrompt(String message) { >- return svgCanvas.showPrompt(message); >- } >+ public void actionPerformed(ActionEvent e) { >+ svgCanvas.stopProcessing(); >+ } > >- /** >- * Shows a prompt dialog box. >- */ >- public String showPrompt(String message, String defaultValue) { >- return svgCanvas.showPrompt(message, defaultValue); >- } >+ public void addJComponent(JComponent c) { >+ components.add(c); >+ c.setEnabled(false); >+ } > >- /** >- * Shows a confirm dialog box. >- */ >- public boolean showConfirm(String message) { >- return svgCanvas.showConfirm(message); >- } >+ public void update(boolean enabled) { >+ Iterator it = components.iterator(); >+ while (it.hasNext()) { >+ ((JComponent) it.next()).setEnabled(enabled); >+ } >+ } >+ } > >- /** >- * Returns the size of a px CSS unit in millimeters. >- */ >- public float getPixelUnitToMillimeter() { >- return 0.26458333333333333333333333333333f; // 96dpi >- } >+ /** >+ * To show the set transform dialog >+ */ >+ public class SetTransformAction extends AbstractAction { >+ public SetTransformAction() { >+ } > >- /** >- * Returns the size of a px CSS unit in millimeters. >- * This will be removed after next release. >- * @see #getPixelUnitToMillimeter() >- */ >- public float getPixelToMM() { >- return getPixelUnitToMillimeter(); >+ public void actionPerformed(ActionEvent e) { >+ if (transformDialog == null) { >+ transformDialog = JAffineTransformChooser.createDialog( >+ JSVGViewerFrame.this, resources >+ .getString("SetTransform.title")); >+ } > >- } >+ AffineTransform txf = transformDialog.showDialog(); >+ if (txf != null) { >+ AffineTransform at = svgCanvas.getRenderingTransform(); >+ if (at == null) { >+ at = new AffineTransform(); >+ } > >- /** >- * Returns the default font family. >- */ >- public String getDefaultFontFamily() { >- return application.getDefaultFontFamily(); >- } >+ txf.concatenate(at); >+ svgCanvas.setRenderingTransform(txf); >+ } >+ } >+ } > >- /** >- * Returns the medium font size. >- */ >- public float getMediumFontSize() { >- // 9pt (72pt == 1in) >- return 9f * 25.4f / (72f * getPixelUnitToMillimeter()); >- } >+ /** >+ * To display the memory monitor. >+ */ >+ public class MonitorAction extends AbstractAction { >+ public MonitorAction() { >+ } > >- /** >- * Returns a lighter font-weight. >- */ >- public float getLighterFontWeight(float f) { >- // Round f to nearest 100... >- int weight = ((int)((f+50)/100))*100; >- switch (weight) { >- case 100: return 100; >- case 200: return 100; >- case 300: return 200; >- case 400: return 300; >- case 500: return 400; >- case 600: return 400; >- case 700: return 400; >- case 800: return 400; >- case 900: return 400; >- default: >- throw new IllegalArgumentException("Bad Font Weight: " + f); >- } >- } >+ public void actionPerformed(ActionEvent e) { >+ if (memoryMonitorFrame == null) { >+ memoryMonitorFrame = new MemoryMonitor(); >+ Rectangle fr = getBounds(); >+ Dimension md = memoryMonitorFrame.getSize(); >+ memoryMonitorFrame.setLocation( >+ fr.x + (fr.width - md.width) / 2, fr.y >+ + (fr.height - md.height) / 2); >+ } >+ memoryMonitorFrame.setVisible(true); >+ } >+ } > >- /** >- * Returns a bolder font-weight. >- */ >- public float getBolderFontWeight(float f) { >- // Round f to nearest 100... >- int weight = ((int)((f+50)/100))*100; >- switch (weight) { >- case 100: return 600; >- case 200: return 600; >- case 300: return 600; >- case 400: return 600; >- case 500: return 600; >- case 600: return 700; >- case 700: return 800; >- case 800: return 900; >- case 900: return 900; >- default: >- throw new IllegalArgumentException("Bad Font Weight: " + f); >- } >- } >+ /** >+ * To display the Find dialog >+ */ >+ public class FindDialogAction extends AbstractAction { >+ public FindDialogAction() { >+ } > >+ public void actionPerformed(ActionEvent e) { >+ if (findDialog == null) { >+ findDialog = new FindDialog(JSVGViewerFrame.this, svgCanvas); >+ findDialog.setGraphicsNode(svgCanvas.getGraphicsNode()); >+ findDialog.pack(); >+ Rectangle fr = getBounds(); >+ Dimension td = findDialog.getSize(); >+ findDialog.setLocation(fr.x + (fr.width - td.width) / 2, fr.y >+ + (fr.height - td.height) / 2); >+ } >+ findDialog.setVisible(true); >+ } >+ } > >- /** >- * Returns the language settings. >- */ >- public String getLanguages() { >- return application.getLanguages(); >- } >+ /** >+ * To display the Thumbnail dialog >+ */ >+ public class ThumbnailDialogAction extends AbstractAction { >+ public ThumbnailDialogAction() { >+ } > >- /** >- * Returns the user stylesheet uri. >- * @return null if no user style sheet was specified. >- */ >- public String getUserStyleSheetURI() { >- return application.getUserStyleSheetURI(); >- } >+ public void actionPerformed(ActionEvent e) { >+ if (thumbnailDialog == null) { >+ thumbnailDialog = new ThumbnailDialog(JSVGViewerFrame.this, >+ svgCanvas); >+ thumbnailDialog.pack(); >+ Rectangle fr = getBounds(); >+ Dimension td = thumbnailDialog.getSize(); >+ thumbnailDialog.setLocation(fr.x + (fr.width - td.width) / 2, >+ fr.y + (fr.height - td.height) / 2); >+ } >+ thumbnailDialog.setInteractionEnabled(!svgCanvas >+ .getDisableInteractions()); >+ thumbnailDialog.setVisible(true); >+ } >+ } > >- /** >- * Returns the class name of the XML parser. >- */ >- public String getXMLParserClassName() { >- return application.getXMLParserClassName(); >- } >+ /** >+ * To display the document full screen >+ */ >+ public class FullScreenAction extends AbstractAction { >+ public FullScreenAction() { >+ } > >- /** >- * Returns true if the XML parser must be in validation mode, false >- * otherwise. >- */ >- public boolean isXMLParserValidating() { >- return application.isXMLParserValidating(); >- } >+ public void actionPerformed(ActionEvent e) { >+ if (window == null || !window.isVisible()) { >+ if (window == null) { >+ window = new JWindow(JSVGViewerFrame.this); >+ Dimension size = Toolkit.getDefaultToolkit() >+ .getScreenSize(); >+ window.setSize(size); >+ } >+ // Go to full screen in JWindow) >+ svgCanvas.getParent().remove(svgCanvas); >+ window.getContentPane().add(svgCanvas); >+ window.setVisible(true); >+ window.toFront(); >+ svgCanvas.requestFocus(); >+ } else { >+ // Go back to JSVGViewerFrame display >+ svgCanvas.getParent().remove(svgCanvas); >+ svgCanvasPanel.add(svgCanvas, BorderLayout.CENTER); >+ window.setVisible(false); >+ } >+ } >+ } > >- /** >- * Returns this user agent's CSS media. >- */ >- public String getMedia() { >- return application.getMedia(); >- } >+ /** >+ * To display the DOM viewer of the document >+ */ >+ public class DOMViewerAction extends AbstractAction { >+ >+ public DOMViewerAction() { >+ } > >- /** >- * Returns this user agent's alternate style-sheet title. >- */ >- public String getAlternateStyleSheet() { >- return alternateStyleSheet; >- } >+ public void actionPerformed(ActionEvent e) { >+ if (domViewer == null) { >+ domViewer = new DOMViewer(); >+ if (svgDocument != null) { >+ domViewer.setDocument(svgDocument, (ViewCSS) svgDocument >+ .getDocumentElement()); >+ } >+ Rectangle fr = getBounds(); >+ Dimension td = domViewer.getSize(); >+ domViewer.setLocation(fr.x + (fr.width - td.width) / 2, fr.y >+ + (fr.height - td.height) / 2); >+ } >+ domViewer.setVisible(true); >+ } >+ >+ public DOMViewer getDOMViewer() { >+ return domViewer; >+ } >+ } > >- /** >- * Opens a link. >- * @param uri The document URI. >- * @param newc Whether the link should be activated in a new component. >- */ >- public void openLink(String uri, boolean newc) { >- if (newc) { >- application.openLink(uri); >- } else { >- showSVGDocument(uri); >- } >- } >+ /** >+ * To display the Timeline viewer of the document >+ */ >+ public class TimelineViewerAction extends AbstractAction { >+ public TimelineViewerAction() { >+ } > >- /** >- * Tells whether the given extension is supported by this >- * user agent. >- */ >- public boolean supportExtension(String s) { >- return false; >- } >+ public void actionPerformed(ActionEvent e) { >+ if (timelineViewer == null) { >+ timelineViewer = new TimelineViewer(svgDocument); >+ Rectangle fr = getBounds(); >+ Dimension td = timelineViewer.getSize(); >+ timelineViewer.setLocation(fr.x + (fr.width - td.width) / 2, fr.y >+ + (fr.height - td.height) / 2); >+ } >+ timelineViewer.setVisible(true); >+ } >+ } > >- public void handleElement(Element elt, Object data){ >- } >+ // ActionMap ///////////////////////////////////////////////////// > >- /** >- * Returns the security settings for the given script >- * type, script url and document url >- * >- * @param scriptType type of script, as found in the >- * type attribute of the <script> element. >- * @param scriptURL url for the script, as defined in >- * the script's xlink:href attribute. If that >- * attribute was empty, then this parameter should >- * be null >- * @param docURL url for the document into which the >- * script was found. >- */ >- public ScriptSecurity getScriptSecurity(String scriptType, >- ParsedURL scriptURL, >- ParsedURL docURL){ >- if (!application.canLoadScriptType(scriptType)) { >- return new NoLoadScriptSecurity(scriptType); >- } else { >- switch(application.getAllowedScriptOrigin()) { >- case ResourceOrigin.ANY: >- return new RelaxedScriptSecurity(scriptType, >- scriptURL, >- docURL); >- case ResourceOrigin.DOCUMENT: >- return new DefaultScriptSecurity(scriptType, >- scriptURL, >- docURL); >- case ResourceOrigin.EMBEDED: >- return new EmbededScriptSecurity(scriptType, >- scriptURL, >- docURL); >- default: >- return new NoLoadScriptSecurity(scriptType); >- } >- } >- } >+ /** >+ * The map that contains the action listeners >+ */ >+ protected Map listeners = new HashMap(); > >- /** >- * This method throws a SecurityException if the script >- * of given type, found at url and referenced from docURL >- * should not be loaded. >- * >- * This is a convenience method to call checkLoadScript >- * on the ScriptSecurity strategy returned by >- * getScriptSecurity. >- * >- * @param scriptType type of script, as found in the >- * type attribute of the <script> element. >- * @param scriptURL url for the script, as defined in >- * the script's xlink:href attribute. If that >- * attribute was empty, then this parameter should >- * be null >- * @param docURL url for the document into which the >- * script was found. >- */ >- public void checkLoadScript(String scriptType, >- ParsedURL scriptURL, >- ParsedURL docURL) throws SecurityException { >- ScriptSecurity s = getScriptSecurity(scriptType, >- scriptURL, >- docURL); >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ Action result = (Action) listeners.get(key); >+ // if (result == null) { >+ // result = canvas.getAction(key); >+ // } >+ if (result == null) { >+ throw new MissingListenerException("Can't find action.", RESOURCES, >+ key); >+ } >+ return result; >+ } > >- if (s != null) { >- s.checkLoadScript(); >- } >- } >+ // SVGDocumentLoaderListener /////////////////////////////////////////// > >- /** >- * Returns the security settings for the given >- * resource url and document url >- * >- * @param resourceURL url for the resource, as defined in >- * the resource's xlink:href attribute. If that >- * attribute was empty, then this parameter should >- * be null >- * @param docURL url for the document into which the >- * resource was found. >- */ >- public ExternalResourceSecurity >- getExternalResourceSecurity(ParsedURL resourceURL, >- ParsedURL docURL){ >- switch(application.getAllowedExternalResourceOrigin()) { >- case ResourceOrigin.ANY: >- return new RelaxedExternalResourceSecurity(resourceURL, >- docURL); >- case ResourceOrigin.DOCUMENT: >- return new DefaultExternalResourceSecurity(resourceURL, >- docURL); >- case ResourceOrigin.EMBEDED: >- return new EmbededExternalResourceSecurity(resourceURL); >- default: >- return new NoLoadExternalResourceSecurity(); >- } >- } >+ long time; // For debug. > >- /** >- * This method throws a SecurityException if the resource >- * found at url and referenced from docURL >- * should not be loaded. >- * >- * This is a convenience method to call checkLoadExternalResource >- * on the ExternalResourceSecurity strategy returned by >- * getExternalResourceSecurity. >- * >- * @param resourceURL url for the script, as defined in >- * the resource's xlink:href attribute. If that >- * attribute was empty, then this parameter should >- * be null >- * @param docURL url for the document into which the >- * resource was found. >- */ >- public void >- checkLoadExternalResource(ParsedURL resourceURL, >- ParsedURL docURL) throws SecurityException { >- ExternalResourceSecurity s >- = getExternalResourceSecurity(resourceURL, docURL); >+ /** >+ * Called when the loading of a document was started. >+ */ >+ public void documentLoadingStarted(SVGDocumentLoaderEvent e) { >+ String msg = resources.getString("Message.documentLoad"); >+ if (debug) { >+ System.out.println(msg); >+ time = System.currentTimeMillis(); >+ } >+ statusBar.setMainMessage(msg); >+ stopAction.update(true); >+ svgCanvas.setCursor(WAIT_CURSOR); >+ } > >- if (s != null) { >- s.checkLoadExternalResource(); >- } >- } >- } >+ /** >+ * Called when the loading of a document was completed. >+ */ >+ public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { >+ if (debug) { >+ System.out.print(resources.getString("Message.documentLoadTime")); >+ System.out.println((System.currentTimeMillis() - time) + " ms"); >+ } > >- /** >- * A FileFilter used when exporting the SVG document as an image. >- */ >- protected static class ImageFileFilter extends FileFilter { >+ setSVGDocument(e.getSVGDocument(), e.getSVGDocument().getURL(), e >+ .getSVGDocument().getTitle(), e.getDocumentDescriptor()); >+ } > >- /** The extension of the image filename. */ >- protected String extension; >+ /** >+ * Forces the viewer frame to show the input SVGDocument >+ */ >+ public void setSVGDocument(SVGDocument svgDocument, String svgDocumentURL, >+ String svgDocumentTitle, DocumentDescriptor docDescriptor) { >+ this.svgDocument = svgDocument; >+ this.docDescriptor = docDescriptor; > >- public ImageFileFilter(String extension) { >- this.extension = extension; >- } >+ if (domViewer != null) { >+ if (domViewer.isVisible() && svgDocument != null) { >+ domViewer.setDocument(svgDocument, (ViewCSS) svgDocument >+ .getDocumentElement()); >+ } else { >+ domViewer.dispose(); >+ domViewer = null; >+ } >+ } >+ if (timelineViewer != null) { >+ if (timelineViewer.isVisible() && svgDocument != null) { >+// timelineViewer.setDocument(svgDocument); >+ } else { >+// timelineViewer.dispose(); >+ timelineViewer = null; >+ } >+ } >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ String s = svgDocumentURL; >+ locationBar.setText(s); >+ if (debugger != null) { >+ debugger.detach(); >+ debugger.setDocumentURL(s); >+ } >+ if (title == null) { >+ title = getTitle(); >+ } > >- /** >- * Returns true if <tt>f</tt> is a file with the correct extension, >- * false otherwise. >- */ >- public boolean accept(File f) { >- boolean accept = false; >- String fileName = null; >- if (f != null) { >- if (f.isDirectory()) { >- accept = true; >- } else { >- fileName = f.getPath().toLowerCase(); >- if (fileName.endsWith(extension)) { >- accept = true; >- } >- } >- } >- return accept; >- } >+ String dt = svgDocumentTitle; >+ if (dt.length() != 0) { >+ setTitle(title + ": " + dt); >+ } else { >+ int i = s.lastIndexOf("/"); >+ if (i == -1) >+ i = s.lastIndexOf("\\"); >+ if (i == -1) { >+ setTitle(title + ": " + s); >+ } else { >+ setTitle(title + ": " + s.substring(i + 1)); >+ } >+ } > >- /** >- * Returns the file description >- */ >- public String getDescription() { >- return extension; >- } >- } >+ localHistory.update(s); >+ application.addVisitedURI(s); >+ backAction.update(); >+ forwardAction.update(); >+ >+ transformHistory = new TransformHistory(); >+ previousTransformAction.update(); >+ nextTransformAction.update(); >+ >+ useStylesheetAction.update(); >+ } >+ >+ /** >+ * Called when the loading of a document was cancelled. >+ */ >+ public void documentLoadingCancelled(SVGDocumentLoaderEvent e) { >+ String msg = resources.getString("Message.documentCancelled"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ } >+ >+ /** >+ * Called when the loading of a document has failed. >+ */ >+ public void documentLoadingFailed(SVGDocumentLoaderEvent e) { >+ String msg = resources.getString("Message.documentFailed"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ } >+ >+ // GVTTreeBuilderListener ////////////////////////////////////////////// >+ >+ /** >+ * Called when a build started. The data of the event is initialized to the >+ * old document. >+ */ >+ public void gvtBuildStarted(GVTTreeBuilderEvent e) { >+ String msg = resources.getString("Message.treeBuild"); >+ if (debug) { >+ System.out.println(msg); >+ time = System.currentTimeMillis(); >+ } >+ statusBar.setMainMessage(msg); >+ stopAction.update(true); >+ svgCanvas.setCursor(WAIT_CURSOR); >+ } >+ >+ /** >+ * Called when a build was completed. >+ */ >+ public void gvtBuildCompleted(GVTTreeBuilderEvent e) { >+ if (debug) { >+ System.out.print(resources.getString("Message.treeBuildTime")); >+ System.out.println((System.currentTimeMillis() - time) + " ms"); >+ } >+ if (findDialog != null) { >+ if (findDialog.isVisible()) { >+ findDialog.setGraphicsNode(svgCanvas.getGraphicsNode()); >+ } else { >+ findDialog.dispose(); >+ findDialog = null; >+ } >+ } >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ svgCanvas.setSelectionOverlayXORMode(application >+ .isSelectionOverlayXORMode()); >+ svgCanvas.requestFocus(); // request focus when load completes. >+ if (debugger != null) { >+ debugger.attach(); >+ } >+ } >+ >+ /** >+ * Called when a build was cancelled. >+ */ >+ public void gvtBuildCancelled(GVTTreeBuilderEvent e) { >+ String msg = resources.getString("Message.treeCancelled"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ svgCanvas.setSelectionOverlayXORMode(application >+ .isSelectionOverlayXORMode()); >+ } >+ >+ /** >+ * Called when a build failed. >+ */ >+ public void gvtBuildFailed(GVTTreeBuilderEvent e) { >+ String msg = resources.getString("Message.treeFailed"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ stopAction.update(false); >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ svgCanvas.setSelectionOverlayXORMode(application >+ .isSelectionOverlayXORMode()); >+ if (autoAdjust) { >+ pack(); >+ } >+ } >+ >+ // SVGLoadEventDispatcherListener ////////////////////////////////////// >+ >+ /** >+ * Called when a onload event dispatch started. >+ */ >+ public void svgLoadEventDispatchStarted(SVGLoadEventDispatcherEvent e) { >+ String msg = resources.getString("Message.onload"); >+ if (debug) { >+ System.out.println(msg); >+ time = System.currentTimeMillis(); >+ } >+ stopAction.update(true); >+ statusBar.setMainMessage(msg); >+ } >+ >+ /** >+ * Called when a onload event dispatch was completed. >+ */ >+ public void svgLoadEventDispatchCompleted(SVGLoadEventDispatcherEvent e) { >+ if (debug) { >+ System.out.print(resources.getString("Message.onloadTime")); >+ System.out.println((System.currentTimeMillis() - time) + " ms"); >+ } >+ stopAction.update(false); >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(resources.getString("Message.done")); >+ } >+ >+ /** >+ * Called when a onload event dispatch was cancelled. >+ */ >+ public void svgLoadEventDispatchCancelled(SVGLoadEventDispatcherEvent e) { >+ String msg = resources.getString("Message.onloadCancelled"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ stopAction.update(false); >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ } >+ >+ /** >+ * Called when a onload event dispatch failed. >+ */ >+ public void svgLoadEventDispatchFailed(SVGLoadEventDispatcherEvent e) { >+ String msg = resources.getString("Message.onloadFailed"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ stopAction.update(false); >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ } >+ >+ // GVTTreeRendererListener ///////////////////////////////////////////// >+ >+ /** >+ * Called when a rendering is in its preparing phase. >+ */ >+ public void gvtRenderingPrepare(GVTTreeRendererEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.treeRenderingPrep"); >+ System.out.println(msg); >+ time = System.currentTimeMillis(); >+ } >+ stopAction.update(true); >+ svgCanvas.setCursor(WAIT_CURSOR); >+ statusBar.setMainMessage(resources.getString("Message.treeRendering")); >+ } >+ >+ /** >+ * Called when a rendering started. >+ */ >+ public void gvtRenderingStarted(GVTTreeRendererEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.treeRenderingPrepTime"); >+ System.out.print(msg); >+ System.out.println((System.currentTimeMillis() - time) + " ms"); >+ time = System.currentTimeMillis(); >+ msg = resources.getString("Message.treeRenderingStart"); >+ System.out.println(msg); >+ } >+ // Do nothing >+ } >+ >+ /** >+ * Called when a rendering was completed. >+ */ >+ public void gvtRenderingCompleted(GVTTreeRendererEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.treeRenderingTime"); >+ System.out.print(msg); >+ System.out.println((System.currentTimeMillis() - time) + " ms"); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(resources.getString("Message.done")); >+ if (!svgCanvas.isDynamic() || managerStopped) { >+ stopAction.update(false); >+ } >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ >+ transformHistory.update(svgCanvas.getRenderingTransform()); >+ previousTransformAction.update(); >+ nextTransformAction.update(); >+ } >+ >+ /** >+ * Called when a rendering was cancelled. >+ */ >+ public void gvtRenderingCancelled(GVTTreeRendererEvent e) { >+ String msg = resources.getString("Message.treeRenderingCancelled"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ if (!svgCanvas.isDynamic()) { >+ stopAction.update(false); >+ } >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ } >+ >+ /** >+ * Called when a rendering failed. >+ */ >+ public void gvtRenderingFailed(GVTTreeRendererEvent e) { >+ String msg = resources.getString("Message.treeRenderingFailed"); >+ if (debug) { >+ System.out.println(msg); >+ } >+ statusBar.setMainMessage(""); >+ statusBar.setMessage(msg); >+ if (!svgCanvas.isDynamic()) { >+ stopAction.update(false); >+ } >+ svgCanvas.setCursor(DEFAULT_CURSOR); >+ } >+ >+ // LinkActivationListener ///////////////////////////////////////// >+ >+ /** >+ * Called when a link was activated. >+ */ >+ public void linkActivated(LinkActivationEvent e) { >+ String s = e.getReferencedURI(); >+ if (svgDocument != null) { >+ ParsedURL docURL = new ParsedURL(svgDocument.getURL()); >+ ParsedURL url = new ParsedURL(docURL, s); >+ if (!url.sameFile(docURL)) { >+ return; >+ } >+ >+ if (s.indexOf('#') != -1) { >+ localHistory.update(s); >+ locationBar.setText(s); >+ if (debugger != null) { >+ debugger.detach(); >+ debugger.setDocumentURL(s); >+ } >+ application.addVisitedURI(s); >+ backAction.update(); >+ forwardAction.update(); >+ >+ transformHistory = new TransformHistory(); >+ previousTransformAction.update(); >+ nextTransformAction.update(); >+ } >+ } >+ } >+ >+ // UpdateManagerListener //////////////////////////////////////////////// >+ >+ /** >+ * Called when the manager was started. >+ */ >+ public void managerStarted(UpdateManagerEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.updateManagerStarted"); >+ System.out.println(msg); >+ } >+ managerStopped = false; >+ playAction.update(false); >+ pauseAction.update(true); >+ stopAction.update(true); >+ } >+ >+ /** >+ * Called when the manager was suspended. >+ */ >+ public void managerSuspended(UpdateManagerEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.updateManagerSuspended"); >+ System.out.println(msg); >+ } >+ playAction.update(true); >+ pauseAction.update(false); >+ } >+ >+ /** >+ * Called when the manager was resumed. >+ */ >+ public void managerResumed(UpdateManagerEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.updateManagerResumed"); >+ System.out.println(msg); >+ } >+ playAction.update(false); >+ pauseAction.update(true); >+ } >+ >+ /** >+ * Called when the manager was stopped. >+ */ >+ public void managerStopped(UpdateManagerEvent e) { >+ if (debug) { >+ String msg = resources.getString("Message.updateManagerStopped"); >+ System.out.println(msg); >+ } >+ managerStopped = true; >+ playAction.update(false); >+ pauseAction.update(false); >+ stopAction.update(false); >+ } >+ >+ /** >+ * Called when an update started. >+ */ >+ public void updateStarted(final UpdateManagerEvent e) { >+ } >+ >+ /** >+ * Called when an update was completed. >+ */ >+ public void updateCompleted(final UpdateManagerEvent e) { >+ } >+ >+ /** >+ * Called when an update failed. >+ */ >+ public void updateFailed(UpdateManagerEvent e) { >+ } >+ >+ /** >+ * This class implements a SVG user agent. >+ */ >+ protected class UserAgent implements SVGUserAgent { >+ >+ /** >+ * Creates a new SVGUserAgent. >+ */ >+ protected UserAgent() { >+ } >+ >+ /** >+ * Displays an error message. >+ */ >+ public void displayError(String message) { >+ if (debug) { >+ System.err.println(message); >+ } >+ JOptionPane pane = new JOptionPane(message, >+ JOptionPane.ERROR_MESSAGE); >+ JDialog dialog = pane.createDialog(JSVGViewerFrame.this, "ERROR"); >+ dialog.setModal(false); >+ dialog.setVisible(true); >+ } >+ >+ /** >+ * Displays an error resulting from the specified Exception. >+ */ >+ public void displayError(Exception ex) { >+ if (debug) { >+ ex.printStackTrace(); >+ } >+ // JErrorPane pane = >+ // new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ if (ex instanceof LiveAttributeException) { >+ LiveAttributeException lex = (LiveAttributeException) ex; >+ ParsedURL purl = new ParsedURL(svgDocument.getURL()); >+ InputStream is = null; >+ try { >+ is = purl.openStream(getInputHandler(purl) >+ .getHandledMimeTypes()); >+ } catch (IOException e) { >+ e.printStackTrace(); >+ // do nothing, error console will report stream not >+ // available >+ } >+ AttributeErrorInfo info = new AttributeErrorInfo(lex, svgDocument >+ .getDocumentURI(), ErrorConsole.ERROR, is, lex >+ .getElement(), docDescriptor, >+ (ViewSourceAction) listeners.get(VIEW_SOURCE_ACTION), >+ (DOMViewerAction) listeners.get(DOM_VIEWER_ACTION)); >+ console.add(info); >+ } else { >+ String uri; >+ if (svgDocument == null) { >+ uri = currentPath.getAbsolutePath(); >+ } else { >+ uri = svgDocument.getDocumentURI(); >+ } >+ ErrorInfo info = new ErrorInfo(ex, >+ uri, ErrorConsole.ERROR); >+ console.add(info); >+ } >+ ErrorConsole.showDialog(JSVGViewerFrame.this); >+ } >+ >+ /** >+ * Displays a message in the User Agent interface. The given message is >+ * typically displayed in a status bar. >+ */ >+ public void displayMessage(String message) { >+ statusBar.setMessage(message); >+ } >+ >+ /** >+ * Shows an alert dialog box. >+ */ >+ public void showAlert(String message) { >+ svgCanvas.showAlert(message); >+ } >+ >+ /** >+ * Shows a prompt dialog box. >+ */ >+ public String showPrompt(String message) { >+ return svgCanvas.showPrompt(message); >+ } >+ >+ /** >+ * Shows a prompt dialog box. >+ */ >+ public String showPrompt(String message, String defaultValue) { >+ return svgCanvas.showPrompt(message, defaultValue); >+ } >+ >+ /** >+ * Shows a confirm dialog box. >+ */ >+ public boolean showConfirm(String message) { >+ return svgCanvas.showConfirm(message); >+ } >+ >+ /** >+ * Returns the size of a px CSS unit in millimeters. >+ */ >+ public float getPixelUnitToMillimeter() { >+ return 0.26458333333333333333333333333333f; // 96dpi >+ } >+ >+ /** >+ * Returns the size of a px CSS unit in millimeters. This will be >+ * removed after next release. >+ * >+ * @see #getPixelUnitToMillimeter() >+ */ >+ public float getPixelToMM() { >+ return getPixelUnitToMillimeter(); >+ >+ } >+ >+ /** >+ * Returns the default font family. >+ */ >+ public String getDefaultFontFamily() { >+ return application.getDefaultFontFamily(); >+ } >+ >+ /** >+ * Returns the medium font size. >+ */ >+ public float getMediumFontSize() { >+ // 9pt (72pt == 1in) >+ return 9f * 25.4f / (72f * getPixelUnitToMillimeter()); >+ } >+ >+ /** >+ * Returns a lighter font-weight. >+ */ >+ public float getLighterFontWeight(float f) { >+ // Round f to nearest 100... >+ int weight = ((int) ((f + 50) / 100)) * 100; >+ switch (weight) { >+ case 100: >+ return 100; >+ case 200: >+ return 100; >+ case 300: >+ return 200; >+ case 400: >+ return 300; >+ case 500: >+ return 400; >+ case 600: >+ return 400; >+ case 700: >+ return 400; >+ case 800: >+ return 400; >+ case 900: >+ return 400; >+ default: >+ throw new IllegalArgumentException("Bad Font Weight: " + f); >+ } >+ } >+ >+ /** >+ * Returns a bolder font-weight. >+ */ >+ public float getBolderFontWeight(float f) { >+ // Round f to nearest 100... >+ int weight = ((int) ((f + 50) / 100)) * 100; >+ switch (weight) { >+ case 100: >+ return 600; >+ case 200: >+ return 600; >+ case 300: >+ return 600; >+ case 400: >+ return 600; >+ case 500: >+ return 600; >+ case 600: >+ return 700; >+ case 700: >+ return 800; >+ case 800: >+ return 900; >+ case 900: >+ return 900; >+ default: >+ throw new IllegalArgumentException("Bad Font Weight: " + f); >+ } >+ } >+ >+ /** >+ * Returns the language settings. >+ */ >+ public String getLanguages() { >+ return application.getLanguages(); >+ } >+ >+ /** >+ * Returns the user stylesheet uri. >+ * >+ * @return null if no user style sheet was specified. >+ */ >+ public String getUserStyleSheetURI() { >+ return application.getUserStyleSheetURI(); >+ } >+ >+ /** >+ * Returns the class name of the XML parser. >+ */ >+ public String getXMLParserClassName() { >+ return application.getXMLParserClassName(); >+ } >+ >+ /** >+ * Returns true if the XML parser must be in validation mode, false >+ * otherwise. >+ */ >+ public boolean isXMLParserValidating() { >+ return application.isXMLParserValidating(); >+ } >+ >+ /** >+ * Returns this user agent's CSS media. >+ */ >+ public String getMedia() { >+ return application.getMedia(); >+ } >+ >+ /** >+ * Returns this user agent's alternate style-sheet title. >+ */ >+ public String getAlternateStyleSheet() { >+ return alternateStyleSheet; >+ } >+ >+ /** >+ * Opens a link. >+ * >+ * @param uri >+ * The document URI. >+ * @param newc >+ * Whether the link should be activated in a new component. >+ */ >+ public void openLink(String uri, boolean newc) { >+ if (newc) { >+ application.openLink(uri); >+ } else { >+ showSVGDocument(uri); >+ } >+ } >+ >+ /** >+ * Tells whether the given extension is supported by this user agent. >+ */ >+ public boolean supportExtension(String s) { >+ return false; >+ } >+ >+ public void handleElement(Element elt, Object data) { >+ } >+ >+ /** >+ * Returns the security settings for the given script type, script url >+ * and document url >+ * >+ * @param scriptType >+ * type of script, as found in the type attribute of the >+ * <script> element. >+ * @param scriptURL >+ * url for the script, as defined in the script's xlink:href >+ * attribute. If that attribute was empty, then this >+ * parameter should be null >+ * @param docURL >+ * url for the document into which the script was found. >+ */ >+ public ScriptSecurity getScriptSecurity(String scriptType, >+ ParsedURL scriptURL, ParsedURL docURL) { >+ if (!application.canLoadScriptType(scriptType)) { >+ return new NoLoadScriptSecurity(scriptType); >+ } else { >+ switch (application.getAllowedScriptOrigin()) { >+ case ResourceOrigin.ANY: >+ return new RelaxedScriptSecurity(scriptType, scriptURL, >+ docURL); >+ case ResourceOrigin.DOCUMENT: >+ return new DefaultScriptSecurity(scriptType, scriptURL, >+ docURL); >+ case ResourceOrigin.EMBEDED: >+ return new EmbededScriptSecurity(scriptType, scriptURL, >+ docURL); >+ default: >+ return new NoLoadScriptSecurity(scriptType); >+ } >+ } >+ } >+ >+ /** >+ * This method throws a SecurityException if the script of given type, >+ * found at url and referenced from docURL should not be loaded. >+ * >+ * This is a convenience method to call checkLoadScript on the >+ * ScriptSecurity strategy returned by getScriptSecurity. >+ * >+ * @param scriptType >+ * type of script, as found in the type attribute of the >+ * <script> element. >+ * @param scriptURL >+ * url for the script, as defined in the script's xlink:href >+ * attribute. If that attribute was empty, then this >+ * parameter should be null >+ * @param docURL >+ * url for the document into which the script was found. >+ */ >+ public void checkLoadScript(String scriptType, ParsedURL scriptURL, >+ ParsedURL docURL) throws SecurityException { >+ ScriptSecurity s = getScriptSecurity(scriptType, scriptURL, docURL); >+ >+ if (s != null) { >+ s.checkLoadScript(); >+ } >+ } >+ >+ /** >+ * Returns the security settings for the given resource url and document >+ * url >+ * >+ * @param resourceURL >+ * url for the resource, as defined in the resource's >+ * xlink:href attribute. If that attribute was empty, then >+ * this parameter should be null >+ * @param docURL >+ * url for the document into which the resource was found. >+ */ >+ public ExternalResourceSecurity getExternalResourceSecurity( >+ ParsedURL resourceURL, ParsedURL docURL) { >+ switch (application.getAllowedExternalResourceOrigin()) { >+ case ResourceOrigin.ANY: >+ return new RelaxedExternalResourceSecurity(resourceURL, docURL); >+ case ResourceOrigin.DOCUMENT: >+ return new DefaultExternalResourceSecurity(resourceURL, docURL); >+ case ResourceOrigin.EMBEDED: >+ return new EmbededExternalResourceSecurity(resourceURL); >+ default: >+ return new NoLoadExternalResourceSecurity(); >+ } >+ } >+ >+ /** >+ * This method throws a SecurityException if the resource found at url >+ * and referenced from docURL should not be loaded. >+ * >+ * This is a convenience method to call checkLoadExternalResource on the >+ * ExternalResourceSecurity strategy returned by >+ * getExternalResourceSecurity. >+ * >+ * @param resourceURL >+ * url for the script, as defined in the resource's >+ * xlink:href attribute. If that attribute was empty, then >+ * this parameter should be null >+ * @param docURL >+ * url for the document into which the resource was found. >+ */ >+ public void checkLoadExternalResource(ParsedURL resourceURL, >+ ParsedURL docURL) throws SecurityException { >+ ExternalResourceSecurity s = getExternalResourceSecurity( >+ resourceURL, docURL); >+ >+ if (s != null) { >+ s.checkLoadExternalResource(); >+ } >+ } >+ } >+ >+ /** >+ * A FileFilter used when exporting the SVG document as an image. >+ */ >+ protected static class ImageFileFilter extends FileFilter { >+ >+ /** The extension of the image filename. */ >+ protected String extension; >+ >+ public ImageFileFilter(String extension) { >+ this.extension = extension; >+ } >+ >+ /** >+ * Returns true if <tt>f</tt> is a file with the correct extension, >+ * false otherwise. >+ */ >+ public boolean accept(File f) { >+ boolean accept = false; >+ String fileName = null; >+ if (f != null) { >+ if (f.isDirectory()) { >+ accept = true; >+ } else { >+ fileName = f.getPath().toLowerCase(); >+ if (fileName.endsWith(extension)) { >+ accept = true; >+ } >+ } >+ } >+ return accept; >+ } >+ >+ /** >+ * Returns the file description >+ */ >+ public String getDescription() { >+ return extension; >+ } >+ } > } >Index: sources/org/apache/batik/apps/svgbrowser/XMLInputHandler.java >=================================================================== >--- sources/org/apache/batik/apps/svgbrowser/XMLInputHandler.java (revision 549415) >+++ sources/org/apache/batik/apps/svgbrowser/XMLInputHandler.java (working copy) >@@ -213,7 +213,7 @@ > sw.close(); > > String parser = XMLResourceDescriptor.getXMLParserClassName(); >- SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); >+ SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser, true); > SVGDocument outDoc = null; > > try { >@@ -234,7 +234,8 @@ > svgViewerFrame.getJSVGCanvas().setSVGDocument(outDoc); > svgViewerFrame.setSVGDocument(outDoc, > uri, >- outDoc.getTitle()); >+ outDoc.getTitle(), >+ f.getDocumentDescriptor()); > } > > /** >Index: sources/org/apache/batik/util/gui/DOMViewer.java >=================================================================== >--- sources/org/apache/batik/util/gui/DOMViewer.java (revision 549415) >+++ sources/org/apache/batik/util/gui/DOMViewer.java (working copy) >@@ -24,9 +24,9 @@ > import java.awt.event.ActionEvent; > import java.awt.event.ItemEvent; > import java.awt.event.ItemListener; >- > import java.util.ArrayList; > import java.util.Collections; >+import java.util.Enumeration; > import java.util.HashMap; > import java.util.Locale; > import java.util.Map; >@@ -52,6 +52,7 @@ > import javax.swing.tree.DefaultTreeModel; > import javax.swing.tree.MutableTreeNode; > import javax.swing.tree.TreeNode; >+import javax.swing.tree.TreePath; > > import org.apache.batik.bridge.svg12.ContentManager; > import org.apache.batik.bridge.svg12.DefaultXBLManager; >@@ -170,6 +171,20 @@ > } > > /** >+ * Sets the node to be selected, none if node is null >+ */ >+ public void setSelectionNode(Node node) { >+ panel.setSelectionNode(node); >+ } >+ >+ /** >+ * Sets the nodes to be selected, none if nodes is null >+ */ >+ public void setSelectionNodes(Node[] nodes) { >+ panel.setSelectionNodes(nodes); >+ } >+ >+ /** > * Returns the action associated with the given string > * or null on error > * @param key the key mapped with the action to get >@@ -412,6 +427,47 @@ > return result; > } > >+ public void setSelectionNode(Node node) { >+ if (node == null) { >+ setSelectionNodes(null); >+ } else { >+ setSelectionNodes(new Node[]{node}); >+ } >+ } >+ >+ public void setSelectionNodes(Node[] nodes) { >+ tree.setSelectionRow(-1); >+ if (nodes == null) { >+ return; >+ } >+ for (int i = 0; i < nodes.length; i++) { >+ DefaultMutableTreeNode treeNode = findNode(tree, nodes[i]); >+ if (treeNode != null) { >+ TreePath path = new TreePath(treeNode.getPath()); >+ tree.setSelectionPath(path); >+ } >+ } >+ } >+ >+ /** >+ * Returns the node in the tree that represents the given node in the >+ * document, or null if not found. >+ */ >+ protected DefaultMutableTreeNode findNode(JTree theTree, Node node) { >+ DefaultMutableTreeNode root = (DefaultMutableTreeNode) theTree >+ .getModel().getRoot(); >+ Enumeration treeNodes = root.breadthFirstEnumeration(); >+ while (treeNodes.hasMoreElements()) { >+ DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) treeNodes >+ .nextElement(); >+ NodeInfo userObject = (NodeInfo) currentNode.getUserObject(); >+ if (userObject.getNode() == node) { >+ return currentNode; >+ } >+ } >+ return null; >+ } >+ > /** > * To listen to the tree selection. > */ >Index: sources/org/apache/batik/util/gui/Timeline.java >=================================================================== >--- sources/org/apache/batik/util/gui/Timeline.java (revision 0) >+++ sources/org/apache/batik/util/gui/Timeline.java (revision 0) >@@ -0,0 +1,447 @@ >+/* >+ >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+ >+ */ >+package org.apache.batik.util.gui; >+ >+import java.awt.BasicStroke; >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Dimension; >+import java.awt.Font; >+import java.awt.FontMetrics; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.GridBagConstraints; >+import java.awt.GridBagLayout; >+import java.awt.Insets; >+import java.awt.Polygon; >+import java.awt.Rectangle; >+import java.awt.Stroke; >+import java.awt.event.ActionEvent; >+import java.awt.event.AdjustmentEvent; >+import java.awt.event.AdjustmentListener; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+import java.awt.event.MouseMotionAdapter; >+import java.awt.event.MouseMotionListener; >+import java.util.HashMap; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.JButton; >+import javax.swing.JComponent; >+import javax.swing.JLabel; >+import javax.swing.JPanel; >+import javax.swing.JPopupMenu; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.border.BevelBorder; >+ >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.ButtonFactory; >+import org.apache.batik.util.gui.resource.JMiniSlider; >+import org.apache.batik.util.gui.resource.MenuFactory; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+ >+ >+public class Timeline extends JPanel implements ActionMap { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resources.TimelineViewer"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The button factory. >+ */ >+ protected ButtonFactory bf = new ButtonFactory(bundle, this); >+ >+ /** >+ * The menu factory. >+ */ >+ protected MenuFactory mf = new MenuFactory(bundle, this); >+ >+ private static final String DEFAULT_HOVER_LABEL = "--:--:--"; >+ >+ private int pitch_milliUnits = 100; >+ >+ private int pixelsPerUnit = 50; >+ >+ private float value = 1; >+ >+ private int knobPosition; >+ >+ private int hoverTime; >+ >+ private TimelineSlider sliderPanel; >+ >+ private JPopupMenu cornerPopup; >+ >+ private JLabel timerLabel; >+ >+ public Timeline() { >+ super(new GridBagLayout()); >+ >+ actions.put("CornerButtonAction", new CornerButtonAction()); >+ actions.put("IncreaseUnitSizeMenuItemAction", >+ new IncreaseUnitSizeMenuItemAction()); >+ actions.put("DecreaseUnitSizeMenuItemAction", >+ new DecreaseUnitSizeMenuItemAction()); >+ >+ GridBagConstraints gc; >+ >+ sliderPanel = new TimelineSlider(); >+ gc = new GridBagConstraints(); >+ gc.gridx = 0; >+ gc.gridy = 0; >+ gc.weightx = 1.0; >+ gc.fill = GridBagConstraints.HORIZONTAL; >+ add(sliderPanel, gc); >+ >+ JButton cornerButton = bf.createJButton("CornerButton"); >+ cornerButton.setFocusable(false); >+ cornerButton.setPreferredSize(new Dimension(0, 0)); >+ cornerPopup = new JPopupMenu(); >+ cornerPopup.add(mf.createJMenuItem("IncreaseUnitSizeMenuItem")); >+ cornerPopup.add(mf.createJMenuItem("DecreaseUnitSizeMenuItem")); >+ gc = new GridBagConstraints(); >+ gc.gridx = 1; >+ gc.gridy = 0; >+ gc.fill = GridBagConstraints.BOTH; >+ add(cornerButton, gc); >+ >+ JScrollPane framesScrollPane = new JScrollPane( >+ new TimelinePanel()); >+ framesScrollPane.setBorder(null); >+ framesScrollPane >+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); >+ framesScrollPane >+ .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); >+ gc = new GridBagConstraints(); >+ gc.gridx = 0; >+ gc.gridy = 1; >+ gc.weightx = 1.0; >+ gc.weighty = 1.0; >+ gc.fill = GridBagConstraints.BOTH; >+ add(framesScrollPane, gc); >+ >+ JPanel footerPanel = new JPanel(new GridBagLayout()); >+ JMiniSlider zoomSlider = new JMiniSlider(1, 10); >+ gc = new GridBagConstraints(); >+ gc.gridy = 0; >+ gc.insets = new Insets(0, 2, 0, 2); >+ footerPanel.add(zoomSlider, gc); >+ >+ timerLabel = new JLabel(DEFAULT_HOVER_LABEL); >+ timerLabel.setFont(new Font("Monospaced", Font.PLAIN, 12)); >+ gc = new GridBagConstraints(); >+ gc.gridy = 0; >+ gc.insets = new Insets(0, 2, 0, 2); >+ footerPanel.add(timerLabel, gc); >+ >+ JScrollBar horizScrollBar = new JScrollBar(JScrollBar.HORIZONTAL); >+ gc = new GridBagConstraints(); >+ gc.gridy = 0; >+ gc.weightx = 1.0; >+ gc.fill = GridBagConstraints.HORIZONTAL; >+ gc.insets = new Insets(0, 2, 0, 0); >+ footerPanel.add(horizScrollBar, gc); >+ >+ int prefHeight = horizScrollBar.getPreferredSize().height; >+ footerPanel >+ .setMaximumSize(new Dimension(Integer.MAX_VALUE, prefHeight)); >+ footerPanel.setMinimumSize(new Dimension(0, prefHeight)); >+ footerPanel.setPreferredSize(footerPanel.getMinimumSize()); >+ >+ gc = new GridBagConstraints(); >+ gc.gridx = 0; >+ gc.gridy = 2; >+ gc.weightx = 1.0; >+ gc.fill = GridBagConstraints.HORIZONTAL; >+ add(footerPanel, gc); >+ } >+ >+ public void setVerticalScrollBar(JScrollBar verticalScrollBar) { >+ GridBagConstraints gc = new GridBagConstraints(); >+ gc.gridx = 1; >+ gc.gridy = 1; >+ gc.weighty = 1.0; >+ gc.fill = GridBagConstraints.VERTICAL; >+ add(verticalScrollBar, gc); >+ verticalScrollBar.addAdjustmentListener(new AdjustmentListener() { >+ public void adjustmentValueChanged(AdjustmentEvent e) { >+ >+ } >+ }); >+ } >+ >+ public int getHoverTime() { >+ return hoverTime; >+ } >+ >+ public void setHoverTime(int time) { >+ if (time < 0) { >+ timerLabel.setText(DEFAULT_HOVER_LABEL); >+ return; >+ } >+ this.hoverTime = time; >+ int subSeconds = time % 100; >+ time /= 100; >+ int seconds = time % 60; >+ time /= 60; >+ int minutes = time % 60; >+ timerLabel.setText(String.format("%2d:%2d:%2d", minutes, seconds, subSeconds)); >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ protected class CornerButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component invoker = (Component) evt.getSource(); >+ cornerPopup.show(invoker, 0, invoker.getHeight()); >+ } >+ } >+ >+ protected class IncreaseUnitSizeMenuItemAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ // TODO: >+ // Increase unit size in timeline slider >+ } >+ } >+ >+ protected class DecreaseUnitSizeMenuItemAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ // TODO: >+ // Decrease unit size in timeline slider >+ } >+ } >+ >+ public void paint(Graphics g) { >+ knobPosition = (int) (value * pixelsPerUnit) + SLIDER_X_OFFSET; >+ >+ super.paint(g); >+ } >+ >+ public static final int SLIDER_X_OFFSET = 10; >+ >+ private static final Color SLIDER_KNOB_FILL_COLOR = new Color(0x77FF7777, >+ true); >+ >+ private static final Color SLIDER_KNOB_STROKE_COLOR = new Color(0x00FF0000); >+ >+ private static final Stroke SLIDER_KNOB_STROKE = new BasicStroke(1, >+ BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 5.0f, >+ new float[] { 5.0f }, 0.0f); >+ >+ private class TimelineSlider extends JComponent { >+ >+ private boolean paintTrack = false; >+ >+ private Polygon knob; >+ >+ private Rectangle knobBounds; >+ >+ private boolean over; >+ >+ private MouseMotionListener mml = new MouseMotionAdapter() { >+ public void mouseMoved(MouseEvent e) { >+ int x = e.getX(), y = e.getY(); >+ boolean b = knobBounds.contains(x, y); >+ over = b; >+ } >+ >+ public void mouseDragged(MouseEvent e) { >+ if (over) { >+ int x = e.getX(); >+ if (x >= SLIDER_X_OFFSET) { >+ value = (float) (x - SLIDER_X_OFFSET) / pixelsPerUnit; >+ Timeline.this.repaint(); >+ } >+ } >+ } >+ }; >+ >+ public TimelineSlider() { >+ int height = 30; >+ >+ setMaximumSize(new Dimension(Integer.MAX_VALUE, height)); >+ setMinimumSize(new Dimension(0, height)); >+ setPreferredSize(getMinimumSize()); >+ setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); >+ addMouseMotionListener(mml); >+ >+ int pos = height / 2 - 3; >+ knob = new Polygon(); >+ knob.addPoint(-4, -pos); >+ knob.addPoint(4, -pos); >+ knob.addPoint(4, pos); >+ knob.addPoint(-4, pos); >+ knob.addPoint(-4, -pos); >+ >+ knobBounds = new Rectangle(6, height); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ super.paintComponent(g); >+ >+ Dimension size = getSize(); >+ if (paintTrack) { >+ int pos = size.height / 2; >+ g.setColor(Color.gray); >+ g.fillRect(0, pos - 1, size.width, 2); >+ g.setColor(Color.white); >+ g.drawLine(0, pos + 1, size.width, pos + 1); >+ } >+ >+ int dx = pixelsPerUnit * pitch_milliUnits / 1000; >+ FontMetrics fm = g.getFontMetrics(); >+ int timeUnit = 0; >+ for (int i = SLIDER_X_OFFSET; i < size.width; i += pixelsPerUnit) { >+ String str = timeUnit++ + ""; >+ int strWidth = fm.stringWidth(str), strHeight = fm.getHeight() >+ - fm.getDescent(); >+ g.setColor(getBackground()); >+ g.fillRect(i - strWidth / 2, (size.height - strHeight) / 2, >+ strWidth, strHeight); >+ g.setColor(Color.black); >+ g.drawString(str, i - strWidth / 2, >+ (size.height + strHeight) / 2); >+ g.setColor(Color.gray); >+ g.drawLine(i, size.height - 2, i, size.height - 7); >+ g.drawLine(i, 2, i, 7); >+ g.setColor(Color.lightGray); >+ for (int j = i + dx; j < i + pixelsPerUnit; j += dx) { >+ g.drawLine(j, size.height - 2, j, size.height - 5); >+ g.drawLine(j, 2, j, 5); >+ } >+ } >+ >+ // Paint knob >+ int x = knobPosition; >+ int y = size.height / 2; >+ knobBounds.x = x - knobBounds.width / 2; >+ knobBounds.y = y - knobBounds.height / 2; >+ >+ g.translate(x, y); >+ g.setColor(SLIDER_KNOB_FILL_COLOR); >+ g.fillPolygon(knob); >+ g.setColor(SLIDER_KNOB_STROKE_COLOR); >+ g.drawPolygon(knob); >+ g.translate(-x, -y); >+ } >+ } >+ >+ private class TimelinePanel extends JPanel { >+ >+ private boolean inside; >+ >+ private int hoverPosition; >+ >+ private MouseListener ml = new MouseAdapter() { >+ public void mouseEntered(MouseEvent e) { >+ inside = true; >+ Timeline.this.repaint(); >+ } >+ >+ public void mouseExited(MouseEvent e) { >+ inside = false; >+ setHoverTime(-1); >+ Timeline.this.repaint(); >+ } >+ }; >+ >+ private MouseMotionListener mml = new MouseMotionAdapter() { >+ public void mouseMoved(MouseEvent e) { >+ int x = e.getX() - SLIDER_X_OFFSET; >+ if (x >= 0) { >+ int dx = pixelsPerUnit * pitch_milliUnits / 1000; >+ x -= x % dx; >+ setHoverTime(x * 100 / pixelsPerUnit); >+ hoverPosition = SLIDER_X_OFFSET + x; >+ Timeline.this.repaint(); >+ } >+ } >+ }; >+ >+ public TimelinePanel() { >+ addMouseListener(ml); >+ addMouseMotionListener(mml); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ Dimension size = getSize(); >+ >+ int dx = pixelsPerUnit * pitch_milliUnits / 1000; >+ g.setColor(Color.lightGray); >+ for (int i = SLIDER_X_OFFSET; i < size.width; i += dx) { >+ g.drawLine(i, 0, i, size.height); >+ } >+ >+ g.setColor(SLIDER_KNOB_STROKE_COLOR); >+ g.drawLine(knobPosition, 0, knobPosition, size.height); >+ >+ if (inside) { >+ Graphics2D g2 = (Graphics2D)g; >+ g2.setStroke(SLIDER_KNOB_STROKE); >+ >+ g2.drawLine(hoverPosition, 0, hoverPosition, size.height); >+ } >+ } >+ } >+} >Index: sources/org/apache/batik/util/gui/resource/ButtonFactory.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/ButtonFactory.java (revision 549415) >+++ sources/org/apache/batik/util/gui/resource/ButtonFactory.java (working copy) >@@ -28,6 +28,7 @@ > import javax.swing.JButton; > import javax.swing.JCheckBox; > import javax.swing.JRadioButton; >+import javax.swing.JToggleButton; > > /** > * This class represents a button factory which builds >@@ -123,6 +124,31 @@ > } > > /** >+ * Creates and returns a new swing button initialised >+ * to be used as a toolbar toggle button >+ * @param name the name of the button in the resource bundle >+ * @throws MissingResourceException if key is not the name of a button. >+ * It is not thrown if the mnemonic and the action keys are missing >+ * @throws ResourceFormatException if the mnemonic is not a single >+ * character >+ * @throws MissingListenerException if the button action is not found in >+ * the action map >+ */ >+ public JToggleButton createJToolbarToggleButton(String name) >+ throws MissingResourceException, >+ ResourceFormatException, >+ MissingListenerException { >+ JToggleButton result; >+ try { >+ result = new JToolbarToggleButton(getString(name+TEXT_SUFFIX)); >+ } catch (MissingResourceException e) { >+ result = new JToolbarToggleButton(); >+ } >+ initializeButton(result, name); >+ return result; >+ } >+ >+ /** > * Creates and returns a new swing radio button > * @param name the name of the button in the resource bundle > * @throws MissingResourceException if key is not the name of a button. >Index: sources/org/apache/batik/util/gui/resource/Banner.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/Banner.java (revision 0) >+++ sources/org/apache/batik/util/gui/resource/Banner.java (revision 0) >@@ -0,0 +1,163 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.BorderLayout; >+import java.awt.Container; >+import java.awt.Dimension; >+import java.awt.SystemColor; >+import java.awt.event.ActionEvent; >+import java.awt.event.ActionListener; >+import java.util.Locale; >+import java.util.ResourceBundle; >+ >+import javax.swing.BorderFactory; >+import javax.swing.Icon; >+import javax.swing.ImageIcon; >+import javax.swing.JButton; >+import javax.swing.JFrame; >+import javax.swing.JLabel; >+import javax.swing.JPanel; >+import javax.swing.UIManager; >+ >+public class Banner extends JPanel { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.GUIUtils"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ private String text; >+ >+ private JLabel label; >+ >+ private JButton close; >+ >+ public Banner() { >+ super(new BorderLayout()); >+ setBackground(UIManager.getColor("ToolTip.background")); >+ setBorder(BorderFactory.createCompoundBorder(BorderFactory >+ .createMatteBorder(1, 0, 1, 0, SystemColor.controlShadow), >+ BorderFactory.createEmptyBorder(2, 2, 2, 2))); >+ setVisible(false); >+ label = new JLabel(); >+ add(label, BorderLayout.WEST); >+ close = new JButton(new ImageIcon(getClass().getResource( >+ resources.getString("Banner.CloseButton.icon")))); >+ close.setToolTipText(resources.getString("Banner.CloseButton.tooltip")); >+ close.setPreferredSize(new Dimension(16, 16)); >+ close.addActionListener(new ActionListener() { >+ public void actionPerformed(ActionEvent e) { >+ hideMessage(); >+ } >+ }); >+ add(close, BorderLayout.EAST); >+ } >+ >+ public synchronized void showMessage(final String text) { >+ System.out.println("show"); >+ showMessage(text, null); >+ } >+ >+ public synchronized void showMessage(final String text, final Icon icon) { >+ if (text == null) { >+ hideMessage(); >+ } >+ Banner.this.text = text; >+ new Thread() { >+ public void run() { >+ synchronized (Banner.this) { >+ if (Banner.this.text == null) { >+ return; >+ } >+ label.setText(Banner.this.text); >+ Dimension dim = getPreferredSize(); >+ Dimension newDim = new Dimension(dim.width, 0); >+ setPreferredSize(newDim); >+ setVisible(true); >+ for (int i = 1; i <= 100; i++) { >+ try { >+ Thread.sleep(10); >+ } catch (InterruptedException e) { >+ } >+ newDim.height = i * dim.height / 100; >+ setPreferredSize(newDim); >+ revalidate(); >+ } >+ } >+ } >+ }.start(); >+ } >+ >+ public synchronized void hideMessage() { >+ System.out.println("hide"); >+ if (text == null) { >+ return; >+ } >+ text = null; >+ new Thread() { >+ public void run() { >+ synchronized (Banner.this) { >+ if (text != null) { >+ return; >+ } >+ Dimension dim = getPreferredSize(); >+ Dimension newDim = new Dimension(dim.width, dim.height); >+ setPreferredSize(newDim); >+ for (int i = 99; i >= 0; i--) { >+ try { >+ Thread.sleep(10); >+ } catch (InterruptedException e) { >+ } >+ newDim.height = i * dim.height / 100; >+ setPreferredSize(newDim); >+ revalidate(); >+ } >+ label.setText(""); >+ label.setIcon(null); >+ setVisible(false); >+ setPreferredSize(dim); >+ } >+ } >+ }.start(); >+ } >+ >+ public static void main(String[] args) { >+ try { >+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ } >+ JFrame frame = new JFrame("Banner Test"); >+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); >+ >+ Container c = frame.getContentPane(); >+ c.setPreferredSize(new Dimension(400, 200)); >+ >+ Banner banner = new Banner(); >+ c.add(banner, BorderLayout.NORTH); >+ >+ frame.pack(); >+ frame.setLocationRelativeTo(null); >+ frame.setVisible(true); >+ banner.showMessage("Hello, World!"); >+ try { >+ Thread.sleep(3000); >+ } catch (InterruptedException e) { >+ } >+ banner.hideMessage(); >+ } >+} >\ No newline at end of file >Index: sources/org/apache/batik/util/gui/resource/Hyperlink.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/Hyperlink.java (revision 0) >+++ sources/org/apache/batik/util/gui/resource/Hyperlink.java (revision 0) >@@ -0,0 +1,72 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.Cursor; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+ >+import javax.swing.JLabel; >+ >+public class Hyperlink extends JLabel { >+ private MouseListener ml = new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ if (callback != null) { >+ callback.linkClicked(new HyperlinkEvent(Hyperlink.this.getCommand())); >+ } >+ } >+ }; >+ >+ private HyperlinkCallback callback; >+ >+ private String command; >+ >+ private static final String HTML_TEXT = "<html><font color=\"blue\"><u>__HTML_TEXT__</u></font></html>"; >+ >+ private String text; >+ >+ public Hyperlink(String text, HyperlinkCallback callback) { >+ this.callback = callback; >+ setLinkText(text); >+ setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); >+ addMouseListener(ml); >+ } >+ >+ public String getLinkText() { >+ return text; >+ } >+ >+ public void setLinkText(String text) { >+ this.text = text; >+ super.setText(HTML_TEXT.replace("__HTML_TEXT__", text)); >+ } >+ >+ public String getCommand() { >+ return command; >+ } >+ >+ public void setCommand(String command) { >+ this.command = command; >+ } >+ >+ public static class HyperlinkEvent { >+ >+ private String command; >+ >+ public HyperlinkEvent(String command) { >+ this.command = command; >+ } >+ >+ public String getCommand() { >+ return command; >+ } >+ >+ public void setCommand(String command) { >+ this.command = command; >+ } >+ } >+ >+ public static interface HyperlinkCallback { >+ public void linkClicked(HyperlinkEvent e); >+ } >+} >+ >Index: sources/org/apache/batik/util/gui/resource/Throbber.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/Throbber.java (revision 0) >+++ sources/org/apache/batik/util/gui/resource/Throbber.java (revision 0) >@@ -0,0 +1,95 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.Font; >+import java.awt.image.BufferedImage; >+import java.io.IOException; >+import java.util.Locale; >+import java.util.ResourceBundle; >+import java.util.Timer; >+import java.util.TimerTask; >+ >+import javax.imageio.ImageIO; >+import javax.swing.ImageIcon; >+import javax.swing.JLabel; >+import javax.swing.SwingConstants; >+ >+ >+public class Throbber extends JLabel { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.GUIUtils"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ private ImageIcon[] tiles; >+ >+ private Timer timer; >+ >+ private int currentTileIndex; >+ >+ public Throbber() { >+ setOpaque(false); >+ setText(resources.getString("Throbber.text")); >+ setHorizontalAlignment(SwingConstants.CENTER); >+ setVerticalAlignment(SwingConstants.CENTER); >+ setFont(new Font("Sans Serif", Font.PLAIN, 12)); >+ >+ BufferedImage image; >+ try { >+ image = ImageIO.read(getClass().getResource( >+ resources.getString("Throbber.image"))); >+ tiles = new ImageIcon[32]; >+ int width = image.getWidth(), height = image.getHeight(); >+ int twidth = width / 8, theight = height / 4; >+ int index = 0; >+ for (int y = theight; y <= height; y += theight) { >+ for (int x = twidth; x <= width; x += twidth) { >+ tiles[index++] = new ImageIcon(image.getSubimage(x >+ - twidth, y - theight, twidth, theight)); >+ } >+ } >+ >+ } catch (IOException e) { >+ tiles = null; >+ } finally { >+ image = null; >+ } >+ } >+ >+ public void start() { >+ stop(); >+ timer = new Timer(); >+ TimerTask timerTask = new TimerTask() { >+ public void run() { >+ currentTileIndex = (currentTileIndex + 1) >+ % tiles.length; >+ if (currentTileIndex == 0) { >+ currentTileIndex = 1; >+ } >+ setIcon(tiles[currentTileIndex]); >+ } >+ }; >+ timer.scheduleAtFixedRate(timerTask, 0, 30); >+ } >+ >+ public void stop() { >+ if (timer != null) { >+ timer.cancel(); >+ } >+ } >+} >Index: sources/org/apache/batik/util/gui/resource/JToolbarButton.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/JToolbarButton.java (revision 549415) >+++ sources/org/apache/batik/util/gui/resource/JToolbarButton.java (working copy) >@@ -23,6 +23,7 @@ > import java.awt.event.MouseEvent; > > import javax.swing.JButton; >+import javax.swing.UIManager; > > /** > * This class represents the buttons used in toolbars. >@@ -57,7 +58,14 @@ > } > setBorderPainted(false); > setMargin(new Insets(2, 2, 2, 2)); >- addMouseListener(new MouseListener()); >+ >+ // Windows XP look and feel seems to have a bug due to which the >+ // size of the parent container changes when the border painted >+ // property is set. Temporary fix: disable mouseover behavior if >+ // installed lnf is Windows XP >+ if (!UIManager.getLookAndFeel().getName().equals("Windows")) { >+ addMouseListener(new MouseListener()); >+ } > } > > /** >Index: sources/org/apache/batik/util/gui/resource/JMiniSlider.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/JMiniSlider.java (revision 0) >+++ sources/org/apache/batik/util/gui/resource/JMiniSlider.java (revision 0) >@@ -0,0 +1,206 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Dimension; >+import java.awt.Graphics; >+import java.awt.SystemColor; >+import java.awt.event.ActionEvent; >+import java.awt.event.ActionListener; >+import java.util.Locale; >+import java.util.ResourceBundle; >+ >+import javax.swing.ImageIcon; >+import javax.swing.JButton; >+import javax.swing.JPanel; >+ >+public class JMiniSlider extends JPanel { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.GUIUtils"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ public static final int HORIZONTAL = 0, VERTICAL = 1; >+ >+ private int min; >+ >+ private int max; >+ >+ private int value; >+ >+ private int extent; >+ >+ private int orientation; >+ >+ private JButton increaseButton; >+ >+ private JButton decreaseButton; >+ >+ public JMiniSlider(int orientation, int min, int max, int value, int extent) { >+ super(new BorderLayout()); >+ >+ setOrientation(orientation); >+ setMin(min); >+ setMax(max); >+ setValue(value); >+ setExtent(extent); >+ >+ Dimension prefSize; >+ Dimension buttonSize = new Dimension(); >+ switch (orientation) { >+ case VERTICAL: >+ prefSize = new Dimension(16, 100); >+ buttonSize.width = prefSize.width; >+ buttonSize.height = (prefSize.height >= (prefSize.width << 1)) ? prefSize.width : (prefSize.height >> 1); >+ break; >+ case HORIZONTAL: >+ default: >+ prefSize = new Dimension(100, 16); >+ buttonSize.width = (prefSize.width >= (prefSize.height << 1)) ? prefSize.height : (prefSize.width >> 1); >+ buttonSize.height = prefSize.height; >+ break; >+ } >+ setPreferredSize(prefSize); >+ setMinimumSize(getPreferredSize()); >+ >+ decreaseButton = new JToolbarButton(); >+ decreaseButton.setIcon(new ImageIcon(getClass().getResource( >+ resources.getString("JMiniSliderDecreaseButton.icon")))); >+ decreaseButton.setToolTipText(resources.getString("JMiniSliderDecreaseButton.tooltip")); >+ decreaseButton.setPreferredSize(buttonSize); >+ decreaseButton.setMinimumSize(buttonSize); >+ decreaseButton.setSize(buttonSize); >+ decreaseButton.addActionListener(new ActionListener() { >+ public void actionPerformed(ActionEvent e) { >+ decreaseValue(1); >+ } >+ }); >+ add(decreaseButton, BorderLayout.WEST); >+ >+ increaseButton = new JToolbarButton(); >+ increaseButton.setIcon(new ImageIcon(getClass().getResource( >+ resources.getString("JMiniSliderIncreaseButton.icon")))); >+ increaseButton.setToolTipText(resources.getString("JMiniSliderIncreaseButton.tooltip")); >+ increaseButton.setPreferredSize(buttonSize); >+ increaseButton.setMinimumSize(buttonSize); >+ increaseButton.setSize(buttonSize); >+ increaseButton.addActionListener(new ActionListener() { >+ public void actionPerformed(ActionEvent e) { >+ increaseValue(1); >+ } >+ }); >+ add(increaseButton, BorderLayout.EAST); >+ } >+ >+ public JMiniSlider(int min, int max, int value) { >+ this(HORIZONTAL, min, max, value, 1); >+ } >+ >+ public JMiniSlider(int min, int max) { >+ this(min, max, (min + max) / 2); >+ } >+ >+ public JMiniSlider(int orientation) { >+ this(orientation, 0, 100, 50, 1); >+ } >+ >+ public JMiniSlider() { >+ this(HORIZONTAL); >+ } >+ >+ public void paintComponent(Graphics g) { >+ super.paintComponent(g); >+ >+ int width = getWidth(), height = getHeight(); >+ >+ g.setColor(SystemColor.control); >+ int cx = decreaseButton.getWidth() + 2; >+ int cy = height / 2 - 1; >+ int cwidth = width - cx - increaseButton.getWidth() - 2; >+ int cheight = 3; >+ g.fillRect(cx, cy, cwidth, cheight); >+ int vwidth = (max != 0 ? value * cwidth / max : 0); >+ g.setColor(Color.black); >+ g.fillRect(cx, cy, vwidth, cheight); >+ g.setColor(SystemColor.controlLtHighlight); >+ g.drawRect(cx, cy, cwidth, cheight); >+ g.setColor(SystemColor.controlShadow); >+ g.drawLine(cx, cy, cx + cwidth, cy); >+ g.drawLine(cx, cy, cx, cy + cheight); >+ } >+ >+ public int getExtent() { >+ return extent; >+ } >+ >+ public void setExtent(int extent) { >+ this.extent = extent; >+ } >+ >+ public int getMax() { >+ return max; >+ } >+ >+ public void setMax(int max) { >+ this.max = max; >+ } >+ >+ public int getMin() { >+ return min; >+ } >+ >+ public void setMin(int min) { >+ this.min = min; >+ } >+ >+ public int getOrientation() { >+ return orientation; >+ } >+ >+ public void setOrientation(int orientation) { >+ this.orientation = orientation; >+ } >+ >+ public int getValue() { >+ return value; >+ } >+ >+ public void setValue(int value) { >+ if (value >= getMin() && value <= getMax()) { >+ this.value = value; >+ } >+ repaint(); >+ } >+ >+ protected void increaseValue(int units) { >+ int newValue = getValue() + getExtent() * units; >+ if (newValue > getMax()) { >+ newValue = getMax(); >+ } >+ setValue(newValue); >+ } >+ >+ protected void decreaseValue(int units) { >+ int newValue = getValue() - getExtent() * units; >+ if (newValue > getMax()) { >+ newValue = getMax(); >+ } >+ setValue(newValue); >+ } >+} >Index: sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java >=================================================================== >--- sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java (revision 0) >+++ sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java (revision 0) >@@ -0,0 +1,84 @@ >+/* >+ >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+ >+ */ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.Insets; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+ >+import javax.swing.JToggleButton; >+import javax.swing.UIManager; >+ >+import org.apache.batik.util.gui.resource.JToolbarButton.MouseListener; >+ >+/** >+ * This class represents the buttons used in toolbars. >+ * >+ * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> >+ * @version $Id: JToolbarButton.java 498555 2007-01-22 08:09:33Z cam $ >+ */ >+public class JToolbarToggleButton extends JToggleButton { >+ /** >+ * Creates a new toolbar button. >+ */ >+ public JToolbarToggleButton() { >+ initialize(); >+ } >+ >+ /** >+ * Creates a new toolbar button. >+ * @param txt The button text. >+ */ >+ public JToolbarToggleButton(String txt) { >+ super(txt); >+ initialize(); >+ } >+ >+ /** >+ * Initializes the button. >+ */ >+ protected void initialize() { >+ if (!System.getProperty("java.version").startsWith("1.3")) { >+ setOpaque(false); >+ setBackground(new java.awt.Color(0, 0, 0, 0)); >+ } >+ setBorderPainted(false); >+ setMargin(new Insets(2, 2, 2, 2)); >+ >+ // Windows XP look and feel seems to have a bug due to which the >+ // size of the parent container changes when the border painted >+ // property is set. Temporary fix: disable mouseover behavior if >+ // installed lnf is Windows XP >+ if (!UIManager.getLookAndFeel().getName().equals("Windows")) { >+ addMouseListener(new MouseListener()); >+ } >+ } >+ >+ /** >+ * To manage the mouse interactions. >+ */ >+ protected class MouseListener extends MouseAdapter { >+ public void mouseEntered(MouseEvent ev) { >+ setBorderPainted(true); >+ } >+ public void mouseExited(MouseEvent ev) { >+ setBorderPainted(false); >+ } >+ } >+} >Index: sources/org/apache/batik/util/gui/TimelineViewer.java >=================================================================== >--- sources/org/apache/batik/util/gui/TimelineViewer.java (revision 0) >+++ sources/org/apache/batik/util/gui/TimelineViewer.java (revision 0) >@@ -0,0 +1,135 @@ >+package org.apache.batik.util.gui; >+ >+import java.awt.Container; >+import java.awt.Dimension; >+import java.io.File; >+ >+import javax.swing.JDialog; >+import javax.swing.JFrame; >+import javax.swing.JScrollBar; >+import javax.swing.JSplitPane; >+ >+import org.apache.batik.dom.svg.SAXSVGDocumentFactory; >+import org.w3c.dom.Document; >+import org.w3c.dom.svg.SVGDocument; >+ >+public class TimelineViewer extends JFrame { >+ >+ private Document document; >+ >+ private TimelineController controller; >+ >+ public TimelineViewer() { >+ this(null); >+ } >+ >+ public TimelineViewer(Document document) { >+ super("Timeline Viewer"); >+ >+ Container contentPane = getContentPane(); >+ contentPane.setPreferredSize(new Dimension(800, 300)); >+ >+ JSplitPane splitPane = new JSplitPane(); >+ splitPane.setResizeWeight(0.0); >+ >+ JScrollBar scrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 100); >+ controller = new TimelineController(document); >+ controller.setVerticalScrollBar(scrollBar); >+ splitPane.setLeftComponent(controller); >+ >+ Timeline timeline = new Timeline(); >+ timeline.setVerticalScrollBar(scrollBar); >+ splitPane.setRightComponent(timeline); >+ contentPane.add(splitPane); >+ >+ pack(); >+ } >+ >+ /** >+ * Sets the document to display. >+ */ >+ public void setDocument(Document doc) { >+ document = doc; >+ controller.setDocument(document); >+ } >+ >+ public static void main(String[] args) throws Exception { >+ File file = new File(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/test-samples/rect.svg"); >+ SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(null, true); >+ SVGDocument doc = (SVGDocument) f.createDocument(file.toURL() >+ .toString()); >+ >+ JFrame tv = new TimelineViewer(doc); >+ tv.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); >+ tv.setVisible(true); >+ } >+ >+// private class DocTreeCellRenderer extends Box implements >+// TreeCellRenderer { >+// >+// private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon"); >+// >+// private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon"); >+// >+// private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon"); >+// >+// private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon"); >+// >+// private Paint gradient; >+// >+// private JLabel label; >+// >+// private JLabel icon; >+// >+// public DocTreeCellRenderer() { >+// super(BoxLayout.X_AXIS); >+// setOpaque(false); >+// >+// icon = new JLabel(SPACER_ICON); >+// add(icon); >+// >+// label = new JLabel(); >+// add(label); >+// >+// Dimension dim = getPreferredSize(); >+// gradient = new GradientPaint(0, 0, Color.white, 0, >+// 2 * dim.height, Color.gray); >+// } >+// >+// public void setBounds(int x, int y, int width, int height) { >+// super.setBounds(x, y, docTree.getWidth(), height); >+// System.out.println(getBounds()); >+// } >+// >+// private ImageIcon getIcon(String name) { >+// String uri = resources.getString(name); >+// System.out.println(uri); >+// return new ImageIcon(TimelineViewer.this.getClass().getResource( >+// uri)); >+// } >+// >+// protected void paintComponent(Graphics g) { >+// Graphics2D g2 = (Graphics2D) g; >+// g2.setPaint(gradient); >+// g2.fillRect(0, 0, getWidth(), getHeight()); >+// >+// super.paintComponent(g); >+// } >+// >+// public Component getTreeCellRendererComponent(JTree tree, Object value, >+// boolean selected, boolean expanded, boolean leaf, int row, >+// boolean hasFocus) { >+// label.setText(value.toString()); >+// >+// if (leaf) { >+// icon.setIcon(LEAF_ICON); >+// } else if (expanded) { >+// icon.setIcon(OPENED_ICON); >+// } else { >+// icon.setIcon(CLOSED_ICON); >+// } >+// return this; >+// } >+// } >+} >Index: sources/org/apache/batik/util/gui/TimelineController.java >=================================================================== >--- sources/org/apache/batik/util/gui/TimelineController.java (revision 0) >+++ sources/org/apache/batik/util/gui/TimelineController.java (revision 0) >@@ -0,0 +1,438 @@ >+package org.apache.batik.util.gui; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Dimension; >+import java.awt.GradientPaint; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.Paint; >+import java.awt.SystemColor; >+import java.awt.event.ActionEvent; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.util.ArrayList; >+import java.util.HashMap; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.DefaultListModel; >+import javax.swing.ImageIcon; >+import javax.swing.JLabel; >+import javax.swing.JList; >+import javax.swing.JPanel; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.JToolBar; >+import javax.swing.ListCellRenderer; >+import javax.swing.border.LineBorder; >+import javax.swing.border.MatteBorder; >+ >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+import org.apache.batik.util.gui.resource.ToolBarFactory; >+import org.w3c.dom.Document; >+import org.w3c.dom.NamedNodeMap; >+import org.w3c.dom.Node; >+import org.w3c.dom.NodeList; >+ >+public class TimelineController extends JPanel implements ActionMap { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resources.TimelineViewer"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The toolbar factory. >+ */ >+ protected ToolBarFactory tf = new ToolBarFactory(bundle, this); >+ >+ private JList nodeList; >+ >+ private JScrollPane nodeListScrollPane; >+ >+ private DocumentTreeNode rootNode; >+ >+ public TimelineController() { >+ this(null); >+ } >+ >+ public TimelineController(Document document) { >+ super(new BorderLayout()); >+ setMinimumSize(new Dimension(300, 0)); >+ setPreferredSize(getMinimumSize()); >+ >+ Dimension prefSize; >+ JToolBar controls = tf.createJToolBar("ControlToolBar"); >+ controls.setBorder(new MatteBorder(0, 0, 1, 0, SystemColor.controlShadow)); >+ prefSize = controls.getPreferredSize(); >+ prefSize.height = 30; >+ controls.setPreferredSize(prefSize); >+ controls.setFloatable(false); >+ add(controls, BorderLayout.NORTH); >+ >+ JToolBar layers = tf.createJToolBar("LayerToolBar"); >+ layers.setBorder(new MatteBorder(1, 0, 0, 0, SystemColor.controlShadow)); >+ prefSize = layers.getPreferredSize(); >+ prefSize.height = 30; >+ layers.setPreferredSize(prefSize); >+ layers.setFloatable(false); >+ >+ add(layers, BorderLayout.SOUTH); >+ >+ nodeList = new JList(new DefaultListModel()) { >+ public String getToolTipText(MouseEvent e) { >+ int index = locationToIndex(e.getPoint()); >+ if (index >= 0) { >+ DocumentTreeNode docTreeNode = (DocumentTreeNode)getModel().getElementAt(index); >+ return docTreeNode.getToolTipText(); >+ } else { >+ return null; >+ } >+ } >+ }; >+ nodeList.setFixedCellHeight(25); >+ nodeList.setCellRenderer(new DocTreeCellRenderer()); >+ nodeListScrollPane = new JScrollPane(nodeList); >+ nodeListScrollPane >+ .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); >+ nodeListScrollPane.setBorder(null); >+ add(nodeListScrollPane); >+ >+ nodeList.addMouseListener(new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ if (e.getClickCount() == 2) { >+ DocumentTreeNode selectedNode = (DocumentTreeNode) nodeList >+ .getSelectedValue(); >+ selectedNode.setExpanded(!selectedNode.isExpanded()); >+ rebuildNodeList(nodeList, rootNode); >+ } >+ } >+ }); >+ >+ setDocument(document); >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ /** >+ * The action associated with the 'All' button. >+ */ >+ protected class DisplayAllButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ } >+ } >+ >+ public void setDocument(Document document) { >+ if (document == null) { >+ DefaultListModel model = (DefaultListModel)nodeList.getModel(); >+ model.removeAllElements(); >+ } else { >+ Node root = document.getDocumentElement(); >+ rootNode = parse(root, null); >+ rebuildNodeList(nodeList, rootNode); >+ } >+ } >+ >+ public JScrollBar getVerticalScrollBar() { >+ return nodeListScrollPane.getVerticalScrollBar(); >+ } >+ >+ public void setVerticalScrollBar(JScrollBar verticalScrollBar) { >+ nodeListScrollPane.setVerticalScrollBar(verticalScrollBar); >+ } >+ >+ private void rebuildNodeList(JList nodeList, DocumentTreeNode node) { >+ DefaultListModel listModel = (DefaultListModel) nodeList.getModel(); >+ listModel.clear(); >+ addNode(listModel, node); >+ } >+ >+ private void addNode(DefaultListModel listModel, DocumentTreeNode node) { >+ DocumentTreeNode parent = node.getParent(); >+ if (parent == null || parent.isExpanded()) { >+ listModel.addElement(node); >+ DocumentTreeNode[] children = node.getChildren(); >+ if (children != null) { >+ for (int i = 0; i < children.length; i++) { >+ addNode(listModel, children[i]); >+ } >+ } >+ } >+ } >+ >+ private DocumentTreeNode parse(Node node, DocumentTreeNode parent) { >+ if (node == null) { >+ return null; >+ } >+ ArrayList childDocNodes = null; >+ DocumentTreeNode docNode = new DocumentTreeNode(parent, node >+ .getNodeName(), node.getNodeValue(), Node.ELEMENT_NODE); >+ NamedNodeMap attrMap = node.getAttributes(); >+ for (int i = 0; i < attrMap.getLength(); i++) { >+ Node item = attrMap.item(i); >+ int type = item.getNodeType(); >+ if (type == Node.ATTRIBUTE_NODE) { >+ if (childDocNodes == null) { >+ childDocNodes = new ArrayList(); >+ } >+ DocumentTreeNode attrNode = new DocumentTreeNode(docNode, item.getNodeName(), item.getNodeValue(), Node.ATTRIBUTE_NODE); >+ childDocNodes.add(attrNode); >+ } >+ } >+ NodeList childNodes = node.getChildNodes(); >+ for (int i = 0; i < childNodes.getLength(); i++) { >+ Node item = childNodes.item(i); >+ int type = item.getNodeType(); >+ if (type == Node.ELEMENT_NODE) { >+ if (childDocNodes == null) { >+ childDocNodes = new ArrayList(); >+ } >+ DocumentTreeNode childDocNode = parse(item, docNode); >+ if (childDocNode != null) { >+ childDocNodes.add(childDocNode); >+ } >+ } >+ } >+ if (childDocNodes != null) { >+ docNode.setChildren((DocumentTreeNode[]) childDocNodes >+ .toArray(new DocumentTreeNode[0])); >+ } >+ >+ return docNode; >+ } >+ >+ private class DocumentTreeNode { >+ >+ private String text; >+ >+ private String toolTipText; >+ >+ private DocumentTreeNode parent; >+ >+ private int type; >+ >+ private int depth; >+ >+ private DocumentTreeNode[] children; >+ >+ private boolean expanded = true; >+ >+ private boolean locked = false; >+ >+ public DocumentTreeNode(DocumentTreeNode parent, String name, String value, int type) { >+ this.parent = parent; >+ this.type = type; >+ this.depth = parent == null ? 0 : parent.depth + 1; >+ this.setText(name); >+ this.setToolTipText(value); >+ } >+ >+ public DocumentTreeNode getParent() { >+ return parent; >+ } >+ >+ public int getDepth() { >+ return depth; >+ } >+ >+ public DocumentTreeNode[] getChildren() { >+ return children; >+ } >+ >+ public int getChildCount() { >+ return children == null ? 0 : children.length; >+ } >+ >+ public void setChildren(DocumentTreeNode[] children) { >+ this.children = children; >+ if (children != null) { >+ for (int i = 0; i < children.length; i++) { >+ children[i].parent = this; >+ } >+ } >+ } >+ >+ public boolean isExpanded() { >+ if (parent == null) { >+ return true; >+ } >+ if (!expanded) { >+ return false; >+ } >+ return parent.isExpanded(); >+ } >+ >+ public void setExpanded(boolean expanded) { >+ this.expanded = expanded; >+ } >+ >+ public String getText() { >+ return text; >+ } >+ >+ public void setText(String text) { >+ this.text = text; >+ } >+ >+ public int getType() { >+ return type; >+ } >+ >+ public void setType(int type) { >+ this.type = type; >+ } >+ >+ public String getToolTipText() { >+ return toolTipText; >+ } >+ >+ public void setToolTipText(String toolTipText) { >+ this.toolTipText = toolTipText; >+ } >+ } >+ >+ private class DocTreeCellRenderer extends JLabel implements >+ ListCellRenderer { >+ >+ private class PaintAttributes { >+ public Paint paint, paintHighlight; >+ >+ public Color colorText, colorHighlightText; >+ } >+ >+ private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon"); >+ >+ private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon"); >+ >+ private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon"); >+ >+ private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon"); >+ >+ private final ImageIcon LOCK_ICON = getIcon("TreeNodeLocked.icon"); >+ >+ private PaintAttributes elementPaint; >+ >+ private PaintAttributes attributePaint; >+ >+ private boolean selected; >+ >+ private int type; >+ >+ private boolean locked = true; >+ >+ public DocTreeCellRenderer() { >+ setIcon(SPACER_ICON); >+ >+ Dimension dim = getPreferredSize(); >+ elementPaint = new PaintAttributes(); >+ elementPaint.paint = new Color(234, 234, 234); >+ elementPaint.paintHighlight = new GradientPaint(0, 0, Color.gray, >+ 0, 2 * dim.height, Color.white); >+ elementPaint.colorText = Color.black; >+ elementPaint.colorHighlightText = Color.white; >+ >+ attributePaint = new PaintAttributes(); >+ attributePaint.paint = new Color(216, 216, 216); >+ attributePaint.paintHighlight = new GradientPaint(0, 0, >+ Color.darkGray, 0, 2 * dim.height, Color.lightGray); >+ attributePaint.colorText = Color.black; >+ attributePaint.colorHighlightText = Color.white; >+ } >+ >+ private ImageIcon getIcon(String name) { >+ return new ImageIcon(TimelineController.this.getClass().getResource( >+ resources.getString(name))); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ Dimension size = getSize(); >+ Graphics2D g2 = (Graphics2D) g; >+ PaintAttributes paintAttributes; >+ switch (type) { >+ case Node.ATTRIBUTE_NODE: >+ paintAttributes = attributePaint; >+ break; >+ case Node.ELEMENT_NODE: >+ default: >+ paintAttributes = elementPaint; >+ break; >+ } >+ g2.setPaint(selected ? paintAttributes.paintHighlight : paintAttributes.paint); >+ g2.fillRect(0, 0, size.width, size.height); >+ >+ g2.setColor(Color.lightGray); >+ g2.drawLine(0, size.height - 2, size.width, size.height - 2); >+ g2.setColor(Color.white); >+ g2.drawLine(0, size.height - 1, size.width, size.height - 1); >+ >+ setForeground(selected ? paintAttributes.colorHighlightText : paintAttributes.colorText); >+ super.paintComponent(g); >+ >+ g.setColor(Color.white); >+ int x, y; >+ x = size.width - 18; >+ y = (size.height - 16) / 2; >+ g.draw3DRect(x, y, 16, 16, false); >+ if (locked) { >+ LOCK_ICON.paintIcon(this, g, x, y); >+ } >+ } >+ >+ public Component getListCellRendererComponent(JList list, Object value, >+ int index, boolean selected, boolean cellHasFocus) { >+ DocumentTreeNode node = (DocumentTreeNode) value; >+ this.selected = selected; >+ this.type = node.getType(); >+ setText(node.getText()); >+ setBorder(BorderFactory.createEmptyBorder(0, node.depth * 10, 0, 0)); >+ if (node.getChildren() == null || node.getChildCount() == 0) {// leaf >+ setIcon(LEAF_ICON); >+ } else if (node.isExpanded()) { >+ setIcon(OPENED_ICON); >+ } else { >+ setIcon(CLOSED_ICON); >+ } >+ >+ return this; >+ } >+ } >+} >Index: sources/org/apache/batik/util/gui/ErrorConsole.java >=================================================================== >--- sources/org/apache/batik/util/gui/ErrorConsole.java (revision 0) >+++ sources/org/apache/batik/util/gui/ErrorConsole.java (revision 0) >@@ -0,0 +1,1388 @@ >+package org.apache.batik.util.gui; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Container; >+import java.awt.Dimension; >+import java.awt.FlowLayout; >+import java.awt.Font; >+import java.awt.Frame; >+import java.awt.GradientPaint; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.GridBagConstraints; >+import java.awt.GridBagLayout; >+import java.awt.SystemColor; >+import java.awt.Toolkit; >+import java.awt.datatransfer.Clipboard; >+import java.awt.datatransfer.StringSelection; >+import java.awt.event.ActionEvent; >+import java.awt.event.ActionListener; >+import java.awt.event.ItemEvent; >+import java.awt.event.ItemListener; >+import java.awt.event.KeyAdapter; >+import java.awt.event.KeyEvent; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+import java.io.BufferedReader; >+import java.io.File; >+import java.io.FileInputStream; >+import java.io.InputStream; >+import java.io.InputStreamReader; >+import java.io.PrintWriter; >+import java.io.StringWriter; >+import java.util.ArrayList; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.LinkedList; >+import java.util.List; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.AbstractButton; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.ButtonGroup; >+import javax.swing.ButtonModel; >+import javax.swing.ImageIcon; >+import javax.swing.JButton; >+import javax.swing.JCheckBoxMenuItem; >+import javax.swing.JDialog; >+import javax.swing.JLabel; >+import javax.swing.JMenu; >+import javax.swing.JMenuItem; >+import javax.swing.JOptionPane; >+import javax.swing.JPanel; >+import javax.swing.JPopupMenu; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.JTextArea; >+import javax.swing.JTextField; >+import javax.swing.JTextPane; >+import javax.swing.JToggleButton; >+import javax.swing.JToolBar; >+import javax.swing.SwingConstants; >+import javax.swing.SwingUtilities; >+import javax.swing.border.MatteBorder; >+import javax.swing.text.BadLocationException; >+import javax.swing.text.DefaultHighlighter; >+import javax.swing.text.Highlighter; >+ >+import org.apache.batik.apps.svgbrowser.JSVGViewerFrame.DOMViewerAction; >+import org.apache.batik.apps.svgbrowser.JSVGViewerFrame.ViewSourceAction; >+import org.apache.batik.apps.svgbrowser.srcview.SourceViewFrame; >+import org.apache.batik.dom.AbstractDocument; >+import org.apache.batik.dom.svg.LiveAttributeException; >+import org.apache.batik.dom.svg.SAXSVGDocumentFactory; >+import org.apache.batik.dom.util.DocumentDescriptor; >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.Banner; >+import org.apache.batik.util.gui.resource.ButtonFactory; >+import org.apache.batik.util.gui.resource.JToolbarSeparator; >+import org.apache.batik.util.gui.resource.MenuFactory; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+import org.apache.batik.util.gui.resource.Throbber; >+import org.w3c.dom.Element; >+import org.w3c.dom.Node; >+import org.w3c.dom.NodeList; >+import org.w3c.dom.svg.SVGDocument; >+ >+public class ErrorConsole implements ActionMap { >+ >+ public static class ErrorInfo { >+ public Throwable throwable; >+ >+ public String uri; >+ >+ public int type; >+ >+ public ErrorInfo(Throwable throwable, String uri, int type) { >+ this.throwable = throwable; >+ this.uri = uri; >+ this.type = type; >+ } >+ } >+ >+ public static class AttributeErrorInfo extends ErrorInfo { >+ public InputStream inputStream; >+ >+ public Element element; >+ >+ public DocumentDescriptor docDescriptor; >+ >+ public ViewSourceAction viewSourceAction; >+ >+ public DOMViewerAction viewDOMAction; >+ >+ public AttributeErrorInfo(LiveAttributeException lex, String uri, >+ int type, InputStream inputStream, Element element, >+ DocumentDescriptor docDescriptor) { >+ this(lex, uri, type, inputStream, element, docDescriptor, null, >+ null); >+ } >+ >+ public AttributeErrorInfo(LiveAttributeException lex, String uri, >+ int type, InputStream inputStream, Element element, >+ DocumentDescriptor docDescriptor, >+ ViewSourceAction viewSourceAction, DOMViewerAction viewDOMAction) { >+ super(lex, uri, type); >+ this.inputStream = inputStream; >+ this.element = element; >+ this.docDescriptor = docDescriptor; >+ this.viewSourceAction = viewSourceAction; >+ this.viewDOMAction = viewDOMAction; >+ } >+ } >+ >+ public static final int ALL = -1, ERROR = 1, WARNING = 2, INFORMATION = 4; >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resources.ErrorConsole"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The button factory. >+ */ >+ protected ButtonFactory bf = new ButtonFactory(bundle, this); >+ >+ /** >+ * The menu factory. >+ */ >+ protected MenuFactory mf = new MenuFactory(bundle, this); >+ >+ private Banner banner; >+ >+ private Box errorList; >+ >+ private ErrorGroup errorGroup; >+ >+ private int displayType; >+ >+ private boolean sortOrderAscending = true; >+ >+ private JPopupMenu popupMenu; >+ >+ private Container contentPane; >+ >+ public ErrorConsole() { >+ actions.put("DisplayAllButtonAction", new DisplayAllButtonAction()); >+ actions.put("DisplayErrorsButtonAction", >+ new DisplayErrorsButtonAction()); >+ actions.put("DisplayWarningsButtonAction", >+ new DisplayWarningsButtonAction()); >+ actions.put("DisplayMessagesButtonAction", >+ new DisplayMessagesButtonAction()); >+ actions.put("ClearButtonAction", new ClearButtonAction()); >+ >+ actions.put("FirstLastSortMenuAction", new FirstLastSortMenuAction()); >+ actions.put("LastFirstSortMenuAction", new LastFirstSortMenuAction()); >+ actions.put("ShowDetailsMenuAction", new ShowDetailsMenuAction()); >+ actions.put("HideDetailsMenuAction", new HideDetailsMenuAction()); >+ actions.put("CopyMenuAction", new CopyMenuAction()); >+ actions.put("SelectAllMenuAction", new SelectAllMenuAction()); >+ actions.put("DeleteMenuAction", new DeleteMenuAction()); >+ actions.put("DeleteRelatedMenuAction", new DeleteRelatedMenuAction()); >+ actions.put("DeleteUnrelatedMenuAction", >+ new DeleteUnrelatedMenuAction()); >+ >+ contentPane = new JPanel(new BorderLayout()); >+ >+ JPanel errorPanel = new JPanel(new BorderLayout()); >+ errorPanel.setBackground(Color.white); >+ >+ JScrollPane errorScrollPane = new JScrollPane(errorPanel); >+ errorScrollPane >+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); >+ contentPane.add(errorScrollPane); >+ >+ errorGroup = new ErrorGroup(); >+ >+ errorList = new Box(BoxLayout.Y_AXIS); >+ errorPanel.add(errorList, BorderLayout.NORTH); >+ >+ popupMenu = createPopupMenu(); >+ >+ final JToolBar[] toolbars = new JToolBar[2]; >+ toolbars[0] = createPrimaryToolBar(); >+ toolbars[1] = createSecondaryToolBar(); >+ >+ final JPopupMenu toolbarPopup = new JPopupMenu(); >+ MouseListener popupMouseHandler = new MouseAdapter() { >+ public void mousePressed(MouseEvent e) { >+ if (e.isPopupTrigger()) { >+ toolbarPopup.show((Component) e.getSource(), e.getX(), e >+ .getY()); >+ } >+ } >+ >+ public void mouseReleased(MouseEvent e) { >+ if (e.isPopupTrigger()) { >+ toolbarPopup.show((Component) e.getSource(), e.getX(), e >+ .getY()); >+ } >+ } >+ }; >+ Box toolbarStack = new Box(BoxLayout.Y_AXIS); >+ toolbarStack.add(Box.createVerticalStrut(2)); >+ final JCheckBoxMenuItem[] menuItems = new JCheckBoxMenuItem[toolbars.length]; >+ ItemListener popupSelectionHandler = new ItemListener() { >+ public void itemStateChanged(ItemEvent e) { >+ for (int i = 0; i < toolbars.length; i++) { >+ toolbars[i].setVisible(menuItems[i].isSelected()); >+ } >+ } >+ }; >+ for (int i = 0; i < toolbars.length; i++) { >+ menuItems[i] = new JCheckBoxMenuItem(); >+ menuItems[i].setText(toolbars[i].getName()); >+ menuItems[i].setSelected(true); >+ menuItems[i].addItemListener(popupSelectionHandler); >+ toolbarPopup.add(menuItems[i]); >+ toolbars[i].addMouseListener(popupMouseHandler); >+ toolbarStack.add(toolbars[i]); >+ } >+ toolbarStack.addMouseListener(popupMouseHandler); >+ >+ banner = new Banner(); >+ toolbarStack.add(banner); >+ contentPane.add(toolbarStack, BorderLayout.NORTH); >+ >+ contentPane.setPreferredSize(new Dimension(575, 400)); >+ } >+ >+ private JToolBar createPrimaryToolBar() { >+ JToolBar toolbar = new JToolBar(); >+ toolbar.setName("Primary Toolbar"); >+ toolbar.setFloatable(false); >+ toolbar.setBorder(BorderFactory.createCompoundBorder(BorderFactory >+ .createMatteBorder(0, 0, 1, 0, SystemColor.controlShadow), >+ BorderFactory.createEmptyBorder(0, 5, 0, 5))); >+ >+ BooleanButtonGroup displayGroup = new BooleanButtonGroup(); >+ >+ JToggleButton displayAll = bf >+ .createJToolbarToggleButton("DisplayAllButton"); >+ displayGroup.add(displayAll); >+ displayAll.setSelected(true); >+ displayType(ALL, true); >+ toolbar.add(displayAll); >+ >+ toolbar.add(new JToolbarSeparator()); >+ >+ JToggleButton displayErrors = bf >+ .createJToolbarToggleButton("DisplayErrorsButton"); >+ displayGroup.addOr(displayErrors); >+ toolbar.add(displayErrors); >+ >+ JToggleButton displayWarnings = bf >+ .createJToolbarToggleButton("DisplayWarningsButton"); >+ displayGroup.addOr(displayWarnings); >+ toolbar.add(displayWarnings); >+ >+ JToggleButton displayMessages = bf >+ .createJToolbarToggleButton("DisplayMessagesButton"); >+ displayGroup.addOr(displayMessages); >+ toolbar.add(displayMessages); >+ >+ toolbar.add(new JToolbarSeparator()); >+ >+ JButton clear = bf.createJToolbarButton("ClearButton"); >+ displayGroup.add(clear); >+ toolbar.add(clear); >+ >+ JPanel searchPanel = new JPanel(new GridBagLayout()); >+ searchPanel.setOpaque(false); >+ GridBagConstraints gc; >+ >+ JLabel searchLabel = new JLabel("Search: "); >+ searchLabel.setHorizontalAlignment(SwingConstants.RIGHT); >+ gc = new GridBagConstraints(); >+ gc.gridx = 0; >+ gc.weightx = 1.0; >+ gc.fill = GridBagConstraints.HORIZONTAL; >+ searchPanel.add(searchLabel, gc); >+ >+ final JTextField searchField = new JTextField(12); >+ searchField.setMinimumSize(searchField.getPreferredSize()); >+ searchField.addKeyListener(new KeyAdapter() { >+ public void keyPressed(KeyEvent e) { >+ if (e.getKeyCode() == KeyEvent.VK_ENTER) { >+ filterErrors(searchField.getText()); >+ } >+ } >+ }); >+ gc = new GridBagConstraints(); >+ gc.gridx = 1; >+ gc.weightx = 0.0; >+ searchPanel.add(searchField, gc); >+ >+ toolbar.add(searchPanel); >+ >+ return toolbar; >+ } >+ >+ private JToolBar createSecondaryToolBar() { >+ JToolBar toolbar = new JToolBar(); >+ toolbar.setName("Secondary Toolbar"); >+ toolbar.setFloatable(false); >+ toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS)); >+ >+ BooleanButtonGroup languageGroup = new BooleanButtonGroup(); >+ >+ JToggleButton svgEntries = bf >+ .createJToolbarToggleButton("DisplaySVGButton"); >+ svgEntries.setSelected(true); >+ languageGroup.addOr(svgEntries); >+ toolbar.add(svgEntries); >+ >+ JToggleButton scriptEntries = bf >+ .createJToolbarToggleButton("DisplayScriptButton"); >+ scriptEntries.setSelected(true); >+ languageGroup.addOr(scriptEntries); >+ toolbar.add(scriptEntries); >+ >+ JToggleButton cssEntries = bf >+ .createJToolbarToggleButton("DisplayCSSButton"); >+ cssEntries.setSelected(true); >+ languageGroup.addOr(cssEntries); >+ toolbar.add(cssEntries); >+ >+ toolbar.add(Box.createHorizontalGlue()); >+ >+ final JPopupMenu optionsPopup = new JPopupMenu(); >+ JMenuItem showAll = new JMenuItem("Show All Errors"); >+ optionsPopup.add(showAll); >+ JMenu showFromDocument = new JMenu("Show Errors from..."); >+ optionsPopup.add(showFromDocument); >+ final JButton options = bf.createJToolbarButton("OptionsButton"); >+ options.addMouseListener(new MouseAdapter() { >+ public void mousePressed(MouseEvent e) { >+ optionsPopup.show(options, 0, options.getSize().height); >+ } >+ }); >+ toolbar.add(options); >+ >+ return toolbar; >+ } >+ >+ private class BooleanButtonGroup extends ButtonGroup implements >+ ItemListener { >+ >+ private List orElements = new ArrayList(); >+ >+ private AbstractButton orButton = new JToggleButton(); >+ >+ public BooleanButtonGroup() { >+ orButton.addItemListener(this); >+ add(orButton); >+ } >+ >+ public void itemStateChanged(ItemEvent e) { >+ if (e.getStateChange() == ItemEvent.DESELECTED) { >+ if (e.getSource() == orButton) { >+ for (Iterator i = orElements.iterator(); i.hasNext();) { >+ AbstractButton button = (AbstractButton) i.next(); >+ button.setSelected(false); >+ } >+ } else if (orButton.isSelected()) { >+ boolean selected = false; >+ for (Iterator i = orElements.iterator(); i.hasNext();) { >+ AbstractButton button = (AbstractButton) i.next(); >+ if (button.isSelected()) { >+ selected = true; >+ break; >+ } >+ } >+ if (!selected) { >+ ((AbstractButton) e.getSource()).setSelected(true); >+ } >+ } >+ } else if (e.getStateChange() == ItemEvent.SELECTED) { >+ setSelected(((AbstractButton) e.getSource()).getModel(), true); >+ } >+ } >+ >+ public void addOr(AbstractButton button) { >+ orElements.add(button); >+ button.addItemListener(this); >+ } >+ >+ public void setSelected(ButtonModel model, boolean selected) { >+ for (Iterator i = orElements.iterator(); i.hasNext();) { >+ AbstractButton button = (AbstractButton) i.next(); >+ if (button.getModel() == model) { >+ orButton.setSelected(selected); >+ return; >+ } >+ } >+ super.setSelected(model, selected); >+ } >+ } >+ >+ private JPopupMenu createPopupMenu() { >+ JPopupMenu popupMenu = mf.createJMenu("PopupMenu").getPopupMenu(); >+ return popupMenu; >+ } >+ >+ protected static ErrorConsole instance; >+ >+ public static ErrorConsole getInstance() { >+ if (instance == null) { >+ instance = new ErrorConsole(); >+ } >+ return instance; >+ } >+ >+ protected static JDialog dialog; >+ >+ public static void showDialog(Component owner) { >+ Frame f = JOptionPane.getFrameForComponent(owner); >+ if (dialog != null && dialog.getOwner() != f) { >+ dialog.dispose(); >+ dialog = null; >+ } >+ if (dialog == null) { >+ dialog = new JDialog(f, "Error Console"); >+ dialog.getContentPane().add(getInstance().contentPane, >+ BorderLayout.CENTER); >+ >+ dialog.pack(); >+ dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); >+ dialog.setLocationRelativeTo(dialog.getOwner()); >+ } >+ dialog.setVisible(true); >+ } >+ >+ protected List documentList = new LinkedList(); >+ >+ public void add(ErrorInfo info) { >+ addToList(new ErrorButton(info)); >+ } >+ >+ public void add(AttributeErrorInfo info) { >+ addToList(new ErrorButton(info)); >+ } >+ >+ protected void addToList(ErrorButton errorButton) { >+ String uri = errorButton.getDocumentURI(); >+ if (!documentList.contains(uri)) { >+ >+ } >+ errorButton.setPopupMenu(popupMenu); >+ errorList.add(errorButton); >+ errorGroup.add(errorButton); >+ errorButton.setVisible((displayType & errorButton.getType()) > 0); >+ dirty = true; >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ /** >+ * The action associated with the 'All' button. >+ */ >+ protected class DisplayAllButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ displayType(ALL, true); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Errors' button. >+ */ >+ protected class DisplayErrorsButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(ERROR, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Warnings' button. >+ */ >+ protected class DisplayWarningsButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(WARNING, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Messages' button. >+ */ >+ protected class DisplayMessagesButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(INFORMATION, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Clear' button. >+ */ >+ protected class ClearButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ clearType(displayType); >+ errorList.revalidate(); >+ } >+ } >+ >+ /** >+ * The action associated with the 'First to Last Sort' menu item. >+ */ >+ protected class FirstLastSortMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ if (sortOrderAscending) { >+ return; >+ } >+ reverseComponentOrder(errorList); >+ sortOrderAscending = true; >+ } >+ } >+ >+ /** >+ * The action associated with the 'Last to First Sort' menu item. >+ */ >+ protected class LastFirstSortMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ if (!sortOrderAscending) { >+ return; >+ } >+ reverseComponentOrder(errorList); >+ sortOrderAscending = false; >+ } >+ } >+ >+ private void reverseComponentOrder(Container container) { >+ Component[] components = container.getComponents(); >+ errorList.removeAll(); >+ for (int i = components.length - 1; i >= 0; i--) { >+ errorList.add(components[i]); >+ } >+ errorList.revalidate(); >+ } >+ >+ /** >+ * The action associated with the 'Show Details' menu item. >+ */ >+ protected class ShowDetailsMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ eb.setShowDetails(true); >+ } >+ } >+ } >+ } >+ >+ /** >+ * The action associated with the 'Hide Details' menu item. >+ */ >+ protected class HideDetailsMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ eb.setShowDetails(false); >+ } >+ } >+ } >+ } >+ >+ /** >+ * The action associated with the 'Copy' menu item. >+ */ >+ protected class CopyMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ StringBuilder copyText = new StringBuilder(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ copyText.append(eb.getMessageText() + "\n"); >+ copyText.append(eb.getDetailText() + "\n\n"); >+ } >+ } >+ String s = copyText.toString().trim(); >+ if (!s.equals("")) { >+ Clipboard clipboard = Toolkit.getDefaultToolkit() >+ .getSystemClipboard(); >+ clipboard.setContents(new StringSelection(s), null); >+ } >+ } >+ } >+ >+ /** >+ * The action associated with the 'Select All' menu item. >+ */ >+ protected class SelectAllMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ eb.setSelected(true); >+ } >+ } >+ } >+ >+ /** >+ * The action associated with the 'Delete' menu item. >+ */ >+ protected class DeleteMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ errorList.remove(eb); >+ errorGroup.remove(eb); >+ } >+ } >+ errorList.revalidate(); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Delete Related' menu item. >+ */ >+ protected class DeleteRelatedMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ List removeWithURIs = new LinkedList(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ String uri = eb.getDocumentURI(); >+ if (!removeWithURIs.contains(uri)) { >+ removeWithURIs.add(uri); >+ } >+ } >+ } >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (removeWithURIs.contains(eb.getDocumentURI())) { >+ errorList.remove(eb); >+ errorGroup.remove(eb); >+ } >+ } >+ errorList.revalidate(); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Delete Unrelated' menu item. >+ */ >+ protected class DeleteUnrelatedMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component[] components = errorList.getComponents(); >+ List keepWithURIs = new LinkedList(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (eb.isSelected()) { >+ String uri = eb.getDocumentURI(); >+ if (!keepWithURIs.contains(uri)) { >+ keepWithURIs.add(uri); >+ } >+ } >+ } >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (!keepWithURIs.contains(eb.getDocumentURI())) { >+ errorList.remove(eb); >+ errorGroup.remove(eb); >+ } >+ } >+ errorList.revalidate(); >+ } >+ } >+ >+ private void clearType(int type) { >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if ((eb.getType() & type) > 0) { >+ errorList.remove(eb); >+ errorGroup.remove(eb); >+ } >+ } >+ } >+ >+ private void displayType(int type, boolean visible) { >+ if (displayType < 0) { >+ displayType = 0; >+ } >+ if (visible) { >+ displayType |= type; >+ } else { >+ displayType &= ~type; >+ } >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ eb.setVisible((displayType & eb.getType()) > 0); >+ } >+ } >+ >+ private boolean dirty = true; >+ >+ private List filteredList = new ArrayList(); >+ >+ private void filterErrors(String searchPhrase) { >+ if (dirty) { >+ rebuildIndex(); >+ dirty = false; >+ } >+ filteredList.clear(); >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if ((displayType & eb.getType()) > 0) { >+ filteredList.add(eb); >+ } >+ } >+ >+ String[] tokens = searchPhrase.split(" "); >+ for (int i = 0; i < tokens.length; i++) { >+ List buttonList = (List) index.get(tokens[i]); >+ if (buttonList != null) { >+ for (Iterator it = buttonList.iterator(); it.hasNext();) { >+ filteredList.remove(it.next()); >+ } >+ } >+ } >+ >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if ((displayType & eb.getType()) > 0) { >+ eb.setVisible(!filteredList.contains(eb)); >+ } >+ } >+ } >+ >+ private HashMap index = new HashMap(); >+ >+ private HashMap rebuildIndex() { >+ index.clear(); >+ Component[] components = errorList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ String[] text = eb.getMessageText().split(" "); >+ for (int j = 0; j < text.length; j++) { >+ List list = (List) index.get(text[j]); >+ if (list == null) { >+ list = new ArrayList(); >+ index.put(text[j], list); >+ } >+ list.add(eb); >+ } >+ } >+ >+ return index; >+ } >+ >+ protected class ErrorButton extends JButton { >+ >+ private String uri; >+ >+ private int type; >+ >+ private JTextPane messageText; >+ >+ private ImageIcon icon; >+ >+ private GradientPaint gradient; >+ >+ private JPanel detailPanel; >+ >+ private JPopupMenu popupMenu; >+ >+ private JScrollPane detailScrollPane; >+ >+ private JTextArea detailText; >+ >+ private Box actionsPanel; >+ >+ private JButton btnShowDetails; >+ >+ private String showDetails, hideDetails; >+ >+ private MouseListener ml = new MouseAdapter() { >+ public void mousePressed(MouseEvent e) { >+ if (!isSelected()) { >+ setSelected(true); >+ } >+ if (e.isPopupTrigger()) { >+ popupMenu.show(ErrorButton.this, e.getX(), e.getY()); >+ } >+ } >+ >+ public void mouseReleased(MouseEvent e) { >+ if (e.isPopupTrigger()) { >+ popupMenu.show(ErrorButton.this, e.getX(), e.getY()); >+ } >+ } >+ }; >+ >+ protected ErrorButton(String uri, int type) { >+ this.uri = uri; >+ this.type = type; >+ >+ setLayout(new BorderLayout(10, 10)); >+ setContentAreaFilled(false); >+ setBorderPainted(false); >+ setOpaque(false); >+ setFocusPainted(false); >+ setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); >+ addMouseListener(ml); >+ >+ String s; >+ switch (type) { >+ case WARNING: >+ s = resources.getString("ErrorButton.warning_icon"); >+ break; >+ case INFORMATION: >+ s = resources.getString("ErrorButton.message_icon"); >+ break; >+ case ERROR: >+ default: >+ s = resources.getString("ErrorButton.error_icon"); >+ break; >+ } >+ icon = new ImageIcon(getClass().getResource(s)); >+ add(new JLabel(icon), BorderLayout.WEST); >+ >+ Box centerPane = new Box(BoxLayout.Y_AXIS); >+ add(centerPane); >+ >+ messageText = new JTextPane(); >+ messageText.setPreferredSize(new Dimension(300, 30)); >+ messageText.setEditable(false); >+ messageText.setOpaque(false); >+ messageText.addMouseListener(new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ passEvent(e); >+ } >+ >+ public void mousePressed(MouseEvent e) { >+ passEvent(e); >+ } >+ >+ public void mouseReleased(MouseEvent e) { >+ passEvent(e); >+ } >+ >+ private void passEvent(MouseEvent e) { >+ e = SwingUtilities.convertMouseEvent(e.getComponent(), e, >+ ErrorButton.this); >+ ErrorButton.this.dispatchEvent(e); >+ } >+ }); >+ centerPane.add(messageText, BorderLayout.NORTH); >+ >+ detailText = new JTextArea(); >+ detailText.setFont(new Font("Monospaced", Font.PLAIN, 12)); >+ detailText.setEditable(false); >+ detailText.setLineWrap(true); >+ detailScrollPane = new JScrollPane(); >+ detailScrollPane.setPreferredSize(new Dimension(300, 100)); >+ detailPanel = new JPanel(new BorderLayout()); >+ detailPanel.add(detailScrollPane); >+ actionsPanel = new Box(BoxLayout.X_AXIS); >+ actionsPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); >+ detailPanel.add(actionsPanel, BorderLayout.SOUTH); >+ detailPanel.setOpaque(false); >+ detailPanel.setVisible(false); >+ add(detailPanel, BorderLayout.SOUTH); >+ >+ hideDetails = resources.getString("ShowDetails.text0"); >+ showDetails = resources.getString("ShowDetails.text1"); >+ btnShowDetails = new JButton(showDetails); >+ btnShowDetails.addActionListener(new ActionListener() { >+ public void actionPerformed(ActionEvent e) { >+ setShowDetails(!isShowDetails()); >+ } >+ }); >+ JPanel button = new JPanel(new FlowLayout(FlowLayout.LEADING)); >+ button.setOpaque(false); >+ button.add(btnShowDetails); >+ centerPane.add(button, BorderLayout.SOUTH); >+ >+ Dimension dim = getPreferredSize(); >+ gradient = new GradientPaint(0, 0, new Color(217, 226, 234), 0, >+ 2 * dim.height, new Color(193, 207, 221)); >+ >+ } >+ >+ public ErrorButton(final ErrorInfo info) { >+ this(info.uri, info.type); >+ >+ setMessageText(info.throwable.getMessage()); >+ >+ StringWriter sw = new StringWriter(); >+ info.throwable.printStackTrace(new PrintWriter(sw)); >+ sw.flush(); >+ >+ detailScrollPane.setViewportView(detailText); >+ setDetailText(sw.toString()); >+ } >+ >+ private TextInfo textInfo; >+ >+ private JButton viewSourceButton; >+ >+ private JButton viewDOMButton; >+ >+ public ErrorButton(final AttributeErrorInfo info) { >+ this(info.uri, info.type); >+ >+ // Get reference to original element if this is a clone >+ AbstractDocument doc = (AbstractDocument) info.element >+ .getOwnerDocument(); >+ Element importedNode = (Element) doc.getImportedNode(info.element); >+ if (importedNode != null) { >+ info.element = importedNode; >+ } >+ final Element element = info.element; >+ >+ if (info.viewSourceAction != null) { >+ viewSourceButton = new JButton(resources >+ .getString("ViewSource.text")); >+ AbstractAction viewSourceActionDecorator = new AbstractAction() { >+ public void actionPerformed(final ActionEvent e) { >+ new Thread() { >+ public void run() { >+ info.viewSourceAction.actionPerformed(e); >+ try { >+ info.viewSourceAction.getDisplayThread() >+ .join(); >+ SourceViewFrame svf = info.viewSourceAction >+ .getSourceViewFrame(); >+ >+ int locline = info.docDescriptor >+ .getLocationLine(element), loccol = info.docDescriptor >+ .getLocationColumn(element); >+ >+ String text = textInfo >+ .getFormattedText(false); >+ int endOffset = textInfo.getOffset(locline, >+ loccol, false) - 1; >+ >+ // find end of line >+ for (; endOffset < text.length() >+ && text.charAt(endOffset) != '\n'; endOffset++) >+ ; >+ >+ // find beginning of tag >+ int startOffset = endOffset - 1; >+ boolean foundTagBegin = false; >+ for (; startOffset >= 0 && !foundTagBegin >+ || text.charAt(startOffset) != '\n'; startOffset--) { >+ if (text.charAt(startOffset) == '<') { >+ foundTagBegin = true; >+ } >+ } >+ startOffset++; >+ >+ if (startOffset >= 0 && endOffset >= 0) { >+ svf.select(startOffset, endOffset); >+ } >+ } catch (InterruptedException ex) { >+ ex.printStackTrace(); >+ } >+ } >+ }.start(); >+ } >+ }; >+ viewSourceButton.addActionListener(viewSourceActionDecorator); >+ viewSourceButton.setEnabled(false); >+ actionsPanel.add(viewSourceButton); >+ actionsPanel.add(Box.createHorizontalStrut(5)); >+ } >+ >+ if (info.viewDOMAction != null) { >+ viewDOMButton = new JButton(resources.getString("ViewDOM.text")); >+ AbstractAction viewDOMActionDecorator = new AbstractAction() { >+ public void actionPerformed(ActionEvent e) { >+ info.viewDOMAction.actionPerformed(e); >+ DOMViewer domViewer = info.viewDOMAction.getDOMViewer(); >+ domViewer.setSelectionNode(element); >+ } >+ }; >+ viewDOMButton.addActionListener(viewDOMActionDecorator); >+ actionsPanel.add(viewDOMButton); >+ actionsPanel.add(Box.createHorizontalStrut(5)); >+ } >+ >+ final Throbber throbber = new Throbber(); >+ detailScrollPane.setViewportView(throbber); >+ throbber.start(); >+ new Thread() { >+ public void run() { >+ LiveAttributeException lex = (LiveAttributeException) info.throwable; >+ String attrName = lex.getAttributeName(); >+ String eltName = lex.getElement().getNodeName(); >+ setMessageText("Error in parsing value for property '" >+ + attrName + "' of element <" + eltName >+ + ">. Declaration dropped"); >+ String text; >+ int endOffset = 0, startOffset; >+ int locline = info.docDescriptor.getLocationLine(element), loccol = info.docDescriptor >+ .getLocationColumn(element); >+ try { >+ Thread.sleep(3000); >+ >+ if (info.inputStream == null) { >+ throw new NullPointerException( >+ "Document text not available"); >+ } else { >+ LinkedList lineList = new LinkedList(); >+ BufferedReader reader = new BufferedReader( >+ new InputStreamReader(info.inputStream)); >+ String line; >+ >+ while ((line = reader.readLine()) != null) { >+ lineList.add(line); >+ } >+ String[] lines = (String[]) lineList >+ .toArray(new String[0]); >+ textInfo = new TextInfo(lines); >+ text = textInfo.getFormattedText(true); >+ endOffset = textInfo.getOffset(locline, loccol, >+ true) - 1; >+ } >+ setDetailText(text); >+ >+ Highlighter highlighter = detailText.getHighlighter(); >+ highlighter.removeAllHighlights(); >+ >+ // find end of line >+ for (; endOffset >= 0 && endOffset < text.length() >+ && text.charAt(endOffset) != '\n'; endOffset++) >+ ; >+ >+ // find beginning of tag >+ startOffset = endOffset - 1; >+ boolean foundTagBegin = false; >+ for (; startOffset >= 0 >+ && (!foundTagBegin || text.charAt(startOffset) != '\n'); startOffset--) { >+ if (text.charAt(startOffset) == '<') { >+ foundTagBegin = true; >+ } >+ } >+ startOffset++; >+ >+ if (startOffset >= 0 && endOffset < text.length()) { >+ try { >+ highlighter >+ .addHighlight( >+ startOffset, >+ endOffset, >+ new DefaultHighlighter.DefaultHighlightPainter( >+ Color.yellow)); >+ } catch (BadLocationException e) { >+ } >+ } >+ >+ if (viewSourceButton != null) { >+ viewSourceButton.setEnabled(true); >+ } >+ } catch (Exception e) { >+ e.printStackTrace(); >+ setDetailText("Error parsing file: " + info.uri); >+ } >+ >+ throbber.stop(); >+ detailScrollPane.setViewportView(detailText); >+ if (locline >= 0) { >+ JScrollBar vsb = detailScrollPane >+ .getVerticalScrollBar(); >+ vsb.setValue(vsb.getUnitIncrement(JScrollBar.VERTICAL) >+ * (locline - 5)); >+ } >+ } >+ }.start(); >+ } >+ >+ protected class TextInfo { >+ private String[] lines; >+ >+ private int indent; >+ >+ public TextInfo(String[] lines) { >+ this.lines = lines.clone(); >+ indent = 1; >+ int len = lines.length; >+ while ((int) (len /= 10) > 0) { >+ indent++; >+ } >+ } >+ >+ public String getFormattedText(boolean showLineNumbers) { >+ StringBuilder sb = new StringBuilder(); >+ if (showLineNumbers) { >+ String format = "%" + indent + "d: %s\n"; >+ for (int i = 0; i < lines.length; i++) { >+ sb.append(String.format(format, i + 1, lines[i])); >+ } >+ } else { >+ for (int i = 0; i < lines.length; i++) { >+ sb.append(lines[i] + "\n"); >+ } >+ } >+ >+ return sb.toString(); >+ } >+ >+ public int getOffset(int locline, int loccol, >+ boolean withLineNumbers) { >+ int offset = 0; >+ for (int i = 0; i < locline; i++) { >+ if (i < locline - 1) { >+ offset += lines[i].length(); >+ } else if (i == locline - 1) { >+ offset += loccol; >+ } >+ } >+ offset += (withLineNumbers ? (indent + 3) : 1) * locline - 1; >+ return offset; >+ } >+ } >+ >+ public void paintComponent(Graphics g) { >+ Graphics2D g2 = (Graphics2D) g; >+ int width = getWidth(), height = getHeight(); >+ g2.setPaint(isSelected() ? gradient : Color.white); >+ g2.fillRect(0, 0, width, height); >+ g2.setColor(SystemColor.controlShadow); >+ g2.drawLine(0, height - 1, width, height - 1); >+ super.paintComponent(g); >+ } >+ >+ public int getType() { >+ return type; >+ } >+ >+ public void setType(int type) { >+ this.type = type; >+ repaint(); >+ } >+ >+ public JPopupMenu getPopupMenu() { >+ return popupMenu; >+ } >+ >+ public void setPopupMenu(JPopupMenu popupMenu) { >+ this.popupMenu = popupMenu; >+ } >+ >+ public String getMessageText() { >+ return messageText.getText(); >+ } >+ >+ public void setMessageText(String text) { >+ messageText.setText(text); >+ } >+ >+ public String getDetailText() { >+ return detailText.getText(); >+ } >+ >+ public void setDetailText(String text) { >+ detailText.setText(text); >+ } >+ >+ public boolean isShowDetails() { >+ return detailPanel.isVisible(); >+ } >+ >+ public void setShowDetails(boolean show) { >+ detailPanel.setVisible(show); >+ btnShowDetails.setText(show ? hideDetails : showDetails); >+ } >+ >+ public String getDocumentURI() { >+ return uri; >+ } >+ } >+ >+ private class ErrorGroup { >+ >+ private List errors; >+ >+ private List selection; >+ >+ private AbstractButton anchor; >+ >+ private MouseListener ml = new MouseAdapter() { >+ public void mousePressed(MouseEvent e) { >+ AbstractButton sel = (AbstractButton) e.getSource(); >+ if (e.isControlDown()) { >+ sel.setSelected(true); >+ anchor = sel; >+ } else if (e.isShiftDown()) { >+ if (anchor != null) { >+ // unselect elements falling out of selection range >+ for (Iterator i = errors.iterator(); i.hasNext();) { >+ AbstractButton b = (AbstractButton) i.next(); >+ if (b != sel && b != anchor) { >+ b.setSelected(false); >+ selection.remove(b); >+ } >+ } >+ >+ // startIndex - start of selection range >+ // endIndex - end of selection range >+ int startIndex = errors.indexOf(anchor); >+ int endIndex = errors.indexOf(sel); >+ >+ if (startIndex > endIndex) { >+ int t = startIndex; >+ startIndex = endIndex; >+ endIndex = t; >+ } >+ >+ // select elements in the selection >+ for (int i = startIndex + 1; i < endIndex; i++) { >+ AbstractButton b = (AbstractButton) errors.get(i); >+ b.setSelected(true); >+ selection.add(b); >+ } >+ } else { >+ anchor = sel; >+ } >+ } else { >+ if (!selection.contains(sel) >+ || SwingUtilities.isLeftMouseButton(e)) { >+ for (Iterator i = errors.iterator(); i.hasNext();) { >+ AbstractButton b = (AbstractButton) i.next(); >+ if (b != sel) { >+ b.setSelected(false); >+ } >+ } >+ } >+ anchor = sel; >+ } >+ if (!selection.contains(sel)) { >+ selection.add(sel); >+ } >+ } >+ }; >+ >+ public ErrorGroup() { >+ errors = new ArrayList(); >+ selection = new ArrayList(); >+ } >+ >+ public void add(AbstractButton button) { >+ button.addMouseListener(ml); >+ errors.add(button); >+ } >+ >+ public void remove(AbstractButton button) { >+ button.removeMouseListener(ml); >+ errors.remove(button); >+ } >+ } >+ >+ private static Element findElementByTagName(Node node, String tagName) { >+ if (node.getNodeType() == Node.ELEMENT_NODE >+ && node.getNodeName().equals(tagName)) { >+ return (Element) node; >+ } >+ NodeList list = node.getChildNodes(); >+ for (int i = 0; i < list.getLength(); i++) { >+ Element e = findElementByTagName(list.item(i), tagName); >+ if (e != null) { >+ return e; >+ } >+ } >+ return null; >+ } >+ >+ private static void loadDocument(String path, String eltName, int type) >+ throws Exception { >+ ErrorConsole ec = ErrorConsole.getInstance(); >+ File file = new File(path); >+ SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(null, true); >+ SVGDocument doc = (SVGDocument) f.createDocument(file.toURL() >+ .toString()); >+ Element elt = findElementByTagName(doc.getDocumentElement(), eltName); >+ DocumentDescriptor desc = f.getDocumentDescriptor(); >+ LiveAttributeException lex = new LiveAttributeException(elt, "x", >+ LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, "1s8"); >+ AttributeErrorInfo info = new AttributeErrorInfo(lex, doc >+ .getDocumentURI(), type, new FileInputStream(file), elt, desc); >+ ec.add(info); >+ } >+ >+ public static void main(String[] args) throws Exception { >+ // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); >+ loadDocument(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/test-samples/rect1.svg", "rect", >+ ERROR); >+ loadDocument(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/test-samples/batikLogo.svg", >+ "rect", WARNING); >+ loadDocument(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/test-samples/ellipse1.svg", >+ "rect", INFORMATION); >+ loadDocument(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/test-samples/ellipse1.svg", >+ "ellipse", ERROR); >+ ErrorConsole.showDialog(null); >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 42741
:
20395
|
20396
|
20443
|
20444
|
20518
|
20519
| 20530 |
20531