From 4b5011eb44f14d2cdbd7a62ed7a76512b7ce102f Mon Sep 17 00:00:00 2001 From: Alexis Deveria Date: Tue, 9 Feb 2010 20:15:52 +0000 Subject: [PATCH] Largely added support for different units (issue 444) git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1364 eee81c28-f429-11dd-99c0-75d572ba1ddd --- editor/svg-editor.js | 17 +---- editor/svgcanvas.js | 178 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 141 insertions(+), 54 deletions(-) diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 5c0cd4ba..174c9d64 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -166,8 +166,6 @@ function svg_edit_setup() { var multiselected = false; var editingsource = false; var docprops = false; - var length_attrs = ['x','y','x1','x2','y1','y2','cx','cy','width','height','r','rx','ry','width','height','radius']; - var length_types = ['em','ex','px','cm','mm','in','pt','pc','%']; var fillPaint = new $.jGraduate.Paint({solidColor: "FF0000"}); // solid red var strokePaint = new $.jGraduate.Paint({solidColor: "000000"}); // solid black @@ -977,20 +975,7 @@ function svg_edit_setup() { $('.attr_changer').change(function() { var attr = this.getAttribute("data-attr"); var val = this.value; - var valid = false; - if($.inArray(attr, length_attrs) != -1) { - if(!isNaN(val)) { - valid = true; - } else { - //TODO: Allow the values in length_types, then uncomment this: -// val = val.toLowerCase(); -// $.each(length_types, function(i, unit) { -// if(valid) return; -// var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); -// if(re.test(val)) valid = true; -// }); - } - } else valid = true; + var valid = svgCanvas.isValidUnit(attr, val); if(!valid) { $.alert(uiStrings.invalidAttrValGiven); diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index ab17ccb1..74d16e4a 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -163,7 +163,7 @@ function ChangeElementCommand(elem, attrs, text) { for(var attr in this.newValues ) { if (this.newValues[attr]) { if (attr == "#text") this.elem.textContent = this.newValues[attr]; - else this.elem.setAttribute(attr, this.newValues[attr]); + else setUnitAttr(this.elem, attr, this.newValues[attr]); } else { if (attr == "#text") this.elem.textContent = ""; @@ -199,7 +199,7 @@ function ChangeElementCommand(elem, attrs, text) { for(var attr in this.oldValues ) { if (this.oldValues[attr]) { if (attr == "#text") this.elem.textContent = this.oldValues[attr]; - else this.elem.setAttribute(attr, this.oldValues[attr]); + else setUnitAttr(this.elem, attr, this.newValues[attr]); } else { if (attr == "#text") this.elem.textContent = ""; @@ -876,7 +876,130 @@ function BatchCommand(text) { return canvas.updateElementFromJson(data) }; - var assignAttributes = function(node, attrs, suspendLength) { + // TODO: declare the variables and set them as null, then move this setup stuff to + // an initialization function - probably just use clear() + var canvas = this, + svgns = "http://www.w3.org/2000/svg", + xlinkns = "http://www.w3.org/1999/xlink", + xmlns = "http://www.w3.org/XML/1998/namespace", + se_ns = "http://svg-edit.googlecode.com", + idprefix = "svg_", + svgdoc = container.ownerDocument, + svgroot = svgdoc.createElementNS(svgns, "svg"); + + $(svgroot).attr({ + width: 640, + height: 480, + id: "svgroot", + xmlns: svgns, + "xmlns:xlink": xlinkns + }).appendTo(container); + + var svgcontent = svgdoc.createElementNS(svgns, "svg"); + $(svgcontent).attr({ + id: 'svgcontent', + width: 640, + height: 480, + x: 640, + y: 480, + overflow: 'visible', + xmlns: svgns, + "xmlns:xlink": xlinkns + }).appendTo(svgroot); + + var convertToNum, convertToUnit, setUnitAttr; + + (function() { + var w_attrs = ['x', 'x1', 'cx', 'rx', 'width']; + var h_attrs = ['y', 'y1', 'cy', 'ry', 'height']; + var unit_attrs = $.merge(['r','radius'], w_attrs); + $.merge(unit_attrs, h_attrs); + + // Converts given values to numbers. Attributes must be supplied in + // case a percentage is given + convertToNum = function(attr, val) { + // Return a number if that's what it already is + if(!isNaN(val)) return val-0; + + if(val.substr(-1) === '%') { + // Deal with percentage, depends on attribute + var num = val.substr(0, val.length-1)/100; + var res = canvas.getResolution(); + + if($.inArray(attr, w_attrs) !== -1) { + return num * res.w; + } else if($.inArray(attr, w_attrs) !== -1) { + return num * res.h; + } else { + return num * Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2); + } + } else { + var unit = val.substr(-2); + var num = val.substr(0, val.length-2); + // Note that this multiplication turns the string into a number + return num * unit_types[unit]; + } + }; + + setUnitAttr = function(elem, attr, val) { + if(!isNaN(val)) { + // New value is a number, so check currently used unit + var old_val = elem.getAttribute(attr); + + if(old_val !== null && isNaN(old_val)) { + // Old value was a number, so get unit, then convert + var unit; + if(old_val.substr(-1) === '%') { + var res = canvas.getResolution(); + unit = '%'; + val *= 100; + if($.inArray(attr, w_attrs) !== -1) { + val = val / res.w; + } else if($.inArray(attr, w_attrs) !== -1) { + val = val / res.h; + } else { + return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2); + } + + } else { + unit = old_val.substr(-2); + val = val / unit_types[unit]; + } + + val += unit; + } + } + + elem.setAttribute(attr, val); + } + + convertToUnit = function(val, unit) { + + } + + canvas.isValidUnit = function(attr, val) { + var valid = false; + if($.inArray(attr, unit_attrs) != -1) { + // True if it's just a number + if(!isNaN(val)) { + valid = true; + } else { + // Not a number, check if it has a valid unit + val = val.toLowerCase(); + $.each(unit_types, function(unit) { + if(valid) return; + var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); + if(re.test(val)) valid = true; + }); + } + } else valid = true; + + return valid; + } + + })(); + + var assignAttributes = function(node, attrs, suspendLength, unitCheck) { if(!suspendLength) suspendLength = 0; // Opera has a problem with suspendRedraw() apparently var handle = null; @@ -885,7 +1008,13 @@ function BatchCommand(text) { for (var i in attrs) { var ns = (i.substr(0,4) == "xml:" ? xmlns : i.substr(0,6) == "xlink:" ? xlinkns : null); - node.setAttributeNS(ns, i, attrs[i]); + + if(ns || !unitCheck) { + node.setAttributeNS(ns, i, attrs[i]); + } else { + setUnitAttr(node, i, attrs[i]); + } + } if (!window.opera) svgroot.unsuspendRedraw(handle); @@ -934,37 +1063,6 @@ function BatchCommand(text) { return shape; }; - // TODO: declare the variables and set them as null, then move this setup stuff to - // an initialization function - probably just use clear() - var canvas = this, - svgns = "http://www.w3.org/2000/svg", - xlinkns = "http://www.w3.org/1999/xlink", - xmlns = "http://www.w3.org/XML/1998/namespace", - se_ns = "http://svg-edit.googlecode.com", - idprefix = "svg_", - svgdoc = container.ownerDocument, - svgroot = svgdoc.createElementNS(svgns, "svg"); - - $(svgroot).attr({ - width: 640, - height: 480, - id: "svgroot", - xmlns: svgns, - "xmlns:xlink": xlinkns - }).appendTo(container); - - var svgcontent = svgdoc.createElementNS(svgns, "svg"); - $(svgcontent).attr({ - id: 'svgcontent', - width: 640, - height: 480, - x: 640, - y: 480, - overflow: 'visible', - xmlns: svgns, - "xmlns:xlink": xlinkns - }).appendTo(svgroot); - (function() { // TODO: make this string optional and set by the client var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ "); @@ -1671,10 +1769,10 @@ function BatchCommand(text) { changes.y = changes.y-0 + Math.min(0,changes.height); changes.width = Math.abs(changes.width); changes.height = Math.abs(changes.height); - assignAttributes(selected, changes, 1000); + assignAttributes(selected, changes, 1000, true); break; case "use": - assignAttributes(selected, changes, 1000); + assignAttributes(selected, changes, 1000, true); break; case "ellipse": changes.rx = Math.abs(changes.rx); @@ -1683,7 +1781,7 @@ function BatchCommand(text) { if(changes.r) changes.r = Math.abs(changes.r); case "line": case "text": - assignAttributes(selected, changes, 1000); + assignAttributes(selected, changes, 1000, true); break; case "polyline": case "polygon": @@ -1828,6 +1926,9 @@ function BatchCommand(text) { if(attrs.length) { changes = $(selected).attr(attrs); + $.each(changes, function(attr, val) { + changes[attr] = convertToNum(attr, val); + }); } // if we haven't created an initial array in polygon/polyline/path, then @@ -5972,6 +6073,7 @@ function BatchCommand(text) { } return true; }; + this.getOffset = function() { return $(svgcontent).attr(['x', 'y']); }