From 6218fc42b7bf9d374b01d77647c66e166bfb7a00 Mon Sep 17 00:00:00 2001 From: Jeff Schiller Date: Thu, 28 Oct 2010 05:50:39 +0000 Subject: [PATCH] Revert changes of previous revision git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1830 eee81c28-f429-11dd-99c0-75d572ba1ddd --- editor/history.js | 321 ----------------------------------------- editor/svg-editor.html | 2 - editor/svgcanvas.js | 309 +++++++++++++++++++++++++++++++++++++-- editor/svgutils.js | 33 ++++- 4 files changed, 329 insertions(+), 336 deletions(-) diff --git a/editor/history.js b/editor/history.js index c7f31674..e69de29b 100644 --- a/editor/history.js +++ b/editor/history.js @@ -1,321 +0,0 @@ -/** - * SVG-edit History Commands - * - * Licensed under the Apache License, Version 2 - * - * Copyright(c) 2010 Jeff Schiller - */ - -// Dependencies: -// 1) jQuery - -(function() { - -if (!window.svgedit) { - window.svgedit = {}; -} - -if (!svgedit.history) { - svgedit.history = {}; -} - -// TODO: create a 'typing' command object that tracks changes in text -// if a new Typing command is created and the top command on the stack is also a Typing -// and they both affect the same element, then collapse the two commands into one - -// Group: Undo/Redo history management - -// Class: svgedit.history.ChangeElementCommand -// History command to make a change to an element. -// Usually an attribute change, but can also be textcontent. -// -// Parameters: -// elem - The DOM element that was changed -// attrs - An object with the attributes to be changed and the values they had *before* the change -// text - An optional string visible to user related to this change -svgedit.history.ChangeElementCommand = function(elem, attrs, text) { - this.elem = elem; - this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName); - this.newValues = {}; - this.oldValues = attrs; - for (var attr in attrs) { - if (attr == "#text") this.newValues[attr] = elem.textContent; - else if (attr == "#href") this.newValues[attr] = getHref(elem); - else this.newValues[attr] = elem.getAttribute(attr); - } - - // Function: ChangeElementCommand.apply - // Performs the stored change action - this.apply = function() { - var bChangedTransform = false; - for(var attr in this.newValues ) { - if (this.newValues[attr]) { - if (attr == "#text") this.elem.textContent = this.newValues[attr]; - else if (attr == "#href") setHref(this.elem, this.newValues[attr]) - else this.elem.setAttribute(attr, this.newValues[attr]); - } - else { - if (attr == "#text") this.elem.textContent = ""; - else { - this.elem.setAttribute(attr, ""); - this.elem.removeAttribute(attr); - } - } - - if (attr == "transform") { bChangedTransform = true; } - else if (attr == "stdDeviation") { canvas.setBlurOffsets(this.elem.parentNode, this.newValues[attr]); } - - } - // relocate rotational transform, if necessary - if(!bChangedTransform) { - var angle = getRotationAngle(elem); - if (angle) { - var bbox = elem.getBBox(); - var cx = bbox.x + bbox.width/2, - cy = bbox.y + bbox.height/2; - var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); - if (rotate != elem.getAttribute("transform")) { - elem.setAttribute("transform", rotate); - } - } - } - // if we are changing layer names, re-identify all layers - if (this.elem.tagName == "title" && this.elem.parentNode.parentNode == svgcontent) { - identifyLayers(); - } - return true; - }; - - // Function: ChangeElementCommand.unapply - // Reverses the stored change action - this.unapply = function() { - var bChangedTransform = false; - for(var attr in this.oldValues ) { - if (this.oldValues[attr]) { - if (attr == "#text") this.elem.textContent = this.oldValues[attr]; - else if (attr == "#href") setHref(this.elem, this.oldValues[attr]); - else this.elem.setAttribute(attr, this.oldValues[attr]); - - if (attr == "stdDeviation") canvas.setBlurOffsets(this.elem.parentNode, this.oldValues[attr]); - } - else { - if (attr == "#text") this.elem.textContent = ""; - else this.elem.removeAttribute(attr); - } - if (attr == "transform") { bChangedTransform = true; } - } - // relocate rotational transform, if necessary - if(!bChangedTransform) { - var angle = getRotationAngle(elem); - if (angle) { - var bbox = elem.getBBox(); - var cx = bbox.x + bbox.width/2, - cy = bbox.y + bbox.height/2; - var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); - if (rotate != elem.getAttribute("transform")) { - elem.setAttribute("transform", rotate); - } - } - } - // if we are changing layer names, re-identify all layers - if (this.elem.tagName == "title" && this.elem.parentNode.parentNode == svgcontent) { - identifyLayers(); - } - - // Remove transformlist to prevent confusion that causes bugs like 575. - if (svgTransformLists[this.elem.id]) { - delete svgTransformLists[this.elem.id]; - } - - return true; - }; - - // Function: ChangeElementCommand.elements - // Returns array with element associated with this command - this.elements = function() { return [this.elem]; } -}; - -// Class: svgedit.history.InsertElementCommand -// History command for an element that was added to the DOM -// -// Parameters: -// elem - The newly added DOM element -// text - An optional string visible to user related to this change -svgedit.history.InsertElementCommand = function(elem, text) { - this.elem = elem; - this.text = text || ("Create " + elem.tagName); - this.parent = elem.parentNode; - - // Function: InsertElementCommand.apply - // Re-Inserts the new element - this.apply = function() { - this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); - - restoreRefElems(this.elem); - - if (this.parent == svgcontent) { - identifyLayers(); - } - }; - - // Function: InsertElementCommand.unapply - // Removes the element - this.unapply = function() { - this.parent = this.elem.parentNode; - this.elem = this.elem.parentNode.removeChild(this.elem); - if (this.parent == svgcontent) { - identifyLayers(); - } - }; - - // Function: InsertElementCommand.elements - // Returns array with element associated with this command - this.elements = function() { return [this.elem]; }; -}; - -// Class: svgedit.history.RemoveElementCommand -// History command for an element removed from the DOM -// -// Parameters: -// elem - The removed DOM element -// parent - The DOM element's parent -// text - An optional string visible to user related to this change -svgedit.history.RemoveElementCommand = function(elem, parent, text) { - this.elem = elem; - this.text = text || ("Delete " + elem.tagName); - this.parent = parent; - - // Function: RemoveElementCommand.apply - // Re-removes the new element - this.apply = function() { - if (svgTransformLists[this.elem.id]) { - delete svgTransformLists[this.elem.id]; - } - - this.parent = this.elem.parentNode; - this.elem = this.parent.removeChild(this.elem); - if (this.parent == svgcontent) { - identifyLayers(); - } - }; - - // Function: RemoveElementCommand.unapply - // Re-adds the new element - this.unapply = function() { - if (svgTransformLists[this.elem.id]) { - delete svgTransformLists[this.elem.id]; - } - - this.parent.insertBefore(this.elem, this.elem.nextSibling); - - restoreRefElems(this.elem); - - if (this.parent === svgcontent) { - identifyLayers(); - } - }; - - // Function: RemoveElementCommand.elements - // Returns array with element associated with this command - this.elements = function() { return [this.elem]; }; - - // special hack for webkit: remove this element's entry in the svgTransformLists map - if (svgTransformLists[elem.id]) { - delete svgTransformLists[elem.id]; - } -}; - -// Class: svgedit.history.MoveElementCommand -// History command for an element that had its DOM position changed -// -// Parameters: -// elem - The DOM element that was moved -// oldNextSibling - The element's next sibling before it was moved -// oldParent - The element's parent before it was moved -// text - An optional string visible to user related to this change -svgedit.history.MoveElementCommand = function(elem, oldNextSibling, oldParent, text) { - this.elem = elem; - this.text = text ? ("Move " + elem.tagName + " to " + text) : ("Move " + elem.tagName); - this.oldNextSibling = oldNextSibling; - this.oldParent = oldParent; - this.newNextSibling = elem.nextSibling; - this.newParent = elem.parentNode; - - // Function: MoveElementCommand.unapply - // Re-positions the element - this.apply = function() { - this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling); - if (this.newParent == svgcontent) { - identifyLayers(); - } - }; - - // Function: MoveElementCommand.unapply - // Positions the element back to its original location - this.unapply = function() { - this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling); - if (this.oldParent == svgcontent) { - identifyLayers(); - } - }; - - // Function: MoveElementCommand.elements - // Returns array with element associated with this command - this.elements = function() { return [this.elem]; }; -}; - - -// Class: svgedit.history.BatchCommand -// History command that can contain/execute multiple other commands -// -// Parameters: -// text - An optional string visible to user related to this change -svgedit.history.BatchCommand = function(text) { - this.text = text || "Batch Command"; - this.stack = []; - - // Function: BatchCommand.apply - // Runs "apply" on all subcommands - this.apply = function() { - var len = this.stack.length; - for (var i = 0; i < len; ++i) { - this.stack[i].apply(); - } - }; - - // Function: BatchCommand.unapply - // Runs "unapply" on all subcommands - this.unapply = function() { - for (var i = this.stack.length-1; i >= 0; i--) { - this.stack[i].unapply(); - } - }; - - // Function: BatchCommand.elements - // Iterate through all our subcommands and returns all the elements we are changing - this.elements = function() { - var elems = []; - var cmd = this.stack.length; - while (cmd--) { - var thisElems = this.stack[cmd].elements(); - var elem = thisElems.length; - while (elem--) { - if (elems.indexOf(thisElems[elem]) == -1) elems.push(thisElems[elem]); - } - } - return elems; - }; - - // Function: BatchCommand.addSubCommand - // Adds a given command to the history stack - // - // Parameters: - // cmd - The undo command object to add - this.addSubCommand = function(cmd) { this.stack.push(cmd); }; - - // Function: BatchCommand.isEmpty - // Returns a boolean indicating whether or not the batch command is empty - this.isEmpty = function() { return this.stack.length == 0; }; -}; - -})(); diff --git a/editor/svg-editor.html b/editor/svg-editor.html index 43885a2f..fb16ba90 100644 --- a/editor/svg-editor.html +++ b/editor/svg-editor.html @@ -19,7 +19,6 @@ - @@ -34,7 +33,6 @@ - diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 29f2b8bf..a6fdc461 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -9,12 +9,6 @@ * */ -// Dependencies: -// 1) jQuery -// 2) browsersupport.js -// 3) history.js -// 4) svgutils.js - if(!window.console) { window.console = {}; window.console.log = function(str) {}; @@ -540,14 +534,305 @@ var restoreRefElems = function(elem) { } } +// Group: Undo/Redo history management + this.undoCmd = {}; -// "Import" svgedit.history classes. -var ChangeElementCommand = this.undoCmd.changeElement = svgedit.history.ChangeElementCommand; -var InsertElementCommand = this.undoCmd.insertElement = svgedit.history.InsertElementCommand; -var RemoveElementCommand = this.undoCmd.removeElement = svgedit.history.RemoveElementCommand; -var MoveElementCommand = this.undoCmd.moveElement = svgedit.history.MoveElementCommand; -var BatchCommand = this.undoCmd.batch = svgedit.history.BatchCommand; +// Function: ChangeElementCommand +// History command to make a change to an element. +// Usually an attribute change, but can also be textcontent. +// +// Parameters: +// elem - The DOM element that was changed +// attrs - An object with the attributes to be changed and the values they had *before* the change +// text - An optional string visible to user related to this change +var ChangeElementCommand = this.undoCmd.changeElement = function(elem, attrs, text) { + this.elem = elem; + this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName); + this.newValues = {}; + this.oldValues = attrs; + for (var attr in attrs) { + if (attr == "#text") this.newValues[attr] = elem.textContent; + else if (attr == "#href") this.newValues[attr] = getHref(elem); + else this.newValues[attr] = elem.getAttribute(attr); + } + + // Function: ChangeElementCommand.apply + // Performs the stored change action + this.apply = function() { + var bChangedTransform = false; + for(var attr in this.newValues ) { + if (this.newValues[attr]) { + if (attr == "#text") this.elem.textContent = this.newValues[attr]; + else if (attr == "#href") setHref(this.elem, this.newValues[attr]) + else this.elem.setAttribute(attr, this.newValues[attr]); + } + else { + if (attr == "#text") this.elem.textContent = ""; + else { + this.elem.setAttribute(attr, ""); + this.elem.removeAttribute(attr); + } + } + + if (attr == "transform") { bChangedTransform = true; } + else if (attr == "stdDeviation") { canvas.setBlurOffsets(this.elem.parentNode, this.newValues[attr]); } + + } + // relocate rotational transform, if necessary + if(!bChangedTransform) { + var angle = getRotationAngle(elem); + if (angle) { + var bbox = elem.getBBox(); + var cx = bbox.x + bbox.width/2, + cy = bbox.y + bbox.height/2; + var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); + if (rotate != elem.getAttribute("transform")) { + elem.setAttribute("transform", rotate); + } + } + } + // if we are changing layer names, re-identify all layers + if (this.elem.tagName == "title" && this.elem.parentNode.parentNode == svgcontent) { + identifyLayers(); + } + return true; + }; + + // Function: ChangeElementCommand.unapply + // Reverses the stored change action + this.unapply = function() { + var bChangedTransform = false; + for(var attr in this.oldValues ) { + if (this.oldValues[attr]) { + if (attr == "#text") this.elem.textContent = this.oldValues[attr]; + else if (attr == "#href") setHref(this.elem, this.oldValues[attr]); + else this.elem.setAttribute(attr, this.oldValues[attr]); + + if (attr == "stdDeviation") canvas.setBlurOffsets(this.elem.parentNode, this.oldValues[attr]); + } + else { + if (attr == "#text") this.elem.textContent = ""; + else this.elem.removeAttribute(attr); + } + if (attr == "transform") { bChangedTransform = true; } + } + // relocate rotational transform, if necessary + if(!bChangedTransform) { + var angle = getRotationAngle(elem); + if (angle) { + var bbox = elem.getBBox(); + var cx = bbox.x + bbox.width/2, + cy = bbox.y + bbox.height/2; + var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); + if (rotate != elem.getAttribute("transform")) { + elem.setAttribute("transform", rotate); + } + } + } + // if we are changing layer names, re-identify all layers + if (this.elem.tagName == "title" && this.elem.parentNode.parentNode == svgcontent) { + identifyLayers(); + } + + // Remove transformlist to prevent confusion that causes bugs like 575. + if (svgTransformLists[this.elem.id]) { + delete svgTransformLists[this.elem.id]; + } + + return true; + }; + + // Function: ChangeElementCommand.elements + // Returns array with element associated with this command + this.elements = function() { return [this.elem]; } +} + +// Function: InsertElementCommand +// History command for an element that was added to the DOM +// +// Parameters: +// elem - The newly added DOM element +// text - An optional string visible to user related to this change +var InsertElementCommand = this.undoCmd.insertElement = function(elem, text) { + this.elem = elem; + this.text = text || ("Create " + elem.tagName); + this.parent = elem.parentNode; + + // Function: InsertElementCommand.apply + // Re-Inserts the new element + this.apply = function() { + this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); + + restoreRefElems(this.elem); + + if (this.parent == svgcontent) { + identifyLayers(); + } + }; + + // Function: InsertElementCommand.unapply + // Removes the element + this.unapply = function() { + this.parent = this.elem.parentNode; + this.elem = this.elem.parentNode.removeChild(this.elem); + if (this.parent == svgcontent) { + identifyLayers(); + } + }; + + // Function: InsertElementCommand.elements + // Returns array with element associated with this command + this.elements = function() { return [this.elem]; }; +} + +// Function: RemoveElementCommand +// History command for an element removed from the DOM +// +// Parameters: +// elem - The removed DOM element +// parent - The DOM element's parent +// text - An optional string visible to user related to this change +var RemoveElementCommand = this.undoCmd.removeElement = function(elem, parent, text) { + this.elem = elem; + this.text = text || ("Delete " + elem.tagName); + this.parent = parent; + + // Function: RemoveElementCommand.apply + // Re-removes the new element + this.apply = function() { + if (svgTransformLists[this.elem.id]) { + delete svgTransformLists[this.elem.id]; + } + + this.parent = this.elem.parentNode; + this.elem = this.parent.removeChild(this.elem); + if (this.parent == svgcontent) { + identifyLayers(); + } + }; + + // Function: RemoveElementCommand.unapply + // Re-adds the new element + this.unapply = function() { + if (svgTransformLists[this.elem.id]) { + delete svgTransformLists[this.elem.id]; + } + + this.parent.insertBefore(this.elem, this.elem.nextSibling); + + restoreRefElems(this.elem); + + if (this.parent === svgcontent) { + identifyLayers(); + } + }; + + // Function: RemoveElementCommand.elements + // Returns array with element associated with this command + this.elements = function() { return [this.elem]; }; + + // special hack for webkit: remove this element's entry in the svgTransformLists map + if (svgTransformLists[elem.id]) { + delete svgTransformLists[elem.id]; + } +} + +// Function: MoveElementCommand +// History command for an element that had its DOM position changed +// +// Parameters: +// elem - The DOM element that was moved +// oldNextSibling - The element's next sibling before it was moved +// oldParent - The element's parent before it was moved +// text - An optional string visible to user related to this change +var MoveElementCommand = this.undoCmd.moveElement = function(elem, oldNextSibling, oldParent, text) { + this.elem = elem; + this.text = text ? ("Move " + elem.tagName + " to " + text) : ("Move " + elem.tagName); + this.oldNextSibling = oldNextSibling; + this.oldParent = oldParent; + this.newNextSibling = elem.nextSibling; + this.newParent = elem.parentNode; + + // Function: MoveElementCommand.unapply + // Re-positions the element + this.apply = function() { + this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling); + if (this.newParent == svgcontent) { + identifyLayers(); + } + }; + + // Function: MoveElementCommand.unapply + // Positions the element back to its original location + this.unapply = function() { + this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling); + if (this.oldParent == svgcontent) { + identifyLayers(); + } + }; + + // Function: MoveElementCommand.elements + // Returns array with element associated with this command + this.elements = function() { return [this.elem]; }; +} + +// TODO: create a 'typing' command object that tracks changes in text +// if a new Typing command is created and the top command on the stack is also a Typing +// and they both affect the same element, then collapse the two commands into one + +// Function: BatchCommand +// History command that can contain/execute multiple other commands +// +// Parameters: +// text - An optional string visible to user related to this change +var BatchCommand = this.undoCmd.batch = function(text) { + this.text = text || "Batch Command"; + this.stack = []; + + // Function: BatchCommand.apply + // Runs "apply" on all subcommands + this.apply = function() { + var len = this.stack.length; + for (var i = 0; i < len; ++i) { + this.stack[i].apply(); + } + }; + + // Function: BatchCommand.unapply + // Runs "unapply" on all subcommands + this.unapply = function() { + for (var i = this.stack.length-1; i >= 0; i--) { + this.stack[i].unapply(); + } + }; + + // Function: BatchCommand.elements + // Iterate through all our subcommands and returns all the elements we are changing + this.elements = function() { + var elems = []; + var cmd = this.stack.length; + while (cmd--) { + var thisElems = this.stack[cmd].elements(); + var elem = thisElems.length; + while (elem--) { + if (elems.indexOf(thisElems[elem]) == -1) elems.push(thisElems[elem]); + } + } + return elems; + }; + + // Function: BatchCommand.addSubCommand + // Adds a given command to the history stack + // + // Parameters: + // cmd - The undo command object to add + this.addSubCommand = function(cmd) { this.stack.push(cmd); }; + + // Function: BatchCommand.isEmpty + // Returns a boolean indicating whether or not the batch command is empty + this.isEmpty = function() { return this.stack.length == 0; }; +} // Set scope for addCommandToHistory var addCommandToHistory; diff --git a/editor/svgutils.js b/editor/svgutils.js index a4962f34..1d4fe534 100644 --- a/editor/svgutils.js +++ b/editor/svgutils.js @@ -290,7 +290,7 @@ svgedit.Utilities.walkTreePost = function(elem, cbFn) { } }; -// Function: getUrlFromAttr +// Function: svgedit.Utilities.getUrlFromAttr // Extracts the URL from the url(...) syntax of some attributes. // Three variants: // * @@ -319,4 +319,35 @@ svgedit.Utilities.getUrlFromAttr = function(attrVal) { return null; }; +// Function: svgedit.Utilities.getHref +// Returns the given element's xlink:href value +svgedit.Utilities.getHref = function(elem) { + return elem.getAttributeNS(xlinkns, "href"); +} + +// Function: svgedit.Utilities.setHref +// Sets the given element's xlink:href value +svgedit.Utilities.setHref = function(elem, val) { + elem.setAttributeNS(xlinkns, "xlink:href", val); +} + +// Function: findDefs +// Parameters: +// svgElement - The element. +// +// Returns: +// The document's element, create it first if necessary +svgedit.Utilities.findDefs = function(svgElement) { + var svgElement = svgDoc.documentElement; + var defs = svgElement.getElementsByTagNameNS(svgns, "defs"); + if (defs.length > 0) { + defs = defs[0]; + } + else { + // first child is a comment, so call nextSibling + defs = svgElement.insertBefore( svgElement.ownerDocument.createElementNS(svgns, "defs" ), svgElement.firstChild.nextSibling); + } + return defs; +}; + })(); \ No newline at end of file