diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index dad9b365..2f2f3922 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -1034,7 +1034,7 @@ this.setRotationAngle = function(val, preventUndo) { // adding the changes to a single batch command var recalculateAllSelectedDimensions = this.recalculateAllSelectedDimensions = function() { var text = (current_resize_mode == "none" ? "position" : "size"); - var batchCmd = new BatchCommand(text); + var batchCmd = new svgedit.history.BatchCommand(text); var i = selectedElements.length; while (i--) { @@ -1813,7 +1813,7 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) { selected.removeAttribute("transform"); } - batchCmd.addSubCommand(new ChangeElementCommand(selected, initial)); + batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(selected, initial)); return batchCmd; }; @@ -3194,7 +3194,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) { } // we create the insert command that is stored on the stack // undo means to call cmd.unapply(), redo means to call cmd.apply() - addCommandToHistory(new InsertElementCommand(element)); + addCommandToHistory(new svgedit.history.InsertElementCommand(element)); call("changed",[element]); }, ani_dur * 1000); @@ -3700,7 +3700,7 @@ var pathActions = canvas.pathActions = function() { // TODO: Move into path.js svgedit.path.Path.prototype.endChanges = function(text) { if (svgedit.browser.isWebkit()) resetD(this.elem); - var cmd = new ChangeElementCommand(this.elem, {d: this.last_d}, text); + var cmd = new svgedit.history.ChangeElementCommand(this.elem, {d: this.last_d}, text); addCommandToHistory(cmd); call("changed", [this.elem]); }; @@ -4259,12 +4259,12 @@ var pathActions = canvas.pathActions = function() { var angle = svgedit.utilities.getRotationAngle(elem); if (angle == 0) return; - var batchCmd = new BatchCommand("Reorient path"); + var batchCmd = new svgedit.history.BatchCommand("Reorient path"); var changes = { d: elem.getAttribute('d'), transform: elem.getAttribute('transform') }; - batchCmd.addSubCommand(new ChangeElementCommand(elem, changes)); + batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(elem, changes)); clearSelection(); this.resetOrientation(elem); @@ -5360,7 +5360,7 @@ var convertToGroup = this.convertToGroup = function(elem) { elem = selectedElements[0]; } var $elem = $(elem); - var batchCmd = new BatchCommand(); + var batchCmd = new svgedit.history.BatchCommand(); var ts; if ($elem.data('gsvg')) { @@ -5397,7 +5397,7 @@ var convertToGroup = this.convertToGroup = function(elem) { var prev = $elem.prev(); // Remove element - batchCmd.addSubCommand(new RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode)); $elem.remove(); // See if other elements reference this symbol @@ -5439,9 +5439,9 @@ var convertToGroup = this.convertToGroup = function(elem) { // remove symbol/svg element var nextSibling = elem.nextSibling; parent.removeChild(elem); - batchCmd.addSubCommand(new RemoveElementCommand(elem, nextSibling, parent)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(elem, nextSibling, parent)); } - batchCmd.addSubCommand(new InsertElementCommand(g)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(g)); } setUseData(g); @@ -5497,12 +5497,12 @@ this.setSvgString = function(xmlString) { this.prepareSvg(newDoc); - var batchCmd = new BatchCommand("Change Source"); + var batchCmd = new svgedit.history.BatchCommand("Change Source"); // remove old svg document var nextSibling = svgcontent.nextSibling; var oldzoom = svgroot.removeChild(svgcontent); - batchCmd.addSubCommand(new RemoveElementCommand(oldzoom, nextSibling, svgroot)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(oldzoom, nextSibling, svgroot)); // set new svg document // If DOM3 adoptNode() available, use it. Otherwise fall back to DOM2 importNode() @@ -5638,10 +5638,10 @@ this.setSvgString = function(xmlString) { this.contentW = attrs['width']; this.contentH = attrs['height']; - batchCmd.addSubCommand(new InsertElementCommand(svgcontent)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(svgcontent)); // update root to the correct size var changes = content.attr(["width", "height"]); - batchCmd.addSubCommand(new ChangeElementCommand(svgroot, changes)); + batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(svgroot, changes)); // reset zoom current_zoom = 1; @@ -5693,7 +5693,7 @@ this.importSvgString = function(xmlString) { } } - var batchCmd = new BatchCommand("Import SVG"); + var batchCmd = new svgedit.history.BatchCommand("Import SVG"); if (useExisting) { var symbol = import_ids[uid].symbol; @@ -5765,7 +5765,7 @@ this.importSvgString = function(xmlString) { }; svgedit.utilities.findDefs().appendChild(symbol); - batchCmd.addSubCommand(new InsertElementCommand(symbol)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(symbol)); } var use_el = svgdoc.createElementNS(NS.SVG, "use"); @@ -5773,7 +5773,7 @@ this.importSvgString = function(xmlString) { setHref(use_el, "#" + symbol.id); (current_group || getCurrentDrawing().getCurrentLayer()).appendChild(use_el); - batchCmd.addSubCommand(new InsertElementCommand(use_el)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(use_el)); clearSelection(); use_el.setAttribute("transform", ts); @@ -5815,9 +5815,9 @@ var identifyLayers = canvas.identifyLayers = function() { // Parameters: // name - The given name this.createLayer = function(name) { - var batchCmd = new BatchCommand("Create Layer"); + var batchCmd = new svgedit.history.BatchCommand("Create Layer"); var new_layer = getCurrentDrawing().createLayer(name); - batchCmd.addSubCommand(new InsertElementCommand(new_layer)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(new_layer)); addCommandToHistory(batchCmd); clearSelection(); call("changed", [new_layer]); @@ -5831,7 +5831,7 @@ this.createLayer = function(name) { // Parameters: // name - The given name this.cloneLayer = function(name) { - var batchCmd = new BatchCommand("Duplicate Layer"); + var batchCmd = new svgedit.history.BatchCommand("Duplicate Layer"); var new_layer = svgdoc.createElementNS(NS.SVG, "g"); var layer_title = svgdoc.createElementNS(NS.SVG, "title"); layer_title.textContent = name; @@ -5848,7 +5848,7 @@ this.cloneLayer = function(name) { clearSelection(); identifyLayers(); - batchCmd.addSubCommand(new InsertElementCommand(new_layer)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(new_layer)); addCommandToHistory(batchCmd); canvas.setCurrentLayer(name); call("changed", [new_layer]); @@ -5863,9 +5863,9 @@ this.deleteCurrentLayer = function() { var parent = current_layer.parentNode; current_layer = getCurrentDrawing().deleteCurrentLayer(); if (current_layer) { - var batchCmd = new BatchCommand("Delete Layer"); + var batchCmd = new svgedit.history.BatchCommand("Delete Layer"); // store in our Undo History - batchCmd.addSubCommand(new RemoveElementCommand(current_layer, nextSibling, parent)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(current_layer, nextSibling, parent)); addCommandToHistory(batchCmd); clearSelection(); call("changed", [parent]); @@ -5908,7 +5908,7 @@ this.renameCurrentLayer = function(newname) { // setCurrentLayer will return false if the name doesn't already exist // this means we are free to rename our oldLayer if (!canvas.setCurrentLayer(newname)) { - var batchCmd = new BatchCommand("Rename Layer"); + var batchCmd = new svgedit.history.BatchCommand("Rename Layer"); // find the index of the layer for (var i = 0; i < drawing.getNumLayers(); ++i) { if (drawing.all_layers[i][1] == oldLayer) break; @@ -5926,7 +5926,7 @@ this.renameCurrentLayer = function(newname) { while (child.firstChild) { child.removeChild(child.firstChild); } child.textContent = newname; - batchCmd.addSubCommand(new ChangeElementCommand(child, {"#text":oldname})); + batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(child, {"#text":oldname})); addCommandToHistory(batchCmd); call("changed", [oldLayer]); return true; @@ -5972,7 +5972,7 @@ this.setCurrentLayerPosition = function(newpos) { refLayer = drawing.all_layers[newpos][1]; } svgcontent.insertBefore(drawing.current_layer, refLayer); - addCommandToHistory(new MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent)); + addCommandToHistory(new svgedit.history.MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent)); identifyLayers(); canvas.setCurrentLayer(drawing.getLayerName(newpos)); @@ -6000,7 +6000,7 @@ this.setLayerVisibility = function(layername, bVisible) { var layer = drawing.setLayerVisibility(layername, bVisible); if (layer) { var oldDisplay = prevVisibility ? 'inline' : 'none'; - addCommandToHistory(new ChangeElementCommand(layer, {'display':oldDisplay}, 'Layer Visibility')); + addCommandToHistory(new svgedit.history.ChangeElementCommand(layer, {'display':oldDisplay}, 'Layer Visibility')); } else { return false; } @@ -6034,7 +6034,7 @@ this.moveSelectedToLayer = function(layername) { } if (!layer) return false; - var batchCmd = new BatchCommand("Move Elements to Layer"); + var batchCmd = new svgedit.history.BatchCommand("Move Elements to Layer"); // loop for each selected element and move it var selElems = selectedElements; @@ -6046,7 +6046,7 @@ this.moveSelectedToLayer = function(layername) { // TODO: this is pretty brittle! var oldLayer = elem.parentNode; layer.appendChild(elem); - batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldLayer)); + batchCmd.addSubCommand(new svgedit.history.MoveElementCommand(elem, oldNextSibling, oldLayer)); } addCommandToHistory(batchCmd); @@ -6055,26 +6055,26 @@ this.moveSelectedToLayer = function(layername) { }; this.mergeLayer = function(skipHistory) { - var batchCmd = new BatchCommand("Merge Layer"); + var batchCmd = new svgedit.history.BatchCommand("Merge Layer"); var drawing = getCurrentDrawing(); var prev = $(drawing.current_layer).prev()[0]; if (!prev) return; var childs = drawing.current_layer.childNodes; var len = childs.length; var layerNextSibling = drawing.current_layer.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(drawing.current_layer, layerNextSibling, svgcontent)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(drawing.current_layer, layerNextSibling, svgcontent)); while (drawing.current_layer.firstChild) { var ch = drawing.current_layer.firstChild; if (ch.localName == 'title') { var chNextSibling = ch.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, drawing.current_layer)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(ch, chNextSibling, drawing.current_layer)); drawing.current_layer.removeChild(ch); continue; } var oldNextSibling = ch.nextSibling; prev.appendChild(ch); - batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, drawing.current_layer)); + batchCmd.addSubCommand(new svgedit.history.MoveElementCommand(ch, oldNextSibling, drawing.current_layer)); } // Remove current layer @@ -6094,7 +6094,7 @@ this.mergeLayer = function(skipHistory) { }; this.mergeAllLayers = function() { - var batchCmd = new BatchCommand("Merge all Layers"); + var batchCmd = new svgedit.history.BatchCommand("Merge all Layers"); var drawing = getCurrentDrawing(); drawing.current_layer = drawing.all_layers[drawing.getNumLayers()-1][1]; while ($(svgcontent).children('g').length > 1) { @@ -6269,24 +6269,24 @@ this.setGroupTitle = function(val) { var ts = $(elem).children('title'); - var batchCmd = new BatchCommand("Set Label"); + var batchCmd = new svgedit.history.BatchCommand("Set Label"); if (!val.length) { // Remove title element var tsNextSibling = ts.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(ts[0], tsNextSibling, elem)); + batchCmd.addSubCommand(new svgedit.history.RemoveElementCommand(ts[0], tsNextSibling, elem)); ts.remove(); } else if (ts.length) { // Change title contents var title = ts[0]; - batchCmd.addSubCommand(new ChangeElementCommand(title, {'#text': title.textContent})); + batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(title, {'#text': title.textContent})); title.textContent = val; } else { // Add title element title = svgdoc.createElementNS(NS.SVG, "title"); title.textContent = val; $(elem).prepend(title); - batchCmd.addSubCommand(new InsertElementCommand(title)); + batchCmd.addSubCommand(new svgedit.history.InsertElementCommand(title)); } addCommandToHistory(batchCmd); @@ -6307,7 +6307,7 @@ this.getDocumentTitle = function() { this.setDocumentTitle = function(newtitle) { var childs = svgcontent.childNodes, doc_title = false, old_title = ''; - var batchCmd = new BatchCommand("Change Image Title"); + var batchCmd = new svgedit.history.BatchCommand("Change Image Title"); for (var i=0; i + @@ -19,7 +20,9 @@ } }; + var svgroot = document.getElementById('svgroot'); var svg = document.createElementNS(svgedit.NS.SVG, 'svg'); + svgroot.appendChild(svg); var elemId = 1; function setUp() { @@ -39,16 +42,29 @@ }); } + function tearDown() { + while(svg.hasChildNodes()) { + svg.removeChild(svg.firstChild); + } + } + // TODO: Since recalculateDimensions() and surrounding code is // probably the largest, most complicated and strange piece of // code in SVG-edit, we need to write a whole lot of unit tests // for it here. + test('Test remapElement(translate) for rect', function() { expect(4); setUp(); - var rect = document.createElementNS(svgns, 'rect'); + var rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + rect.setAttribute('x', '200'); + rect.setAttribute('y', '150'); + rect.setAttribute('width', '250'); + rect.setAttribute('height', '120'); + svg.appendChild(rect); + var attrs = { x: '200', y: '150', @@ -68,7 +84,241 @@ equals(rect.getAttribute('y'), '100'); equals(rect.getAttribute('width'), '125'); equals(rect.getAttribute('height'), '75'); + + tearDown(); }); + + test('Test remapElement(scale) for rect', function() { + expect(4); + setUp(); + + var rect = document.createElementNS(svgedit.NS.SVG, 'rect'); + rect.setAttribute('width', '250'); + rect.setAttribute('height', '120'); + svg.appendChild(rect); + + var attrs = { + x: '0', + y: '0', + width: '250', + height: '120' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(rect, attrs, m); + + equals(rect.getAttribute('x'), '0'); + equals(rect.getAttribute('y'), '0'); + equals(rect.getAttribute('width'), '500'); + equals(rect.getAttribute('height'), '60'); + + tearDown(); + }); + + test('Test remapElement(translate) for circle', function() { + expect(3); + setUp(); + + var circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + circle.setAttribute('cx', '200'); + circle.setAttribute('cy', '150'); + circle.setAttribute('r', '125'); + svg.appendChild(circle); + + var attrs = { + cx: '200', + cy: '150', + r: '125' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(circle, attrs, m); + + equals(circle.getAttribute('cx'), '300'); + equals(circle.getAttribute('cy'), '100'); + equals(circle.getAttribute('r'), '125'); + + tearDown(); + }); + + test('Test remapElement(scale) for circle', function() { + expect(3); + setUp(); + + var circle = document.createElementNS(svgedit.NS.SVG, 'circle'); + circle.setAttribute('cx', '200'); + circle.setAttribute('cy', '150'); + circle.setAttribute('r', '250'); + svg.appendChild(circle); + + var attrs = { + cx: '200', + cy: '150', + r: '250' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(circle, attrs, m); + + equals(circle.getAttribute('cx'), '400'); + equals(circle.getAttribute('cy'), '75'); + // Radius is the minimum that fits in the new bounding box. + equals(circle.getAttribute('r'), '125'); + + tearDown(); + }); + + test('Test remapElement(translate) for ellipse', function() { + expect(4); + setUp(); + + var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + ellipse.setAttribute('cx', '200'); + ellipse.setAttribute('cy', '150'); + ellipse.setAttribute('rx', '125'); + ellipse.setAttribute('ry', '75'); + svg.appendChild(ellipse); + + var attrs = { + cx: '200', + cy: '150', + rx: '125', + ry: '75' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(ellipse, attrs, m); + + equals(ellipse.getAttribute('cx'), '300'); + equals(ellipse.getAttribute('cy'), '100'); + equals(ellipse.getAttribute('rx'), '125'); + equals(ellipse.getAttribute('ry'), '75'); + + tearDown(); + }); + + test('Test remapElement(scale) for ellipse', function() { + expect(4); + setUp(); + + var ellipse = document.createElementNS(svgedit.NS.SVG, 'ellipse'); + ellipse.setAttribute('cx', '200'); + ellipse.setAttribute('cy', '150'); + ellipse.setAttribute('rx', '250'); + ellipse.setAttribute('ry', '120'); + svg.appendChild(ellipse); + + var attrs = { + cx: '200', + cy: '150', + rx: '250', + ry: '120' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(ellipse, attrs, m); + + equals(ellipse.getAttribute('cx'), '400'); + equals(ellipse.getAttribute('cy'), '75'); + equals(ellipse.getAttribute('rx'), '500'); + equals(ellipse.getAttribute('ry'), '60'); + + tearDown(); + }); + + test('Test remapElement(translate) for line', function() { + expect(4); + setUp(); + + var line = document.createElementNS(svgedit.NS.SVG, 'line'); + line.setAttribute('x1', '50'); + line.setAttribute('y1', '100'); + line.setAttribute('x2', '120'); + line.setAttribute('y2', '200'); + svg.appendChild(line); + + var attrs = { + x1: '50', + y1: '100', + x2: '120', + y2: '200' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 1; m.b = 0; + m.c = 0; m.d = 1; + m.e = 100; m.f = -50; + + svgedit.coords.remapElement(line, attrs, m); + + equals(line.getAttribute('x1'), '150'); + equals(line.getAttribute('y1'), '50'); + equals(line.getAttribute('x2'), '220'); + equals(line.getAttribute('y2'), '150'); + + tearDown(); + }); + + test('Test remapElement(scale) for line', function() { + expect(4); + setUp(); + + var line = document.createElementNS(svgedit.NS.SVG, 'line'); + line.setAttribute('x1', '50'); + line.setAttribute('y1', '100'); + line.setAttribute('x2', '120'); + line.setAttribute('y2', '200'); + svg.appendChild(line); + + var attrs = { + x1: '50', + y1: '100', + x2: '120', + y2: '200' + } + + // Create a translate. + var m = svg.createSVGMatrix(); + m.a = 2; m.b = 0; + m.c = 0; m.d = 0.5; + m.e = 0; m.f = 0; + + svgedit.coords.remapElement(line, attrs, m); + + equals(line.getAttribute('x1'), '100'); + equals(line.getAttribute('y1'), '50'); + equals(line.getAttribute('x2'), '240'); + equals(line.getAttribute('y2'), '100'); + + tearDown(); + }); + }); @@ -78,7 +328,6 @@

- +