diff --git a/editor/svg-editor.css b/editor/svg-editor.css
index 9a8b99b9..97bf1601 100644
--- a/editor/svg-editor.css
+++ b/editor/svg-editor.css
@@ -121,7 +121,7 @@ div.color_block {
display: none;
}
-#svg_editor #group_panel {
+#svg_editor #g_panel {
display: none;
}
diff --git a/editor/svg-editor.html b/editor/svg-editor.html
index 309558d8..e1a7acd6 100644
--- a/editor/svg-editor.html
+++ b/editor/svg-editor.html
@@ -104,7 +104,7 @@
-
+
diff --git a/editor/svg-editor.js b/editor/svg-editor.js
index 1ae89f5a..de3b4b02 100644
--- a/editor/svg-editor.js
+++ b/editor/svg-editor.js
@@ -81,7 +81,10 @@ function svg_edit_setup() {
// updates the toolbar (colors, opacity, etc) based on the selected element
var updateToolbar = function() {
- if (selectedElement != null && selectedElement.tagName != "image") { //the image thing might be a hack.
+ if (selectedElement != null &&
+ selectedElement.tagName != "image" &&
+ selectedElement.tagName != "g")
+ {
// get opacity values
var fillOpacity = parseFloat(selectedElement.getAttribute("fill-opacity"));
if (isNaN(fillOpacity)) {
@@ -167,7 +170,7 @@ function svg_edit_setup() {
return;
}
- $('#selected_panel, #multiselected_panel, #rect_panel, #circle_panel,\
+ $('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\
#ellipse_panel, #line_panel, #text_panel, #image_panel').hide();
if (elem != null) {
$('#angle').val(svgCanvas.getRotationAngle(elem));
@@ -175,6 +178,7 @@ function svg_edit_setup() {
// update contextual tools here
var panels = {
+ g: [],
rect: ['radius','x','y','width','height'],
image: ['x','y','width','height'],
circle: ['cx','cy','r'],
@@ -557,7 +561,14 @@ function svg_edit_setup() {
};
var clickGroup = function(){
- console.log("Group not implemented yet");
+ // group
+ if (multiselected) {
+ svgCanvas.groupSelectedElements();
+ }
+ // ungroup
+ else {
+ svgCanvas.ungroupSelectedElement();
+ }
};
var clickClone = function(){
diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js
index e8312613..f1a319ef 100644
--- a/editor/svgcanvas.js
+++ b/editor/svgcanvas.js
@@ -13,6 +13,7 @@ var svgWhiteList = {
"circle": ["cx", "cy", "fill", "fill-opacity", "id", "opacity", "r", "stroke", "stroke-dasharray", "stroke-opacity", "stroke-width", "transform"],
"defs": [],
"ellipse": ["cx", "cy", "fill", "fill-opacity", "id", "opacity", "rx", "ry", "stroke", "stroke-dasharray", "stroke-opacity", "stroke-width", "transform"],
+ "g": ["id", "transform"],
"image": ["height", "id", "opacity", "transform", "width", "x", "xlink:href", "xlink:title", "y"],
"line": ["fill", "fill-opacity", "id", "opacity", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-opacity", "stroke-width", "transform", "x1", "x2", "y1", "y2"],
"linearGradient": ["id", "gradientTransform", "gradientUnits", "spreadMethod", "x1", "x2", "y1", "y2"],
@@ -2456,7 +2457,6 @@ function BatchCommand(text) {
};
this.setFillColor = function(val,preventUndo) {
- console.log('setFillColor(' + val + ')');
cur_properties.fill = val;
cur_properties.fill_paint = {type:"solidColor"};
// take out any path/line elements when setting fill
@@ -2840,6 +2840,8 @@ function BatchCommand(text) {
while (i--) {
var elem = elems[i];
if (elem == null) continue;
+ // only allow the transform attribute to change on
elements, slightly hacky
+ if (elem.tagName == "g" && attr != "transform") continue;
var oldval = attr == "#text" ? elem.textContent : elem.getAttribute(attr);
if (oldval == null) oldval = "";
if (oldval != newValue) {
@@ -2924,7 +2926,7 @@ function BatchCommand(text) {
this.deleteSelectedElements = function() {
var batchCmd = new BatchCommand("Delete Elements");
var len = selectedElements.length;
- var selectedCopy = []; //selectedElements is being delted
+ var selectedCopy = []; //selectedElements is being deleted
for (var i = 0; i < len; ++i) {
var selected = selectedElements[i];
if (selected == null) break;
@@ -2941,6 +2943,66 @@ function BatchCommand(text) {
if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
call("selected", selectedCopy);
};
+
+ this.groupSelectedElements = function() {
+ var batchCmd = new BatchCommand("Group Elements");
+
+ // create and insert the group element
+ var g = addSvgElementFromJson({
+ "element": "g",
+ "attr": {
+ "id": getNextId()
+ }
+ });
+ batchCmd.addSubCommand(new InsertElementCommand(g));
+
+ // now move all children into the group
+ var i = selectedElements.length;
+ while (i--) {
+ var elem = selectedElements[i];
+ var oldNextSibling = elem.nextSibling;
+ var oldParent = elem.parentNode;
+ g.appendChild(elem);
+ batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
+ }
+ if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
+
+ // ensure selectors are at bottom and update selection
+ selectorManager.update();
+ canvas.clearSelection();
+ canvas.addToSelection([g]);
+ };
+
+ this.ungroupSelectedElement = function() {
+ var g = selectedElements[0];
+ if (g.tagName == "g") {
+ var batchCmd = new BatchCommand("Ungroup Elements");
+ var parent = g.parentNode;
+ var anchor = g.previousSibling;
+ var children = new Array(g.childNodes.length);
+ var i = 0;
+ while (g.firstChild) {
+ var elem = g.firstChild;
+ var oldNextSibling = elem.nextSibling;
+ var oldParent = elem.parentNode;
+ children[i++] = elem = parent.insertBefore(elem, anchor);
+ batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
+ }
+
+ // remove the group from the selection
+ canvas.clearSelection();
+
+ // delete the group element (but make undo-able)
+ g = parent.removeChild(g);
+ batchCmd.addSubCommand(new RemoveElementCommand(g, parent));
+
+ if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
+
+ // ensure selectors are at bottom and update selection
+ selectorManager.update();
+ canvas.addToSelection(children);
+ }
+ };
this.moveToTopSelectedElement = function() {
var selected = selectedElements[0];