Large number of small fixes. Multi-select getting closer now (still not working)

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@243 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
Jeff Schiller
2009-07-01 19:28:08 +00:00
parent 71e3b92e3c
commit 797f53345b
2 changed files with 89 additions and 136 deletions

View File

@@ -20,11 +20,12 @@ function svg_edit_setup() {
var selectedElement = null; var selectedElement = null;
// called when we've selected a different element // called when we've selected a different element
var selectedChanged = function(window,elem) { var selectedChanged = function(window,elems) {
selectedElement = elem; // if elems[1] is present, then we have more than one element
if (elem != null) { selectedElement = (elems.length == 1 || elems[1] == null ? elems[0] : null);
if (selectedElement != null) {
// always set the mode of the editor to select because // unless we're already in always set the mode of the editor to select because
// upon creation of a text element the editor is switched into // upon creation of a text element the editor is switched into
// select mode and this event fires - we need our UI to be in sync // select mode and this event fires - we need our UI to be in sync
if (svgCanvas.getMode() != "multiselect") { if (svgCanvas.getMode() != "multiselect") {

View File

@@ -159,7 +159,7 @@ function SvgCanvas(c)
this.selectorGrips[dir] = this.selectorGroup.appendChild( addSvgElementFromJson({ this.selectorGrips[dir] = this.selectorGroup.appendChild( addSvgElementFromJson({
"element": "rect", "element": "rect",
"attr": { "attr": {
"id": (dir + "_grip" + this.id), "id": ("selectorGrip_" + dir + "_" + this.id),
"fill": "blue", "fill": "blue",
"width": 6, "width": 6,
"height": 6, "height": 6,
@@ -172,12 +172,13 @@ function SvgCanvas(c)
// This works in Opera and WebKit, but does not work in Firefox // This works in Opera and WebKit, but does not work in Firefox
// see https://bugzilla.mozilla.org/show_bug.cgi?id=500174 // see https://bugzilla.mozilla.org/show_bug.cgi?id=500174
"stroke-width": 2, "stroke-width": 2,
"pointer-events": "all", "pointer-events":"all",
"display":"none"
} }
}) ); }) );
$('#'+this.selectorGrips[dir].id).mousedown( function() { $('#'+this.selectorGrips[dir].id).mousedown( function() {
current_mode = "resize"; current_mode = "resize";
current_resize_mode = this.id.substr(0,this.id.indexOf("_")); current_resize_mode = this.id.substr(13,this.id.indexOf("_",13)-13);
}); });
} }
@@ -230,8 +231,6 @@ function SvgCanvas(c)
}; };
// TODO: add accessor methods to determine number of currently selected elements // TODO: add accessor methods to determine number of currently selected elements
// TODO: move selectElement into SelectorManager and allow multiple selected elements
// with each call
function SelectorManager() { function SelectorManager() {
// this will hold the <g> element that contains all selector rects/grips // this will hold the <g> element that contains all selector rects/grips
@@ -303,6 +302,7 @@ function SvgCanvas(c)
delete this.selectorMap[elem]; delete this.selectorMap[elem];
sel.locked = false; sel.locked = false;
sel.selectedElement = null; sel.selectedElement = null;
sel.showGrips(false);
// remove from DOM and store reference in JS but only if it exists in the DOM // remove from DOM and store reference in JS but only if it exists in the DOM
try { try {
@@ -329,17 +329,17 @@ function SvgCanvas(c)
if (this.rubberBandBox == null) { if (this.rubberBandBox == null) {
this.rubberBandBox = this.selectorParentGroup.appendChild( this.rubberBandBox = this.selectorParentGroup.appendChild(
addSvgElementFromJson({ "element": "rect", addSvgElementFromJson({ "element": "rect",
"attr": { "attr": {
"id": "selectorRubberBand", "id": "selectorRubberBand",
"fill": "blue", "fill": "blue",
"fill-opacity": 0.15, "fill-opacity": 0.15,
"stroke": "blue", "stroke": "blue",
"stroke-width": 0.5, "stroke-width": 0.5,
"display": "none", "display": "none",
"pointer-events": "none", "style": "pointer-events:none",
} }
})); }));
} }
return this.rubberBandBox; return this.rubberBandBox;
} }
@@ -383,7 +383,7 @@ function SvgCanvas(c)
// default size of 1 until it needs to grow bigger // default size of 1 until it needs to grow bigger
var selectedElements = new Array(1); var selectedElements = new Array(1);
// this holds the selected's bbox // this holds the selected's bbox
var selectedBBox = null; var selectedBBoxes = new Array(1);
// this object manages selectors for us // this object manages selectors for us
var selectorManager = new SelectorManager(); var selectorManager = new SelectorManager();
// this object holds the one-and-only selector (for now) // this object holds the one-and-only selector (for now)
@@ -395,6 +395,8 @@ function SvgCanvas(c)
// Since the only browser that supports getIntersectionList is Opera, we need to // Since the only browser that supports getIntersectionList is Opera, we need to
// provide an implementation here. We brute-force it for now. // provide an implementation here. We brute-force it for now.
// Firefox does not implement getIntersectionList(), see https://bugzilla.mozilla.org/show_bug.cgi?id=501421
// Webkit does not implement getIntersectionList(), see https://bugs.webkit.org/show_bug.cgi?id=11274
var getIntersectionList = function(rect) { var getIntersectionList = function(rect) {
var resultList = null; var resultList = null;
try { try {
@@ -514,6 +516,7 @@ function SvgCanvas(c)
var recalculateSelectedDimensions = function() { var recalculateSelectedDimensions = function() {
var selected = selectedElements[0]; var selected = selectedElements[0];
var selectedBBox = selectedBBoxes[0];
var box = selected.getBBox(); var box = selected.getBBox();
// if we have not moved/resized, then immediately leave // if we have not moved/resized, then immediately leave
@@ -618,6 +621,7 @@ function SvgCanvas(c)
var recalculateSelectedOutline = function() { var recalculateSelectedOutline = function() {
var selected = selectedElements[0]; var selected = selectedElements[0];
var selectedBBox = selectedBBoxes[0]
var theSelector = selectorManager.requestSelector(selected); var theSelector = selectorManager.requestSelector(selected);
if (selected != null && theSelector != null) { if (selected != null && theSelector != null) {
theSelector.resize(selectedBBox); theSelector.resize(selectedBBox);
@@ -627,81 +631,7 @@ function SvgCanvas(c)
// public events // public events
// TODO: grab code here and add to addSelection... // TODO: grab code here and add to addSelection...
// TODO: use addSelection instead of selectElement throughout
// call this function to set a single selected element
// call this function with null to clear the selected element
var selectElement = function(newSelected, multi)
{
var rubberBox = selectorManager.getRubberBandBox();
// if the element to be selected is actually the rubber-band box
// then simply return (do not select it)
if (newSelected == rubberBox) {
return;
}
// if we are not in multi-mode and newSelected is already selected
// then simply return
// otherwise clear all previous selectors
var multi = multi || false;
if (!multi) {
var selected = selectedElements[0];
if (selectedElements[0] == newSelected) {
return;
}
for (var i = 0; i < selectedElements.length; ++i) {
selectorManager.releaseSelector(selectedElements[i]);
}
}
// Firefox does not implement getIntersectionList(), see
// https://bugzilla.mozilla.org/show_bug.cgi?id=501421
// Webkit does not implement getIntersectionList(), see
// https://bugs.webkit.org/show_bug.cgi?id=11274
// TODO: for these browsers we will need to brute force getIntersectionList()
// var nodes = svgroot.getIntersectionList(rubberBox.getBBox(), null);
// find next slot in selectedElements array
var index = 0;
/* index = selectedElements.length;
for (var i = 0; i < selectedElements.length; ++i) {
if (selectedElements[i] == null) { index = i; break; }
}
*/
selectedElements[index] = newSelected;
selected = selectedElements[index];
if (selected != null) {
selectedBBox = selected.getBBox();
// the manager gives us a selector
var theSelector = selectorManager.requestSelector(selected);
// recalculate size and then re-append to bottom of document
recalculateSelectedOutline();
// set all our current styles to the selected styles
current_fill = selected.getAttribute("fill");
current_fill_opacity = selected.getAttribute("fill-opacity");
current_stroke = selected.getAttribute("stroke");
current_stroke_opacity = selected.getAttribute("stroke-opacity");
current_stroke_width = selected.getAttribute("stroke-width");
current_stroke_style = selected.getAttribute("stroke-dasharray");
if (selected.tagName == "text") {
current_font_size = selected.getAttribute("font-size");
current_font_family = selected.getAttribute("font-family");
}
// do not show resize grips on text elements
theSelector.showGrips(selected.tagName != "text" && current_mode != "multiselect");
}
call("selected", selected);
};
//
this.clearSelection = function() { this.clearSelection = function() {
if (selectedElements[0] == null) { return; } if (selectedElements[0] == null) { return; }
// console.log("clearSelection() with length=" + selectedElements.length); // console.log("clearSelection() with length=" + selectedElements.length);
@@ -711,12 +641,13 @@ function SvgCanvas(c)
if (elem == null) break; if (elem == null) break;
selectorManager.releaseSelector(elem); selectorManager.releaseSelector(elem);
selectedElements[i] = null; selectedElements[i] = null;
selectedBBoxes[i] = null;
} }
call("selected", null); call("selected", selectedElements);
// console.log(selectedElements);
}; };
this.addToSelection = function(elemsToAdd) { this.addToSelection = function(elemsToAdd) {
// console.log("addToSelection() with: " + elemsToAdd);
if (elemsToAdd.length == 0) { return; } if (elemsToAdd.length == 0) { return; }
// find the first null in our selectedElements array // find the first null in our selectedElements array
@@ -727,18 +658,20 @@ function SvgCanvas(c)
} }
++j; ++j;
} }
// console.log("addToSelection() with j=" + j + " and # to add is " + elemsToAdd.length); // console.log(" j=" + j + " and # to add is " + elemsToAdd.length);
// console.log(selectedElements); // console.log(selectedElements);
// now add each element consecutively // now add each element consecutively
for (var i = 0; i < elemsToAdd.length; ++i) { for (var i = 0; i < elemsToAdd.length; ++i) {
var elem = elemsToAdd[i]; var elem = elemsToAdd[i];
// we ignore any selectors
if (elem.id.substr(0,13) == "selectorGrip_") continue;
// if it's not already there, add it // if it's not already there, add it
if (selectedElements.indexOf(elem) == -1) { if (selectedElements.indexOf(elem) == -1) {
selectedElements[j++] = elem; selectedElements[j] = elem;
selectedBBoxes[j++] = elem.getBBox();
selectorManager.requestSelector(elem); selectorManager.requestSelector(elem);
selectedBBox = elem.getBBox(); call("selected", selectedElements);
call("selected", elem);
// console.log(selectorManager.selectors); // console.log(selectorManager.selectors);
// console.log(selectorManager.selectorMap); // console.log(selectorManager.selectorMap);
} }
@@ -763,8 +696,8 @@ function SvgCanvas(c)
newSelectedItems[j++] = elem; newSelectedItems[j++] = elem;
} }
else { // remove the item and its selector else { // remove the item and its selector
console.log(selectorManager.selectors); // console.log(selectorManager.selectors);
console.log(selectorManager.selectorMap); // console.log(selectorManager.selectorMap);
selectorManager.releaseSelector(elem); selectorManager.releaseSelector(elem);
} }
} }
@@ -775,13 +708,14 @@ function SvgCanvas(c)
// in mouseDown : // in mouseDown :
// - when we are in a create mode, the element is added to the canvas // - when we are in a create mode, the element is added to the canvas
// but the action is not recorded until mouseUp // but the action is not recorded until mousing up
// - when we are in select mode, select the element, remember the position // - when we are in select mode, select the element, remember the position
// and do nothing else // and do nothing else
var mouseDown = function(evt) var mouseDown = function(evt)
{ {
var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft; var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft;
var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop; var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop;
// console.log("mouseDown, current_mode=" + current_mode);
switch (current_mode) { switch (current_mode) {
case "select": case "select":
started = true; started = true;
@@ -795,8 +729,11 @@ function SvgCanvas(c)
canvas.addToSelection([t]); canvas.addToSelection([t]);
} }
else { else {
canvas.clearSelection();
current_mode = "multiselect"; current_mode = "multiselect";
rubberBox = selectorManager.getRubberBandBox(); if (rubberBox == null) {
rubberBox = selectorManager.getRubberBandBox();
}
rubberBox.x.baseVal.value = start_x; rubberBox.x.baseVal.value = start_x;
rubberBox.y.baseVal.value = start_y; rubberBox.y.baseVal.value = start_y;
rubberBox.width.baseVal.value = 0; rubberBox.width.baseVal.value = 0;
@@ -955,32 +892,31 @@ function SvgCanvas(c)
{ {
case "select": case "select":
// we temporarily use a translate on the element being dragged // we temporarily use a translate on the element being dragged
// this transform is removed upon mouseUp and the element is relocated to the // this transform is removed upon mousing up and the element is
// new location // relocated to the new location
if (selected != null) { if (selected != null) {
var dx = x - start_x; var dx = x - start_x;
var dy = y - start_y; var dy = y - start_y;
selectedBBox = selected.getBBox(); selectedBBoxes[0] = selected.getBBox();
selectedBBox.x += dx; selectedBBoxes[0].x += dx;
selectedBBox.y += dy; selectedBBoxes[0].y += dy;
var ts = "translate(" + dx + "," + dy + ")"; var ts = "translate(" + dx + "," + dy + ")";
selected.setAttribute("transform", ts); selected.setAttribute("transform", ts);
recalculateSelectedOutline(); recalculateSelectedOutline();
} }
break; break;
case "multiselect": case "multiselect":
if (rubberBox != null) { rubberBox.x.baseVal.value = Math.min(start_x,x);
rubberBox.x.baseVal.value = Math.min(start_x,x); rubberBox.y.baseVal.value = Math.min(start_y,y);
rubberBox.y.baseVal.value = Math.min(start_y,y); rubberBox.width.baseVal.value = Math.abs(x-start_x);
rubberBox.width.baseVal.value = Math.abs(x-start_x); rubberBox.height.baseVal.value = Math.abs(y-start_y);
rubberBox.height.baseVal.value = Math.abs(y-start_y);
}
// evt.target is the element that the mouse pointer is passing over // evt.target is the element that the mouse pointer is passing over
// TODO: add new targets to the selectedElements array, create a // TODO: add new targets to the selectedElements array, create a
// selector for it, etc // selector for it, etc
var nodeName = evt.target.nodeName; var nodeName = evt.target.nodeName;
if (nodeName != "div" && nodeName != "svg") { if (nodeName != "div" && nodeName != "svg") {
addToSelection([evt.target]); canvas.addToSelection([evt.target]);
} }
break; break;
case "resize": case "resize":
@@ -1006,6 +942,7 @@ function SvgCanvas(c)
sx = (width-dx)/width; sx = (width-dx)/width;
} }
var selectedBBox = selectedBBoxes[0];
selectedBBox.x = left+tx; selectedBBox.x = left+tx;
selectedBBox.y = top+ty; selectedBBox.y = top+ty;
selectedBBox.width = width*sx; selectedBBox.width = width*sx;
@@ -1020,7 +957,6 @@ function SvgCanvas(c)
selectedBBox.height = -selectedBBox.height; selectedBBox.height = -selectedBBox.height;
} }
ts = "translate(" + (left+tx) + "," + (top+ty) + ") scale(" + (sx) + "," + (sy) + ts = "translate(" + (left+tx) + "," + (top+ty) + ") scale(" + (sx) + "," + (sy) +
") translate(" + (-left) + "," + (-top) + ")"; ") translate(" + (-left) + "," + (-top) + ")";
selected.setAttribute("transform", ts); selected.setAttribute("transform", ts);
@@ -1090,29 +1026,44 @@ function SvgCanvas(c)
var mouseUp = function(evt) var mouseUp = function(evt)
{ {
if (!started) return; if (!started) return;
// console.log("mouseUp, current_mode=" + current_mode);
var selected = selectedElements[0];
started = false; started = false;
var element = svgdoc.getElementById(getId()); var element = svgdoc.getElementById(getId());
var keep = false; var keep = false;
switch (current_mode) switch (current_mode)
{ {
// fall-through to select here // intentionally fall-through to select here
case "resize": case "resize":
current_mode = "select";
case "select":
if (selected != null) {
recalculateSelectedDimensions();
recalculateSelectedOutline();
// we return immediately from select so that the obj_num is not incremented
return;
}
break;
case "multiselect": case "multiselect":
if (rubberBox != null) { if (rubberBox != null) {
rubberBox.setAttribute("display", "none"); rubberBox.setAttribute("display", "none");
} }
current_mode = "select"; current_mode = "select";
case "select":
if (selectedElements[0] != null) {
// if we only have one selected element
if (selectedElements[1] == null) {
// set our current stroke/fill properties to the element's
var selected = selectedElements[0];
current_fill = selected.getAttribute("fill");
current_fill_opacity = selected.getAttribute("fill-opacity");
current_stroke = selected.getAttribute("stroke");
current_stroke_opacity = selected.getAttribute("stroke-opacity");
current_stroke_width = selected.getAttribute("stroke-width");
current_stroke_style = selected.getAttribute("stroke-dasharray");
if (selected.tagName == "text") {
current_font_size = selected.getAttribute("font-size");
current_font_family = selected.getAttribute("font-family");
}
selectorManager.requestSelector(selected).showGrips(selected.tagName != "text");
}
recalculateSelectedDimensions();
recalculateSelectedOutline();
// we return immediately from select so that the obj_num is not incremented
return;
}
break; break;
case "path": case "path":
keep = true; keep = true;
@@ -1183,7 +1134,8 @@ function SvgCanvas(c)
break; break;
case "text": case "text":
keep = true; keep = true;
selectElement(element); canvas.clearSelection();
canvas.addToSelection([element]);
break; break;
} }
d_attr = null; d_attr = null;
@@ -1385,7 +1337,7 @@ function SvgCanvas(c)
if (oldval != val) { if (oldval != val) {
if (attr == "#text") selected.textContent = val; if (attr == "#text") selected.textContent = val;
else selected.setAttribute(attr, val); else selected.setAttribute(attr, val);
selectedBBox = selected.getBBox(); selectedBBoxes[0] = selected.getBBox();
recalculateSelectedOutline(); recalculateSelectedOutline();
var changes = {}; var changes = {};
changes[attr] = oldval; changes[attr] = oldval;
@@ -1442,9 +1394,9 @@ function SvgCanvas(c)
this.moveSelectedElement = function(dx,dy) { this.moveSelectedElement = function(dx,dy) {
var selected = selectedElements[0]; var selected = selectedElements[0];
if (selected != null) { if (selected != null) {
selectedBBox = selected.getBBox(); selectedBBoxes[0] = selected.getBBox();
selectedBBox.x += dx; selectedBBoxes[0].x += dx;
selectedBBox.y += dy; selectedBBoxes[0].y += dy;
recalculateSelectedDimensions(); recalculateSelectedDimensions();
recalculateSelectedOutline(); recalculateSelectedOutline();