Added convert-to-group option for SVG elements, added label (title) field for groups/SVGs
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1643 eee81c28-f429-11dd-99c0-75d572ba1dddmaster
parent
1a9b08bed6
commit
b2f2df4eac
|
@ -227,6 +227,12 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
||||||
|
|
||||||
<div id="g_panel">
|
<div id="g_panel">
|
||||||
<div class="tool_sep"></div>
|
<div class="tool_sep"></div>
|
||||||
|
|
||||||
|
<label id="group_title" title="Group identification label">
|
||||||
|
<span>label:</span>
|
||||||
|
<input id="g_title" data-attr="title" size="10" type="text"/>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div class="push_button" id="tool_ungroup" title="Ungroup Elements [G]"></div>
|
<div class="push_button" id="tool_ungroup" title="Ungroup Elements [G]"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -352,6 +358,10 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
||||||
<!-- Not visible, but still used -->
|
<!-- Not visible, but still used -->
|
||||||
<input id="text" type="text" size="35"/>
|
<input id="text" type="text" size="35"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="gsvg_panel">
|
||||||
|
<!-- Add viewBox field here? -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="path_node_panel">
|
<div id="path_node_panel">
|
||||||
<div class="tool_sep"></div>
|
<div class="tool_sep"></div>
|
||||||
|
|
|
@ -207,7 +207,15 @@
|
||||||
|
|
||||||
var extFunc = function() {
|
var extFunc = function() {
|
||||||
$.each(curConfig.extensions, function() {
|
$.each(curConfig.extensions, function() {
|
||||||
$.getScript(curConfig.extPath + this);
|
var extname = this;
|
||||||
|
$.getScript(curConfig.extPath + extname, function(d) {
|
||||||
|
// Fails locally in Chrome 5
|
||||||
|
if(!d) {
|
||||||
|
var s = document.createElement('script');
|
||||||
|
s.src = curConfig.extPath + extname;
|
||||||
|
document.querySelector('head').appendChild(s);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,7 +1285,7 @@
|
||||||
}
|
}
|
||||||
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
|
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
|
||||||
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\
|
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\
|
||||||
#ellipse_panel, #line_panel, #text_panel, #image_panel').hide();
|
#ellipse_panel, #line_panel, #text_panel, #image_panel, #gsvg_panel').hide();
|
||||||
if (elem != null) {
|
if (elem != null) {
|
||||||
var elname = elem.nodeName;
|
var elname = elem.nodeName;
|
||||||
|
|
||||||
|
@ -1366,13 +1374,14 @@
|
||||||
circle: ['cx','cy','r'],
|
circle: ['cx','cy','r'],
|
||||||
ellipse: ['cx','cy','rx','ry'],
|
ellipse: ['cx','cy','rx','ry'],
|
||||||
line: ['x1','y1','x2','y2'],
|
line: ['x1','y1','x2','y2'],
|
||||||
text: []
|
text: [],
|
||||||
|
gsvg: []
|
||||||
};
|
};
|
||||||
|
|
||||||
var el_name = elem.tagName;
|
var el_name = elem.tagName;
|
||||||
|
|
||||||
if($(elem).data('gsvg')) {
|
if($(elem).data('gsvg')) {
|
||||||
el_name = 'svg';
|
$('#gsvg_panel').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(panels[el_name]) {
|
if(panels[el_name]) {
|
||||||
|
@ -1411,6 +1420,11 @@
|
||||||
var href = elem.getAttributeNS(xlinkNS, "href");
|
var href = elem.getAttributeNS(xlinkNS, "href");
|
||||||
setImageURL(href);
|
setImageURL(href);
|
||||||
} // image
|
} // image
|
||||||
|
else if(el_name == 'g') {
|
||||||
|
console.log('is group');
|
||||||
|
var title = svgCanvas.getTitle();
|
||||||
|
$('#g_title').val(title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // if (elem != null)
|
} // if (elem != null)
|
||||||
else if (multiselected) {
|
else if (multiselected) {
|
||||||
|
@ -1605,6 +1619,11 @@
|
||||||
$('#image_url').change(function(){
|
$('#image_url').change(function(){
|
||||||
setImageURL(this.value);
|
setImageURL(this.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#g_title').change(function() {
|
||||||
|
svgCanvas.setGroupTitle(this.value);
|
||||||
|
$(this).width(17 + this.value.length * 5);
|
||||||
|
});
|
||||||
|
|
||||||
$('.attr_changer').change(function() {
|
$('.attr_changer').change(function() {
|
||||||
var attr = this.getAttribute("data-attr");
|
var attr = this.getAttribute("data-attr");
|
||||||
|
@ -2140,7 +2159,7 @@
|
||||||
svgCanvas.moveToBottomSelectedElement();
|
svgCanvas.moveToBottomSelectedElement();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var convertToPath = function() {
|
var convertToPath = function() {
|
||||||
if (selectedElement != null) {
|
if (selectedElement != null) {
|
||||||
svgCanvas.convertToPath();
|
svgCanvas.convertToPath();
|
||||||
|
|
|
@ -3279,6 +3279,22 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||||
if (!childTlist) continue;
|
if (!childTlist) continue;
|
||||||
|
|
||||||
var m = transformListToTransform(childTlist).matrix;
|
var m = transformListToTransform(childTlist).matrix;
|
||||||
|
|
||||||
|
// Convert a matrix to a scale if applicable
|
||||||
|
// if(hasMatrixTransform(childTlist) && childTlist.numberOfItems == 1) {
|
||||||
|
// if(m.b==0 && m.c==0 && m.e==0 && m.f==0) {
|
||||||
|
// childTlist.removeItem(0);
|
||||||
|
// var translateOrigin = svgroot.createSVGTransform(),
|
||||||
|
// scale = svgroot.createSVGTransform(),
|
||||||
|
// translateBack = svgroot.createSVGTransform();
|
||||||
|
// translateOrigin.setTranslate(0, 0);
|
||||||
|
// scale.setScale(m.a, m.d);
|
||||||
|
// translateBack.setTranslate(0, 0);
|
||||||
|
// childTlist.appendItem(translateBack);
|
||||||
|
// childTlist.appendItem(scale);
|
||||||
|
// childTlist.appendItem(translateOrigin);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
var angle = getRotationAngle(child);
|
var angle = getRotationAngle(child);
|
||||||
var old_start_transform = start_transform;
|
var old_start_transform = start_transform;
|
||||||
|
@ -3444,6 +3460,8 @@ var recalculateDimensions = this.recalculateDimensions = function(selected) {
|
||||||
start_transform = child.getAttribute("transform");
|
start_transform = child.getAttribute("transform");
|
||||||
var childTlist = getTransformList(child);
|
var childTlist = getTransformList(child);
|
||||||
|
|
||||||
|
if (!childTlist) continue;
|
||||||
|
|
||||||
var em = matrixMultiply(m, transformListToTransform(childTlist).matrix);
|
var em = matrixMultiply(m, transformListToTransform(childTlist).matrix);
|
||||||
var e2m = svgroot.createSVGTransform();
|
var e2m = svgroot.createSVGTransform();
|
||||||
e2m.setMatrix(em);
|
e2m.setMatrix(em);
|
||||||
|
@ -7827,6 +7845,89 @@ var uniquifyElems = this.uniquifyElems = function(g) {
|
||||||
obj_num++;
|
obj_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: svgToGroup
|
||||||
|
// Converts a child SVG element to a group
|
||||||
|
var svgToGroup = this.svgToGroup = function(elem) {
|
||||||
|
if(!elem) {
|
||||||
|
elem = selectedElements[0];
|
||||||
|
}
|
||||||
|
if(elem.tagName == 'g') {
|
||||||
|
// Use the gsvg as the new group
|
||||||
|
var svg = elem.firstChild;
|
||||||
|
var pt = $(svg).attr(['x', 'y']);
|
||||||
|
|
||||||
|
$(elem.firstChild.firstChild).unwrap();
|
||||||
|
$(elem).removeData('gsvg');
|
||||||
|
|
||||||
|
var tlist = getTransformList(elem);
|
||||||
|
var xform = svgroot.createSVGTransform();
|
||||||
|
xform.setTranslate(pt.x, pt.y);
|
||||||
|
tlist.appendItem(xform);
|
||||||
|
recalculateDimensions(elem);
|
||||||
|
call("selected", [elem]);
|
||||||
|
// addToSelection(elem]);
|
||||||
|
return;
|
||||||
|
// elem = $(elem).data('gsvg');
|
||||||
|
}
|
||||||
|
if(elem.tagName != 'svg') return;
|
||||||
|
|
||||||
|
var g = svgdoc.createElementNS(svgns, "g");
|
||||||
|
while (elem.hasChildNodes())
|
||||||
|
g.appendChild(elem.firstChild);
|
||||||
|
// if (ts)
|
||||||
|
// g.setAttribute("transform", ts);
|
||||||
|
|
||||||
|
var parent = elem.parentNode;
|
||||||
|
|
||||||
|
if(parent) parent.removeChild(elem);
|
||||||
|
|
||||||
|
uniquifyElems(g);
|
||||||
|
|
||||||
|
// now give the g itself a new id
|
||||||
|
g.id = getNextId();
|
||||||
|
|
||||||
|
current_layer.appendChild(g);
|
||||||
|
|
||||||
|
// change image href vals if possible
|
||||||
|
// $(svgcontent).find('image').each(function() {
|
||||||
|
// var image = this;
|
||||||
|
// preventClickDefault(image);
|
||||||
|
// var val = this.getAttributeNS(xlinkns, "href");
|
||||||
|
// if(val.indexOf('data:') === 0) {
|
||||||
|
// // Check if an SVG-edit data URI
|
||||||
|
// var m = val.match(/svgedit_url=(.*?);/);
|
||||||
|
// if(m) {
|
||||||
|
// var url = decodeURIComponent(m[1]);
|
||||||
|
// $(new Image()).load(function() {
|
||||||
|
// image.setAttributeNS(xlinkns,'xlink:href',url);
|
||||||
|
// }).attr('src',url);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // Add to encodableImages if it loads
|
||||||
|
// canvas.embedImage(val);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
var batchCmd = new BatchCommand();
|
||||||
|
|
||||||
|
if(parent) {
|
||||||
|
batchCmd.addSubCommand(new RemoveElementCommand(elem, parent));
|
||||||
|
batchCmd.addSubCommand(new InsertElementCommand(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
// recalculate dimensions on the top-level children so that unnecessary transforms
|
||||||
|
// are removed
|
||||||
|
walkTreePost(svgcontent, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}});
|
||||||
|
|
||||||
|
// batchCmd.addSubCommand(new InsertElementCommand(svgcontent));
|
||||||
|
|
||||||
|
// reset transform lists
|
||||||
|
// svgTransformLists = {};
|
||||||
|
clearSelection();
|
||||||
|
addToSelection([g]);
|
||||||
|
addCommandToHistory(batchCmd);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Function: setSvgString
|
// Function: setSvgString
|
||||||
// This function sets the current drawing as the input SVG XML.
|
// This function sets the current drawing as the input SVG XML.
|
||||||
|
@ -8084,62 +8185,15 @@ this.importSvgString = function(xmlString, toElements) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var g = svgToGroup(importedNode);
|
||||||
|
|
||||||
|
|
||||||
// TODO: Find way to add this in a recalculateDimensions-parsable way
|
// TODO: Find way to add this in a recalculateDimensions-parsable way
|
||||||
// if (vb[0] != 0 || vb[1] != 0)
|
// if (vb[0] != 0 || vb[1] != 0)
|
||||||
// ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts;
|
// ts = "translate(" + (-vb[0]) + "," + (-vb[1]) + ") " + ts;
|
||||||
|
|
||||||
// add all children of the imported <svg> to the <g> we create
|
// add all children of the imported <svg> to the <g> we create
|
||||||
var g = svgdoc.createElementNS(svgns, "g");
|
|
||||||
while (importedNode.hasChildNodes())
|
|
||||||
g.appendChild(importedNode.firstChild);
|
|
||||||
if (ts)
|
|
||||||
g.setAttribute("transform", ts);
|
|
||||||
|
|
||||||
uniquifyElems(g);
|
|
||||||
|
|
||||||
// now give the g itself a new id
|
|
||||||
g.id = getNextId();
|
|
||||||
|
|
||||||
current_layer.appendChild(g);
|
|
||||||
|
|
||||||
// change image href vals if possible
|
|
||||||
// $(svgcontent).find('image').each(function() {
|
|
||||||
// var image = this;
|
|
||||||
// preventClickDefault(image);
|
|
||||||
// var val = this.getAttributeNS(xlinkns, "href");
|
|
||||||
// if(val.indexOf('data:') === 0) {
|
|
||||||
// // Check if an SVG-edit data URI
|
|
||||||
// var m = val.match(/svgedit_url=(.*?);/);
|
|
||||||
// if(m) {
|
|
||||||
// var url = decodeURIComponent(m[1]);
|
|
||||||
// $(new Image()).load(function() {
|
|
||||||
// image.setAttributeNS(xlinkns,'xlink:href',url);
|
|
||||||
// }).attr('src',url);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Add to encodableImages if it loads
|
|
||||||
// canvas.embedImage(val);
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
// recalculate dimensions on the top-level children so that unnecessary transforms
|
|
||||||
// are removed
|
|
||||||
walkTreePost(svgcontent, function(n){try{recalculateDimensions(n)}catch(e){console.log(e)}});
|
|
||||||
|
|
||||||
|
|
||||||
batchCmd.addSubCommand(new InsertElementCommand(svgcontent));
|
|
||||||
|
|
||||||
// reset zoom - TODO: why?
|
|
||||||
// current_zoom = 1;
|
|
||||||
|
|
||||||
// identify layers
|
|
||||||
// identifyLayers();
|
|
||||||
|
|
||||||
// reset transform lists
|
|
||||||
svgTransformLists = {};
|
|
||||||
clearSelection();
|
|
||||||
|
|
||||||
addCommandToHistory(batchCmd);
|
|
||||||
call("changed", [svgcontent]);
|
call("changed", [svgcontent]);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
@ -8640,9 +8694,13 @@ this.setConfig = function(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function: getDocumentTitle
|
// Function: getDocumentTitle
|
||||||
// Returns the current document title or an empty string if not found
|
// Returns the current group/SVG's title contents
|
||||||
this.getDocumentTitle = function() {
|
this.getTitle = function(elem) {
|
||||||
var childs = svgcontent.childNodes;
|
elem = elem || selectedElements[0];
|
||||||
|
if(!elem) return;
|
||||||
|
elem = $(elem).data('gsvg') || elem;
|
||||||
|
|
||||||
|
var childs = elem.childNodes;
|
||||||
for (var i=0; i<childs.length; i++) {
|
for (var i=0; i<childs.length; i++) {
|
||||||
if(childs[i].nodeName == 'title') {
|
if(childs[i].nodeName == 'title') {
|
||||||
return childs[i].textContent;
|
return childs[i].textContent;
|
||||||
|
@ -8651,6 +8709,43 @@ this.getDocumentTitle = function() {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: setGroupTitle
|
||||||
|
// Sets the group/SVG's title content
|
||||||
|
// TODO: Combine this with setDocumentTitle
|
||||||
|
this.setGroupTitle = function(val) {
|
||||||
|
var elem = selectedElements[0];
|
||||||
|
elem = $(elem).data('gsvg') || elem;
|
||||||
|
|
||||||
|
var ts = $(elem).children('title');
|
||||||
|
|
||||||
|
var batchCmd = new BatchCommand("Set Label");
|
||||||
|
|
||||||
|
if(!val.length) {
|
||||||
|
// Remove title element
|
||||||
|
batchCmd.addSubCommand(new RemoveElementCommand(ts[i], elem));
|
||||||
|
ts.remove();
|
||||||
|
} else if(ts.length) {
|
||||||
|
// Change title contents
|
||||||
|
var title = ts[0];
|
||||||
|
batchCmd.addSubCommand(new ChangeElementCommand(title, {'#text': title.textContent}));
|
||||||
|
title.textContent = val;
|
||||||
|
} else {
|
||||||
|
// Add title element
|
||||||
|
title = svgdoc.createElementNS(svgns, "title");
|
||||||
|
title.textContent = val;
|
||||||
|
$(elem).prepend(title);
|
||||||
|
batchCmd.addSubCommand(new InsertElementCommand(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
addCommandToHistory(batchCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function: getDocumentTitle
|
||||||
|
// Returns the current document title or an empty string if not found
|
||||||
|
this.getDocumentTitle = function() {
|
||||||
|
return canvas.getTitle(svgcontent);
|
||||||
|
}
|
||||||
|
|
||||||
// Function: setDocumentTitle
|
// Function: setDocumentTitle
|
||||||
// Adds/updates a title element for the document with the given name.
|
// Adds/updates a title element for the document with the given name.
|
||||||
// This is an undoable action
|
// This is an undoable action
|
||||||
|
@ -9915,6 +10010,12 @@ this.groupSelectedElements = function() {
|
||||||
this.ungroupSelectedElement = function() {
|
this.ungroupSelectedElement = function() {
|
||||||
var g = selectedElements[0];
|
var g = selectedElements[0];
|
||||||
if (g.tagName == "g") {
|
if (g.tagName == "g") {
|
||||||
|
if($(g).data('gsvg')) {
|
||||||
|
// Is gsvg, so actually convert to group
|
||||||
|
svgToGroup(g);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var batchCmd = new BatchCommand("Ungroup Elements");
|
var batchCmd = new BatchCommand("Ungroup Elements");
|
||||||
var parent = g.parentNode;
|
var parent = g.parentNode;
|
||||||
var anchor = g.previousSibling;
|
var anchor = g.previousSibling;
|
||||||
|
@ -9941,6 +10042,14 @@ this.ungroupSelectedElement = function() {
|
||||||
var elem = g.firstChild;
|
var elem = g.firstChild;
|
||||||
var oldNextSibling = elem.nextSibling;
|
var oldNextSibling = elem.nextSibling;
|
||||||
var oldParent = elem.parentNode;
|
var oldParent = elem.parentNode;
|
||||||
|
|
||||||
|
// Remove child title elements
|
||||||
|
if(elem.tagName == 'title') {
|
||||||
|
batchCmd.addSubCommand(new RemoveElementCommand(elem, oldParent));
|
||||||
|
oldParent.removeChild(elem);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
children[i++] = elem = parent.insertBefore(elem, anchor);
|
children[i++] = elem = parent.insertBefore(elem, anchor);
|
||||||
batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
|
batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
|
||||||
|
|
||||||
|
@ -9989,6 +10098,9 @@ this.ungroupSelectedElement = function() {
|
||||||
|
|
||||||
var chtlist = getTransformList(elem);
|
var chtlist = getTransformList(elem);
|
||||||
|
|
||||||
|
// Hopefully not a problem to add this. Necessary for elements like <desc/>
|
||||||
|
if(!chtlist) continue;
|
||||||
|
|
||||||
if (glist.numberOfItems) {
|
if (glist.numberOfItems) {
|
||||||
// TODO: if the group's transform is just a rotate, we can always transfer the
|
// TODO: if the group's transform is just a rotate, we can always transfer the
|
||||||
// rotate() down to the children (collapsing consecutive rotates and factoring
|
// rotate() down to the children (collapsing consecutive rotates and factoring
|
||||||
|
|
Loading…
Reference in New Issue