transformlist branch: fix some undo problems, remove some more dead code

git-svn-id: http://svg-edit.googlecode.com/svn/branches/transformlist@924 eee81c28-f429-11dd-99c0-75d572ba1ddd
master
Jeff Schiller 2009-11-10 15:16:49 +00:00
parent f603b01efc
commit d7c3f73d02
1 changed files with 42 additions and 232 deletions

View File

@ -1,10 +1,10 @@
/* /*
TODOs for TransformList: TODOs for TransformList:
* See if I can transfer scales at the end of the tlist down to the children
* Groups of scaled groups have selector box sizing problems
* Fix rotating of resized groups (need to re-center?) * Fix rotating of resized groups (need to re-center?)
* Ensure resizing in negative direction works (nope! broken!)
* Ensure ungrouping works (surely broken) * Ensure ungrouping works (surely broken)
* Ensure undo still works properly (nope! broken!)
*/ */
/* /*
TODOs for Localizing: TODOs for Localizing:
@ -829,6 +829,7 @@ function BatchCommand(text) {
var obj_num = 1; var obj_num = 1;
var start_x = null; var start_x = null;
var start_y = null; var start_y = null;
var start_transform = null;
var current_mode = "select"; var current_mode = "select";
var current_resize_mode = "none"; var current_resize_mode = "none";
@ -1286,6 +1287,17 @@ function BatchCommand(text) {
var tlist = canvas.getTransformList(selected); var tlist = canvas.getTransformList(selected);
if (tlist.numberOfItems == 0) return null; if (tlist.numberOfItems == 0) return null;
// remove any stray identity transforms
if (tlist && tlist.numberOfItems > 0) {
var k = tlist.numberOfItems;
while (k--) {
var xform = tlist.getItem(k);
if (xform.type == 0 || xform.type == 1) {
tlist.removeItem(k);
}
}
}
// we know we have some transforms, so set up return variable // we know we have some transforms, so set up return variable
var batchCmd = new BatchCommand("Transform"); var batchCmd = new BatchCommand("Transform");
@ -1364,8 +1376,8 @@ function BatchCommand(text) {
if (initial == null) { if (initial == null) {
initial = jQuery.extend(true, {}, changes); initial = jQuery.extend(true, {}, changes);
} }
// save the transform value too // save the start transform value too
initial["transform"] = selected.getAttribute("transform"); initial["transform"] = start_transform ? start_transform : "";
// reduce the transform list here... // reduce the transform list here...
var box = canvas.getBBox(selected); var box = canvas.getBBox(selected);
@ -1470,8 +1482,8 @@ function BatchCommand(text) {
tlist.appendItem(newscale); tlist.appendItem(newscale);
} }
// TODO: if we have a rotate, we need to update its center // TODO: if we have a rotate, we need to update its center and
// now loop through the other transforms and adjust accordingly // adjust the transforms again
/* /*
var newBox = canvas.getBBox(selected); var newBox = canvas.getBBox(selected);
for ( var j = 0; j < tlist.numberOfItems; ++j) { for ( var j = 0; j < tlist.numberOfItems; ++j) {
@ -1729,17 +1741,6 @@ function BatchCommand(text) {
break; break;
} }
// remove any stray identity transforms
if (tlist && tlist.numberOfItems > 0) {
var k = tlist.numberOfItems;
while (k--) {
var xform = tlist.getItem(k);
if (xform.type == 0 || xform.type == 1) {
tlist.removeItem(k);
}
}
}
// if the transform list has been emptied, remove it // if the transform list has been emptied, remove it
if (tlist.numberOfItems == 0) { if (tlist.numberOfItems == 0) {
selected.removeAttribute("transform"); selected.removeAttribute("transform");
@ -1756,12 +1757,6 @@ function BatchCommand(text) {
// if we have not moved/resized, then immediately leave // if we have not moved/resized, then immediately leave
var xform = selected.getAttribute("transform"); var xform = selected.getAttribute("transform");
if ( (!xform || xform == "") && box.x == selectedBBox.x && box.y == selectedBBox.y &&
box.width == selectedBBox.width && box.height == selectedBBox.height)
{
return null;
}
var bScaleMatrix = false; var bScaleMatrix = false;
var tlist = selected.transform.baseVal; var tlist = selected.transform.baseVal;
var t = tlist.numberOfItems; var t = tlist.numberOfItems;
@ -1903,203 +1898,6 @@ function BatchCommand(text) {
return batchCmd; return batchCmd;
} }
var changes = {};
switch (selected.tagName)
{
case "g":
// do work here :P
break;
// NOTE: at the moment, there's no way to create an actual polygon element except by
// editing source or importing from somewhere else but we'll cover it here anyway
// polygon is handled just like polyline
case "polygon":
case "polyline":
// extract the points from the polygon/polyline, adjust it and write back the new points
// but first, save the old points
changes["points"] = selected.getAttribute("points");
var list = selected.points;
var len = list.numberOfItems;
var newpoints = "";
for (var i = 0; i < len; ++i) {
var pt = list.getItem(i);
pt = remap(pt.x,pt.y);
newpoints += pt.x + "," + pt.y + " ";
}
selected.setAttributeNS(null, "points", newpoints);
break;
case "path":
// extract the x,y from the path, adjust it and write back the new path
// but first, save the old path
changes["d"] = selected.getAttribute("d");
var M = selected.pathSegList.getItem(0);
var curx = M.x, cury = M.y;
var pt = remap(curx,cury);
var newd = "M" + pt.x + "," + pt.y;
var segList = selected.pathSegList;
var len = segList.numberOfItems;
// for all path segments in the path, we first turn them into relative path segments,
// then we remap the coordinates from the resize
for (var i = 1; i < len; ++i) {
var seg = segList.getItem(i);
// if these properties are not in the segment, set them to zero
var x = seg.x || 0,
y = seg.y || 0,
x1 = seg.x1 || 0,
y1 = seg.y1 || 0,
x2 = seg.x2 || 0,
y2 = seg.y2 || 0;
var type = seg.pathSegType;
switch (type) {
case 1: // z,Z closepath (Z/z)
newd += "z";
continue;
// turn this into a relative segment then fall through
case 3: // relative move (m)
case 5: // relative line (l)
case 13: // relative horizontal line (h)
case 15: // relative vertical line (v)
case 19: // relative smooth quad (t)
x += curx;
y += cury;
case 2: // absolute move (M)
case 4: // absolute line (L)
case 12: // absolute horizontal line (H)
case 14: // absolute vertical line (V)
case 18: // absolute smooth quad (T)
curx = x;
cury = y;
var pt = remap(x,y);
newd += [" ", pathMap[type], pt.x, ",", pt.y].join('');
break;
case 7: // relative cubic (c)
x += curx; x1 += curx; x2 += curx;
y += cury; y1 += curx; y2 += cury;
case 6: // absolute cubic (C)
curx = x;
cury = y;
var pt = remap(x,y), pt1 = remap(x1,y1), pt2 = remap(x2,y2);
newd += [" ", pathMap[type], pt1.x, ",", pt1.y, " ", pt2.x, ",", pt2.y,
" ", pt.x, ",", pt.y].join('');
break;
case 9: // relative quad (q)
x += curx; x1 += curx;
y += cury; y1 += cury;
case 8: // absolute quad (Q)
curx = x;
cury = y;
var pt = remap(x,y), pt1 = remap(x1,y1);
newd += [" ", pathMap[type], pt1.x, ",", pt1.y, " ", pt.x, ",", pt.y].join('');
break;
case 11: // relative elliptical arc (a)
x += curx;
y += cury;
case 10: // absolute elliptical arc (A)
curx = x;
cury = y;
var pt = remap(x,y);
newd += [" ", pathMap[type], scalew(seg.r1), ",", scaleh(seg.r2), " ", seg.angle, " ",
(seg.largeArcFlag ? 1 : 0), " ", (seg.sweepFlag ? 1 : 0), " ",
pt.x, ",", pt.y ].join('')
break;
case 17: // relative smooth cubic (s)
x += curx; x2 += curx;
y += cury; y2 += cury;
var pt = remap(x,y), pt2 = remap(x2,y2);
case 16: // absolute smooth cubic (S)
curx = x;
cury = y;
newd += [" ", pathMap[type], pt2.x, ",", pt2.y, " ", pt.x, ",", pt.y].join('');
break;
} // switch on path segment type
} // for each segment
selected.setAttributeNS(null, "d", newd);
break;
case "line":
changes["x1"] = selected.getAttribute("x1");
changes["y1"] = selected.getAttribute("y1");
changes["x2"] = selected.getAttribute("x2");
changes["y2"] = selected.getAttribute("y2");
var pt1 = remap(changes["x1"],changes["y1"]),
pt2 = remap(changes["x2"],changes["y2"]);
assignAttributes(selected, {
'x1': pt1.x,
'y1': pt1.y,
'x2': pt2.x,
'y2': pt2.y,
}, 1000);
break;
case "circle":
changes["cx"] = selected.getAttribute("cx");
changes["cy"] = selected.getAttribute("cy");
changes["r"] = selected.getAttribute("r");
var pt = remap(changes["cx"], changes["cy"]);
assignAttributes(selected, {
'cx': pt.x,
'cy': pt.y,
// take the minimum of the new selected box's dimensions for the new circle radius
'r': Math.min(selectedBBox.width/2,selectedBBox.height/2)
}, 1000);
break;
case "ellipse":
changes["cx"] = selected.getAttribute("cx");
changes["cy"] = selected.getAttribute("cy");
changes["rx"] = selected.getAttribute("rx");
changes["ry"] = selected.getAttribute("ry");
var pt = remap(changes["cx"], changes["cy"]);
assignAttributes(selected, {
'cx': pt.x,
'cy': pt.y,
'rx': scalew(changes["rx"]),
'ry': scaleh(changes["ry"])
}, 1000);
break;
case "text":
changes["x"] = selected.getAttribute("x");
changes["y"] = selected.getAttribute("y");
var pt = remap(changes["x"], changes["y"]);
assignAttributes(selected, {
'x': pt.x,
'y': pt.y
}, 1000);
break;
case "image":
changes["x"] = selected.getAttribute("x");
changes["y"] = selected.getAttribute("y");
changes["width"] = selected.getAttribute("width");
changes["height"] = selected.getAttribute("height");
var pt = remap(changes["x"], changes["y"]);
assignAttributes(selected, {
'x': pt.x,
'y': pt.y,
'width': scalew(changes["width"]),
'height': scaleh(changes["height"])
}, 1000);
break;
case "rect":
changes["x"] = selected.getAttribute("x");
changes["y"] = selected.getAttribute("y");
changes["width"] = selected.getAttribute("width");
changes["height"] = selected.getAttribute("height");
var pt = remap(changes["x"], changes["y"]);
assignAttributes(selected, {
'x': pt.x,
'y': pt.y,
'width': scalew(changes["width"]),
'height': scaleh(changes["height"])
}, 1000);
break;
default: // rect
console.log("Unknown shape type: " + selected.tagName);
break;
}
if (changes) {
batchCmd.addSubCommand(new ChangeElementCommand(selected, changes));
}
return batchCmd;
}; };
// public events // public events
@ -2348,6 +2146,7 @@ function BatchCommand(text) {
mouse_target = selectedElements[0]; mouse_target = selectedElements[0];
} }
start_transform = mouse_target.getAttribute("transform");
var tlist = canvas.getTransformList(mouse_target); var tlist = canvas.getTransformList(mouse_target);
switch (current_mode) { switch (current_mode) {
@ -3988,6 +3787,8 @@ function BatchCommand(text) {
addCommandToHistory(new InsertElementCommand(element)); addCommandToHistory(new InsertElementCommand(element));
call("changed",[element]); call("changed",[element]);
} }
start_transform = null;
}; };
// public functions // public functions
@ -5053,6 +4854,7 @@ function BatchCommand(text) {
return ret; return ret;
}; };
// TODO: do we need to sum up all rotation angles?
this.getRotationAngle = function(elem) { this.getRotationAngle = function(elem) {
var selected = elem || selectedElements[0]; var selected = elem || selectedElements[0];
// find the rotation transform (if any) and set it // find the rotation transform (if any) and set it
@ -5067,11 +4869,6 @@ function BatchCommand(text) {
return 0; return 0;
}; };
// TODO: if transforms are going to stay on <g> then we need to properly find the right
// place to insert a rotate. This would be searching from the end of the tlist and
// going back until we either:
// - find an existing rotate OR
// - find a translate that is not part of a scale
this.setRotationAngle = function(val,preventUndo) { this.setRotationAngle = function(val,preventUndo) {
var elem = selectedElements[0]; var elem = selectedElements[0];
// we use the actual element's bbox (not the calculated one) since the // we use the actual element's bbox (not the calculated one) since the
@ -5079,29 +4876,42 @@ function BatchCommand(text) {
var bbox = elem.getBBox(); var bbox = elem.getBBox();
var cx = round(bbox.x+bbox.width/2), cy = round(bbox.y+bbox.height/2); var cx = round(bbox.x+bbox.width/2), cy = round(bbox.y+bbox.height/2);
var tlist = canvas.getTransformList(elem); var tlist = canvas.getTransformList(elem);
var rotIndex = -1;
// find the index of the rotation trnasform
var n = tlist.numberOfItems;
while (n--) {
var xform = tlist.getItem(n);
if (xform.type == 4) {
rotIndex = n;
break;
}
}
// if we are not rotated yet, insert a dummy xform // if we are not rotated yet, insert a dummy xform
if (tlist.numberOfItems == 0 || tlist.getItem(0).type != 4) { if (rotIndex == -1) {
tlist.insertItemBefore(svgroot.createSVGTransform(), 0); tlist.insertItemBefore(svgroot.createSVGTransform(), 0);
rotIndex = 0;
} }
var newrot = tlist.getItem(0); var newrot = tlist.getItem(rotIndex);
newrot.setRotate(val, cx, cy); newrot.setRotate(val, cx, cy);
// TODO: remove this seperate chunk of code where we replace the rotation transform
// because calling setRotate() above changes the live transform in the list
if (preventUndo) { if (preventUndo) {
// we don't need to undo, just update the transform list // we don't need to undo, just update the transform list
// Opera Bug: for whatever reason, sometimes Opera doesn't let you // Opera Bug: for whatever reason, sometimes Opera doesn't let you
// replace the 0th transform (perhaps if it's an identity matrix?) // replace the 0th transform (perhaps if it's an identity matrix?)
try { try {
tlist.replaceItem(newrot, 0); tlist.replaceItem(newrot, rotIndex);
} catch(e) { } catch(e) {
tlist.insertItemBefore(newrot,0); tlist.insertItemBefore(newrot,rotIndex);
} }
} }
else { else {
// FIXME: we need to do it, then undo it, then redo it so it can be undo-able! :) // FIXME: we need to do it, then undo it, then redo it so it can be undo-able! :)
// TODO: figure out how to make changes to transform list undo-able cross-browser // TODO: figure out how to make changes to transform list undo-able cross-browser
var oldTransform = elem.getAttribute("transform"); var oldTransform = elem.getAttribute("transform");
tlist.replaceItem(newrot, 0); tlist.replaceItem(newrot, rotIndex);
var newTransform = elem.getAttribute("transform"); var newTransform = elem.getAttribute("transform");
elem.setAttribute("transform", oldTransform); elem.setAttribute("transform", oldTransform);
this.changeSelectedAttribute("transform",newTransform,selectedElements); this.changeSelectedAttribute("transform",newTransform,selectedElements);
@ -5111,7 +4921,7 @@ function BatchCommand(text) {
setPointContainerTransform(elem.getAttribute("transform")); setPointContainerTransform(elem.getAttribute("transform"));
} }
var selector = selectorManager.requestSelector(selectedElements[0]); var selector = selectorManager.requestSelector(selectedElements[0]);
selector.resize();//bbox); // TODO: remove box arg selector.resize();
selector.updateGripCursors(val); selector.updateGripCursors(val);
}; };