You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by ca...@apache.org on 2007/11/13 01:40:58 UTC

svn commit: r594367 [4/9] - in /xmlgraphics/batik/trunk: ./ resources/org/apache/batik/apps/svgbrowser/resources/ resources/org/apache/batik/util/gui/resources/ sources-1.3/org/apache/batik/util/ sources-1.3/org/apache/batik/util/gui/ sources-1.4/org/a...

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/HistoryBrowserInterface.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/HistoryBrowserInterface.java?rev=594367&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/HistoryBrowserInterface.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/HistoryBrowserInterface.java Mon Nov 12 16:40:53 2007
@@ -0,0 +1,1427 @@
+/*
+
+   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.apps.svgbrowser;
+
+import java.util.ArrayList;
+
+import org.apache.batik.apps.svgbrowser.HistoryBrowser.CommandController;
+import org.apache.batik.apps.svgbrowser.HistoryBrowser.HistoryBrowserEvent;
+import org.apache.batik.dom.util.DOMUtilities;
+import org.apache.batik.util.SVGConstants;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * The wrapper for the history browser. The commands for the historyBrowser
+ * are implemented here
+ *
+ * @version $Id$
+ */
+public class HistoryBrowserInterface {
+
+    // ATOM COMMANDS
+    private static final String ATTRIBUTE_ADDED_COMMAND = "Attribute added: ";
+
+    private static final String ATTRIBUTE_REMOVED_COMMAND = "Attribute removed: ";
+
+    private static final String ATTRIBUTE_MODIFIED_COMMAND = "Attribute modified: ";
+
+    private static final String NODE_INSERTED_COMMAND = "Node inserted: ";
+
+    private static final String NODE_REMOVED_COMMAND = "Node removed: ";
+
+    private static final String CHAR_DATA_MODIFIED_COMMAND = "Node value changed: ";
+
+    // OTHER COMMANDS
+    /**
+     * The changes being performed outside of the DOMViewer.
+     */
+    private static final String OUTER_EDIT_COMMAND = "Document changed outside DOM Viewer";
+
+    /**
+     * Compound tree node dropped command name.
+     */
+    private static final String COMPOUND_TREE_NODE_DROP = "Node moved";
+
+    /**
+     * Remove selected nodes command name.
+     */
+    private static final String REMOVE_SELECTED_NODES = "Nodes removed";
+
+    /**
+     * The history browser.
+     */
+    protected HistoryBrowser historyBrowser;
+
+    /**
+     * Used to group custom number of changes into a single command.
+     */
+    protected AbstractCompoundCommand currentCompoundCommand;
+
+    /**
+     * Constructor. Creates the history browser.
+     */
+    public HistoryBrowserInterface(CommandController commandController) {
+        historyBrowser = new HistoryBrowser(commandController);
+    }
+
+    /**
+     * Sets the history browser's command controller.
+     *
+     * @param newCommandController
+     *            The commandController to set
+     */
+    public void setCommmandController(CommandController newCommandController) {
+        historyBrowser.setCommandController(newCommandController);
+    }
+
+    /**
+     * Creates the compound update command, that consists of custom number of
+     * commands.
+     *
+     * @param commandName
+     *            Compound command name
+     * @return CompoundUpdateCommand
+     */
+    public CompoundUpdateCommand
+            createCompoundUpdateCommand(String commandName) {
+        CompoundUpdateCommand cmd = new CompoundUpdateCommand(commandName);
+        return cmd;
+    }
+
+    /**
+     * Creates the compound NodeChangedCommand. Used to create the 'dynamic'
+     * NodeChangedCommand name
+     *
+     * @return the CompoundUpdateCommand
+     */
+    public CompoundUpdateCommand createNodeChangedCommand(Node node) {
+        return new CompoundUpdateCommand(getNodeChangedCommandName(node));
+    }
+
+    /**
+     * Creates the compound NodesDroppedCommand. Used to create the 'dynamic'
+     * NodesDroppedCommand name
+     *
+     * @param nodes
+     *            The list of the nodes that are being dropped
+     * @return the CompoundUpdateCommand
+     */
+    public CompoundUpdateCommand createNodesDroppedCommand(ArrayList nodes) {
+        return new CompoundUpdateCommand(COMPOUND_TREE_NODE_DROP);
+    }
+
+    /**
+     * Creates the compound RemoveSelectedTreeNodesCommand. Used to create the
+     * 'dynamic' RemoveSelectedTreeNodesCommand name
+     *
+     * @param nodes
+     *            The list of the nodes that are selected and should be removed
+     * @return the RemoveSelectedTreeNodesCommand
+     */
+    public CompoundUpdateCommand
+            createRemoveSelectedTreeNodesCommand(ArrayList nodes) {
+        return new CompoundUpdateCommand(REMOVE_SELECTED_NODES);
+    }
+
+    /**
+     * Executes the given compound update command.
+     *
+     * @param command
+     *            The given compound update command
+     */
+    public void performCompoundUpdateCommand(UndoableCommand command) {
+        historyBrowser.addCommand(command);
+    }
+
+    /**
+     * The compound command.
+     */
+    public static class CompoundUpdateCommand extends AbstractCompoundCommand {
+
+        /**
+         * Constructor.
+         *
+         * @param commandName
+         *            The compound command name
+         */
+        public CompoundUpdateCommand(String commandName) {
+            setName(commandName);
+        }
+    }
+
+    /**
+     * Gets the history browser.
+     *
+     * @return the historyBrowser
+     */
+    public HistoryBrowser getHistoryBrowser() {
+        return historyBrowser;
+    }
+
+
+    // ATOM COMMANDS
+
+    /**
+     * Adds the NodeInsertedCommand to historyBrowser.
+     *
+     * @param newParent
+     *            New parent node
+     * @param newSibling
+     *            New (next) sibling node
+     * @param contextNode
+     *            The node to be appended
+     */
+    public void nodeInserted(Node newParent, Node newSibling, Node contextNode) {
+        historyBrowser.addCommand(createNodeInsertedCommand(newParent,
+                newSibling, contextNode));
+    }
+
+    /**
+     * Creates the NodeInserted command.
+     *
+     * @param newParent
+     *            New parent node
+     * @param newSibling
+     *            New (next) sibling node
+     * @param contextNode
+     *            The node to be appended
+     */
+    public NodeInsertedCommand createNodeInsertedCommand(Node newParent,
+                                                         Node newSibling,
+                                                         Node contextNode) {
+        return new NodeInsertedCommand
+            (NODE_INSERTED_COMMAND + getBracketedNodeName(contextNode),
+             newParent, newSibling, contextNode);
+    }
+
+    /**
+     * Inserts the given node as a child of another.
+     */
+    public static class NodeInsertedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node's next sibling.
+         */
+        protected Node newSibling;
+
+        /**
+         * The node's new parent.
+         */
+        protected Node newParent;
+
+        /**
+         * The node to be appended.
+         */
+        protected Node contextNode;
+
+        /**
+         * Constructor.
+         */
+        public NodeInsertedCommand(String commandName, Node parent,
+                                   Node sibling, Node contextNode) {
+            setName(commandName);
+            this.newParent = parent;
+            this.contextNode = contextNode;
+            this.newSibling = sibling;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            newParent.removeChild(contextNode);
+        }
+
+        public void redo() {
+            if (newSibling != null) {
+                newParent.insertBefore(contextNode, newSibling);
+            } else {
+                newParent.appendChild(contextNode);
+            }
+        }
+
+        public boolean shouldExecute() {
+            if (newParent == null || contextNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds the NodeRemovedCommand to historyBrowser.
+     *
+     * @param oldParent
+     *            The node's old parent
+     * @param oldSibling
+     *            The node's old next sibling
+     * @param contextNode
+     *            The node to be removed
+     */
+    public void nodeRemoved(Node oldParent, Node oldSibling, Node contextNode) {
+        historyBrowser.addCommand
+            (createNodeRemovedCommand(oldParent, oldSibling, contextNode));
+    }
+
+    /**
+     * Creates the NodeRemoved command.
+     *
+     * @param oldParent
+     *            The node's old parent
+     * @param oldSibling
+     *            The node's old next sibling
+     * @param contextNode
+     *            The node to be removed
+     */
+    public NodeRemovedCommand createNodeRemovedCommand(Node oldParent,
+                                                       Node oldSibling,
+                                                       Node contextNode) {
+        return new NodeRemovedCommand
+            (NODE_REMOVED_COMMAND + getBracketedNodeName(contextNode),
+             oldParent, oldSibling, contextNode);
+    }
+
+    /**
+     * Removes the node from its parent node.
+     */
+    public static class NodeRemovedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node's old sibling.
+         */
+        protected Node oldSibling;
+
+        /**
+         * The node's new parent.
+         */
+        protected Node oldParent;
+
+        /**
+         * The node to be appended.
+         */
+        protected Node contextNode;
+
+        /**
+         * Constructor.
+         */
+        public NodeRemovedCommand(String commandName, Node oldParent,
+                                  Node oldSibling, Node contextNode) {
+            setName(commandName);
+            this.oldParent = oldParent;
+            this.contextNode = contextNode;
+            this.oldSibling = oldSibling;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            if (oldSibling != null) {
+                oldParent.insertBefore(contextNode, oldSibling);
+            } else {
+                oldParent.appendChild(contextNode);
+            }
+        }
+
+        public void redo() {
+            oldParent.removeChild(contextNode);
+        }
+
+        public boolean shouldExecute() {
+            if (oldParent == null || contextNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds the AttributeAddedCommand to historyBrowser.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param newAttributeValue
+     *            The attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public void attributeAdded(Element contextElement, String attributeName,
+                               String newAttributeValue, String namespaceURI) {
+        historyBrowser.addCommand
+            (createAttributeAddedCommand(contextElement, attributeName,
+                                         newAttributeValue, namespaceURI));
+    }
+
+    /**
+     * Creates the AttributeAdded command.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param newAttributeValue
+     *            The attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public AttributeAddedCommand
+            createAttributeAddedCommand(Element contextElement,
+                                        String attributeName,
+                                        String newAttributeValue,
+                                        String namespaceURI) {
+        return new AttributeAddedCommand
+            (ATTRIBUTE_ADDED_COMMAND + getBracketedNodeName(contextElement),
+             contextElement, attributeName, newAttributeValue, namespaceURI);
+    }
+
+    /**
+     * Adds the attribute to an element (MutationEvent.ADDITION)
+     */
+    public static class AttributeAddedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The context element.
+         */
+        protected Element contextElement;
+
+        /**
+         * The attribute name.
+         */
+        protected String attributeName;
+
+        /**
+         * The attribute value.
+         */
+        protected String newValue;
+
+        /**
+         * The namespaceURI.
+         */
+        protected String namespaceURI;
+
+        /**
+         * Constructor.
+         *
+         * @param commandName
+         *            The name of this command.
+         * @param contextElement
+         *            The context element
+         * @param attributeName
+         *            The attribute name
+         * @param newAttributeValue
+         *            The attribute value
+         * @param namespaceURI
+         *            The namespaceURI
+         */
+        public AttributeAddedCommand(String commandName,
+                                     Element contextElement,
+                                     String attributeName,
+                                     String newAttributeValue,
+                                     String namespaceURI) {
+            setName(commandName);
+            this.contextElement = contextElement;
+            this.attributeName = attributeName;
+            this.newValue = newAttributeValue;
+            this.namespaceURI = namespaceURI;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            contextElement.removeAttributeNS(namespaceURI, attributeName);
+        }
+
+        public void redo() {
+            contextElement.setAttributeNS
+                (namespaceURI, attributeName, newValue);
+        }
+
+        public boolean shouldExecute() {
+            if (contextElement == null || attributeName.length() == 0) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds the AttributeRemovedCommand to historyBrowser.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param prevAttributeValue
+     *            The previous attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public void attributeRemoved(Element contextElement,
+                                 String attributeName,
+                                 String prevAttributeValue,
+                                 String namespaceURI) {
+        historyBrowser.addCommand
+            (createAttributeRemovedCommand(contextElement, attributeName,
+                                           prevAttributeValue, namespaceURI));
+    }
+
+    /**
+     * Creates the AttributeRemoved command.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param prevAttributeValue
+     *            The previous attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public AttributeRemovedCommand
+            createAttributeRemovedCommand(Element contextElement,
+                                          String attributeName,
+                                          String prevAttributeValue,
+                                          String namespaceURI) {
+        return new AttributeRemovedCommand
+            (ATTRIBUTE_REMOVED_COMMAND + getBracketedNodeName(contextElement),
+             contextElement, attributeName, prevAttributeValue, namespaceURI);
+    }
+
+    /**
+     * Removes the attribute of an element (MutationEvent.REMOVAL)
+     */
+    public static class AttributeRemovedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The context element.
+         */
+        protected Element contextElement;
+
+        /**
+         * The attribute name.
+         */
+        protected String attributeName;
+
+        /**
+         * The previous attribute value.
+         */
+        protected String prevValue;
+
+        /**
+         * The namespaceURI.
+         */
+        protected String namespaceURI;
+
+        /**
+         * Constructor.
+         *
+         * @param commandName
+         *            The name of this command.
+         * @param contextElement
+         *            The context element
+         * @param attributeName
+         *            The attribute name
+         * @param prevAttributeValue
+         *            The previous attribute value
+         * @param namespaceURI
+         *            The namespaceURI
+         */
+        public AttributeRemovedCommand(String commandName,
+                                       Element contextElement,
+                                       String attributeName,
+                                       String prevAttributeValue,
+                                       String namespaceURI) {
+            setName(commandName);
+            this.contextElement = contextElement;
+            this.attributeName = attributeName;
+            this.prevValue = prevAttributeValue;
+            this.namespaceURI = namespaceURI;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            contextElement.setAttributeNS
+                (namespaceURI, attributeName, prevValue);
+        }
+
+        public void redo() {
+            contextElement.removeAttributeNS(namespaceURI, attributeName);
+        }
+
+        public boolean shouldExecute() {
+            if (contextElement == null || attributeName.length() == 0) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds the AttributeModifiedCommand to historyBrowser.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param prevAttributeValue
+     *            The previous attribute value
+     * @param newAttributeValue
+     *            The new attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public void attributeModified(Element contextElement,
+                                  String attributeName,
+                                  String prevAttributeValue,
+                                  String newAttributeValue,
+                                  String namespaceURI) {
+        historyBrowser.addCommand
+            (createAttributeModifiedCommand(contextElement, attributeName,
+                                            prevAttributeValue,
+                                            newAttributeValue, namespaceURI));
+    }
+
+    /**
+     * Creates the AttributeModified command.
+     *
+     * @param contextElement
+     *            The context element
+     * @param attributeName
+     *            The attribute name
+     * @param prevAttributeValue
+     *            The previous attribute value
+     * @param newAttributeValue
+     *            The new attribute value
+     * @param namespaceURI
+     *            The namespaceURI
+     */
+    public AttributeModifiedCommand
+            createAttributeModifiedCommand(Element contextElement,
+                                           String attributeName,
+                                           String prevAttributeValue,
+                                           String newAttributeValue,
+                                           String namespaceURI) {
+        return new AttributeModifiedCommand
+            (ATTRIBUTE_MODIFIED_COMMAND + getBracketedNodeName(contextElement),
+             contextElement, attributeName, prevAttributeValue,
+             newAttributeValue, namespaceURI);
+    }
+
+    /**
+     * Modifies the attribute of an element (MutationEvent.MODIFICATION)
+     */
+    public static class AttributeModifiedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The context element.
+         */
+        protected Element contextElement;
+
+        /**
+         * The attribute name.
+         */
+        protected String attributeName;
+
+        /**
+         * Previous attribute value.
+         */
+        protected String prevAttributeValue;
+
+        /**
+         * New attribute value.
+         */
+        protected String newAttributeValue;
+
+        /**
+         * The namespaceURI.
+         */
+        protected String namespaceURI;
+
+        /**
+         * Constructor.
+         *
+         * @param commandName
+         *            The name of this command.
+         * @param contextElement
+         *            The context element
+         * @param attributeName
+         *            The attribute name
+         * @param prevAttributeValue
+         *            The previous attribute value
+         * @param newAttributeValue
+         *            The new attribute value
+         * @param namespaceURI
+         *            The namespaceURI
+         */
+        public AttributeModifiedCommand(String commandName,
+                                        Element contextElement,
+                                        String attributeName,
+                                        String prevAttributeValue,
+                                        String newAttributeValue,
+                                        String namespaceURI) {
+            setName(commandName);
+            this.contextElement = contextElement;
+            this.attributeName = attributeName;
+            this.prevAttributeValue = prevAttributeValue;
+            this.newAttributeValue = newAttributeValue;
+            this.namespaceURI = namespaceURI;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            contextElement.setAttributeNS
+                (namespaceURI, attributeName, prevAttributeValue);
+        }
+
+        public void redo() {
+            contextElement.setAttributeNS
+                (namespaceURI, attributeName, newAttributeValue);
+        }
+
+        public boolean shouldExecute() {
+            if (contextElement == null || attributeName.length() == 0) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds CharDataModifiedCommand to historyBrowser.
+     *
+     * @param contextNode
+     *            The node whose nodeValue changed
+     * @param oldValue
+     *            The old node value
+     * @param newValue
+     *            The new node value
+     */
+    public void charDataModified(Node contextNode, String oldValue,
+                                 String newValue) {
+        historyBrowser.addCommand
+            (createCharDataModifiedCommand(contextNode, oldValue, newValue));
+    }
+
+    /**
+     * Creates the CharDataModified command.
+     *
+     * @param contextNode
+     *            The node whose nodeValue changed
+     * @param oldValue
+     *            The old node value
+     * @param newValue
+     *            The new node value
+     */
+    public CharDataModifiedCommand
+            createCharDataModifiedCommand(Node contextNode,
+                                          String oldValue,
+                                          String newValue) {
+        return new CharDataModifiedCommand
+            (CHAR_DATA_MODIFIED_COMMAND + getBracketedNodeName(contextNode),
+             contextNode, oldValue, newValue);
+    }
+
+    /**
+     * Sets the node value.
+     */
+    public static class CharDataModifiedCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node whose value changed.
+         */
+        protected Node contextNode;
+
+        /**
+         * Old node value.
+         */
+        protected String oldValue;
+
+        /**
+         * New node value.
+         */
+        protected String newValue;
+
+        /**
+         * Constructor.
+         *
+         * @param commandName
+         *            The command name
+         * @param contextNode
+         *            Context node
+         * @param oldValue
+         *            Old node value
+         * @param newValue
+         *            New node value
+         */
+        public CharDataModifiedCommand(String commandName, Node contextNode,
+                String oldValue, String newValue) {
+            setName(commandName);
+            this.contextNode = contextNode;
+            this.oldValue = oldValue;
+            this.newValue = newValue;
+        }
+
+        public void execute() {
+        }
+
+        public void undo() {
+            contextNode.setNodeValue(oldValue);
+        }
+
+        public void redo() {
+            contextNode.setNodeValue(newValue);
+        }
+
+        public boolean shouldExecute() {
+            if (contextNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    // OTHER COMMANDS
+
+    /**
+     * Adds and executes the AppendChildCommand to historyBrowser.
+     *
+     * @param parent
+     *            The given parent
+     * @param child
+     *            The node to be appended
+     */
+    public void appendChild(Node parent, Node child) {
+        historyBrowser.addCommand(createAppendChildCommand(parent, child));
+    }
+
+
+    /**
+     * Creates and return the AppendChild command.
+     *
+     * @param parent
+     *            The given parent
+     * @param child
+     *            The node to be appended
+     * @return the AppendChild command
+     */
+    public AppendChildCommand createAppendChildCommand(Node parent,
+                                                       Node child) {
+        return new AppendChildCommand
+            (getAppendChildCommandName(parent, child), parent, child);
+    }
+
+    /**
+     * The AppendChild command. Appends the given node to the given parent node
+     * as a last child.
+     */
+    public static class AppendChildCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node's previous parent.
+         */
+        protected Node oldParentNode;
+
+        /**
+         * The node's previous next sibling.
+         */
+        protected Node oldNextSibling;
+
+        /**
+         * The node's new parent.
+         */
+        protected Node parentNode;
+
+        /**
+         * The node to be appended.
+         */
+        protected Node childNode;
+
+        /**
+         * Constructor.
+         */
+        public AppendChildCommand(String commandName, Node parentNode,
+                                  Node childNode) {
+            setName(commandName);
+            this.oldParentNode = childNode.getParentNode();
+            this.oldNextSibling = childNode.getNextSibling();
+            this.parentNode = parentNode;
+            this.childNode = childNode;
+        }
+
+        public void execute() {
+            parentNode.appendChild(childNode);
+        }
+
+        public void undo() {
+            if (oldParentNode != null) {
+                oldParentNode.insertBefore(childNode, oldNextSibling);
+            } else {
+                parentNode.removeChild(childNode);
+            }
+        }
+
+        public void redo() {
+            execute();
+        }
+
+        public boolean shouldExecute() {
+            if (parentNode == null || childNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds and executes the InsertNodeBeforeCommand to historyBrowser.
+     *
+     * @param parent
+     *            The given parent
+     * @param sibling
+     *            Points where to be inserted
+     * @param child
+     *            The node to insert
+     */
+    public void insertChildBefore(Node parent, Node sibling, Node child) {
+        if (sibling == null) {
+            historyBrowser.addCommand(createAppendChildCommand(parent, child));
+        } else {
+            historyBrowser.addCommand
+                (createInsertNodeBeforeCommand(parent, sibling, child));
+        }
+    }
+
+    /**
+     * Creates InsertChildBefore or AppendChild command, depending on the value
+     * of siblingNode.
+     *
+     * @param parent
+     *            The parent node
+     * @param sibling
+     *            The sibling node
+     * @param child
+     *            The child node
+     * @return AppendChild command if sibling node is null, InsertChildBefore
+     *         otherwise
+     */
+    public UndoableCommand createInsertChildCommand(Node parent,
+                                                    Node sibling,
+                                                    Node child) {
+        if (sibling == null) {
+            return createAppendChildCommand(parent, child);
+        } else {
+            return createInsertNodeBeforeCommand(parent, sibling, child);
+        }
+    }
+    /**
+     * Creates and returns the InsertNodeBeforeCommand.
+     *
+     * @param parent
+     *            The given parent
+     * @param sibling
+     *            Points where to be inserted
+     * @param child
+     *            The node to insert
+     * @return the InsertNodeBeforeCommand
+     */
+    public InsertNodeBeforeCommand createInsertNodeBeforeCommand(Node parent,
+                                                                 Node sibling,
+                                                                 Node child) {
+        return new InsertNodeBeforeCommand
+            (getInsertBeforeCommandName(parent, child, sibling),
+             parent, sibling, child);
+    }
+
+    /**
+     * Inserts the given node as a child to the given parent node before the
+     * specified sibling node, or as the last child of the given parent, if the
+     * sibling node is null.
+     */
+    public static class InsertNodeBeforeCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node's previous parent.
+         */
+        protected Node oldParent;
+
+        /**
+         * The node's previous next sibling.
+         */
+        protected Node oldNextSibling;
+
+        /**
+         * The node's new next sibling.
+         */
+        protected Node newNextSibling;
+
+        /**
+         * The node's new parent.
+         */
+        protected Node parent;
+
+        /**
+         * The node to be appended.
+         */
+        protected Node child;
+
+        /**
+         * Constructor.
+         */
+        public InsertNodeBeforeCommand(String commandName, Node parent,
+                                       Node sibling, Node child) {
+            setName(commandName);
+            this.oldParent = child.getParentNode();
+            this.oldNextSibling = child.getNextSibling();
+            this.parent = parent;
+            this.child = child;
+            this.newNextSibling = sibling;
+        }
+
+        public void execute() {
+            if (newNextSibling != null) {
+                parent.insertBefore(child, newNextSibling);
+            } else {
+                parent.appendChild(child);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.batik.util.gui.AbstractUndoableCommand#undo()
+         */
+        public void undo() {
+            if (oldParent != null) {
+                oldParent.insertBefore(child, oldNextSibling);
+            } else {
+                parent.removeChild(child);
+            }
+        }
+
+        public void redo() {
+            execute();
+        }
+
+        public boolean shouldExecute() {
+            if (parent == null || child == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+
+    /**
+     * Adds and executes the ReplaceChild command to historyBrowser.
+     *
+     * @param parent
+     *            The parent node
+     * @param newChild
+     *            Points where to be inserted
+     * @param oldChild
+     *            The node to be appended
+     */
+    public void replaceChild(Node parent, Node newChild, Node oldChild) {
+//        if (sibling == null) {
+//            historyBrowser.addCommand(new AppendChildCommand(
+//                    APPEND_CHILD_COMMAND, parent, child));
+//        } else {
+//            historyBrowser.addCommand(new InsertNodeBeforeCommand(
+//                    REPLACE_CHILD_COMMAND, parent, sibling, child));
+//        }
+    }
+
+    /**
+     * insertBefore
+     */
+    public static class ReplaceChildCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node's previous parent.
+         */
+        protected Node oldParent;
+
+        /**
+         * The node's previous next sibling.
+         */
+        protected Node oldNextSibling;
+
+        /**
+         * The node's new next sibling.
+         */
+        protected Node newNextSibling;
+
+        /**
+         * The node's new parent.
+         */
+        protected Node parent;
+
+        /**
+         * The node to be appended.
+         */
+        protected Node child;
+
+        /**
+         * Constructor.
+         */
+        public ReplaceChildCommand(String commandName, Node parent,
+                                   Node sibling, Node child) {
+            setName(commandName);
+            this.oldParent = child.getParentNode();
+            this.oldNextSibling = child.getNextSibling();
+            this.parent = parent;
+            this.child = child;
+            this.newNextSibling = sibling;
+        }
+
+        public void execute() {
+            if (newNextSibling != null) {
+                parent.insertBefore(child, newNextSibling);
+            } else {
+                parent.appendChild(child);
+            }
+        }
+
+        public void undo() {
+            if (oldParent != null) {
+                oldParent.insertBefore(child, oldNextSibling);
+            } else {
+                parent.removeChild(child);
+            }
+        }
+
+        public void redo() {
+            execute();
+        }
+
+        public boolean shouldExecute() {
+            if (parent == null || child == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds and executes the RemoveChild command to the History Browser.
+     *
+     * @param parent
+     *            The given parent
+     * @param child
+     *            The given child
+     */
+    public void removeChild(Node parent, Node child) {
+        historyBrowser.addCommand(createRemoveChildCommand(parent, child));
+    }
+
+    /**
+     * Creates and returns the RemoveChild command.
+     *
+     * @param parent
+     *            The parent node
+     * @param child
+     *            The child node
+     * @return The RemoveChild command
+     */
+    public RemoveChildCommand createRemoveChildCommand(Node parent,
+                                                       Node child) {
+        return new RemoveChildCommand
+            (getRemoveChildCommandName(parent, child), parent, child);
+    }
+
+    /**
+     * The RemoveChild command. Removes the given child node from its given
+     * parent node.
+     */
+    public static class RemoveChildCommand extends AbstractUndoableCommand {
+
+        /**
+         * Node's previous parent.
+         */
+        protected Node parentNode;
+
+        /**
+         * The node to be removed.
+         */
+        protected Node childNode;
+
+        /**
+         * Node's index in parent's children array.
+         */
+        protected int indexInChildrenArray;
+
+        /**
+         * Constructor.
+         */
+        public RemoveChildCommand(String commandName, Node parentNode,
+                                  Node childNode) {
+            setName(commandName);
+            this.parentNode = parentNode;
+            this.childNode = childNode;
+        }
+
+        public void execute() {
+            indexInChildrenArray =
+                DOMUtilities.getChildIndex(childNode, parentNode);
+            parentNode.removeChild(childNode);
+        }
+
+        public void undo() {
+            Node refChild =
+                parentNode.getChildNodes().item(indexInChildrenArray);
+            parentNode.insertBefore(childNode, refChild);
+        }
+
+        public void redo() {
+            parentNode.removeChild(childNode);
+        }
+
+        public boolean shouldExecute() {
+            if (parentNode == null || childNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Adds and executes the ChangeNodeValueCommand to historyBrowser.
+     *
+     * @param contextNode
+     *            The node whose nodeValue changed
+     * @param newValue
+     *            The new node value
+     */
+    public void setNodeValue(Node contextNode, String newValue) {
+        historyBrowser.addCommand
+            (createChangeNodeValueCommand(contextNode, newValue));
+    }
+
+    /**
+     * Creates and returns the ChangeNodeValue command.
+     *
+     * @param contextNode
+     *            The node whose nodeValue changed
+     * @param newValue
+     *            The new node value
+     * @return the ChangeNodeValue command
+     */
+    public ChangeNodeValueCommand
+            createChangeNodeValueCommand(Node contextNode, String newValue) {
+        return new ChangeNodeValueCommand
+            (getChangeNodeValueCommandName(contextNode, newValue),
+             contextNode, newValue);
+    }
+
+    /**
+     * The Change Node Value command. Sets the given node value to the given
+     * node.
+     */
+    public static class ChangeNodeValueCommand extends AbstractUndoableCommand {
+
+        /**
+         * The node whose value changed.
+         */
+        protected Node contextNode;
+
+        /**
+         * New node value.
+         */
+        protected String newValue;
+
+        /**
+         * Constructor.
+         */
+        public ChangeNodeValueCommand(String commandName, Node contextNode,
+                                      String newValue) {
+            setName(commandName);
+            this.contextNode = contextNode;
+            this.newValue = newValue;
+        }
+
+        public void execute() {
+            String oldNodeValue = contextNode.getNodeValue();
+            contextNode.setNodeValue(newValue);
+            newValue = oldNodeValue;
+        }
+
+        public void undo() {
+            execute();
+        }
+
+        public void redo() {
+            execute();
+        }
+
+        public boolean shouldExecute() {
+            if (contextNode == null) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Gets the current compound command.
+     *
+     * @return the currentCompoundCommand
+     */
+    public AbstractCompoundCommand getCurrentCompoundCommand() {
+        if (currentCompoundCommand == null) {
+            currentCompoundCommand =
+                createCompoundUpdateCommand(OUTER_EDIT_COMMAND);
+        }
+        return currentCompoundCommand;
+    }
+
+    /**
+     * Adds the given command to current compound command.
+     *
+     * @param cmd
+     *            The command to add
+     */
+    public void addToCurrentCompoundCommand(AbstractUndoableCommand cmd) {
+        getCurrentCompoundCommand().addCommand(cmd);
+        // Fire the 'doCompoundEdit' event
+        historyBrowser.fireDoCompoundEdit
+            (new HistoryBrowserEvent(getCurrentCompoundCommand()));
+    }
+
+    /**
+     * Adds and executes the current compound command to history browser.
+     */
+    public void performCurrentCompoundCommand() {
+        if (getCurrentCompoundCommand().getCommandNumber() > 0) {
+            historyBrowser.addCommand(getCurrentCompoundCommand());
+            // Fire the 'compoundEditPerformed' event
+            historyBrowser.fireCompoundEditPerformed
+                (new HistoryBrowserEvent(currentCompoundCommand));
+            // Reset the current compound command
+            currentCompoundCommand = null;
+        }
+    }
+
+    // Command names
+    /**
+     * Gets the node name and the nodes id (nodeName + "nodeId").
+     *
+     * @param node
+     *            The given node
+     * @return e.g. node name with quoted node id or node name if id is empty
+     *         String
+     */
+    private String getNodeAsString(Node node) {
+        String id = "";
+        if (node.getNodeType() == Node.ELEMENT_NODE) {
+            Element e = (Element) node;
+            id = e.getAttributeNS(null, SVGConstants.SVG_ID_ATTRIBUTE);
+        }
+        if (id.length() != 0) {
+            return node.getNodeName() + " \"" + id + "\"";
+        }
+        return node.getNodeName();
+    }
+
+    /**
+     * Gets the node info in brackets.
+     *
+     * @param node
+     *            The given node
+     * @return e.g (rect "23")
+     */
+    private String getBracketedNodeName(Node node) {
+        return "(" + getNodeAsString(node) + ")";
+    }
+
+    /**
+     * Generates the "Append Child" command name.
+     *
+     * @param parentNode
+     *            The parent node
+     * @param childNode
+     *            The child node
+     * @return The command name
+     */
+    private String getAppendChildCommandName(Node parentNode, Node childNode) {
+        return "Append " + getNodeAsString(childNode) + " to "
+                + getNodeAsString(parentNode);
+    }
+
+    /**
+     * Generates the "Insert Child Before" command name.
+     *
+     * @param parentNode
+     *            The parentNode
+     * @param childNode
+     *            The node being inserted
+     * @param siblingNode
+     *            The new sibling node
+     * @return The command name
+     */
+    private String getInsertBeforeCommandName(Node parentNode, Node childNode,
+                                              Node siblingNode) {
+        return "Insert " + getNodeAsString(childNode) + " to "
+                + getNodeAsString(parentNode) + " before "
+                + getNodeAsString(siblingNode);
+    }
+
+    /**
+     * Generates the "Remove Child" command name.
+     *
+     * @param parent
+     *            The parent node
+     * @param child
+     *            The child node
+     * @return The command name
+     */
+    private String getRemoveChildCommandName(Node parent, Node child) {
+        return "Remove " + getNodeAsString(child) + " from "
+                + getNodeAsString(parent);
+    }
+
+    /**
+     * Generates the "Change Node Value" command name.
+     *
+     * @param contextNode
+     *            The node whose value is to be changed
+     * @param newValue
+     *            The new node value
+     * @return The command name
+     */
+    private String getChangeNodeValueCommandName(Node contextNode,
+                                                 String newValue) {
+        return "Change " + getNodeAsString(contextNode) + " value to "
+                + newValue;
+    }
+
+    /**
+     * Generates the "Node Changed" command name.
+     * @return    The command name
+     */
+    private String getNodeChangedCommandName(Node node) {
+        return "Node " + getNodeAsString(node) + " changed";
+    }
+}

Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java?rev=594367&r1=594366&r2=594367&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java Mon Nov 12 16:40:53 2007
@@ -109,6 +109,7 @@
 import org.apache.batik.swing.JSVGCanvas;
 import org.apache.batik.swing.gvt.GVTTreeRendererEvent;
 import org.apache.batik.swing.gvt.GVTTreeRendererListener;
+import org.apache.batik.swing.gvt.Overlay;
 import org.apache.batik.swing.svg.GVTTreeBuilderEvent;
 import org.apache.batik.swing.svg.GVTTreeBuilderListener;
 import org.apache.batik.swing.svg.LinkActivationEvent;
@@ -132,7 +133,6 @@
 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.LocationBar;
 import org.apache.batik.util.gui.MemoryMonitor;
@@ -144,6 +144,7 @@
 import org.apache.batik.util.gui.resource.ToolBarFactory;
 import org.apache.batik.util.resources.ResourceManager;
 import org.apache.batik.xml.XMLUtilities;
+
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.css.ViewCSS;
@@ -309,7 +310,7 @@
     /**
      * An extension of JSVGCanvas that exposes the Rhino interpreter.
      */
-    protected static class Canvas extends JSVGCanvas {
+    protected class Canvas extends JSVGCanvas {
 
         /**
          * Creates a new Canvas.
@@ -328,6 +329,48 @@
             }
             return bridgeContext.getInterpreter("text/ecmascript");
         }
+
+        /**
+         * JSVGViewerFrame DOMViewerController implementation.
+         */
+        protected class JSVGViewerDOMViewerController
+                // extends CanvasDOMViewerController {
+                implements DOMViewerController {
+
+            public boolean canEdit() {
+                return getUpdateManager() != null;
+            }
+
+            public ElementOverlayManager createSelectionManager() {
+                if (canEdit()) {
+                    return new ElementOverlayManager(Canvas.this);
+                }
+                return null;
+            }
+
+            public org.w3c.dom.Document getDocument() {
+                return svgDocument;
+            }
+
+            public void performUpdate(Runnable r) {
+                if (canEdit()) {
+                    getUpdateManager().getUpdateRunnableQueue().invokeLater(r);
+                } else {
+                    r.run();
+                }
+            }
+
+            public void removeSelectionOverlay(Overlay selectionOverlay) {
+                getOverlays().remove(selectionOverlay);
+            }
+
+            public void selectNode(Node node) {
+                DOMViewerAction dViewerAction =
+                    (DOMViewerAction) getAction(DOM_VIEWER_ACTION);
+                dViewerAction.openDOMViewer();
+                domViewer.selectNode(node);
+            }
+        }
     }
 
     /**
@@ -2225,20 +2268,28 @@
      * To display the DOM viewer of the document
      */
     public class DOMViewerAction extends AbstractAction {
-        public DOMViewerAction() {}
+
+        public DOMViewerAction() {
+        }
+
         public void actionPerformed(ActionEvent e) {
+            openDOMViewer();
+        }
+
+        public void openDOMViewer() {
             if (domViewer == null) {
-                domViewer = new DOMViewer();
-                if (svgDocument != null) {
-                    domViewer.setDocument(svgDocument,
-                                          (ViewCSS)svgDocument.getDocumentElement());
-                }
+                domViewer = new DOMViewer
+                    (svgCanvas.new JSVGViewerDOMViewerController());
                 Rectangle fr = getBounds();
                 Dimension td = domViewer.getSize();
-                domViewer.setLocation(fr.x + (fr.width  - td.width) / 2,
+                domViewer.setLocation(fr.x + (fr.width - td.width) / 2,
                                       fr.y + (fr.height - td.height) / 2);
             }
             domViewer.setVisible(true);
+        }
+
+        public DOMViewer getDOMViewer() {
+            return domViewer;
         }
     }
 

Added: xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/NodePickerController.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/NodePickerController.java?rev=594367&view=auto
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/NodePickerController.java (added)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/apps/svgbrowser/NodePickerController.java Mon Nov 12 16:40:53 2007
@@ -0,0 +1,43 @@
+/*
+
+   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.apps.svgbrowser;
+
+import org.w3c.dom.Element;
+
+/**
+ * Provides the information to control the NodePickerPanel behaviour.
+ *
+ * @version $Id$
+ */
+public interface NodePickerController {
+
+    /**
+     * Whether NodePickerPanel is should be editable.
+     */
+    boolean isEditable();
+
+    /**
+     * Whether the given element can be edited with the NodePickerPanel.
+     *
+     * @param el
+     *            The given element
+     * @return True if the given element can be edited by a NodePickerPanel
+     */
+    boolean canEdit(Element el);
+}