//Javascript document
/***************************/
/* LOAD, SAVE, EXPORT */
/***************************/
function png(sf,crop) {
if (draw.path.length == 0) return
if (typeof sf == 'undefined') sf = 1;
if (typeof crop == 'undefined') crop = false;
deselectAllPaths();
if (crop == false) {
var canvas = drawPathsToCanvas(undefined,draw.path,undefined,sf);
//window.open(canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"),'_blank');
} else {
var l,t,r,b;
for (var p = 0; p < draw.path.length; p++) {
if (un(l)) {
l = draw.path[p].border[0];
t = draw.path[p].border[1];
r = draw.path[p].border[4];
b = draw.path[p].border[5];
} else {
l = Math.min(l,draw.path[p].border[0]);
t = Math.min(t,draw.path[p].border[1]);
r = Math.max(r,draw.path[p].border[4]);
b = Math.max(b,draw.path[p].border[5]);
}
}
var canvas2 = drawPathsToCanvas(undefined,draw.path,undefined,sf);
var canvas = newctx({rect:[0,0,r-l,b-t],vis:false}).canvas;
canvas.ctx.drawImage(canvas,-l,-t);
//window.open(canvas2.toDataURL("image/png"),'_blank');
}
saveCanvasAsPNG(canvas,'img.png');
}
function pngPath(path,sf,crop) {
if (un(path)) var path = draw.path;
if (draw.path.length == 0) return
if (un(sf)) sf = 1;
if (un(crop)) crop = false;
deselectAllPaths();
if (crop == false) {
var canvas = drawPathsToCanvas(undefined,path,undefined,sf);
window.open(canvas.toDataURL("image/png"),'_blank');
} else {
var l,t,r,b;
for (var p = 0; p < path.length; p++) {
if (un(l)) {
l = path[p].tightBorder[0];
t = path[p].tightBorder[1];
r = path[p].tightBorder[4];
b = path[p].tightBorder[5];
} else {
l = Math.min(l,path[p].tightBorder[0]);
t = Math.min(t,path[p].tightBorder[1]);
r = Math.max(r,path[p].tightBorder[4]);
b = Math.max(b,path[p].tightBorder[5]);
}
}
var canvas2 = drawPathsToCanvas(undefined,path,undefined,sf);
var canvas = newctx({rect:[0,0,r-l,b-t],vis:false}).canvas;
canvas.ctx.drawImage(canvas2,-l,-t);
window.open(canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"),'_blank');
//window.open(canvas.toDataURL("image/png"),'_blank');
}
//saveCanvasAsPNG(canvas,'img.png');
}
if (un(draw)) var draw = {};
draw.loadPaths = function(url,callback,index,setDrawPaths) {
loadScript(url,function(index) {
var paths = clone(fileData);
delete window.fileData;
draw.convertLoadedPaths(paths);
if (boolean(setDrawPaths,true) == true) {
clearDrawPaths();
draw.path = !un(paths) ? paths : [];
draw.updateAllBorders();
drawCanvasPaths();
draw.undo.reset();
}
if (typeof callback == 'function') callback(index,paths);
return paths;
},undefined,index);
}
draw.convertLoadedPaths = function(paths) {
if (typeof paths == 'undefined') paths = draw.path;
for (var p = paths.length-1; p >= 0; p--) {
var path = paths[p];
path.selected = false;
//delete path.qBox;
if (!un(path.trigger) && path.trigger.length == 0) delete path.trigger;
for (var o = path.obj.length-1; o >= 0; o--) {
if (un(path.obj[o])) {
console.log(o,path.obj);
continue;
}
var obj = path.obj[o];
switch (obj.type) {
case 'text':
path.obj[o] = draw.convertTextToText2(obj);
break;
case 'text2':
draw.text2.extractStartTags(obj);
break;
case 'input':
case 'button':
case 'multChoice':
path.obj.splice(o,1);
break;
case 'table':
case 'table2':
path.obj[o] = draw.convertTable(obj);
break;
case 'image':
draw.loadImage(obj);
break;
}
}
if (path.obj.length == 0) path.splice(p,1);
}
return paths;
}
draw.convertTextToText2 = function(obj) {
var align = [-1,-1];
if (obj.mathsInput.textAlign == 'left') align[0] = -1;
if (obj.mathsInput.textAlign == 'center') align[0] = 0;
if (obj.mathsInput.textAlign == 'right') align[0] = 1;
if (obj.mathsInput.vertAlign == 'top') align[1] = -1;
if (obj.mathsInput.vertAlign == 'middle') align[1] = 0;
if (obj.mathsInput.vertAlign == 'bottom') align[1] = 1;
var txt = obj.mathsInput.richText;
txt = textArrayReplace(txt,'<
>',br);
txt = textArrayReplace(txt,'Segoe Print','segoePrint');
var rect = [obj.left,obj.top,obj.width,obj.height];
//console.log('---',obj,obj.mathsInput,obj.mathsInput.leftPoint)
if (!un(obj.mathsInput.leftPoint)) {
rect[0] += obj.mathsInput.leftPoint;
rect[1] += obj.mathsInput.leftPoint;
rect[2] -= obj.mathsInput.leftPoint;
}
var obj2 = {
type:'text2',
text:txt,
rect:rect,
align:align
}
if (obj.showBorder == true) {
obj2.box = {type:'loose'};
if (!un(obj.fillColor)) obj2.box.color = obj.fillColor;
if (!un(obj.color)) obj2.box.borderColor = obj.color;
if (!un(obj.thickness)) obj2.box.borderWidth = obj.thickness;
if (!un(obj.radius)) obj2.box.radius = obj.radius;
}
var keysToKeep = ['pathPin','trigger'];
for (var k = 0; k < keysToKeep.length; k++) {
if (!un(obj[keysToKeep[k]])) obj2[keysToKeep[k]] = obj[keysToKeep[k]];
}
return obj2;
}
draw.convertTable = function(obj) {
if (!un(obj.mInputs)) {
for (var r = 0; r < obj.mInputs.length; r++) {
for (var c = 0; c < obj.mInputs[r].length; c++) {
var m = obj.mInputs[r][c];
var txt = m.richText;
txt = textArrayReplace(txt,'<
>',br);
txt = textArrayReplace(txt,'Segoe Print','segoePrint');
obj.cells[r][c].text = txt;
var align = [0,0];
if (m.textAlign == 'left' || m.align == 'left') align[0] = -1;
if (m.textAlign == 'right' || m.align == 'right') align[0] = 1;
if (m.vertAlign == 'top') align[1] = -1;
if (m.vertAlign == 'bottom') align[1] = 1;
obj.cells[r][c].align = align;
obj.cells[r][c].padding = 10;
}
}
}
if (obj.type == 'table') {
obj.widths = [];
obj.heights = [];
for (var x = 0; x < obj.xPos.length-1; x++) obj.widths[x] = obj.xPos[x+1] - obj.xPos[x];
for (var y = 0; y < obj.yPos.length-1; y++) obj.heights[y] = obj.yPos[y+1] - obj.yPos[y];
obj.type = 'table2';
}
delete obj.cell;
delete obj.mInputs;
return obj;
}
draw.loadImage = function(obj) {
obj.image = new Image;
obj.image.onload = function() {
drawCanvasPaths();
}
if (!un(obj.src)) {
obj.image.src = obj.src;
} else if (!un(obj.filename)) {
obj.image.src = 'images/'+obj.filename;
}
}
draw.savePaths = function(filePath,fileName,pngData,paths,callback) {
if (un(paths)) var paths = clone(draw.path);
/*var drawPaths = 'var fileData = '+JSON.stringify(paths,function(key,value) {
if (['borderButtons','border','tightBorder','selected','ctx','qBox',"data","cursorData","textLoc","cursorPos","cursorMap","allMap","canvas","ctx","cursorCanvas","cursorctx","startText","startRichText","startTags","stringJS","currBackColor","preText","postText"].includes(key)) return undefined;
if (typeof value == 'number') return Number(value.toFixed(3));
return value;
});*/
var drawPaths = draw.stringifyDrawPaths(paths);
var params = "filePath="+encodeURIComponent(filePath)+"&fileName="+encodeURIComponent(fileName)+"&drawPaths="+encodeURIComponent(drawPaths);
if (un(pngData)) {
var canvas = drawPathsToCanvas(undefined,draw.path,undefined,0.15);
var pngData = canvas.toDataURL("image/png");
}
params += "&pngData="+encodeURIComponent(pngData);
console.log(filePath,fileName);
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("post", "/i2/draw_savePaths.php", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.onreadystatechange = function() {
if (this.readyState == 4) {
var response = this.responseText == 'true' ? true : false;
console.log('saved:',response);
if (response == false) console.log(drawPaths);
if (!un(callback)) callback();
}
}
xmlHttp.send(params);
}
draw.stringifyDrawPaths = function(paths,includeVarFileData) {
if (un(paths)) paths = draw.path;
paths = draw.compressPaths(paths);
var str = draw.stringify(paths);
if (boolean(includeVarFileData,true) == true) str = 'var fileData = '+str;
return str;
}
draw.compressPaths = function(paths) {
//paths = clone(paths);
for (var p = paths.length-1; p >= 0; p--) {
var path = paths[p];
draw.compressPath(path);
if (path.obj.length == 0) paths.splice(p,1);
}
//console.log(paths);
return paths;
}
draw.compressPath = function(path) {
function isEmpty(obj) {
for(var key in obj) {
if(obj.hasOwnProperty(key))
return false;
}
return true;
}
if (!un(path.isInput) && isEmpty(path.isInput)) delete path.isInput;
if (!un(path.interact) && isEmpty(path.interact)) delete path.interact;
for (var o = path.obj.length-1; o >= 0; o--) {
var obj = path.obj[o];
if (!un(obj.interact) && isEmpty(obj.interact)) delete obj.interact;
var deleteProperties = ['edit','drawing','textEdit'];
if (obj.type == 'text2') {
if ((un(obj.text) || textArrayCheckIfEmpty(obj.text)) && un(obj.id) && (un(obj.box) || obj.box.type == 'none')) {
path.obj.splice(o,1);
continue;
}
var tags = clone(defaultTags);
if (!un(obj.align)) tags.align = obj.align == -1 ? 'left' : obj.align == 1 ? 'right' : 'center';
if (!un(obj.text)) {
obj.text = simplifyText(obj.text);
obj.text = textArrayRemoveDefaultTags(obj.text,tags);
obj.text = removeTagsOfType(obj.text,'selected');
}
deleteProperties.push('tightRect');
} else if (obj.type == 'table2') {
deleteProperties.push('rows','cols','xPos','yPos','width','height','drawing','minCellWidth','minCellHeight','horizAlign');
var deleteCellProperties = ['minWidth','minHeight','highlight','selected','styled','tightRect'];
var cells = draw.table2.getAllCells(obj);
var tags = clone(defaultTags);
if (!un(obj.text)) {
if (!un(obj.text.font)) tags.font = obj.text.font;
if (!un(obj.text.size)) tags.fontSize = obj.text.size;
if (!un(obj.text.color)) tags.color = obj.text.color;
}
for (var c = 0; c < cells.length; c++) {
for (var d = 0; d < deleteCellProperties.length; d++) delete cells[c][deleteCellProperties[d]];
if (!un(cells[c].trigger) && cells[c].trigger.length == 0) delete cells[c].trigger;
if (cells[c].color == 'none') delete cells[c].color;
if (!un(cells[c].box) && cells[c].box.type == 'none') delete cells[c].box;
if (!un(cells[c].box) && (cells[c].box.color == 'none' && cells[c].box.borderColor == 'none')) delete cells[c].box;
if (!un(cells[c].text)) {
var cellTags = clone(tags);
if (!un(cells[c].align)) cellTags.align = cells[c].align[0] == -1 ? 'left' : cells[c].align[0] == 1 ? 'right' : 'center';
cells[c].text = simplifyText(cells[c].text);
cells[c].text = textArrayRemoveDefaultTags(cells[c].text,cellTags);
cells[c].text = removeTagsOfType(cells[c].text,'selected');
}
}
}/* else if (obj.type == 'polygon') {
if (!un(obj.angles)) {
for (var a = 0; a < obj.angles.length; a++) {
if (un(obj.angles[a])) continue;
if (obj.angles[a].drawCurve !== true && obj.angles[a].measureLabelOnly !== false) {
delete obj.angles[a];
}
}
if (obj.angles.length == 0) {
delete obj.angles;
}
}
}*/
for (var d = 0; d < deleteProperties.length; d++) delete obj[deleteProperties[d]];
for (var key in obj) if (key.charAt(0) == '_' || (obj[key] instanceof Array && obj[key].isEmpty() == true)) delete obj[key];
}
delete path.border;
delete path.borderButtons;
delete path.selected;
delete path.tightBorder;
return path;
}
draw.stringify = function(obj) {
var circular = []; // store all objects to check for circular refs
var str = stringify(obj);
return str;
function stringify(obj) {
var str = "";
if (circular.indexOf(obj) > -1) return "null";
if (obj instanceof Array) {
for (var i = 0; i < obj.length; i++) {
if (typeof obj[i] == 'object') {
circular.push(obj);
break;
}
}
str += "[";
for (var i = 0; i < obj.length; i++) str += stringify(obj[i])+',';
if (str.slice(-1) == ',') str = str.slice(0,-1);
str += "]";
} else if (typeof obj == 'object') {
for (var key in obj) {
if (typeof obj[key] == 'object') {
circular.push(obj);
break;
}
}
str += "{";
for (var key in obj) {
if (['borderButtons','border','tightBorder','selected','ctx','qBox',"data","cursorData","textLoc","cursorPos","cursorMap","allMap","canvas","ctx","cursorCanvas","cursorctx","startText","startRichText","startTags","stringJS","currBackColor","preText","postText"].includes(key) || key.indexOf('_') == 0 || obj.hasOwnProperty(key) == false) continue;
var value = stringify(obj[key]);
if (value == '') continue;
str += '"'+key+'":'+value+",";
}
if (str.slice(-1) == ',') str = str.slice(0,-1);
str += "}";
} else if (typeof obj == 'function') {
str += obj.toString().replace(/\r?\n|\r|\t/g,"");
} else if (typeof obj == 'number') {
str += String(Number(obj.toFixed(3)));
} else if (typeof obj == 'string') {
var escapeString = replaceAll(obj,"\"","\\\"");
str += '"'+escapeString+'"';
} else if (typeof obj == 'boolean') {
str += obj;
} else {
if (typeof obj !== 'undefined') console.log('draw.stringify type not included: ',typeof obj,obj);
}
return str;
}
}
/***************************/
/* PATH DRAWING */
/***************************/
draw.rotationMode = false;
draw.divMode = function() {
if (!un(draw.div)) return;
var div = document.createElement('div');
container.appendChild(div);
draw.div = div;
div.width = 1225;
div.height = 700;
div.setAttribute('draggable', 'false');
div.setAttribute('class', 'buttonClass');
div.style.overflow = 'auto';
div.style.cursor = 'default';
div.zoom = 1;
div.getScrollBarWidth = function() {
// https://stackoverflow.com/questions/13382516/getting-scroll-bar-width-using-javascript
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
outer.style.overflow = "scroll";
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll+2;
}
div.resize = function() {
var xsf = canvasDisplayWidth / mainCanvasWidth;
var ysf = canvasDisplayHeight / mainCanvasHeight;
draw.div.style.left = (canvasDisplayLeft + 0 * xsf) + "px";
draw.div.style.top = (0 * ysf) + "px";
draw.div.style.width = (1225 * xsf) + "px";
draw.div.style.height = (700 * ysf) + "px";
draw.div.setZoom(draw.div.zoom);
}
div.setZoom = function(sf) {
if (un(draw.div.scrollBarWidth)) draw.div.scrollBarWidth = draw.div.getScrollBarWidth();
var clientRect = canvas.getBoundingClientRect();
var viewportWidth = clientRect.width-draw.div.scrollBarWidth;
var w = viewportWidth*sf;
var h = w*(1700/1200);
//var l = 0;
//var l = (viewportWidth*(1-sf))/2;
var l = Math.max(0,(viewportWidth*(1-sf))/2);
for (var p = 0; p < draw.div.children.length; p++) {
var pageDiv = draw.div.children[p];
pageDiv.pageIndex = 0;
pageDiv.style.width = w+'px';
pageDiv.style.height = h+'px';
pageDiv.style.left = l+'px';
for (var c = 0; c < pageDiv.children.length; c++) {
var child = pageDiv.children[c];
child.style.width = w+'px';
child.style.height = h+'px';
child.style.left = '0px';
}
}
draw.div.zoom = sf;
}
div.setPos = function(pos) {
var bounds = draw.drawCanvas[0].getBoundingClientRect();
draw.div.scrollTop = pos[1]*(1700/bounds.height);
draw.div.scrollLeft = pos[0]*(1200/bounds.width);
}
div.zoomToRect = function(rect) {
var sf = Math.min(1200/rect[2],700/rect[3]);
draw.div.setZoom(sf);
draw.div.setPos(rect);
}
div.zoomReset = function() {
draw.div.zoomToRect([0,0,1200,700]);
}
div.zoomPageHeight = function() {
draw.div.zoomToRect([0,0,1200,1700]);
}
div.createPageDiv = function(page) {
if (!un(page._div)) return;
page._div = document.createElement('div');
page._div.className = 'page-div';
page._div.pageIndex = p;
page._div.innerHTML = '';
page._drawCanvas = [];
for (var i = 0; i < 7; i++) {
var pe = i == 6 ? true : false;
var canvas = createCanvas(0,0,1200,1700,false,false,pe,draw.zIndex+2*i);
canvas.pageIndex = pageIndex;
canvas.setAttribute('class', 'drawDivCanvas');
if (i == 0) {
canvas.style.backgroundColor = '#FFF';
canvas.style.border = '1px solid black';
}
if (i < 5) {
page._drawCanvas.push(canvas);
} else if (i == 5) {
page._toolsCanvas = canvas;
} else if (i == 6) {
page._cursorCanvas = canvas;
canvas.style.pointerEvents = true;
canvas.data[7] = true;
}
page._div.appendChild(canvas);
}
};
/*
if (!un(scroller)) hideScroller(scroller);
draw.div.setZoom(1);
//*/
/*
for (var c = 0; c < draw.drawCanvas.length; c++) {
hideObj(draw.drawCanvas[c]);
}
hideObj(draw.toolsCanvas);
hideObj(draw.cursorCanvas);
if (!un(scroller)) hideScroller(scroller);
draw.div.setZoom(1);
//*/
//*
var pageDiv = document.createElement('div');
pageDiv.className = 'page-div';
div.appendChild(pageDiv);
div.style.backgroundColor = '#999';
draw.drawCanvas[0].style.backgroundColor = '#FFF';
draw.drawCanvas[0].style.border = '1px solid black';
for (var c = 0; c < draw.drawCanvas.length; c++) {
hideObj(draw.drawCanvas[c]);
pageDiv.appendChild(draw.drawCanvas[c]);
draw.drawCanvas[c].setAttribute('class', 'drawDivCanvas');
}
hideObj(draw.toolsCanvas);
pageDiv.appendChild(draw.toolsCanvas);
draw.toolsCanvas.setAttribute('class', 'drawDivCanvas');
hideObj(draw.cursorCanvas);
pageDiv.appendChild(draw.cursorCanvas);
draw.cursorCanvas.setAttribute('class', 'drawDivCanvas');
//if (!un(scroller)) hideScroller(scroller);
draw.div.setZoom(1);
//*/
}
draw.multiPage = {
on: function() {
if (draw.multiPage.isOn === true) return;
if (un(draw.div)) draw.divMode();
draw.div.innerHTML = '';
for (var p = 0; p < file.resources[resourceIndex].pages.length; p++) {
var page = file.resources[resourceIndex].pages[p];
draw.div.appendChild(page._div);
if (page.pageVis === false) {
page._drawCanvas.last().style.backgroundColor = colorA('#666',0.65);
} else {
page._drawCanvas.last().style.backgroundColor = 'none';
}
//console.log(p,page._div,page._div.parentNode);
}
draw.multiPage.isOn = true;
draw.div.setZoom(1);
hideObj(draw.drawCanvas);
hideObj(draw.toolsCanvas);
hideObj(draw.cursorCanvas);
draw.multiPage.pageFocus(pIndex);
draw.multiPage.scrollToPage(pIndex);
draw.div.onscroll = draw.multiPage.onscroll;
},
off: function() {
if (draw.multiPage.isOn !== true) return;
for (var c = draw.div.children.length-1; c >= 0; c--) {
if (c == pIndex) continue;
draw.div.removeChild(draw.div.children[c]);
}
draw.multiPage.isOn = false;
draw.div.onscroll = function() {};
},
/*addPageCanvases: function(page,pageIndex) {
page._drawCanvas = [];
for (var i = 0; i < 7; i++) {
var pe = i == 6 ? true : false;
var canvas = createCanvas(0,0,1200,1700,false,false,pe,draw.zIndex+2*i);
canvas.pageIndex = pageIndex;
canvas.setAttribute('class', 'drawDivCanvas');
if (i == 0) {
canvas.style.backgroundColor = '#FFF';
canvas.style.border = '1px solid black';
drawPathsToCanvas(canvas,page.paths);
}
if (i < 5) {
page._drawCanvas.push(canvas);
} else if (i == 5) {
page._toolsCanvas = canvas;
} else if (i == 6) {
page._cursorCanvas = canvas;
canvas.style.pointerEvents = true;
canvas.data[7] = true;
}
}
//console.log(pageIndex,page);
addListenerMove(page._cursorCanvas,draw.multiPage.changePageListener);
},*/
changePageListener: function(e) {
draw.multiPage.changePage(e.target.pageIndex);
},
changePage: function(p) {
draw.multiPage.pageBlur(pIndex);
pIndex = p;
draw.multiPage.pageFocus(pIndex);
},
pageBlur: function(p) {
if (!un(pages[p])) {
var page = pages[p];
page.paths = [];
page.pen = [];
for (var p2 = 0; p2 < draw.path.length; p2++) {
if (draw.path[p2]._deletable === false) {
page.paths.push(draw.path[p2]);
} else {
page.pen.push(draw.path[p2]);
}
}
page._cursorPositions = draw.cursorPositions;
}
draw.path = [];
addListenerMove(draw.cursorCanvas,draw.multiPage.changePageListener);
removeListenerMove(draw.cursorCanvas,drawCanvasMove);
removeListenerStart(draw.cursorCanvas,drawCanvasStart);
draw.interact.stopAnimation();
},
pageFocus: function(p) {
var page = pages[p];
draw.drawCanvas = page._drawCanvas;
draw.toolsCanvas = page._toolsCanvas;
draw.cursorCanvas = page._cursorCanvas;
removeListenerMove(draw.cursorCanvas,draw.multiPage.changePageListener);
addListenerMove(draw.cursorCanvas,drawCanvasMove);
addListenerStart(draw.cursorCanvas,drawCanvasStart);
//console.log(p,clone(pages[p]));
if (!un(page.paths)) {
for (var p = 0; p < page.paths.length; p++) page.paths[p]._deletable = false;
draw.path = page.paths;
}
if (!un(pages[pIndex].pen)) draw.path = draw.path.concat(pages[pIndex].pen);
if (!un(page._cursorPositions)) {
draw.cursorPositions = page._cursorPositions;
} else {
for (var p = 0; p < draw.path.length; p++) {
draw.path[p].selected = false;
updateBorder(draw.path[p]);
}
calcCursorPositions();
}
presentButtons.update();
},
scrollToPage: function(p) {
if (draw.multiPage.isOn !== true) return;
if (un(draw.div.children[p])) return;
draw.div.children[p].scrollIntoView(true);
draw.multiPage.changePage(p);
},
onscroll: function(e) {
var p = Math.floor(pages.length*draw.div.scrollTop/draw.div.scrollHeight);
if (p == pIndex) return;
draw.multiPage.changePage(p);
}
}
draw.getColorAtPixel = function(x,y) {
var color;
for (var i = 0; i < draw.drawCanvas.length; i++) {
var p = draw.drawCanvas[i].ctx.getImageData(x,y,1,1).data;
if (p[3] === 0) continue;
color = 'rgba('+p[0]+', '+p[1]+', '+p[2]+', '+p[3]+')';
}
if (un(color)) color = mainCanvasFillStyle;
return color;
}
function drawCanvasPaths() {
if (typeof draw.beforeDraw == 'function') draw.beforeDraw();
while (draw.drawCanvas.length < 5) addDrawCanvas();
draw.drawCanvas[0].ctx.clear(); // unselected
draw.drawCanvas[1].ctx.clear(); // selected
draw.drawCanvas[2].ctx.clear(); // overlay (eg. construction buttons)
//draw.drawCanvas[3]; // select canvas 1 (movable)
//draw.drawCanvas[4]; // select canvas 2 (static)
var drawFirst = [], unselected = [], drawLast = [], overlay = [], selected = [];
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) path.obj[o]._path = path;
//if (path._visible == false) continue;
/*if (draw.mode == 'interact' && !un(path.isInput)) {
if (path.isInput.type == 'drag') {
if (un(path._canvas)) {
updateBorder(path);
var rect = clone(path.tightBorder);
rect[0] += -3 - draw.drawRelPos[0];
rect[1] += -3 - draw.drawRelPos[1];
rect[2] += 6;
rect[3] += 6;
path._canvas = newctx({rect:rect,drag:true,pe:true,z:10000}).canvas;
path._canvas.drawPos = clone(path.tightBorder);
path._canvas.dragPath = path;
if (!un(path.isInput.dragArea)) path._canvas.dragArea = path.isInput.dragArea;
path._canvas.ctx.translate(-rect[0],-rect[1]);
for (var o = 0; o < path.obj.length; o++) {
drawObjToCtx(path._canvas.ctx,path,path.obj[o],1,1,0,0);
}
}
showObj(path._canvas);
continue;
}
}
if (draw.mode !== 'interact' && !un(path._canvas)) {
hideObj(path._canvas);
}*/
if (path.selected == true || path._interacting === true) {
selected.push(path);
} else {
var isOverlay = false; drawFirst1 = false; drawLast1 = false;
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (!un(obj.interact) && obj.interact.overlay == true) {
isOverlay = true;
break;
} else if (obj.drawFirst == true || obj.type == 'qTable') {
drawFirst1 = true;
break;
} else if (obj.drawLast == true) {
drawLast1 = true;
break;
}
}
if (isOverlay == true) {
overlay.push(path);
} else if (drawFirst1 == true) {
drawFirst.push(path);
} else if (drawLast1 == true) {
drawLast.push(path);
} else {
unselected.push(path);
}
}
}
if (draw.mode !== 'interact' && draw.drawing == true && draw.path.last().selected !== true) selected.push(unselected.pop());
draw.pathCursorOrder = drawFirst.concat(unselected).concat(drawLast).concat(selected).concat(overlay);
for (var p = 0; p < draw.pathCursorOrder.length; p++) {
var path = draw.pathCursorOrder[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(draw[obj.type])) continue;
if (typeof draw[obj.type].drawUnderlay === 'function') draw[obj.type].drawUnderlay(draw.drawCanvas[0].ctx,obj,path);
}
}
if (drawFirst.length > 0) drawPathsToCanvas(draw.drawCanvas[0],drawFirst);
if (unselected.length > 0) drawPathsToCanvas(draw.drawCanvas[0],unselected);
if (drawLast.length > 0) drawPathsToCanvas(draw.drawCanvas[0],drawLast);
if (draw.mode == 'interact' && draw.appearMode == true) { // draw appear button positions
var ctx = draw.drawCanvas[0].ctx;
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (un(path.appear) || path.appear.active === false) continue;
var visible = boolean(path._visible,false);
if (visible == true && path.appear.reversible !== true) continue;
if (typeof path.appear.visible == 'function' && path.appear.visible(path) === false) continue;
if (typeof path.appear.visible == 'string') {
var testPath = draw.getPathById(path.appear.visible);
if (testPath !== false && getPathVis(testPath) == false) {
continue;
}
}
if (un(path.appear.pos)) {
if (un(path.border)) updateBorder(path);
if (un(path.border)) continue;
var l = path.border[0]+0.5*path.border[2]-20;
var t = path.border[1]+0.5*path.border[3]-20;
} else {
var l = path.appear.pos[0]-20;
var t = path.appear.pos[1]-20;
}
if (visible == false) {
roundedRect(ctx, l+3, t+3, 40 - 6, 40 - 6, 3, 6, '#96C', '#C9F');
ctx.beginPath();
ctx.fillStyle = '#FFF';
drawStar({
ctx: ctx,
center: [l+20,t+20],
radius: 12,
points: 5
});
ctx.fill();
} else {
roundedRect(ctx, l+3, t+3, 40 - 6, 40 - 6, 3, 6, colorA('#C9F',0.75), '#FFF');
ctx.beginPath();
ctx.fillStyle = colorA('#C9F',0.75);
drawStar({
ctx: ctx,
center: [l+20,t+20],
radius: 12,
points: 5
});
ctx.fill();
}
}
}
if (selected.length > 0) drawPathsToCanvas(draw.drawCanvas[1],selected);
if (overlay.length > 0) drawPathsToCanvas(draw.drawCanvas[2],overlay);
for (var p = 0; p < draw.pathCursorOrder.length; p++) {
var path = draw.pathCursorOrder[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(draw[obj.type])) continue;
if (typeof draw[obj.type].drawOverlay === 'function') draw[obj.type].drawOverlay(draw.drawCanvas[2].ctx,obj,path);
}
}
drawSelectCanvas();
drawSelectCanvas2();
draw.undo.saveState();
/*window.requestIdleCallback(function() {
draw.fillPath.updateDrawPolygons();
});*/
if (typeof draw.afterDraw == 'function') draw.afterDraw();
if (draw.mode === 'edit' && !un(window.pathList) && typeof window.pathList.update == 'function') window.pathList.update();
draw.ids.update();
/*if (draw.mode === 'edit' && !un(previews) && !un(previews.updateCurrentPage)) {
previews.updateCurrentPage()
}*/
}
function drawSelectedPaths(drawOverlay) {
while (draw.drawCanvas.length < 4) addDrawCanvas();
draw.drawCanvas[1].ctx.clear();
var selected = [];
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (path.selected == true || path._interacting === true) {
selected.push(draw.path[p]);
}
}
if (draw.drawing == true && draw.path.last().selected !== true) selected.push(draw.path.last());
if (selected.length > 0) drawPathsToCanvas(draw.drawCanvas[1],selected);
/*if (drawOverlay !== false) {
draw.drawCanvas[2].ctx.clear();
for (var p = 0; p < selected.length; p++) {
var path = selected[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(draw[obj.type])) continue;
if (typeof draw[obj.type].drawOverlay === 'function') draw[obj.type].drawOverlay(draw.drawCanvas[2].ctx,obj,path);
}
}
if (draw.mode !== 'interact') {
drawSelectCanvas();
drawSelectCanvas2();
draw.undo.saveState();
}
}*/
}
function drawPathsToCanvas(canvas2,paths,triggerNum,sf,backColor,relPos,fillBack,drawAllPaths,log) {
if (un(paths)) return;
if (un(sf)) sf = draw.scale || 1;
if (un(backColor)) backColor = mainCanvasFillStyle;
if (un(drawAllPaths)) drawAllPaths = false;
if (un(canvas2)) {
var canvas = document.createElement('canvas');
canvas.width = draw.drawCanvas[0].width*sf;
canvas.height = draw.drawCanvas[0].height*sf;
canvas.data = clone(draw.drawCanvas[0].data);
canvas.data[2] = draw.drawCanvas[0].data[2]*sf;
canvas.data[3] = draw.drawCanvas[0].data[3]*sf;
canvas.data[102] = draw.drawCanvas[0].data[102]*sf;
canvas.data[103] = draw.drawCanvas[0].data[103]*sf;
} else {
var canvas = canvas2;
}
//if (!un(draw.drawCanvas)) console.log(draw.drawCanvas.indexOf(canvas2),canvas2,paths);
var ctx = canvas.getContext('2d');
ctx.setTransform(1, 0, 0, 1, 0, 0);
if (relPos instanceof Array) ctx.translate(relPos[0],relPos[1]);
if (sf !== 1) ctx.scale(sf,sf);
if (boolean(fillBack,false) == true) {
ctx.fillStyle = backColor;
ctx.fillRect(0,0,canvas.width,canvas.height);
}
for (var p = 0; p < paths.length; p++) {
var path = paths[p];
if (un(path) || (drawAllPaths == false && getPathVis(path) == false)) continue;
if (path.notesOverlay === true && draw.notesOverlay !== true) continue;
if (!un(path.rotation)) {
ctx.translate(path.border[0]+0.5*path.border[2],path.border[1]+0.5*path.border[3]);
ctx.rotate(path.rotation);
ctx.translate(-path.border[0]-0.5*path.border[2],-path.border[1]-0.5*path.border[3]);
}
for (var o = 0; o < path.obj.length; o++) {
if (un(path.obj[o])) continue;
var obj = path.obj[o];
if (drawAllPaths == false && typeof obj.trigger !== 'undefined' && draw.ansMode == true && obj.trigger[0] == false && draw.showAns == false) continue;
if (obj.visible === false || obj.vis === false) continue;
if (log === true && obj.type === 'text2' && obj.text[0].indexOf("3. ") === 0) console.log(obj);
drawObjToCtx(ctx,path,obj,1,1,0,0,1);
}
if (!un(path.rotation)) {
ctx.translate(path.border[0]+0.5*path.border[2],path.border[1]+0.5*path.border[3]);
ctx.rotate(-path.rotation);
ctx.translate(-path.border[0]-0.5*path.border[2],-path.border[1]-0.5*path.border[3]);
}
}
ctx.setTransform(1, 0, 0, 1, 0, 0);
return canvas;
}
function getPathVis(path) {
if (typeof path == 'string') {
path = draw.getPathById(path);
if (path == false) return false;
}
if (un(path)) return false;
if (!un(path._path)) path = path._path;
if (path.notesOverlay === true && draw.notesOverlay !== true) return false;
if (!un(path.appear) && typeof path.appear.visible == 'function') {
var visibleTest = path.appear.visible(path);
if (visibleTest === true) return true;
if (visibleTest === false) return false;
}
if (!un(path.appear) && typeof path.appear.visible == 'string') {
if (getPathVis(path.appear.visible) == false) return false;
}
if (boolean(path.vis,true) == false) return false;
if (boolean(path._visible,true) == false) return false;
var vis = true;
if (typeof path.trigger == 'object') {
for (var l = 0; l <= draw.triggerNum; l++) {
if (typeof path.trigger[l] == 'boolean' && path.trigger[l] == true) {
vis = true;
} else if (typeof path.trigger[l] == 'boolean' && path.trigger[l] == false) {
vis = false;
}
}
if (draw.triggerNum == 1 && arraysEqual(path.trigger,[false])) vis = true;
}
return vis;
}
function drawObjToCtx(ctx,path,obj) {
if (!un(obj.trigger) && draw.ansMode == true && obj.trigger[0] == false && draw.showAns == false) return;
if (!un(draw[obj.type]) && !un(draw[obj.type].draw)) {
ctx.save();
ctx.lineWidth = obj.thickness || obj.lineWidth || 2;
ctx.strokeStyle = obj.lineColor || obj.strokeStyle || obj.color || '#000';
ctx.fillStyle = obj.fillColor || obj.fillStyle || 'none';
ctx.beginPath();
draw[obj.type].draw(ctx,obj,path);
ctx.restore();
ctx.setLineDash([]);
return;
}
}
function drawSelectCanvas() { // movable draw canvas
var canvas = draw.drawCanvas.last();
var ctx = canvas.ctx;
ctx.clearRect(draw.drawArea[0],draw.drawArea[1],draw.drawArea[2],draw.drawArea[3]);
if (draw.mode === 'interact') {
return;
}
ctx.scale(draw.scale,draw.scale);
var paths = selPaths();
for (var p = 0; p < paths.length; p++) {
var path = paths[p];
/*if (draw.rotationMode == true && !un(path.rotation) && path.rotation !== 0) {
ctx.translate(path.border[0]+0.5*path.border[2],path.border[1]+0.5*path.border[3]);
ctx.rotate(path.rotation);
ctx.translate(-path.border[0]-0.5*path.border[2],-path.border[1]-0.5*path.border[3]);
}*/
if (draw.mode !== 'interact') {
drawBorderButtons(path);
ctx.strokeStyle = draw.selectColor;
ctx.lineWidth = 1;
ctx.strokeRect(path.border[0],path.border[1],path.border[2],path.border[3]);
}
if (!un(draw.controlPanel) && paths.length == 1 && path.obj.length == 1 && ['three','qBox'].indexOf(path.obj[0].type) > -1) draw.controlPanel.draw(ctx,path.obj[0],path);
/*if (draw.rotationMode == true) {
ctx.beginPath();
ctx.moveTo(path.border[0]+0.5*path.border[2],path.border[1]);
ctx.lineTo(path.border[0]+0.5*path.border[2],path.border[1]-30);
ctx.stroke();
ctx.fillStyle = draw.selectColor;
ctx.beginPath();
ctx.arc(path.border[0]+0.5*path.border[2],path.border[1]-30,10,0,2*Math.PI);
ctx.fill();
}*/
//draw center lines
/*ctx.beginPath();
ctx.moveTo(path.border[0]+0.5*path.border[2],path.border[1]);
ctx.lineTo(path.border[0]+0.5*path.border[2],path.border[1]+path.border[3]);
ctx.moveTo(path.border[0],path.border[1]+0.5*path.border[3]);
ctx.lineTo(path.border[0]+path.border[2],path.border[1]+0.5*path.border[3]);
ctx.stroke();*/
/*if (draw.rotationMode == true && !un(path.rotation) && path.rotation !== 0) {
ctx.translate(path.border[0]+0.5*path.border[2],path.border[1]+0.5*path.border[3]);
ctx.rotate(-path.rotation);
ctx.translate(-path.border[0]-0.5*path.border[2],-path.border[1]-0.5*path.border[3]);
}*/
}
//if (!un(draw.controlPanel2) && !un(draw.controlPanel2.ctx)) draw.controlPanel2.draw();
ctx.setTransform(1, 0, 0, 1, 0, 0);
//console.log('-----');
}
function drawSelectCanvas2(){ // static draw canvas
var canvas = draw.drawCanvas[draw.drawCanvas.length-2];
var ctx = canvas.ctx;
ctx.clearRect(draw.drawArea[0],draw.drawArea[1],draw.drawArea[2],draw.drawArea[3]);
if (draw.mode === 'interact') {
calcCursorPositions();
return;
}
ctx.scale(draw.scale,draw.scale);
//ctx.fillStyle = colorA('#F00',0.2);
//ctx.fillRect(draw.drawArea[0],draw.drawArea[1],draw.drawArea[2],draw.drawArea[3]);
if (draw.appearMoveMode == true) {
ctx.strokeStyle = '#999';
ctx.lineWidth = 1;
ctx.beginPath();
for (var x = 0; x < draw.drawArea[2]; x += 10) {
ctx.moveTo(x,0);
ctx.lineTo(x,draw.drawArea[3]);
}
for (var y = 0; y < draw.drawArea[3]; y += 10) {
ctx.moveTo(0,y);
ctx.lineTo(draw.drawArea[2],y);
}
ctx.stroke();
ctx.lineWidth = 3;
ctx.beginPath();
for (var x = 0; x < draw.drawArea[2]; x += 100) {
ctx.moveTo(x,0);
ctx.lineTo(x,draw.drawArea[3]);
}
for (var y = 0; y < draw.drawArea[3]; y += 100) {
ctx.moveTo(0,y);
ctx.lineTo(draw.drawArea[2],y);
}
ctx.stroke();
}
if (draw.mode == 'edit' && draw.appearMode == true) { // draw appear button positions
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (un(path.appear)) continue;
if (un(path.border)) updateBorder(path);
if (un(path.border)) continue;
if (un(path.appear.pos)) {
var l = path.border[0]+0.5*path.border[2]-20;
var t = path.border[1]+0.5*path.border[3]-20;
} else {
var l = path.appear.pos[0]-20;
var t = path.appear.pos[1]-20;
}
w = 40; h = 40;
if (path.selected == true) {
ctx.fillStyle = colorA('#96C',0.66);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = mainCanvasFillStyle;
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
} else {
ctx.fillStyle = colorA('#96C',0.33);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = mainCanvasFillStyle;
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
}
}
}
if (draw.drawMode == 'selectRect') {
ctx.save();
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
if (!ctx.setLineDash) {ctx.setLineDash = function () {}}
ctx.setLineDash([5,5]);
ctx.strokeRect(draw.selectRect[0],draw.selectRect[1],draw.selectRect[2],draw.selectRect[3]);
ctx.setLineDash([]);
ctx.restore();
} else if (draw.drawMode == 'zoomRect') {
ctx.save();
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
if (!ctx.setLineDash) {ctx.setLineDash = function () {}}
ctx.setLineDash([5,5]);
ctx.strokeRect(draw.zoomRect[0],draw.zoomRect[1],draw.zoomRect[2],draw.zoomRect[3]);
ctx.setLineDash([]);
ctx.restore();
}
/*if (draw.showSnapPoints == true) {
ctx.fillStyle = '#F00';
for (var i = 0; i < draw.snapPoints.length; i++) {
ctx.beginPath();
//console.log(draw.snapPoints[i][0],draw.snapPoints[i][1]);
ctx.arc(draw.snapPoints[i][0],draw.snapPoints[i][1],5,0,2*Math.PI);
ctx.fill();
}
}*/
ctx.setTransform(1, 0, 0, 1, 0, 0);
calcCursorPositions();
}
function drawBorderButtons(path) {
if (un(path.borderButtons)) return;
var buttons = path.borderButtons;
var canvas = draw.drawCanvas.last();
var ctx = canvas.ctx;
for (var i = 0; i < buttons.length; i++) {
if (un(buttons[i].dims)) continue;
var l = buttons[i].dims[0];
var t = buttons[i].dims[1];
var w = buttons[i].dims[2];
var h = buttons[i].dims[3];
var path = draw.path[buttons[i].pathNum];
if (typeof buttons[i].draw == 'function') {
buttons[i].draw(path,ctx,l,t,w,h);
continue;
}
switch (buttons[i].buttonType) {
case 'isInput-type':
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>'+buttons[i].type],box:{type:'loose',color:'#F96',borderColor:'#F96'}});
break;
case 'isInput-dragArea-snapToggle':
var snap = boolean(path.isInput.snap,false);
if (snap == true) {
ctx.fillStyle = '#00F';
ctx.fillRect(l,t,w,h);
var color = '#FFF';
} else {
var color = '#00F';
}
ctx.lineWidth = 2;
ctx.strokeStyle = '#00F';
ctx.strokeRect(l,t,w,h);
var textColor = snap == true ? '#FFF' : '#00F';
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<><>snap']});
break;
case 'isInput-drag-value':
var path = draw.path[buttons[i].pathNum];
var value = path.isInput.value !== "" ? path.isInput.value : '<>no value';
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>'+value],box:{type:'loose',color:'#F96',borderColor:'#F96'}});
break;
case 'isInput-drag-shuffleToggle':
var path = draw.path[buttons[i].pathNum];
var shuffle = boolean(path.isInput.shuffle,false);
if (shuffle == true) {
ctx.fillStyle = '#00F';
ctx.fillRect(l,t,w,h);
var color = '#FFF';
} else {
var color = '#00F';
}
ctx.lineWidth = 2;
ctx.strokeStyle = '#00F';
ctx.strokeRect(l,t,w,h);
var textColor = shuffle == true ? '#FFF' : '#00F';
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<><>shuffle']});
break;
case 'select-input-selColors':
var colors = buttons[i].selColors;
ctx.fillStyle = colors[0];
ctx.beginPath();
ctx.moveTo(l,t);
ctx.lineTo(l+w,t);
ctx.lineTo(l,t+h);
ctx.lineTo(l,t);
ctx.fill();
ctx.fillStyle = colors[1];
ctx.beginPath();
ctx.moveTo(l,t+w);
ctx.lineTo(l+w,t+h);
ctx.lineTo(l+w,t);
ctx.lineTo(l,t+w);
ctx.fill();
break;
case 'select-input-shuffleToggle':
var path = draw.path[buttons[i].pathNum];
var shuffle = boolean(path.isInput.shuffle,false);
if (shuffle == true) {
ctx.fillStyle = '#00F';
ctx.fillRect(l,t,w,h);
var color = '#FFF';
} else {
var color = '#00F';
}
ctx.lineWidth = 2;
ctx.strokeStyle = '#00F';
ctx.strokeRect(l,t,w,h);
var textColor = shuffle == true ? '#FFF' : '#00F';
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<><>shuffle']});
break;
case 'select-input-cellToggle':
var cell = draw.path[buttons[i].pathNum].obj[0].cells[buttons[i].row][buttons[i].col];
if (cell.ans == true) {
ctx.fillStyle = '#060';
ctx.fillRect(l,t,w,h);
var color = '#FFF';
} else {
var color = '#060';
}
ctx.lineWidth = 2;
ctx.strokeStyle = '#060';
ctx.strokeRect(l,t,w,h);
drawTick(ctx,w*0.8,h,color,l+w*0.1,t,w*0.1);
break;
case 'text-input-prevAns':
drawArrow({ctx:ctx,startX:l+0.75*w,startY:t+0.5*h,finX:l+0.25*w,finY:t+0.5*h,arrowLength:0.5*w,color:'#393',lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.5});
break;
case 'text-input-ansInfo':
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>'+buttons[i].text]});
break;
case 'text-input-nextAns':
drawArrow({ctx:ctx,startX:l+0.25*w,startY:t+0.5*h,finX:l+0.75*w,finY:t+0.5*h,arrowLength:0.5*w,color:'#393',lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.5});
break;
case 'text-input-algText':
if (buttons[i].algText) {
ctx.fillStyle = colorA('#393',0.5);
ctx.fillRect(l,t,w,h);
}
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<><>x']});
break;
case 'text-input-num':
if(buttons[i].num) {
ctx.fillStyle = colorA('#393',0.5);
ctx.fillRect(l,t,w,h);
}
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>#']});
break;
case 'text-input-oe':
if(buttons[i].oe) {
ctx.fillStyle = colorA('#393',0.5);
ctx.fillRect(l,t,w,h);
}
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>oe']});
break;
case 'text-input-tickStyle':
drawTick(ctx,w*0.8,w,'#060',l+w*0.1,t,w*(7/40));
break;
case 'resize':
case 'resize-path':
ctx.fillStyle = colorA(draw.selectColor,0.5);
ctx.fillRect(l,t,w,h);
drawArrow({ctx:ctx,startX:l+0.2*w,startY:t+0.2*h,finX:l+0.8*w,finY:t+0.8*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
drawArrow({ctx:ctx,finX:l+0.2*w,finY:t+0.2*h,startX:l+0.8*w,startY:t+0.8*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'text-horizResize':
ctx.fillStyle = colorA(draw.selectColor,0.5);
ctx.fillRect(l,t,w,h);
drawArrow({ctx:ctx,startX:l+0.2*w,startY:t+0.5*h,finX:l+0.8*w,finY:t+0.5*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
drawArrow({ctx:ctx,finX:l+0.2*w,finY:t+0.5*h,startX:l+0.8*w,startY:t+0.5*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'text2-fracScale':
ctx.fillStyle = colorA('#69F',0.5);
ctx.fillRect(l,t,w,h);
ctx.fillStyle = '#000';
ctx.fillRect(l+0.4*w,t+0.15*w,0.2*w,0.2*w);
ctx.fillRect(l+0.4*w,t+0.65*w,0.2*w,0.2*w);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(l+0.32*w,t+0.5*h);
ctx.lineTo(l+0.68*w,t+0.5*h);
ctx.stroke();//text({ctx:ctx,rect:[l,t,w,h*0.9],align:[0,0],text:['<>',['frac',[String.fromCharCode(0x25A0)],[String.fromCharCode(0x25A0)]]]});
break;
case 'text2-underline':
ctx.fillStyle = colorA('#FFC',0.5);
ctx.fillRect(l,t,w,h);
text({ctx:ctx,rect:[l,t,w,h*0.9],align:[0,0],text:['<>u']});
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.32*w,t+0.8*h);
ctx.lineTo(l+0.68*w,t+0.8*h);
ctx.stroke();
break;
case 'text2-algPadding':
var obj = path.obj[0];
if (un(obj.algPadding)) {
ctx.strokeStyle = colorA('#F9C',0.5);
ctx.lineWidth = 1;
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,rect:[l,t,w,h*0.9],align:[0,0],text:['<>-'],algPadding:0});
} else {
ctx.fillStyle = colorA('#F9C',0.5);
ctx.fillRect(l,t,w,h);
text({ctx:ctx,rect:[l,t,w,h*0.9],align:[0,0],text:['<>'+obj.algPadding],algPadding:0});
}
break;
case 'table2-draw.table2.questionFit':
case 'text2-fullWidth':
ctx.fillStyle = colorA('#9FC',0.5);
ctx.fillRect(l,t,w,h);
drawArrow({ctx:ctx,startX:l+0.2*w,startY:t+0.5*h,finX:l+0.8*w,finY:t+0.5*h,arrowLength:4,color:'#000',lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
drawArrow({ctx:ctx,finX:l+0.2*w,finY:t+0.5*h,startX:l+0.8*w,startY:t+0.5*h,arrowLength:4,color:'#000',lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'table2-draw.table2.questionGrid':
ctx.fillStyle = colorA('#9CF',0.5);
ctx.fillRect(l,t,w,h);
text({ctx:ctx,rect:[l,t,w,h],align:[0,0],text:['<>(a)']});
break;
case 'text-horizResizeCollapse' :
ctx.fillStyle = colorA('#F0F',0.5);
ctx.fillRect(l,t,w,h);
drawArrow({ctx:ctx,finX:l+0.2*w,finY:t+0.5*h,startX:l+0.8*w,startY:t+0.5*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'text-vertResizeCollapse' :
ctx.fillStyle = colorA('#F0F',0.5);
ctx.fillRect(l,t,w,h);
drawArrow({ctx:ctx,finX:l+0.5*w,finY:t+0.2*h,startX:l+0.5*w,startY:t+0.8*h,arrowLength:4,color:mainCanvasFillStyle,lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'delete':
ctx.fillStyle = colorA('#F00',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.strokeStyle = mainCanvasFillStyle;
ctx.beginPath();
ctx.moveTo(l+0.2*w,t+0.2*h);
ctx.lineTo(l+0.8*w,t+0.8*h);
ctx.moveTo(l+0.2*w,t+0.8*h);
ctx.lineTo(l+0.8*w,t+0.2*h);
ctx.stroke();
break;
case 'appear':
case 'appear-button':
case 'trigger':
case 'triggerTableCell':
var reversible = false;
if (draw.triggerEnabled == true || draw.appearMode == true) {
if (buttons[i].buttonType == 'appear') {
var vis = !un(path.appear) ? false : true;
if (!un(path.appear) && path.appear.reversible === true) reversible = true;
} else if (buttons[i].buttonType == 'appearButton') {
var vis = true;
} else {
if (buttons[i].buttonType == 'trigger') {
var trigger = path.trigger;
} else if (buttons[i].buttonType == 'triggerTableCell') {
var trigger = path.obj[0].cells[buttons[i].r][buttons[i].c].trigger;
}
var vis = true;
if (typeof trigger == 'object') {
for (var m = 0; m <= draw.triggerNum; m++) {
if (typeof trigger[m] == 'boolean' && trigger[m] == true) {
vis = true;
} else if (typeof trigger[m] == 'boolean' && trigger[m] == false) {
vis = false;
}
}
}
}
var color = reversible == true ? '#F00' : '#96C';
if (vis == true) {
ctx.fillStyle = colorA(color,0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = mainCanvasFillStyle;
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
} else {
ctx.strokeStyle = colorA(color,0.5);
ctx.strokeRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = colorA(color,0.5);
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
}
}
break;
case 'toggle-draggable':
if (!un(path.interact) && path.interact.draggable == true) {
ctx.strokeStyle = colorA('#393',0.5);
ctx.strokeRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = colorA('#393',0.5);
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
} else {
ctx.fillStyle = colorA('#393',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = mainCanvasFillStyle;
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
}
break;
case 'toggle-notesOverlay':
if (path.notesOverlay === true) {
ctx.strokeStyle = colorA('#C60',0.5);
ctx.strokeRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = colorA('#C60',0.5);
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
} else {
ctx.fillStyle = colorA('#C60',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.fillStyle = mainCanvasFillStyle;
drawStar({ctx:ctx,center:[l+0.5*w,t+0.5*h],radius:0.4*Math.min(w,h),points:5});
ctx.fill();
}
break;
case 'orderMinus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#F60',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.stroke();
break;
case 'orderPlus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#F60',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.moveTo(l+0.5*w,t+0.3*h);
ctx.lineTo(l+0.5*w,t+0.7*h);
ctx.stroke();
break;
case 'anglesAroundPoint-pointsMinus':
case 'table2-paddingVMinus':
case 'table2-paddingHMinus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#06F',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.stroke();
break;
case 'anglesAroundPoint-pointsPlus':
case 'table2-paddingVPlus':
case 'table2-paddingHPlus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#06F',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.moveTo(l+0.5*w,t+0.3*h);
ctx.lineTo(l+0.5*w,t+0.7*h);
ctx.stroke();
break;
case 'anglesAroundPoint-fixRadius':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#F06',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.arc(l+0.5*w,t+0.5*h,0.35*w,0,2*Math.PI);
ctx.stroke();
break;
case 'qPos-bottomRight':
case 'qPos-center':
if (buttons[i].buttonType.indexOf(path.qPos) > -1) {
ctx.fillStyle = colorA('#090',0.5);
ctx.fillRect(l,t,w,h);
} else {
ctx.fillStyle = colorA('#0F0',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
ctx.fillStyle = colorA('#000',0.5);
if (buttons[i].buttonType == 'qPos-bottomRight') {
ctx.fillRect(l+0.5*w,t+0.6*h,0.5*w,0.4*h);
} else if (buttons[i].buttonType == 'qPos-center') {
ctx.fillRect(l+0.25*w,t+0.3*h,0.5*w,0.4*h);
}
break;
case 'qPos-fillWidth':
if (path.qFillWidth == true) {
ctx.fillStyle = colorA('#090',0.5);
ctx.fillRect(l,t,w,h);
} else {
ctx.fillStyle = colorA('#0F0',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
drawArrow({ctx:ctx,startX:l+0.2*w,startY:t+0.5*h,finX:l+0.8*w,finY:t+0.5*h,arrowLength:4,color:colorA('#000',0.5),lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
drawArrow({ctx:ctx,finX:l+0.2*w,finY:t+0.5*h,startX:l+0.8*w,startY:t+0.5*h,arrowLength:4,color:colorA('#000',0.5),lineWidth:2,fillArrow:true,doubleEnded:false,angleBetweenLinesRads:0.7});
break;
case 'angle-showLines':
if (typeof path.obj[0].drawLines == 'undefined' || path.obj[0].drawLines == true) {
ctx.fillStyle = colorA('#F90',0.5);
ctx.fillRect(l,t,w,h);
var showLines = true;
} else {
ctx.fillStyle = colorA('#FC3',0.5);
ctx.fillRect(l,t,w,h);
var showLines = false;
}
drawAngle({ctx:ctx,a:[l+0.5*w,t+0.2*h],b:[l+0.2*w,t+0.8*h],c:[l+0.8*w,t+0.8*h],radius:0.4*w,lineWidth:1,drawLines:showLines});
break;
case 'angle-showAngle':
ctx.fillStyle = colorA('#F90',0.5);
ctx.fillRect(l,t,w,h);
text({ctx:ctx,textArray:['<>37'+degrees],left:l,top:t,width:w,height:h,textAlign:'center',vertAlign:'middle'});
break;
case 'angle-numOfCurves':
ctx.fillStyle = colorA('#F90',0.5);
ctx.fillRect(l,t,w,h);
drawAngle({ctx:ctx,a:[l+0.5*w,t+0.2*h],b:[l+0.2*w,t+0.8*h],c:[l+0.8*w,t+0.8*h],radius:0.4*w,lineWidth:1,drawLines:true,numOfCurves:2,curveGap:3});
break;
case 'polygon-makeRegular':
ctx.fillStyle = colorA('#F90',0.5);
ctx.fillRect(l,t,w,h);
var center = [l+0.5*w,t+0.5*h];
var radius = 0.4*Math.min(w,h);
var angle = -0.5*Math.PI;
var pos = [];
for (var p = 0; p < 5; p++) {
pos[p] = [center[0]+radius*Math.cos(angle),center[1]+radius*Math.sin(angle)];
angle += (2*Math.PI)/5;
}
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
/*ctx.beginPath();
ctx.arc(center[0],center[1],radius,0,2*Math.PI);
ctx.stroke();*/
drawPath({ctx:ctx,path:pos,closed:true});
for (var p = 0; p < 5; p++) {
drawDash(ctx,pos[p][0],pos[p][1],pos[(p+1)%5][0],pos[(p+1)%5][1],radius/5);
}
break;
case 'polygon-verticesPlus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#06F',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.moveTo(l+0.5*w,t+0.3*h);
ctx.lineTo(l+0.5*w,t+0.7*h);
ctx.stroke();
break;
case 'polygon-verticesMinus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#06F',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.stroke();
break;
case 'polygon-setPrism' :
ctx.fillStyle = colorA('#3F9',0.5);
ctx.fillRect(l,t,w,h);
drawPolygon({
ctx:ctx,
points:[[l+0.7*w,t+0.8*h],[l+0.2*w,t+0.8*h],[l+0.2*w,t+0.4*h],[l+0.5*w,t+0.4*h]],
lineColor:'#000',
lineWidth:1,
solidType:'prism',
prismVector:[0.15*w,-0.15*h],
});
break;
case 'polygon-setOuterAngles' :
ctx.fillStyle = colorA('#F0F',0.5);
ctx.fillRect(l,t,w,h);
drawPolygon({
ctx:ctx,
points:[[l+0.7*w,t+0.7*h],[l+0.5*w,t+0.3*h],[l+0.3*w,t+0.7*h]],
lineColor:'#000',
lineWidth:1,
anglesMode:'outer',
outerAngles:[
{radius:0.2*w,fill:true,fillColor:"#66F",lineWidth:0.5},
{radius:0.2*w,fill:true,fillColor:"#66F",lineWidth:0.5},
{radius:0.2*w,fill:true,fillColor:"#66F",lineWidth:0.5}
]
});
break;
case 'polygon-setExteriorAngles' :
ctx.fillStyle = colorA('#F93',0.5);
ctx.fillRect(l,t,w,h);
break;
case 'polygon-setTypeSquare' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'square') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.3*h);
ctx.lineTo(l+0.3*w,t+0.7*h);
ctx.lineTo(l+0.7*w,t+0.7*h);
ctx.lineTo(l+0.7*w,t+0.3*h);
ctx.lineTo(l+0.3*w,t+0.3*h);
ctx.stroke();
break;
case 'polygon-setTypeRect' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'rect') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.2*w,t+0.35*h);
ctx.lineTo(l+0.2*w,t+0.65*h);
ctx.lineTo(l+0.8*w,t+0.65*h);
ctx.lineTo(l+0.8*w,t+0.35*h);
ctx.lineTo(l+0.2*w,t+0.35*h);
ctx.stroke();
break;
case 'polygon-setTypePara' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'para') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.2*w,t+0.35*h);
ctx.lineTo(l+0.35*w,t+0.65*h);
ctx.lineTo(l+0.8*w,t+0.65*h);
ctx.lineTo(l+0.65*w,t+0.35*h);
ctx.lineTo(l+0.2*w,t+0.35*h);
ctx.stroke();
break;
case 'polygon-setTypeTrap' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'trap') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.35*w,t+0.35*h);
ctx.lineTo(l+0.2*w,t+0.65*h);
ctx.lineTo(l+0.8*w,t+0.65*h);
ctx.lineTo(l+0.65*w,t+0.35*h);
ctx.lineTo(l+0.35*w,t+0.35*h);
ctx.stroke();
break;
case 'polygon-setTypeRhom' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'rhom') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.5*w,t+0.3*h);
ctx.lineTo(l+0.2*w,t+0.5*h);
ctx.lineTo(l+0.5*w,t+0.7*h);
ctx.lineTo(l+0.8*w,t+0.5*h);
ctx.lineTo(l+0.5*w,t+0.3*h);
ctx.stroke();
break;
case 'polygon-setTypeKite' :
ctx.strokeStyle = mainCanvasFillStyle;
if (path.obj[0].polygonType == 'kite') {
ctx.fillStyle = colorA('#393',0.5);
} else {
ctx.fillStyle = colorA('#939',0.5);
}
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.5*w,t+0.25*h);
ctx.lineTo(l+0.3*w,t+0.4*h);
ctx.lineTo(l+0.5*w,t+0.75*h);
ctx.lineTo(l+0.7*w,t+0.4*h);
ctx.lineTo(l+0.5*w,t+0.25*h);
ctx.stroke();
break;
case 'text-border':
ctx.fillStyle = colorA('#F90',0.5);
ctx.fillRect(l,t,w,h);
ctx.fillStyle = colorA('#99F',0.5);
ctx.clearRect(l+0.15*w,t+0.25*h,w*0.7,h*0.5);
ctx.fillRect(l+0.15*w,t+0.25*h,w*0.7,h*0.5);
ctx.lineWidth = 3;
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l+0.15*w,t+0.25*h,w*0.7,h*0.5);
break;
case 'grid-resize':
ctx.fillStyle = colorA('#F9F',0.5);
ctx.fillRect(l,t,w,h);
ctx.strokeStyle = colorA('#F0F',0.5);
ctx.strokeRect(l,t,w,h);
drawArrow({ctx:ctx,startX:l+0.1*w,startY:t+0.5*h,finX:l+0.9*w,finY:t+0.5*h,arrowLength:4,color:colorA('#000',0.5),lineWidth:2,fillArrow:true,doubleEnded:true,angleBetweenLinesRads:0.7});
drawArrow({ctx:ctx,finX:l+0.5*w,finY:t+0.1*h,startX:l+0.5*w,startY:t+0.9*h,arrowLength:4,color:colorA('#000',0.5),lineWidth:2,fillArrow:true,doubleEnded:true,angleBetweenLinesRads:0.7});
break;
case 'grid-plot':
var obj = path.obj[0];
ctx.fillStyle = obj._interactMode == 'plot' ? colorA('#00F',0.5) : colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.strokeRect(l,t,w,h);
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.3*h);
ctx.lineTo(l+0.7*w,t+0.7*h);
ctx.moveTo(l+0.3*w,t+0.7*h);
ctx.lineTo(l+0.7*w,t+0.3*h);
ctx.stroke();
break;
case 'grid-lineSegment':
ctx.fillStyle = obj._interactMode == 'lineSegment' ? colorA('#00F',0.5) : colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.strokeRect(l,t,w,h);
ctx.beginPath();
/*ctx.moveTo(l+0.2*w,t+0.3*h);
ctx.lineTo(l+0.4*w,t+0.5*h);
ctx.moveTo(l+0.2*w,t+0.5*h);
ctx.lineTo(l+0.4*w,t+0.3*h);*/
ctx.moveTo(l+0.3*w,t+0.4*h);
ctx.lineTo(l+0.7*w,t+0.6*h);
/*ctx.moveTo(l+0.6*w,t+0.5*h);
ctx.lineTo(l+0.8*w,t+0.7*h);
ctx.moveTo(l+0.6*w,t+0.7*h);
ctx.lineTo(l+0.8*w,t+0.5*h);*/
ctx.stroke();
break;
case 'grid-line':
ctx.fillStyle = obj._interactMode == 'line' ? colorA('#00F',0.5) : colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.strokeRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l,t+0.3*h);
ctx.lineTo(l+w,t+0.7*h);
ctx.stroke();
break;
case 'grid-undo':
ctx.fillStyle = colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,textArray:['<>undo'],left:l,top:t,width:w,height:h,align:[0,0]});
break;
case 'grid-clear':
ctx.fillStyle = colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,textArray:['<>CLR'],left:l,top:t,width:w,height:h,align:[0,0]});
break;
case 'grid-function':
ctx.fillStyle = colorA('#99F',0.5);
ctx.fillRect(l,t,w,h);
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,textArray:['<><>f(x)'],left:l,top:t,width:w,height:h,align:[0,0]});
break;
case 'grid-showGrid':
if (path.obj.length == 1 && path.obj[0].type == 'grid') {
if (typeof path.obj[0].showGrid == 'undefined' || path.obj[0].showGrid == true) {
ctx.fillStyle = colorA('#F96',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(l+0.4*w,t+0.2*h);
ctx.lineTo(l+0.4*w,t+0.8*h);
ctx.moveTo(l+0.6*w,t+0.2*h);
ctx.lineTo(l+0.6*w,t+0.8*h);
ctx.moveTo(l+0.2*w,t+0.4*h);
ctx.lineTo(l+0.8*w,t+0.4*h);
ctx.moveTo(l+0.2*w,t+0.6*h);
ctx.lineTo(l+0.8*w,t+0.6*h);
ctx.stroke();
}
break;
case 'grid-showScales':
if (path.obj.length == 1 && (path.obj[0].type == 'grid' || path.obj[0].type == 'numberline')) {
if (typeof path.obj[0].showScales == 'undefined' || path.obj[0].showScales == true) {
ctx.fillStyle = colorA('#F96',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,textArray:['<>123'],left:l,top:t,width:w,height:h,textAlign:'center',vertAlign:'middle'});
}
break;
case 'grid-showLabels':
if (path.obj.length == 1 && path.obj[0].type == 'grid') {
if (typeof path.obj[0].showLabels == 'undefined' || path.obj[0].showLabels == true) {
ctx.fillStyle = colorA('#F96',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
text({ctx:ctx,textArray:['<><>xy'],left:l,top:t,width:w,height:h,textAlign:'center',vertAlign:'middle'});
}
break;
case 'grid-showBorder':
if (path.obj.length == 1 && path.obj[0].type == 'grid') {
if (typeof path.obj[0].showBorder == 'undefined' || path.obj[0].showBorder == true) {
ctx.fillStyle = colorA('#F96',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l+w*0.2,t+h*0.2,w*0.6,h*0.6);
}
break;
case 'grid-originStyle':
if (path.obj.length == 1 && path.obj[0].type == 'grid') {
if (typeof path.obj[0].originStyle == 'undefined' || path.obj[0].originStyle == 'circle') {
ctx.fillStyle = colorA('#F96',0.5);
ctx.fillRect(l,t,w,h);
}
ctx.strokeStyle = colorA('#000',0.5);
ctx.strokeRect(l,t,w,h);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
text({ctx:ctx,textArray:['<><>(0,0)'],left:l,top:t,width:w,height:h,textAlign:'center',vertAlign:'middle'});
}
break;
case 'simpleGrid-xPlus':
case 'simpleGrid-yPlus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#F0F',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.moveTo(l+0.5*w,t+0.3*h);
ctx.lineTo(l+0.5*w,t+0.7*h);
ctx.stroke();
break;
case 'simpleGrid-xMinus':
case 'simpleGrid-yMinus':
ctx.strokeStyle = mainCanvasFillStyle;
ctx.fillStyle = colorA('#F0F',0.5);
ctx.fillRect(l,t,w,h);
ctx.beginPath();
ctx.moveTo(l+0.3*w,t+0.5*h);
ctx.lineTo(l+0.7*w,t+0.5*h);
ctx.stroke();
break;
}
}
}
function flattenCanvases(canvas1, canvas2, offsetLeft, offsetTop) {
if (typeof offsetLeft !== 'number') {
if (typeof canvas1.data == 'object' && typeof canvas2.data == 'object') {
var offsetLeft = canvas2.data[100] - canvas1.data[100];
} else {
var offsetLeft = 0;
}
}
if (typeof offsetTop !== 'number') {
if (typeof canvas1.data == 'object' && typeof canvas2.data == 'object') {
var offsetTop = canvas2.data[101] - canvas1.data[101];
} else {
var offsetTop = 0;
}
}
var ctx = canvas1.getContext('2d');
ctx.drawImage(canvas2, offsetLeft, offsetTop);
}
function calcCursorPositions() {
draw.updateAllBorders();
var pos = [];
if (un(draw.cursors)) draw.cursors = {default:'default'};
pos.push({shape:'rect',dims:[0,0,draw.drawArea[2],draw.drawArea[3]],cursor:draw.cursors.default});
switch (draw.drawMode) {
case 'grid-drawLineSegment':
case 'grid-drawLineSegmentPoints':
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (['grid','simpleGrid'].includes(obj.type)) {
pos.push({shape:'rect',dims:[obj.left-20,obj.top-20,obj.width+40,obj.height+40],cursor:'url('+draw.lineCursor+') '+draw.lineCursorHotspot[0]+' '+draw.lineCursorHotspot[1]+', auto',func:draw.grid.gridPathStart,obj:obj,highlight:-1,mode:draw.drawMode});
}
}
}
break;
case 'grid-move':
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (['grid','simpleGrid'].includes(obj.type)) {
pos.push({shape:'rect',dims:[obj.left-20,obj.top-20,obj.width+40,obj.height+40],cursor:draw.cursors.move1,func:draw.grid.moveStart,obj:obj,highlight:-1,mode:draw.drawMode});
}
}
}
break;
case 'floodFill':
pos.push({shape:'rect',dims:draw.drawArea,cursor:draw.cursors.fill,func:drawClickFloodFillClick,highlight:-1});
break;
case 'pen':
pos.push({shape:'rect',dims:draw.drawArea,cursor:draw.cursors.pen,func:drawClickStartDraw,highlight:-1});
break;
case 'line':
case 'rect':
case 'square':
case 'circle':
case 'ellipse':
case 'polygon':
case 'point':
pos.push({shape:'rect',dims:draw.drawArea,cursor:'url('+draw.lineCursor+') '+draw.lineCursorHotspot[0]+' '+draw.lineCursorHotspot[1]+', auto',func:drawClickStartDraw,highlight:-1});
break;
case 'grid-resize':
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (path.selected == true) {
var obj = path.obj[0];
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.move1,func:drawClickGridStartDrag,pathNum:i});
pos.push({shape:'rect',dims:[obj.xZero-15,obj.top,30,obj.height],cursor:draw.cursors.ns,func:drawClickGridStartRescaleY,pathNum:i});
pos.push({shape:'rect',dims:[obj.left,obj.yZero-15,obj.width,30],cursor:draw.cursors.ew,func:drawClickGridStartRescaleX,pathNum:i});
if (path.borderButtons !== 'undefined') {
for (var j = 0; j < path.borderButtons.length; j++) {
if (['grid-resize','grid-xMajorPlus','grid-xMajorMinus','grid-xMinorPlus','grid-xMinorMinus','grid-yMajorPlus','grid-yMajorMinus','grid-yMinorPlus','grid-yMinorMinus'].indexOf(path.borderButtons[j].buttonType) > -1) {
pos.push(path.borderButtons[j]);
}
}
}
}
}
break;
case 'grid-plot':
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (path.selected == true) {
var obj = path.obj[0];
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.pointer,func:drawClickGridPlotPoint,pathNum:i});
if (path.borderButtons !== 'undefined') {
for (var j = 0; j < path.borderButtons.length; j++) {
if (path.borderButtons[j].buttonType == 'grid-plot') pos.push(path.borderButtons[j]);
}
}
}
}
break;
case 'grid-lineSegment':
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (path.selected == true) {
var obj = path.obj[0];
// draw line segment start
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.pointer,func:drawClickGridStartLineSegment,pathNum:i});
if (path.borderButtons !== 'undefined') {
for (var j = 0; j < path.borderButtons.length; j++) {
if (path.borderButtons[j].buttonType == 'grid-lineSegment') pos.push(path.borderButtons[j]);
}
}
}
}
break;
case 'grid-line':
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (path.selected == true) {
var obj = path.obj[0];
// draw line start
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.pointer,func:drawClickGridStartLine,pathNum:i});
if (path.borderButtons !== 'undefined') {
for (var j = 0; j < path.borderButtons.length; j++) {
if (path.borderButtons[j].buttonType == 'grid-line') pos.push(path.borderButtons[j]);
}
}
}
}
break;
case 'zoom':
pos.push({shape:'rect',dims:[0,0,draw.drawArea[2],draw.drawArea[3]],cursor:draw.cursors.default,func:drawClickStartZoomRect,highlight:-1});
break;
case 'select':
case 'textEdit':
pos.push({shape:'rect',dims:[0,0,draw.drawArea[2],draw.drawArea[3]],cursor:draw.cursors.default,func:drawClickStartSelectRect,highlight:-1});
var pos2 = [];
//unselected
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (getPathVis(path) == false) continue;
if (path.notesOverlay === true && draw.notesOverlay !== true) continue;
//if ((draw.ansMode == true && draw.showAns == false) && !un(path.trigger) && path.trigger[0] == false) continue;
if (path.selected == true) continue;
if (!un(path.isInput) && path.isInput._mode === 'addAnswers') continue;
for (var j = 0; j < path.obj.length; j++) {
var obj = path.obj[j];
if (!un(draw[obj.type]) && !un(draw[obj.type].getCursorPositionsUnselected)) {
pos = pos.concat(draw[obj.type].getCursorPositionsUnselected(obj,i));
continue;
}
switch (obj.type) {
case 'pen' :
pos.push({shape:'path',dims:[obj.pos,draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
break;
case 'line' :
pos.push({shape:'line',dims:[obj.startPos,obj.finPos,draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
break;
case 'rect' :
case 'square' :
var x1 = obj.startPos[0];
var y1 = obj.startPos[1];
var x2 = obj.finPos[0];
var y2 = obj.finPos[1];
if (obj.fillColor !== 'none') {
pos.push({shape:'rect',dims:[x1,y1,(x2-x1),(y2-y1)],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else {
pos.push({shape:'openRect',dims:[x1,y1,(x2-x1),(y2-y1),draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
}
break;
case 'circle' :
if (obj.fillColor !== 'none') {
pos.push({shape:'circle',dims:[obj.center[0],obj.center[1],obj.radius],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else {
pos.push({shape:'openCircle',dims:[obj.center[0],obj.center[1],obj.radius,draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
}
break;
case 'ellipse' :
if (obj.fillColor !== 'none') {
pos.push({shape:'ellipse',dims:[obj.center[0],obj.center[1],obj.radiusX,obj.radiusY],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else {
pos.push({shape:'ellipse',dims:[obj.center[0],obj.center[1],obj.radiusX,obj.radiusY,draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
}
break;
case 'curve' :
pos.push({shape:'path',dims:[obj.points,draw.selectTolerance],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:1});
break;
case 'text2' :
var dims = clone(obj._tightRect);
var dims2 = clone(obj.rect);
pos.push({shape:'rect',dims:dims2,cursor:draw.cursors.pointer,func:drawClickSelect,obj:obj,pathNum:i,highlight:-1});
pos.push({shape:'rect',dims:dims,cursor:draw.cursors.text,func:textEdit.selectStart,obj:obj,pathNum:i,highlight:-1});
break;
case 'table2' :
case 'qTable' :
for (var r = 0; r < obj.cells.length; r++) {
for (var c = 0; c < obj.cells[r].length; c++) {
//console.log(r,c,obj.cells[r][c],obj.cells[r][c].tightRect);
pos.push({shape:'rect',dims:obj.cells[r][c].tightRect,cursor:draw.cursors.text,func:textEdit.tableSelectStart,pathNum:i,obj:obj,cell:[r,c]});
}
}
var xPos = draw.table2.getXPos(obj);
var yPos = draw.table2.getYPos(obj);
pos.push({shape:'table',dims:[obj.left,obj.top,obj.width,obj.height,draw.selectTolerance],xPos:xPos,yPos:yPos,cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
break;
default :
if (obj.type === 'grid' && obj._interactMode === 'move') {
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.move1,func:draw.grid.moveStart,pathNum:i,obj:obj,highlight:-1});
} else if (!un(obj._left) && !un(obj._top) && !un(obj._width) && !un(obj._height)) {
pos.push({shape:'rect',dims:[obj._left,obj._top,obj._width,obj._height],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else if (!un(obj.left) && !un(obj.top) && !un(obj.width) && !un(obj.height)) {
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else if (!un(draw[obj.type]) && !un(draw[obj.type].getRect)) {
pos.push({shape:'rect',dims:draw[obj.type].getRect(obj),cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
} else {
//pos.push({shape:'rect',dims:clone(path.border),cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
}
//pos.push({shape:'rect',dims:path.border,cursor:draw.cursors.pointer,func:drawClickSelect,pathNum:i,highlight:-1});
break;
}
}
}
//selected
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (draw.ansMode == true && draw.showAns == false && !un(path.trigger) && path.trigger[0] == false) continue;
if (!un(path.isInput) && path.isInput._mode === 'addAnswers') continue;
if (path.selected == true) {
pos.push({shape:'rect',dims:[path.border[0],path.border[1],path.border[2],path.border[3]],cursor:draw.cursors.move1,func:drawClickStartDragObject,pathNum:i,highlight:-1});
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (obj.type === 'grid' && obj._interactMode === 'move') {
pos.push({shape:'rect',dims:[obj.left,obj.top,obj.width,obj.height],cursor:draw.cursors.move1,func:draw.grid.moveStart,pathNum:i,obj:obj,highlight:-1});
}
}
if (draw.rotationMode == true) {
pos.push({shape:'circle',dims:[path.border[0]+0.5*path.border[2],path.border[1]-30,10],cursor:draw.cursors.rotate,func:draw.rotateStart,pathNum:i});
}
if (path.obj.length == 1) {
var obj = path.obj[0];
if (obj.visible === false) continue;
if (!un(draw[obj.type]) && !un(draw[obj.type].getCursorPositionsSelected)) {
pos = pos.concat(draw[obj.type].getCursorPositionsSelected(obj,i));
}
}
if (typeof path.borderButtons == 'object') {
for (var j = 0; j < path.borderButtons.length; j++) {
pos.push(path.borderButtons[j]);
}
}
}
}
pos = pos2.concat(pos);
break;
case 'selectDrag': // if an object is being dragged
pos.push({shape:'rect',dims:draw.drawArea,cursor:draw.cursors.move2});
break;
case 'textStart':
pos.push({shape:'rect',dims:draw.drawArea,cursor:'text',func:draw.text2.start,pathNum:draw.path.length});
break;
case 'table' :
case 'tableChange' :
case 'tableBorders' :
case 'tableCellColor' :
pos.push({shape:'rect',dims:draw.drawArea,cursor:draw.cursors.default,func:tableMenuClose});
break;
case 'none':
default:
break;
}
if (draw.mode == 'interact') {
if (!un(draw.pathCursorOrder)) {
for (var p = 0; p < draw.pathCursorOrder.length; p++) {
var path = draw.pathCursorOrder[p];
if (path._visible === false) continue;
var visible = false;
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(obj.visible) || obj.visible == true) visible = true;
}
if (visible == false) continue;
var pathInteract = draw.getPathInteract(path);
if (pathInteract.type == 'check') {
pos.push({shape:'rect',dims:obj.rect,cursor:draw.cursors.pointer,func:draw.interact.checkPage,interact:true,path:path});
}
if (pathInteract.allowInteraction !== false && pathInteract.disabled !== true && pathInteract._disabled !== true) {
if (typeof pathInteract.dragPathCircle == 'string') {
var circleObj = draw.getObjById(pathInteract.dragPathCircle);
if (circleObj !== false) {
pos.push({shape:'rect',dims:clone(path.border.slice(0,4)),cursor:draw.cursors.move1,func:draw.interact.dragStart,interact:true,path:path,dragType:'circle',center:circleObj.center,radius:circleObj.radius,circle:circleObj});
}
} else if (typeof pathInteract.dragPathLineSegment == 'string') {
var lineSegmentObj = draw.getObjById(pathInteract.dragPathLineSegment);
if (lineSegmentObj !== false) {
pos.push({shape:'rect',dims:clone(path.border.slice(0,4)),cursor:draw.cursors.move1,func:draw.interact.dragStart,interact:true,path:path,dragType:'lineSegment',lineSegment:lineSegmentObj});
}
} else if (pathInteract.draggable == true) {
pos.push({shape:'rect',dims:clone(path.tightBorder.slice(0,4)),cursor:draw.cursors.move1,func:draw.interact.dragStart,interact:true,path:path});
}
if (pathInteract.drag3d == true) {
pos.push({shape:'rect',dims:clone(path.border.slice(0,4)),cursor:draw.cursors.move1,func:draw.three.drag3dStart,interact:true,path:path,obj:path.obj[0]});
}
if (pathInteract.cubeBuilding == 'build') {
var positions = draw.three.cubeDrawing.getCursorPositionsBuild(path.obj[0]);
draw.color = '#000';
draw.cursors.update();
for (var p2 = 0; p2 < positions.length; p2++) {
pos.push({shape:'polygon',dims:positions[p2].pos2d,cursor:'url('+draw.lineCursor+') '+draw.lineCursorHotspot[0]+' '+draw.lineCursorHotspot[1]+', auto',func:draw.three.cubeDrawing.click,interact:true,path:path,obj:path.obj[0],position:positions[p2],mode:'build'});
}
} else if (pathInteract.cubeBuilding == 'remove') {
var positions = draw.three.cubeDrawing.getCursorPositionsRemove(path.obj[0]);
draw.color = '#F00';
draw.cursors.update();
for (var p2 = 0; p2 < positions.length; p2++) {
pos.push({shape:'polygon',dims:positions[p2].pos2d,cursor:'url('+draw.lineCursor+') '+draw.lineCursorHotspot[0]+' '+draw.lineCursorHotspot[1]+', auto',func:draw.three.cubeDrawing.click,interact:true,path:path,obj:path.obj[0],position:positions[p2],mode:'remove'});
}
} else if (pathInteract.edit3dShape == true) {
pos = pos.concat(draw.three.getCursorPositionsSelected(path.obj[0],p,true));
}
if (typeof pathInteract.click == 'function') {
pos.push({shape:'rect',dims:clone(path.border.slice(0,4)),cursor:draw.cursors.pointer,func:draw.interact.click,click:pathInteract.click,interact:true,path:path,obj:path.obj[0]});
}
}
for (var o2 = 0; o2 < path.obj.length; o2++) {
var obj = path.obj[o2];
var isOverlayObj = false;
if (!un(path.interact) && path.interact.overlay == true) isOverlayObj = true;
if (!un(obj.interact) && obj.interact.overlay == true) isOverlayObj = true;
if (obj.type == 'dropMenu') isOverlayObj = true;
if (isOverlayObj == true) continue;
if (typeof draw[obj.type].getCursorPositionsInteract == 'function') {
pos = pos.concat(draw[obj.type].getCursorPositionsInteract(obj,path,p));
}
if (!un(obj._cursorPos)) {
pos = pos.concat(obj._cursorPos);
}
var objInteract = draw.getObjInteract(obj);
if (obj.type == 'slider') {
//pos.push({shape:'circle',dims:obj._pos,cursor:draw.cursors.move1,func:draw.slider.dragStart,interact:true,path:path,obj:obj});
} else if (objInteract.allowInteraction === false || objInteract.disabled === true || objInteract._disabled === true) {
continue;
} else if (obj.type == 'grid' || obj.type == 'simpleGrid') {
if (['lineSegment','lineSegmentPoints','line','linePoints','point'].indexOf(objInteract.type) > -1) {
pos.push({shape:'rect',dims:[obj.left-20,obj.top-20,obj.width+40,obj.height+40],cursor:'url('+draw.lineCursor+') '+draw.lineCursorHotspot[0]+' '+draw.lineCursorHotspot[1]+', auto',func:draw.grid.gridPathStart,obj:obj,highlight:-1,mode:objInteract.type});
}
} else if (!un(objInteract.click) && objInteract.click.length > 0) {
pos.push({shape:'rect',dims:draw[obj.type].getRect(obj),cursor:draw.cursors.pointer,func:draw.interact.click,interact:true,path:path,obj:obj});
} else if (typeof objInteract.click == 'function') {
pos.push({shape:'rect',dims:draw[obj.type].getRect(obj),cursor:draw.cursors.pointer,func:draw.interact.click,click:objInteract.click,interact:true,path:path,obj:obj});
}
}
}
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (un(path.appear)) continue;
var visible = boolean(path._visible,false);
if (visible == true && path.appear.reversible !== true) continue;
if (typeof path.appear.visible == 'function' && path.appear.visible(path) === false) continue;
if (typeof path.appear.visible == 'string' && getPathVis(path.appear.visible) == false) continue;
if (un(path.appear.pos)) {
if (un(path.border)) updateBorder(path);
if (un(path.border)) continue;
var l = path.border[0]+0.5*path.border[2]-20;
var t = path.border[1]+0.5*path.border[3]-20;
} else {
var l = path.appear.pos[0]-20;
var t = path.appear.pos[1]-20;
}
pos.push({shape:'rect',dims:[l,t,40,40],cursor:draw.cursors.pointer,func:draw.interact.appear,interact:true,path:path});
}
}
for (var p = 0; p < draw.path.length; p++) { // add cursor positions for overlay buttons
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
var isOverlayObj = false;
if (!un(path.interact) && path.interact.overlay == true) isOverlayObj = true;
if (!un(obj.interact) && obj.interact.overlay == true) isOverlayObj = true;
if (obj.type == 'dropMenu') isOverlayObj = true;
if (obj.visible === false || isOverlayObj == false) continue;
if (obj.type == 'colorPicker' && draw.colorSelectVisible == false) continue;
if (obj.type == 'lineWidthSelect' && draw.lineWidthSelectVisible == false) continue;
if (typeof draw[obj.type].getCursorPositionsInteract == 'function') {
pos = pos.concat(draw[obj.type].getCursorPositionsInteract(obj,path,p));
}
if (obj.type == 'slider') {
pos.push({shape:'circle',dims:obj._pos,cursor:draw.cursors.move1,func:draw.slider.dragStart,interact:true,path:path,obj:obj});
} else if (!un(obj.interact) && !un(obj.interact.click) && obj.interact.click.length > 0) {
pos.push({shape:'rect',dims:draw[obj.type].getRect(obj),cursor:draw.cursors.pointer,func:draw.interact.click,interact:true,path:path,obj:obj});
} else if (!un(obj.interact) && typeof obj.interact.click == 'function') {
pos.push({shape:'rect',dims:draw[obj.type].getRect(obj),cursor:draw.cursors.pointer,func:draw.interact.click,click:obj.interact.click,interact:true,path:path,obj:obj});
}
}
}
} else {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (!un(path.isInput) && path.isInput._mode === 'addAnswers') {
if (path.isInput.type === 'drag') {
pos.push({shape:'rect',dims:path.tightBorder.slice(0,4),cursor:draw.cursors.move1,func:draw.interact.dragStart,path:draw.path[p]});
continue;
} else if (path.isInput.type === 'grid') {
var pos2 = draw.grid.getCursorPositionsInteract(path.obj[0],path,p);
pos = pos.concat(pos2);
continue;
}
}
for (var o2 = 0; o2 < path.obj.length; o2++) {
var obj = path.obj[o2];
if (!un(obj._cursorPos)) pos = pos.concat(obj._cursorPos);
}
}
for (var p = 0; p < draw.path.length; p++) { // add cursor positions for appear buttons
var path = draw.path[p];
if (un(path.appear)) continue;
if (un(path.appear.pos)) {
var l = path.border[0]+0.5*path.border[2]-20;
var t = path.border[1]+0.5*path.border[3]-20;
} else {
var l = path.appear.pos[0]-20;
var t = path.appear.pos[1]-20;
}
pos.push({buttonType:'appear-dont-draw',shape:'rect',dims:[l,t,40,40],cursor:draw.cursors.move1,func:drawClickAppearMoveStart,pathNum:p});
}
}
if (!un(draw.controlPanel)) pos = pos.concat(draw.controlPanel.cursorPositions);
draw.cursorPositions = pos;
//console.log(pos);
}
draw.getPathInteract = function(path) {
var interact = {};
for (var o2 = 0; o2 < path.obj.length; o2++) {
var obj = path.obj[o2];
if (!un(obj.interact)) {
for (var key in obj.interact) {
if (key === 'click') continue;
if (un(interact[key])) {
interact[key] = obj.interact[key];
}
}
}
}
if (!un(path.isInput)) {
for (var key in path.isInput) {
interact[key] = path.isInput[key];
}
}
if (!un(path.interact)) {
for (var key in path.interact) {
interact[key] = path.interact[key];
}
}
return interact;
}
draw.getObjInteract = function(obj) {
var interact = {};
if (!un(obj.interact)) {
for (var key in obj.interact) {
if (un(interact[key])) {
interact[key] = obj.interact[key];
}
}
}
return interact;
}
function drawCanvasMove(e) {
e.preventDefault();
if (typeof draw == 'undefined' || draw.drawing == true || ['tableColResize','tableRowResize','gridDrag','gridRecaleX','gridRecaleY','compassMove1','compassMove2','compassDraw','protractorRotate','protractorMove','rulerRotate','rulerMove','selectDrag','selectRect','selectResize','tableInputSelect','tableCellSelect','tableColSelect','tableRowSelect','textInputSelect'].indexOf(draw.drawMode) > -1) return;
//console.log(draw.drawMode);
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
//var x = mouse.x - draw.drawRelPos[0];
//var y = mouse.y - draw.drawRelPos[1];
draw.currCursor = getCursorAtPosition(x,y);
draw.cursorCanvas.style.cursor = draw.currCursor.cursor;
//console.log(draw.currCursor,draw.cursorCanvas.style.cursor);
cursorPosHighlight();
}
function drawCanvasStart(e) {
updateMouse(e);
calcCursorPositions();
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.currCursor = getCursorAtPosition(x,y); // necessary for touch events, where move function will not have run
draw.table2.deselectTables();
if (!un(draw.currCursor)) {
if (un(draw.currCursor.obj) || (draw.currCursor.obj.type !== 'colorPicker' && draw.currCursor.obj.type !== 'buttonColorPicker')) {
draw.colorSelectVisible = false;
}
if (un(draw.currCursor.obj) || (draw.currCursor.obj.type !== 'lineWidthSelect' && draw.currCursor.obj.type !== 'buttonLineWidthPicker')) {
draw.lineWidthSelectVisible = false;
}
if (!un(draw.currCursor.func)) {
draw.currCursor.func.apply();
if (draw.currCursor.interact == true) draw.interact.update();
} else {
drawCanvasPaths();
}
} else {
draw.colorSelectVisible = false;
draw.lineWidthSelectVisible = false;
drawCanvasPaths();
}
}
function showCursorPositions() {
var ctx = draw.drawCanvas.last().ctx;
ctx.scale(draw.scale,draw.scale);
//ctx.clearRect(draw.drawArea[0],draw.drawArea[1],draw.drawArea[2],draw.drawArea[3]);
var colorMove = colorA('#00F',0.3);
var colorPointer = colorA('#F00',0.3);
var colorText = colorA('#0F0',0.3);
var colorMisc = colorA('#FF0',0.3);
for (var i = 0; i < draw.cursorPositions.length; i++) {
var pos = draw.cursorPositions[i];
if (pos.cursor == draw.cursors.move1) {
ctx.fillStyle = colorMove;
} else if (pos.cursor == draw.cursors.pointer) {
ctx.fillStyle = colorPointer;
} else if (pos.cursor == 'text') {
ctx.fillStyle = colorText;
} else {
ctx.fillStyle = colorMisc;
}
if (pos.shape == 'rect') {
ctx.fillRect(pos.dims[0],pos.dims[1],pos.dims[2],pos.dims[3]);
} else if (pos.shape == 'circle') {
ctx.beginPath();
ctx.arc(pos.dims[0],pos.dims[1],pos.dims[2],0,2*Math.PI);
ctx.fill();
} else if (pos.shape == 'line') {
}
}
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
function getCursorAtPosition(x,y) {
var overTool = isPosOverTool(x-draw.drawArea[0],y-draw.drawArea[1]);
if (typeof overTool == 'object' || overTool !== false) return overTool;
if (typeof draw.cursorPositions == 'undefined') calcCursorPositions();
var pos = draw.cursorPositions;
var currPos = {cursor:draw.cursors.default,func:function(){}};
var x2 = x-draw.drawArea[0];
var y2 = y-draw.drawArea[1];
for (var i = 0; i < pos.length; i++) {
if (draw.cursorPosHitTest(pos[i],x2,y2) == true) {
pos[i].pos = i;
currPos = pos[i];
}
/*
var dims = clone(pos[i].dims);
if (typeof dims == 'undefined') continue;
//console.log(i,pos[i],pos[i].dims);
if (pos[i].shape == 'table') {
for (var x = 0; x < pos[i].xPos.length; x++) {
var x3 = pos[i].xPos[x];
if (distancePointToLineSegment([x2,y2],[x3,dims[1]],[x3,dims[1]+dims[3]]) < dims[4]) {
pos[i].pos = i;
currPos = pos[i];
break;
}
}
for (var y = 0; y < pos[i].yPos.length; y++) {
var y3 = pos[i].yPos[y];
if (distancePointToLineSegment([x2,y2],[dims[0],y3],[dims[0]+dims[2],y3]) < dims[4]) {
pos[i].pos = i;
currPos = pos[i];
break;
}
}
} else if ((pos[i].shape == 'rect' && x2 >= dims[0] && x2 <= (dims[0]+dims[2]) && y2 >= dims[1] && y2 <= (dims[1]+dims[3])) ||
(pos[i].shape == 'openRect' &&
(distancePointToLineSegment([x2,y2],[dims[0],dims[1]],[dims[0]+dims[2],dims[1]]) < dims[4]) ||
(distancePointToLineSegment([x2,y2],[dims[0]+dims[2],dims[1]],[dims[0]+dims[2],dims[1]+dims[3]]) < dims[4]) ||
(distancePointToLineSegment([x2,y2],[dims[0]+dims[2],dims[1]+dims[3]],[dims[0],dims[1]+dims[3]]) < dims[4]) ||
(distancePointToLineSegment([x2,y2],[dims[0],dims[1]+dims[3]],[dims[0],dims[1]]) < dims[4])
) ||
(pos[i].shape == 'circle' && dist(x2,y2,dims[0],dims[1]) <= dims[2]) ||
(pos[i].shape == 'sector' && isPointInSector([x2,y2],dims) == true) ||
(pos[i].shape == 'openCircle' && dist(x2,y2,dims[0],dims[1]) >= dims[2]-dims[3] && dist(x2,y2,dims[0],dims[1]) <= dims[2]+dims[3]) ||
(pos[i].shape == 'ellipse' && isPointInEllipse([x2,y2],[dims[0],dims[1]],dims[2],dims[3]) == true) ||
(pos[i].shape == 'openEllipse' && isPointOnEllipse([x2,y2],[dims[0],dims[1]],dims[2],dims[3],dims[4]) == true) ||
(pos[i].shape == 'line' && (distancePointToLineSegment([x2,y2],dims[0],dims[1]) < dims[2])) ||
(pos[i].shape == 'path' && (distancePointToPath([x2,y2],dims[0]) <= dims[1])) ||
(pos[i].shape == 'polygon' && hitTestPolygon([x2,y2],dims,true) == true)
) {
pos[i].pos = i;
currPos = pos[i];
}
*/
}
//console.log(currPos,x2,y2);
return currPos;
}
draw.cursorPosHitTest = function(pos,x,y) {
var dims = clone(pos.dims);
if (typeof dims == 'undefined') return false;
if (pos.shape == 'table') {
if (typeof pos.xPos !== 'undefined' && typeof pos.yPos !== 'undefined') {
for (var c = 0; c < pos.xPos.length; c++) {
var x3 = pos.xPos[c];
if (distancePointToLineSegment([x,y],[x3,dims[1]],[x3,dims[1]+dims[3]]) < dims[4]) return true;
}
for (var r = 0; r < pos.yPos.length; r++) {
var y3 = pos.yPos[r];
if (distancePointToLineSegment([x,y],[dims[0],y3],[dims[0]+dims[2],y3]) < dims[4]) return true;
}
}
} else if ((pos.shape == 'rect' && x >= dims[0] && x <= (dims[0]+dims[2]) && y >= dims[1] && y <= (dims[1]+dims[3])) ||
(pos.shape == 'openRect' &&
(distancePointToLineSegment([x,y],[dims[0],dims[1]],[dims[0]+dims[2],dims[1]]) < dims[4]) ||
(distancePointToLineSegment([x,y],[dims[0]+dims[2],dims[1]],[dims[0]+dims[2],dims[1]+dims[3]]) < dims[4]) ||
(distancePointToLineSegment([x,y],[dims[0]+dims[2],dims[1]+dims[3]],[dims[0],dims[1]+dims[3]]) < dims[4]) ||
(distancePointToLineSegment([x,y],[dims[0],dims[1]+dims[3]],[dims[0],dims[1]]) < dims[4])
) ||
(pos.shape == 'circle' && dist(x,y,dims[0],dims[1]) <= dims[2]) ||
(pos.shape == 'sector' && isPointInSector([x,y],dims) == true) ||
(pos.shape == 'openCircle' && dist(x,y,dims[0],dims[1]) >= dims[2]-dims[3] && dist(x,y,dims[0],dims[1]) <= dims[2]+dims[3]) ||
(pos.shape == 'ellipse' && isPointInEllipse([x,y],[dims[0],dims[1]],dims[2],dims[3]) == true) ||
(pos.shape == 'openEllipse' && isPointOnEllipse([x,y],[dims[0],dims[1]],dims[2],dims[3],dims[4]) == true) ||
(pos.shape == 'line' && (distancePointToLineSegment([x,y],dims[0],dims[1]) < dims[2])) ||
(pos.shape == 'path' && (distancePointToPath([x,y],dims[0]) <= dims[1])) ||
(pos.shape == 'polygon' && hitTestPolygon([x,y],dims,true) == true)
) {
return true;
}
return false;
}
function cursorPosHighlight(clr) {
return;
if (draw.highlightCursorPositions == false) return;
if (un(draw.cursorPosHighlight)) {
draw.cursorPosHighlight = newctx({z:99999999});
var ctx = draw.cursorPosHighlight;
ctx.lineWidth = draw.selectTolerance * 2;
ctx.strokeStyle = colorA('#FF0',0.4);
ctx.fillStyle = colorA('#FF0',0.4);
}
var ctx = draw.cursorPosHighlight;
ctx.clear();
if (boolean(clr,false) == true) return;
var c = draw.currCursor;
if (c.cursor == 'default' || c.cursor == 'move1') return;
if (draw.highlightCursorPositions == 'part' && c.highlight == -1) return;
switch (c.shape) {
case 'rect':
ctx.fillRect(c.dims[0],c.dims[1],c.dims[2],c.dims[3]);
break;
case 'openRect':
ctx.strokeRect(c.dims[0],c.dims[1],c.dims[2],c.dims[3]);
break;
case 'circle':
ctx.beginPath();
ctx.arc(c.dims[0],c.dims[1],c.dims[2],0,2*Math.PI);
ctx.fill();
break;
case 'sector':
ctx.beginPath();
ctx.moveTo(c.dims[0],c.dims[1]);
ctx.lineTo(c.dims[0]+c.dims[2]*Math.cos(c.dims[3]),c.dims[1]+c.dims[2]*Math.sin(c.dims[3]));
ctx.arc(c.dims[0],c.dims[1],c.dims[2],c.dims[3],c.dims[4]);
ctx.lineTo(c.dims[0],c.dims[1]);
ctx.fill();
break;
case 'openCircle':
ctx.beginPath();
ctx.arc(c.dims[0],c.dims[1],c.dims[2],0,2*Math.PI);
ctx.stroke();
break;
case 'ellipse':
break;
case 'openEllipse':
break;
case 'line':
ctx.beginPath();
ctx.moveTo(c.dims[0][0],c.dims[0][1]);
ctx.lineTo(c.dims[1][0],c.dims[1][1]);
ctx.stroke();
break;
case 'path':
break;
}
if (draw.highlightCursorPositions == 'part') return;
for (var p = c.pos+1; p < draw.cursorPositions.length; p++) {
var c = draw.cursorPositions[p];
switch (c.shape) {
case 'rect':
ctx.clearRect(c.dims[0],c.dims[1],c.dims[2],c.dims[3]);
break;
case 'openRect':
clearLineRounded(ctx,c.dims[0],c.dims[1],c.dims[0]+c.dims[2],c.dims[1],draw.selectTolerance*2);
clearLineRounded(ctx,c.dims[0]+c.dims[2],c.dims[1],c.dims[0]+c.dims[2],c.dims[1]+c.dims[3],draw.selectTolerance*2);
clearLineRounded(ctx,c.dims[0]+c.dims[2],c.dims[1]+c.dims[3],c.dims[0],c.dims[1]+c.dims[3],draw.selectTolerance*2);
clearLineRounded(ctx,c.dims[0],c.dims[1]+c.dims[3],c.dims[0],c.dims[1],draw.selectTolerance*2);
break;
case 'circle':
clearCircle(ctx,c.dims[0],c.dims[1],c.dims[2]);
break;
case 'openCircle':
break;
case 'ellipse':
break;
case 'openEllipse':
break;
case 'line':
clearLineRounded(ctx,c.dims[0][0],c.dims[0][1],c.dims[1][0],c.dims[1][1],draw.selectTolerance*2);
break;
case 'path':
break;
}
}
}
function clearCircle(context,x,y,radius) {
context.save();
context.beginPath();
context.arc(x, y, radius, 0, 2*Math.PI, true);
context.clip();
context.clearRect(x-radius,y-radius,radius*2,radius*2);
context.restore();
}
function clearLineSquared(context,x1,y1,x2,y2,thickness) {
var tmp, length;
// swap coordinate pairs if x-coordinates are RTL to make them LTR
if (x2 < x1) {
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
length = dist(x1,y1,x2,y2);
context.save();
context.translate(x1,y1);
context.rotate(Math.atan2(y2-y1,x2-x1));
context.clearRect(0,0,length,thickness);
context.restore();
}
function clearLineRounded(context,x1,y1,x2,y2,thickness) {
if (thickness <= 2) {
clearLineSquared(context,x1,y1,x2,y2,thickness);
return;
}
var tmp, half_thickness = thickness / 2, length,
PI15 = 1.5 * Math.PI, PI05 = 0.5 * Math.PI
;
// swap coordinate pairs if x-coordinates are RTL to make them LTR
if (x2 < x1) {
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
}
length = dist(x1,y1,x2,y2);
context.save();
context.translate(x1,y1);
context.rotate(Math.atan2(y2-y1,x2-x1));
x1 = 0;
y1 = 0;
x2 = length - 1;
y2 = 0;
// draw a complex "line" shape with rounded corner caps
context.moveTo(x1,y1-half_thickness);
context.lineTo(x2,y2-half_thickness);
context.arc(x2,y2,half_thickness,PI15,PI05,false);
context.lineTo(x1,y1-half_thickness+thickness);
context.arc(x1,y1,half_thickness,PI05,PI15,false);
context.closePath();
x1 -= half_thickness;
y1 -= half_thickness;
context.clip();
context.clearRect(x1,y1,length+thickness,thickness);
context.restore();
}
draw.getPathObjTypes = function(path) {
if (un(path)) path = draw.path;
var types = [];
if (path instanceof Array) {
for (var p = 0; p < path.length; p++) processPath(path[p]);
} else {
processPath(path);
}
return types;
function processPath(path2) {
for (var o = 0; o < path2.obj.length; o++) {
var obj = path2.obj[o];
if (types.indexOf(obj.type) == -1) types.push(obj.type);
}
}
}
draw.updateAllBorders = function(paths) {
if (un(paths)) paths = draw.path;
for (var p = 0; p < paths.length; p++) updateBorder(paths[p]);
}
draw.updateSelectedBorders = function() {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) updateBorder(draw.path[p]);
}
}
function updateBorder(path,override) {
if (un(draw.path) && boolean(override,false) == true) return;
var x1,y1,x2,y2, buttons = [], left = [], top = [], right = [], bottom = [];
for (var i = 0; i < path.obj.length; i++) {
if (un(path.obj[i])) continue;
var obj = path.obj[i];
if (!un(draw[obj.type]) && !un(draw[obj.type].getRect)) {
var rect = draw[obj.type].getRect(obj);
if (!un(rect)) {
left[i] = rect[0];
top[i] = rect[1];
right[i] = rect[0]+rect[2];
bottom[i] = rect[1]+rect[3];
}
} else {
left[i] = obj.left;
top[i] = obj.top;
right[i] = obj.left + obj.width;
bottom[i] = obj.top + obj.height;
}
}
var x1 = arrayMin(left);
var y1 = arrayMin(top);
var x2 = arrayMax(right);
var y2 = arrayMax(bottom);
path.tightBorder = [x1,y1,x2-x1,y2-y1,x2,y2];
path._center = [(x1+x2)/2,(y1+y2)/2];
var padding = draw.selectPadding;
x1 -= padding;
y1 -= padding;
x2 += padding;
y2 += padding;
path.border = [x1,y1,x2-x1,y2-y1,x2,y2];
if (un(draw.path) || typeof draw.path.indexOf !== 'function') return;
var pathNum = draw.path.indexOf(path);
if (path.obj.length == 1 && (['image','rect','square','circle','ellipse','simpleGrid','anglesAroundPoint','text2','table2'].indexOf(path.obj[0].type) > -1 || path.obj[0].type == 'angle' && un(path.obj[0].d) || (!un(draw[path.obj[0].type]) && draw[path.obj[0].type].resizable == true))) {
// resize handle in bottom right corner
buttons.push({buttonType:'resize',shape:'rect',dims:[x2-20,y2-20,20,20],cursor:draw.cursors.nw,func:drawClickStartResizeObject,pathNum:pathNum});
} else if (path.obj.length > 1) {
buttons.push({buttonType:'resize-path',shape:'rect',dims:[x2-20,y2-20,20,20],cursor:draw.cursors.nw,func:drawClickStartResizePath,pathNum:pathNum});
}
if (path.obj.length == 1 && !un(draw[path.obj[0].type]) && !un(draw[path.obj[0].type].getButtons)) {
buttons = buttons.concat(draw[path.obj[0].type].getButtons(x1,y1,x2,y2,pathNum,path));
}
if (!un(path.isInput)) {
buttons.push({buttonType:'isInput-type',shape:'rect',dims:[(x1+x2)/2-40,y1,80,20],cursor:draw.cursors.default,func:function() {},pathNum:pathNum,type:path.isInput.type});
if (path.isInput.type == 'text' && path.obj.length == 1 && path.obj[0].type == 'text2') {
} else if (!un(draw.selectInput) && path.isInput.type == 'select' && path.obj.length == 1 && path.obj[0].type == 'table2') {
/*var obj = path.obj[0];
for (var r = 0; r < obj.cells.length; r++) {
for (var c = 0; c < obj.cells[r].length; c++) {
buttons.push({buttonType:'select-input-cellToggle',shape:'rect',dims:[obj.xPos[c+1]-20,obj.yPos[r],20,20],cursor:draw.cursors.pointer,func:draw.selectInput.cellToggle,pathNum:pathNum,row:r,col:c});
}
}
buttons.push({buttonType:'select-input-shuffleToggle',shape:'rect',dims:[x1+20,y2-20,60,20],cursor:draw.cursors.pointer,func:draw.selectInput.shuffleToggle,pathNum:pathNum,shuffle:path.isInput.shuffle});
if (!un(path.isInput.selColors)) {
buttons.push({buttonType:'select-input-selColors',shape:'rect',dims:[x1+80,y2-20,20,20],cursor:draw.cursors.pointer,func:draw.selectInput.selColors,pathNum:pathNum,selColors:path.isInput.selColors});
}*/
} else if (!un(draw.isInput) && path.isInput.type == 'drag') {
buttons.push({buttonType:'isInput-drag-value',shape:'rect',dims:[x1+20,y2-20,80,20],cursor:draw.cursors.pointer,func:draw.isInput.dragSetValue,pathNum:pathNum});
buttons.push({buttonType:'isInput-drag-shuffleToggle',shape:'rect',dims:[x2-80,y2-20,60,20],cursor:draw.cursors.pointer,func:draw.isInput.dragShuffleToggle,pathNum:pathNum});
} else if (!un(draw.isInput) && path.isInput.type == 'dragArea') {
//buttons.push({buttonType:'isInput-drag-value',shape:'rect',dims:[x1+20,y2-20,80,20],cursor:draw.cursors.pointer,func:draw.isInput.dragSetValue,pathNum:pathNum});
buttons.push({buttonType:'isInput-dragArea-snapToggle',shape:'rect',dims:[x2-80,y2-20,60,20],cursor:draw.cursors.pointer,func:draw.isInput.dragAreaSnapToggle,pathNum:pathNum});
}
}
// plus & minus zIndex buttons in bottom left corner
buttons.push({buttonType:'orderPlus',shape:'rect',dims:[x1,y2-40,20,20],cursor:draw.cursors.pointer,func:drawClickOrderPlus,pathNum:pathNum});
buttons.push({buttonType:'orderMinus',shape:'rect',dims:[x1,y2-20,20,20],cursor:draw.cursors.pointer,func:drawClickOrderMinus,pathNum:pathNum});
// delete button in top right corner
buttons.push({buttonType:'delete',shape:'rect',dims:[x2-20,y1,20,20],cursor:draw.cursors.pointer,func:drawClickDelete,pathNum:pathNum});
if (draw.appearMode == true) {
buttons.push({buttonType:'appear',shape:'rect',dims:[x1,y1,20,20],cursor:draw.cursors.pointer,func:drawClickAppear,pathNum:pathNum});
} else {
buttons.push({buttonType:'trigger',shape:'rect',dims:[x1,y1,20,20],cursor:draw.cursors.pointer,func:drawClickTrigger,pathNum:pathNum});
}
buttons.push({buttonType:'toggle-draggable',shape:'rect',dims:[x1+20,y1,20,20],cursor:draw.cursors.pointer,func:draw.togglePathDraggable,pathNum:pathNum,path:path});
buttons.push({buttonType:'toggle-notesOverlay',shape:'rect',dims:[x1+40,y1,20,20],cursor:draw.cursors.pointer,func:draw.toggleNotesOverlay,pathNum:pathNum,path:path});
path.borderButtons = buttons;
return path.border;
}
draw.toggleNotesOverlay = function() {
var path = draw.currCursor.path;
if (path.notesOverlay === true) {
delete path.notesOverlay;
} else {
path.notesOverlay = true;
}
drawCanvasPaths();
}
draw.getPathFunctions = function(path) {
var funcs = [];
for (var key in path) if (typeof path[key] === 'function') funcs.push([path,key,'path.'+key+'()']);
if (!un(path.interact)) {
for (var key in path.interact) if (typeof path.interact[key] === 'function') funcs.push([path.interact,key,'path.interact.'+key+'()']);
}
if (!un(path.isInput)) {
for (var key in path.isInput) if (typeof path.isInput[key] === 'function') funcs.push([path.isInput,key,'path.isInput.'+key+'()']);
}
return funcs;
}
draw.getObjFunctions = function(obj) {
var funcs = [];
for (var key in obj) if (typeof obj[key] === 'function') funcs.push([obj,key,'obj.'+key]);
if (!un(obj.interact)) {
for (var key in obj.interact) if (typeof obj.interact[key] === 'function') funcs.push([obj.interact,key,'obj.interact.'+key+'()']);
}
return funcs;
}
function cycleSelected(reverse) {
var selected = selPathNum();
deselectAllPaths();
if (boolean(reverse,false) == false) {
selected = (selected+1)%draw.path.length;
} else {
selected = selected-1;
if (selected == -1) selected = draw.path.length-1;
}
draw.path[selected].selected = true;
calcCursorPositions();
drawCanvasPaths();
}
function sel() {
if (un(draw) || un(draw.path)) return false;
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
return draw.path[p].obj[0];
}
}
return false;
}
function selObjs() {
if (un(draw) || un(draw.path)) return false;
var objs = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
for (var o = 0; o < draw.path[p].obj.length; o++) {
objs.push(draw.path[p].obj[o]);
}
}
}
return objs;
}
function selPath() {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
return draw.path[p];
}
}
return false;
}
function selPathNum() {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
return p;
}
}
return -1;
}
function selPathNums() {
var nums = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) nums.push(p);
}
return nums;
}
function selPaths() {
if (un(draw) || un(draw.path)) return [];
var paths = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
paths.push(draw.path[p]);
}
}
return paths;
}
draw.undo = {
save:true,
saveState: function() {
if (draw.undo.save == false) return;
if (un(draw.undo.undoStack[0]) || draw.undo.pathsEqual(draw.path,draw.undo.undoStack[0]) == false) {
draw.undo.undoStack.unshift(clone(draw.path));
draw.undo.redoStack = [];
}
},
undoStack:[],
undo:function() {
while (!un(draw.undo.undoStack[0]) && draw.undo.pathsEqual(draw.path,draw.undo.undoStack[0])) {
draw.undo.undoStack.shift();
}
if (un(draw.undo.undoStack[0])) return;
draw.undo.redoStack.unshift(clone(draw.path));
draw.path = draw.undo.undoStack.shift();
draw.undo.save = false;
deselectAllPaths();
draw.undo.save = true;
},
redoStack:[],
redo:function() {
while (!un(draw.undo.redoStack[0]) && draw.undo.pathsEqual(draw.path,draw.undo.redoStack[0])) {
draw.undo.redoStack.shift();
}
if (draw.undo.redoStack.length == 0) return;
draw.undo.undoStack.unshift(clone(draw.path));
draw.path = draw.undo.redoStack.shift();
draw.undo.save = false;
deselectAllPaths();
draw.undo.save = true;
},
reset: function() {
draw.undo.undoStack = [];
draw.undo.redoStack = [];
},
pathsEqual: function(a,b) {
if (a.length !== b.length) return false;
for (var p = 0; p < a.length; p++) {
var path1 = a[p];
var path2 = b[p];
if (path1.obj.length !== path2.obj.length) return false;
if ((!un(path1.appear) || !un(path2.appear)) && isEqual(path1.appear,path2.appear) == false) return false;
for (var o = 0; o < path1.obj.length; o++) {
var obj1 = path1.obj[o];
var obj2 = path2.obj[o];
for (var key in obj1) {
if (['ctx','text'].includes(key) || key.indexOf('_') == 0 || !obj1.hasOwnProperty(key) || isElement(obj1[key])) continue;
if (isEqual(obj1[key],obj2[key]) == false) return false;
}
}
}
return true;
}
}
draw.scalePath = function(path,sf) {
if (un(path.border)) updateBorder(path);
var center = [path.border[0],path.border[1]];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(draw[obj.type]) || un (draw[obj.type].scale)) continue;
draw[obj.type].scale(obj,sf,center);
}
updateBorder(path);
drawCanvasPaths();
}
/***************************/
/* KEYBOARD SHORTCUTS */
/***************************/
var snapToObj2Mode = 'ctrl';
var snapToObj2On = false;
var snapBordersOn = false;
var shiftOn = false;
var ctrlOn = false;
var altOn = false;
window.addEventListener('keydown', keydown, false);
function keydown(e) {
if (e.keyCode == 16) {
shiftOn = true;
} else if (e.keyCode == 17) {
ctrlOn = true;
snapToObj2On = true;
} else if (e.keyCode == 18) {
altOn = true;
}
if (typeof window.keynav !== 'undefined') window.keynav(e);
}
window.addEventListener('keyup', keyup ,false);
function keyup(e) {
if (e.keyCode == 16) {
shiftOn = false;
} else if (e.keyCode == 17) {
ctrlOn = false;
if (snapToObj2Mode == 'ctrl') snapToObj2On = false;
} else if (e.keyCode == 18) {
altOn = false;
}
}
function addKeyboardShortcuts() {
window.addEventListener('keydown', keydown1, false);
//window.addEventListener('keyup', keyup1, false);
}
function removeKeyboardShortcuts() {
window.removeEventListener('keydown', keydown1, false);
//window.removeEventListener('keyup', keyup1, false);
}
function keydown1(e) {
if (!un(draw.codeEditor) && draw.codeEditor.div.parentNode == container) {
if (e.key == 'Escape') draw.codeEditor.close();
return;
}
if (e.target.allowDefault === true) return;
if (textEdit.obj !== null) return;
if (e.key == 'Tab') {
e.preventDefault();
cycleSelected(e.getModifierState('Shift'));
return;
}
if (e.getModifierState('Control')) {
//console.log(e.key);
if (e.key == 'z' || e.key == 'Z') {
e.preventDefault();
draw.undo.undo();
} else if (e.key == 'y' || e.key == 'Y') {
e.preventDefault();
draw.undo.redo();
} else if (e.key == 's' || e.key == 'S') {
e.preventDefault();
var objects = selObjs();
for (var o = 0; o < objects.length; o++) {
console.log(objects[o]);
}
} else if (e.key == 'o' || e.key == 'O') {
e.preventDefault();
console.log(selPath().obj);
} else if (e.key == 'p' || e.key == 'P') {
e.preventDefault();
console.log(selPath());
} else if (e.key == 'x' || e.key == 'X') {
e.preventDefault();
cutPaths(e);
} else if (e.key == 'c' || e.key == 'C') {
e.preventDefault();
copyPaths(e);
} else if (e.key == 'v' || e.key == 'V') {
e.preventDefault();
pastePaths(e);
} else if (e.key == 'b' || e.key == 'B') {
e.preventDefault();
if (typeof textMenu !== 'undefined') textMenu.applyValue("bold",!textEdit.menu.currentStyle.bold);
} else if (e.key == 'i' || e.key == 'I') {
e.preventDefault();
if (typeof textMenu !== 'undefined') textMenu.applyValue("italic",!textEdit.menu.currentStyle.italic);
} else if (e.key == 'g' || e.key == 'G') {
e.preventDefault();
groupPaths();
} else if (e.key == 'u' || e.key == 'U') {
e.preventDefault();
ungroupPaths();
} else if (e.key == 't' || e.key == 'T') {
e.preventDefault();
//addTitle();
} else if (e.key == 'd' || e.key == 'D') {
e.preventDefault();
clonePaths();
} else if (e.key == 'a' || e.key == 'A') {
e.preventDefault();
selectAllPaths();
} else if (e.key == 'q' || e.key == 'Q') {
e.preventDefault();
if (typeof textMenu !== 'undefined') textMenu.applyValue("font");
//showCursorPositions();
} else if (e.keyCode == 38) { // up
e.preventDefault();
//fontSizeUp();
} else if (e.keyCode == 40) { // down
e.preventDefault();
//fontSizeDown();
} else if (e.keyCode == 46) { // delete
e.preventDefault();
deleteSelectedPaths();
} else if (e.key == 'm' || e.key == 'M') {
e.preventDefault();
centerDistributeText();
}
} else if (e.getModifierState('Shift')) {
if (e.keyCode == 37) { // left
e.preventDefault();
movePaths(-5,0);
} else if (e.keyCode == 38) { // up
e.preventDefault();
movePaths(0,-5);
} else if (e.keyCode == 39) { // right
e.preventDefault();
movePaths(5,0);
} else if (e.keyCode == 40) { // down
e.preventDefault();
movePaths(0,5);
}
} else if (e.getModifierState('Alt')) {
if (e.keyCode == 37) { // left
e.preventDefault();
movePaths(-1,0);
} else if (e.keyCode == 38) { // up
e.preventDefault();
movePaths(0,-1);
} else if (e.keyCode == 39) { // right
e.preventDefault();
movePaths(1,0);
} else if (e.keyCode == 40) { // down
e.preventDefault();
movePaths(0,1);
} else if (e.keyCode == 76) { // l
e.preventDefault();
alignPaths('left');
} else if (e.keyCode == 67) { // c
e.preventDefault();
alignPaths('center');
} else if (e.keyCode == 82) { // r
e.preventDefault();
alignPaths('right');
} else if (e.keyCode == 84) { // t
e.preventDefault();
alignPaths('top');
} else if (e.keyCode == 77) { // m
e.preventDefault();
alignPaths('middle');
} else if (e.keyCode == 66) { // b
e.preventDefault();
alignPaths('bottom');
} else if (e.key.toLowerCase() == 'e') {
e.preventDefault();
draw.text2.horizAlignToEquals();
}
}
}
/*window.addEventListener('paste', onpaste, false);
function onpaste(e) {
// if ?
console.log(event.clipboardData.getData('Text'));
};*/
draw.keyboard = {
active:false,
create:function(obj) {
createKeyboard(obj);
draw.keyboard.active = true;
},
show:function(lightUp) {
showKeyboard2(lightUp);
},
hide:function() {
hideKeyboard2();
},
showButton:function() {
hideKeyboard2();
showObj(keyboardButton1[0]);
hideObj(keyboardButton2[0]);
},
hideButton:function() {
hideKeyboard2();
hideObj(keyboardButton1[0]);
hideObj(keyboardButton2[0]);
},
getPosition:function() {
var data = keyboard[0].data;
return [data[100],data[101]];
},
setPosition:function(pos) {
keyboard[0].data[100] = pos[0];
keyboard[0].data[101] = pos[1];
resizeCanvas2(keyboard[0],pos[0],pos[1]);
for (i = 0; i < key1[pageIndex].length; i++) {
if (boolean(key1[pageIndex][i].static,false) == false) {
key1Data[pageIndex][i][100] = pos[0] + key1Data[pageIndex][i][4];
key1Data[pageIndex][i][101] = pos[1] + key1Data[pageIndex][i][5];
resizeCanvas2(key1[pageIndex][i],key1Data[pageIndex][i][100],key1Data[pageIndex][i][101]);
}
}
},
moveAwayFromTextInput: function() {
var textRect = textEdit.obj.rect.slice(0);
textRect[0] += draw.drawRelPos[0];
textRect[1] += draw.drawRelPos[1];
var keyboardRect = keyboard[0].data.slice(100,104);
if (hitTestTwoRects(textRect,keyboardRect) === false) return;
//console.log(textRect,keyboardRect);
if (textRect[0] >= keyboardRect[2]) {
draw.keyboard.setPosition([textRect[0]-keyboardRect[2],keyboardRect[1]]);
} else if ((1200-(textRect[0]+textRect[2])) >= keyboardRect[2]) {
draw.keyboard.setPosition([textRect[0]+textRect[2],keyboardRect[1]]);
} else if (textRect[1] >= keyboardRect[3]) {
draw.keyboard.setPosition([keyboardRect[0],textRect[1]-keyboardRect[3]]);
} else if ((700-(textRect[1]+textRect[3])) >= keyboardRect[3]) {
draw.keyboard.setPosition([keyboardRect[0],textRect[1]+textRect[3]]);
}
}
}
/***************************/
/* DRAWING OBJECTS */
/***************************/
function drawClickFloodFillClick(e) {
deselectAllPaths(false);
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
//var x = mouse.x - draw.drawRelPos[0] - draw.drawArea[0];
//var y = mouse.y - draw.drawRelPos[1] - draw.drawArea[1];
draw.fillPath.fillPolygonAtPoint(x,y);
}
function floodFill(canvas, startX, startY, fillColor) {
startX = Math.round(startX);
startY = Math.round(startY);
var dstImg = canvas.ctx.getImageData(0,0,canvas.width,canvas.height);
var dstData = dstImg.data;
var alteredPixels = [];
var startPos = getPixelPos(startX, startY);
var startColor = {
r: dstData[startPos],
g: dstData[startPos+1],
b: dstData[startPos+2],
a: dstData[startPos+3]
};
var todo = [[startX,startY]];
while (todo.length) {
var pos = todo.pop();
var x = pos[0];
var y = pos[1];
var currentPos = getPixelPos(x, y);
while((y-- >= 0) && matchStartColor(dstData, currentPos, startColor)) {
currentPos -= canvas.width * 4;
}
currentPos += canvas.width * 4;
++y;
var reachLeft = false;
var reachRight = false;
while((y++ < canvas.height-1) && matchStartColor(dstData, currentPos, startColor)) {
colorPixel(dstData, currentPos, fillColor);
if (x > 0) {
if (matchStartColor(dstData, currentPos-4, startColor)) {
if (!reachLeft) {
todo.push([x-1, y]);
reachLeft = true;
}
} else if (reachLeft) {
reachLeft = false;
}
}
if (x < canvas.width-1) {
if (matchStartColor(dstData, currentPos+4, startColor)) {
if (!reachRight) {
todo.push([x+1, y]);
reachRight = true;
}
} else if (reachRight) {
reachRight = false;
}
}
currentPos += canvas.width * 4;
}
}
return alteredPixels;
function getPixelPos(x, y) {
return (y * canvas.width + x) * 4;
};
function getPixelPosInverse(pos) {
var pos2 = Math.floor(pos/4);
return [pos2%canvas.width,Math.floor(pos2/canvas.width)];
};
function matchStartColor(data, pos, startColor) {
return (
data[pos] === startColor.r &&
data[pos+1] === startColor.g &&
data[pos+2] === startColor.b &&
data[pos+3] === startColor.a);
};
function colorPixel(data, pos, color) {
alteredPixels.push(getPixelPosInverse(pos));
data[pos] = color.r || 0;
data[pos+1] = color.g || 0;
data[pos+2] = color.b || 0;
data[pos+3] = color.hasOwnProperty("a") ? color.a : 255;
};
};
function drawClickStartDraw() {
deselectAllPaths(false);
//var x = mouse.x - draw.drawRelPos[0] - draw.drawArea[0];
//var y = mouse.y - draw.drawRelPos[1] - draw.drawArea[1];
//updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
if (snapToObj2On && draw.drawMode !== 'pen' && un(draw.snapToObjs)) {
updateSnapPoints(); // update intersection points
var pos = snapToObj2([x,y]);
x = pos[0];
y = pos[1];
}
switch (draw.drawMode) {
case 'pen':
draw.drawing = true;
draw.prevX = x;
draw.prevY = y;
var obj = {
type:'pen',
color:draw.color,
thickness:draw.thickness,
pos:[[x,y]],
};
if (!un(draw.dash) && draw.dash.length > 0) obj.dash = clone(draw.dash);
draw.path.push({obj:[obj],selected:false,time:Date.parse(new Date())});
//addListenerMove(window,penDrawMove);
//addListenerEnd(window,penDrawStop);
draw.animate(penDrawMove,penDrawStop,drawSelectedPaths);
break;
case 'line':
// if too many lines, delete oldest
var lineCount = 0;
for (var i = draw.path.length - 1; i >= 0; i--) {
for (var o = 0; o < draw.path[i].obj.length; o++) {
if (draw.path[i].obj[o].type == 'line') {
lineCount++;
if (lineCount >= draw.maxLines) {
draw.path.splice(i,1);
}
}
}
}
var point = [x,y];
if (draw.snap == true) {
updateSnapPoints();
point = snapToPoints(point,draw.snapPoints,draw.snapTolerance);
} else if (draw.gridSnap == true) {
//startX = roundToNearest(startX,draw.gridSnapSize);
//startY = roundToNearest(startY,draw.gridSnapSize);
}
if (snapToObj2On) {
point = snapToObj2(point,-1);
}
draw.drawing = true;
draw.startX = point[0];
draw.startY = point[1];
var obj = {
type:'line',
color:draw.color,
thickness:draw.thickness,
startPos:point,
drawing:true
};
if (!un(draw.dash) && draw.dash.length > 0) obj.dash = clone(draw.dash)
draw.path.push({obj:[obj],selected:false});
if (boolean(draw.vector,false)) {
draw.path.last().obj[0].endMid = 'open';
draw.path.last().obj[0].endMidSize = draw.thickness*5;
}
//addListenerMove(window,lineDrawMove);
//addListenerEnd(window,lineDrawStop);
draw.animate(lineDrawMove,lineDrawStop,drawSelectedPaths);
break;
case 'rect' :
case 'square' :
var startX = x;
var startY = y;
if (draw.gridSnap == true) {
startX = roundToNearest(startX,draw.gridSnapSize);
startY = roundToNearest(startY,draw.gridSnapSize);
}
draw.drawing = true;
draw.startX = startX;
draw.startY = startY;
draw.path.push({obj:[{
type:draw.drawMode,
color:draw.color,
thickness:draw.thickness,
fillColor:draw.fillColor,
startPos:[startX,startY],
edit:false
}],selected:false});
//addListenerMove(window,rectDrawMove);
//addListenerEnd(window,rectDrawStop);
draw.animate(rectDrawMove,rectDrawStop,drawSelectedPaths);
break;
case 'polygon' :
var pos = [x,y];
if (draw.gridSnap == true) {
pos = [roundToNearest(startX,draw.gridSnapSize),roundToNearest(startY,draw.gridSnapSize)];
}
if (snapToObj2On) {
pos = snapToObj2(pos,-1);
}
draw.drawing = true;
draw.startX = startX;
draw.startY = startY;
draw.path.push({obj:[{
type:draw.drawMode,
color:draw.color,
thickness:draw.thickness,
fillColor:draw.fillColor,
points:[pos,[]],
closed:false,
lineDecoration:[],
angles:[],
clockwise:true,
edit:false,
drawing:true
}],selected:false});
//console.log(draw.path[draw.path.length-1]);
changeDrawMode('polygon-drawing');
//addListenerMove(window,polygonDrawMove);
//addListenerEnd(window,polygonDrawStop);
draw.animate(polygonDrawMove,polygonDrawStop,drawSelectedPaths);
break;
case 'circle' :
var startX = x;
var startY = y;
if (draw.gridSnap == true) {
startX = roundToNearest(startX,draw.gridSnapSize);
startY = roundToNearest(startY,draw.gridSnapSize);
}
draw.drawing = true;
draw.startX = startX;
draw.startY = startY;
draw.path.push({obj:[{
type:draw.drawMode,
color:draw.color,
thickness:draw.thickness,
fillColor:draw.fillColor,
center:[startX,startY],
radius:0,
showCenter:true,
edit:false
}],selected:false});
//addListenerMove(window,circleDrawMove);
//addListenerEnd(window,circleDrawStop);
draw.animate(circleDrawMove,circleDrawStop,drawSelectedPaths);
break;
case 'point' :
var startX = x;
var startY = y;
if (draw.gridSnap == true) {
startX = roundToNearest(startX,draw.gridSnapSize);
startY = roundToNearest(startY,draw.gridSnapSize);
}
var point = [startX,startY]
if (snapToObj2On) point = snapToObj2(point,-1);
draw.path.push({obj:[{
type:draw.drawMode,
color:draw.color,
thickness:draw.thickness,
fillColor:draw.fillColor,
center:point,
radius:draw.thickness,
showCenter:false,
edit:false
}],selected:false});
break;
case 'ellipse' :
var startX = x;
var startY = y;
if (draw.gridSnap == true) {
startX = roundToNearest(startX,draw.gridSnapSize);
startY = roundToNearest(startY,draw.gridSnapSize);
}
draw.drawing = true;
draw.startX = startX;
draw.startY = startY;
draw.path.push({obj:[{
type:draw.drawMode,
color:draw.color,
thickness:draw.thickness,
fillColor:draw.fillColor,
center:[startX,startY],
radiusX:0,
radiusY:0,
showCenter:true,
edit:false
}],selected:false});
//addListenerMove(window,ellipseDrawMove);
//addListenerEnd(window,ellipseDrawStop);
draw.animate(ellipseDrawMove,ellipseDrawStop,drawSelectedPaths);
break;
}
drawCanvasPaths();
drawSelectCanvas();
};
function penDrawMove(e) {
//var x = draw.getRelMouseX(e), y = draw.getRelMouseY();
updateMouse(e);
var pos = draw.mouse;
if (pos[0] !== draw.prevX || pos[1] !== draw.prevY) {
draw.path.last().obj[0].pos.push(clone(pos));
//drawSelectedPaths();
draw.prevX = pos[0];
draw.prevY = pos[1];
}
}
function penDrawStop(e) {
//removeListenerMove(window,penDrawMove);
//removeListenerEnd(window,penDrawStop);
draw.prevX = null;
draw.prevY = null;
draw.drawing = false;
var pathNum = draw.path.length-1;
if (draw.groupPenPaths !== false) {
for (var i = draw.path.length-2; i > -1; i--) {
if (typeof draw.path[i].obj == 'object') {
var penPath = true;
for (var j = 0; j < draw.path[i].obj.length; j++) {
if (draw.path[i].obj[j].type !== 'pen') {
penPath = false;
}
}
if (penPath == true) {
pathNum = i;
break;
}
}
}
}
if (pathNum < draw.path.length-1) {
var path = draw.path[pathNum];
path.obj.push(draw.path[draw.path.length-1].obj[0]);
removePathObject(draw.path.length-1);
} else {
var path = draw.path[draw.path.length-1];
}
var x1 = path.obj[0].pos[0][0];
var y1 = path.obj[0].pos[0][1];
var x2 = path.obj[0].pos[0][0];
var y2 = path.obj[0].pos[0][1];
for (var i = 0; i < path.obj[0].pos.length; i++) {
x1 = Math.min(x1,path.obj[0].pos[i][0]);
y1 = Math.min(y1,path.obj[0].pos[i][1]);
x2 = Math.max(x1,path.obj[0].pos[i][0]);
y2 = Math.max(y1,path.obj[0].pos[i][1]);
}
path.obj[0].left = x1;
path.obj[0].top = y1;
path.obj[0].width = x2-x1;
path.obj[0].height = y2-y1;
updateBorder(path);
drawCanvasPaths();
}
function lineDrawMove(e) {
//var x = draw.getRelMouseX(e), y = draw.getRelMouseY();
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
var pathNum = draw.path.length - 1;
var obj = draw.path[pathNum].obj[0];
if (draw.drawMode == 'lineStart') {
if (shiftOn) {
if (Math.abs(obj.finPos[0]-x) < Math.abs(obj.finPos[1]-y)) {
obj.startPos = [obj.finPos[0],y];
} else {
obj.startPos = [x,obj.finPos[1]];
}
} else if (snapToObj2On || draw.snapLinesTogether) {
obj.startPos = snapToObj2([x,y],pathNum);
} else {
obj.startPos = [x,y];
}
} else if (draw.drawMode == 'lineFin' || draw.drawMode == 'line') {
if (shiftOn) {
if (Math.abs(obj.startPos[0]-x) < Math.abs(obj.startPos[1]-y)) {
obj.finPos = [obj.startPos[0],y];
} else {
obj.finPos = [x,obj.startPos[1]];
}
} else if (snapToObj2On || draw.snapLinesTogether) {
obj.finPos = snapToObj2([x,y],pathNum);
} else {
obj.finPos = [x,y];
}
}
/*drawSelectedPaths();
if (draw.drawMode !== 'draw') {
updateBorder(draw.path[pathNum]);
drawSelectCanvas();
drawSelectCanvas2();
}*/
}
function lineDrawStop(e) {
//console.log('lineDrawStop');
//removeListenerMove(window,lineDrawMove);
removeListenerMove(window,rulerDrawMove1);
removeListenerMove(window,rulerDrawMove2);
removeListenerEnd(window,lineDrawStop);
draw.startX = null;
draw.startY = null;
draw.drawing = false;
var path = draw.path.last();
var obj = path.obj[0];
if (typeof obj.finPos == 'undefined' || getDist(obj.startPos,obj.finPos) < 5) {
removePathObject(draw.path.length-1);
if (draw.defaultMode == 'select') {
changeDrawMode();
}
} else {
if (draw.gridSnap == true && shiftOn == false) {
obj.finPos[0] = roundToNearest(obj.finPos[0],draw.gridSnapSize);
obj.finPos[1] = roundToNearest(obj.finPos[1],draw.gridSnapSize);
}
if (draw.defaultMode == 'select') {
path.selected = true;
updateBorder(path);
changeDrawMode();
} else {
path.selected = false;
}
path.trigger = [];
for (var i = 0; i < draw.path.length; i++) {
for (var j = 0; j < draw.path[i].obj.length; j++) {
draw.path[i].obj[j].drawing = false;
}
}
updateBorder(path);
}
redrawButtons();
drawCanvasPaths();
if (!un(draw.contextMenu)) draw.contextMenu.update();
}
function rectDrawMove(e) {
//var x = draw.getRelMouseX(e), y = draw.getRelMouseY();
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
if (draw.drawMode == 'square') {
var dx = x-draw.path[draw.path.length-1].obj[0].startPos[0];
var dy = y-draw.path[draw.path.length-1].obj[0].startPos[1];
if (Math.abs(dx) >= Math.abs(dy)) {
x = draw.path[draw.path.length-1].obj[0].startPos[0] + dx;
y = draw.path[draw.path.length-1].obj[0].startPos[1] + dx;
} else {
x = draw.path[draw.path.length-1].obj[0].startPos[0] + dy;
y = draw.path[draw.path.length-1].obj[0].startPos[1] + dy;
}
}
draw.path[draw.path.length-1].obj[0].finPos = [x,y];
//drawSelectedPaths();
}
function rectDrawStop(e) {
//removeListenerMove(window,rectDrawMove);
//removeListenerEnd(window,rectDrawStop);
draw.startX = null;
draw.startY = null;
draw.drawing = false;
if (typeof draw.path[draw.path.length-1].obj[0].finPos == 'undefined' || dist(draw.path[draw.path.length-1].obj[0].startPos[0],draw.path[draw.path.length-1].obj[0].startPos[1],draw.path[draw.path.length-1].obj[0].finPos[0],draw.path[draw.path.length-1].obj[0].finPos[1]) < 5) {
draw.path.pop();
} else if (draw.gridSnap == true) {
draw.path[draw.path.length-1].obj[0].finPos[0] = roundToNearest(draw.path[draw.path.length-1].obj[0].finPos[0],draw.gridSnapSize);
draw.path[draw.path.length-1].obj[0].finPos[1] = roundToNearest(draw.path[draw.path.length-1].obj[0].finPos[1],draw.gridSnapSize);
}
changeDrawMode();
draw.path[draw.path.length-1].selected = true;
// trigger array
draw.path[draw.path.length-1].trigger = [];
redrawButtons();
updateBorder(draw.path.last());
drawCanvasPaths();
}
function polygonDrawMove(e) {
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
var obj = draw.path[draw.path.length-1].obj[0];
if (shiftOn == true) {
var dx = x - obj.points[obj.points.length-2][0];
var dy = y - obj.points[obj.points.length-2][1];
if (Math.abs(dx/dy) >= 1) {
// horizontal line
var newPoint = [Math.min(Math.max(x,draw.drawArea[0]),draw.drawArea[0]+draw.drawArea[2]),obj.points[obj.points.length-2][1]];
} else {
// vertical line
var newPoint = [obj.points[obj.points.length-2][0],Math.min(Math.max(y,draw.drawArea[1]),draw.drawArea[1]+draw.drawArea[3])];
}
} else {
var newPoint = [Math.min(Math.max(x,draw.drawArea[0]),draw.drawArea[0]+draw.drawArea[2]),Math.min(Math.max(y,draw.drawArea[1]),draw.drawArea[1]+draw.drawArea[3])];
if (snapToObj2On || draw.snapLinesTogether) {
newPoint = snapToObj2(newPoint,draw.path.length - 1);
}
}
obj.points[obj.points.length-1] = newPoint;
if (obj.points.length >= 2) obj.clockwise = polygonClockwiseTest(obj.points);
//drawSelectedPaths();
}
function polygonDrawStop(e) {
var x = draw.mouse[0];
var y = draw.mouse[1];
var obj = draw.path[draw.path.length-1].obj[0];
if (obj.points.length > 2 && dist(x,y,obj.points[0][0],obj.points[0][1]) < draw.selectTolerance * 2) {
// close polygon
//removeListenerMove(window,polygonDrawMove);
//removeListenerEnd(window,polygonDrawStop);
obj.closed = true;
obj.drawing = false;
obj.points.pop();
if (obj.clockwise == true) {
obj.points.reverse();
obj.clockwise = false;
}
draw.startX = null;
draw.startY = null;
draw.drawing = false;
changeDrawMode();
obj.angles = [];
for (var p = 0; p < obj.points.length; p++) {
obj.angles[p] = {style:0,radius:30,labelMeasure:true,labelFontSize:25,labelRadius:33,drawCurve:false,measureLabelOnly:true};
}
draw.path[draw.path.length-1].selected = true;
draw.path[draw.path.length-1].trigger = [];
redrawButtons();
updateBorder(draw.path.last());
drawCanvasPaths();
if (!un(draw.contextMenu)) draw.contextMenu.update();
} else if (dist(obj.points[obj.points.length-2][0],obj.points[obj.points.length-2][1],obj.points[obj.points.length-1][0],obj.points[obj.points.length-1][1]) < draw.selectTolerance * 2) {
// leave polygon open
//removeListenerMove(window,polygonDrawMove);
//removeListenerEnd(window,polygonDrawStop);
obj.drawing = false;
obj.points.pop();
if (obj.clockwise == true) {
obj.points.reverse();
obj.clockwise = false;
}
draw.startX = null;
draw.startY = null;
draw.drawing = false;
changeDrawMode();
obj.angles = [];
for (var p = 1; p < obj.points.length-1; p++) {
obj.angles[p] = {style:0,radius:30,labelMeasure:true,labelFontSize:25,labelRadius:33,drawCurve:false,measureLabelOnly:true};
}
draw.path[draw.path.length-1].selected = true;
draw.path[draw.path.length-1].trigger = [];
redrawButtons();
updateBorder(draw.path.last());
if (obj.points.length == 1) draw.path.pop();
drawCanvasPaths();
if (!un(draw.contextMenu)) draw.contextMenu.update();
} else {
var newPoint = [x,y];
if (draw.gridSnap == true) {
newPoint[0] = roundToNearest(newPoint[0],draw.gridSnapSize);
newPoint[1] = roundToNearest(newPoint[1],draw.gridSnapSize);
}
obj.points.push(newPoint);
//drawSelectedPaths();
draw.animate(polygonDrawMove,polygonDrawStop,drawSelectedPaths);
if (!un(draw.contextMenu)) draw.contextMenu.update();
}
}
function circleDrawMove(e) {
//var x = draw.getRelMouseX(e), y = draw.getRelMouseY();
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.path[draw.path.length-1].obj[0].radius = Math.abs(dist(x,y,draw.path[draw.path.length-1].obj[0].center[0],draw.path[draw.path.length-1].obj[0].center[1]));
draw.path[draw.path.length-1].obj[0].showCenter = true;
//redrawButtons();
//drawSelectedPaths();
}
function circleDrawStop(e) {
//removeListenerMove(window,circleDrawMove);
//removeListenerEnd(window,circleDrawStop);
draw.startX = null;
draw.startY = null;
draw.drawing = false;
if (draw.gridSnap == true) {
draw.path[draw.path.length-1].obj[0].radius = roundToNearest(draw.path[draw.path.length-1].obj[0].radius,draw.gridSnapSize);
}
draw.path[draw.path.length-1].obj[0].showCenter = false;
changeDrawMode();
draw.path[draw.path.length-1].selected = true;
draw.path[draw.path.length-1].trigger = [];
redrawButtons();
updateBorder(draw.path.last());
drawCanvasPaths();
}
function ellipseDrawMove(e) {
//var x = draw.getRelMouseX(e), y = draw.getRelMouseY();
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.path[draw.path.length-1].obj[0].radiusX = Math.abs(x-draw.path[draw.path.length-1].obj[0].center[0]);
draw.path[draw.path.length-1].obj[0].radiusY = Math.abs(y-draw.path[draw.path.length-1].obj[0].center[1]);
draw.path[draw.path.length-1].obj[0].showCenter = true;
//drawSelectedPaths();
}
function ellipseDrawStop(e) {
//removeListenerMove(window,ellipseDrawMove);
//removeListenerEnd(window,ellipseDrawStop);
draw.startX = null;
draw.startY = null;
draw.drawing = false;
if (draw.gridSnap == true) {
draw.path[draw.path.length-1].obj[0].radiusX = roundToNearest(draw.path[draw.path.length-1].obj[0].radiusX,draw.gridSnapSize);
draw.path[draw.path.length-1].obj[0].radiusY = roundToNearest(draw.path[draw.path.length-1].obj[0].radiusY,draw.gridSnapSize);
}
draw.path[draw.path.length-1].obj[0].showCenter = false;
changeDrawMode();
draw.path[draw.path.length-1].selected = true;
draw.path[draw.path.length-1].trigger = [];
redrawButtons();
updateBorder(draw.path.last());
drawCanvasPaths();
}
/*draw.getRelMouseX = function(e) {
if (!un(e)) updateMouse(e);
var x = mouse.x - draw.drawRelPos[0] - draw.drawArea[0];
x = Math.max(x,0);
x = Math.min(x,draw.drawArea[2]);
return x;
}
draw.getRelMouseY = function(e) {
if (!un(e)) updateMouse(e);
var y = mouse.y - draw.drawRelPos[1] - draw.drawArea[1];
y = Math.max(y,0);
y = Math.min(y,draw.drawArea[3]);
return y;
}*/
/***************************/
/* GENERAL OBJ INTERACTION */
/***************************/
draw.getPathOfObj = function(obj) {
if (!un(obj._path)) return obj._path;
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
if (obj == path.obj[o]) return path;
}
}
return false;
}
draw.getPathById = function(id) {
if (!un(draw.ids.path[id])) return draw.ids.path[id];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].id == id) return draw.path[p];
}
for (var p = 0; p < draw.path.length; p++) {
for (var o = 0; o < draw.path[p].obj.length; o++) {
if (draw.path[p].obj[o].id === id) return draw.path[p].obj[o]._path;
}
}
return false;
}
draw.getObjById = function(id) {
if (!un(draw.ids.obj[id])) return draw.ids.obj[id];
for (var p = 0; p < draw.path.length; p++) {
for (var o = 0; o < draw.path[p].obj.length; o++) {
if (draw.path[p].obj[o].id === id) return draw.path[p].obj[o];
}
}
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].id == id) return draw.path[p];
}
return false;
}
draw.getObjs = function(type) {
var objs = [];
for (var p = 0; p < draw.path.length; p++) {
for (var o = 0; o < draw.path[p].obj.length; o++) {
if (!un(type) && draw.path[p].obj[o].type !== type) continue;
objs.push(draw.path[p].obj[o]);
}
}
return objs;
}
draw.objs = function(func) {
/* apply a function to all objects
draw.objs(function(obj) {
if (!un(obj.interact) && !un(obj.interact.update)) obj.interact.update(obj);
});
*/
for (var p = 0; p < draw.path.length; p++) {
for (var o = 0; o < draw.path[p].obj.length; o++) {
func(draw.path[p].obj[o],draw.path[p]);
}
}
}
draw.ids = {
obj:{},
path:{},
update:function() {
draw.ids.obj = {};
draw.ids.path = {};
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (!un(path.id)) {
if (!un(draw.ids.path[path.id])) {
console.log('paths with same id:',draw.ids.path[path.id],path);
} else {
draw.ids.path[path.id] = path;
}
}
for (var o2 = 0; o2 < path.obj.length; o2++) {
var obj = path.obj[o2];
if (!un(obj.id)) {
if (!un(draw.ids.obj[obj.id])) {
console.log('objs with same id:',draw.ids.obj[obj.id],obj);
} else {
draw.ids.obj[obj.id] = obj;
}
}
}
}
}
};
draw.interact = {
standardProperties: {
obj: [
{key:'disabled',value:true},
{key:'overlay',value:true},
{key:'click',value:function(obj) {}},
{key:'drag3d',value:false,condition:function(obj) {
return obj.type === 'three';
}},
{key:'cubeBuilding',value:'build',cycle:['build','remove'],condition:function(obj) {
return obj.type === 'three';
}},
{key:'edit3dShape',value:true,condition:function(obj) {
return obj.type === 'three';
}},
],
path: [
{key:'disabled',value:true},
{key:'draggable',value:true},
{key:'moveToFront',value:true,condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return pathInteract.draggable === true;
}},
{key:'dragPathLineSegment',value:'id?'},
{key:'dragPathCircle',value:'id?'},
{key:'checkAllowDrag',value:function(path,pos) {},condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return (pathInteract.draggable === true || !un(pathInteract.dragPathCircle) || !un(pathInteract.dragPathLineSegment));
}},
{key:'dragRect',value:[0,0,1200,1700],condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return pathInteract.draggable === true;
}},
{key:'onDrop',value:function(dragAreaObj,dragPath) {},condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return pathInteract.draggable === true;
}},
{key:'onUndrop',value:function(dragAreaObj,dragPath) {},condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return pathInteract.draggable === true;
}},
{key:'onDragMove',value:function(path) {},condition:function(path) {
var pathInteract = draw.getPathInteract(path);
return (pathInteract.draggable === true || !un(pathInteract.dragPathCircle) || !un(pathInteract.dragPathLineSegment));
}},
{key:'type',value:'check',cycle:['check']},
{key:'update',value:function(path) {}}
]
},
appear: function() {
var path = draw.currCursor.path;
path._visible = !path._visible;
if (path._visible == true && !un(path.appear) && typeof path.appear.onappear == 'function') {
path.appear.onappear(path);
}
if (path._visible == false && !un(path.appear) && typeof path.appear.ondisappear == 'function') {
path.appear.ondisappear(path);
}
drawCanvasPaths();
drawSelectCanvas2();
},
buttons: {
textInput:{
drawButton: function(ctx,size) {
ctx.fillStyle = '#FFF';
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.beginPath();
ctx.fillRect(size*8/55,size*15/55,size*(55-16)/55,size*25/55);
ctx.strokeRect(size*8/55,size*15/55,size*(55-16)/55,size*25/55);
ctx.stroke();
text({context:ctx,left:size*8/55,width:size*(55-16)/55,top:size*15/55,textArray:['<><><>I']});
},
click: function() {
var paths = selPaths();
var count = 0;
for (var p = 0; p < paths.length; p++) {
var path = paths[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (typeof obj == 'undefined' || obj.type !== 'text2' || !un(obj.isInput)) continue;
obj.box = {type:"loose",borderColor:"#000",borderWidth:2,color:"#FFF"};
obj.align = [0,0];
path.isInput = {type:'text'};
obj.ansIndex = 0;
obj.ans = [];
count++;
}
updateBorder(path);
}
if (count == 0) {
Notifier.error('Select a text object');
} else {
drawCanvasPaths();
}
}
},
multiSelectTable:{
drawButton: function(ctx,size) {
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
ctx.fillStyle = '#FFF';
ctx.fillRect(10,11,35,33);
ctx.fillStyle = '#393';
ctx.fillRect(10+11*1,11+0*33/4,35/3,33/4);
ctx.fillRect(10+11*0,11+1*33/4,35/3,33/4);
ctx.fillRect(10+11*2,11+3*33/4,35/3,33/4);
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(10,11+i*33/4);
ctx.lineTo(45,11+i*33/4);
}
for (var i = 0; i < 4; i++) {
ctx.moveTo(10+i*35/3,11);
ctx.lineTo(10+i*35/3,44);
}
ctx.stroke();
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.strokeRect(10,11,35,33);
},
click: function() {
var path = selPath();
if (path == false) {
Notifier.error('Select a table object');
return;
}
var obj = path.obj[0];
if (obj.type !== 'table2') {
Notifier.error('Select a table object');
return;
} else if (!un(obj.isInput)) {
return;
}
path.isInput = {type:'select',shuffle:true,multiSelect:true,checkSelectCount:false,selColors:['#CCF','#66F']};
obj.isInput = path.isInput;
updateBorder(path);
drawCanvasPaths();
}
},
singleSelectTable:{
drawButton: function(ctx,size) {
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
ctx.fillStyle = '#FFF';
ctx.fillRect(10,11,35,33);
ctx.fillStyle = '#393';
ctx.fillRect(10,11,35/2,33/2);
ctx.beginPath();
for (var i = 0; i < 3; i++) {
ctx.moveTo(10,11+i*33/2);
ctx.lineTo(45,11+i*33/2);
}
for (var i = 0; i < 3; i++) {
ctx.moveTo(10+i*35/2,11);
ctx.lineTo(10+i*35/2,44);
}
ctx.stroke();
ctx.lineWidth = 1;
ctx.strokeStyle = '#000';
ctx.strokeRect(10,11,35,33);
},
click: function() {
var path = selPath();
if (path == false) {
Notifier.error('Select a table object');
return;
}
var obj = path.obj[0];
if (obj.type !== 'table2') {
Notifier.error('Select a table object');
return;
} else if (!un(obj.isInput)) {
return;
}
path.isInput = {type:'select',shuffle:true,multiSelect:false,checkSelectCount:true,selColors:['#CCF','#66F']};
obj.isInput = clone(path.isInput);
updateBorder(path);
drawCanvasPaths();
}
},
tickCrossTableHoriz:{
drawButton: function(ctx,size) {
ctx.fillStyle = '#FFF';
ctx.fillRect(7.5,17.5,40,20);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(27.5,17.5);
ctx.lineTo(27.5,37.5);
ctx.stroke();
ctx.strokeRect(7.5,17.5,40,20);
drawTick(ctx,15,18,'#060',7.5+2.5,17.5+1,3);
drawCross(ctx,15,18,'#F00',27.5+2.5,17.5+1,3);
},
click: function() {
deselectAllPaths();
var paths1 = {obj:[{type:"tick",rect:[155,125,40,50],lineWidth:10,lineColor:"#060"}]};
var paths2 = {obj:[{type:"cross",rect:[305,125,40,50],lineWidth:10,lineColor:"#F00"}]};
updateBorder(paths1);
updateBorder(paths2);
var obj = {type:"table2",left:100,top:100,widths:[150,150],heights:[100],text:{font:"Arial",size:28,color:"#000"},outerBorder:{show:false},innerBorder:{show:false},cells:[[{text:[""],align:[0,0],box:{type:"loose",borderColor:"#000",borderWidth:5,radius:10,show:true},paths:[paths1],selColors:["none","#6F6"],ans:false},{text:[""],align:[0,0],box:{type:"loose",borderColor:"#000",borderWidth:5,radius:10,show:true},paths:[paths2],selColors:["none","#F66"],ans:false}]]};
obj.xPos = [obj.left];
for (var i = 0; i < obj.widths.length; i++) obj.xPos.push(obj.xPos.last()+obj.widths[i]);
obj.yPos = [obj.top];
for (var i = 0; i < obj.heights.length; i++) obj.yPos.push(obj.yPos.last()+obj.heights[i]);
draw.path.push({obj:[obj],selected:true,isInput:{type:'select',shuffle:true,multiSelect:false,checkSelectCount:true}});
updateBorder(draw.path.last());
drawCanvasPaths();
}
},
tickCrossTableVert:{
drawButton: function(ctx,size) {
ctx.fillStyle = '#FFF';
ctx.fillRect(17.5,7.5,20,40);
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(17.5,27.5);
ctx.lineTo(37.5,27.5);
ctx.stroke();
ctx.strokeRect(17.5,7.5,20,40);
drawTick(ctx,15,18,'#060',17.5+2.5,7.5+1,3);
drawCross(ctx,15,18,'#F00',17.5+2.5,27.5+1,3);
},
click: function() {
deselectAllPaths();
var paths1 = {obj:[{type:"tick",rect:[155,125,40,50],lineWidth:10,lineColor:"#060"}]};
var paths2 = {obj:[{type:"cross",rect:[305,125,40,50],lineWidth:10,lineColor:"#F00"}]};
updateBorder(paths1);
updateBorder(paths2);
var obj = {type:"table2",left:100,top:100,widths:[100],heights:[100,100],text:{font:"Arial",size:28,color:"#000"},outerBorder:{show:false},innerBorder:{show:false},cells:[[{text:[""],align:[0,0],box:{type:"loose",borderColor:"#000",borderWidth:5,radius:10,show:true},paths:[paths1],selColors:["none","#6F6"],ans:false}],[{text:[""],align:[0,0],box:{type:"loose",borderColor:"#000",borderWidth:5,radius:10,show:true},paths:[paths2],selColors:["none","#F66"],ans:false}]]};
obj.xPos = [obj.left];
for (var i = 0; i < obj.widths.length; i++) obj.xPos.push(obj.xPos.last()+obj.widths[i]);
obj.yPos = [obj.top];
for (var i = 0; i < obj.heights.length; i++) obj.yPos.push(obj.yPos.last()+obj.heights[i]);
draw.path.push({obj:[obj],selected:true,isInput:{type:'select',shuffle:true,multiSelect:false,checkSelectCount:true}});
updateBorder(draw.path.last());
drawCanvasPaths();
}
},
drag:{
drawButton: function(ctx,size) {
drawArrow({ctx:ctx,startX:35,startY:35,finX:45,finY:45,lineWidth:2,arrowLength:8,fillArrow:true,color:'#000'});
text({ctx:ctx,text:['<><><>12'],align:[0,0],rect:[10,10,25,25],box:{type:'loose',color:'#CCF',borderWidth:2,borderColor:'#000',radius:3}});
},
click: function() {
var paths = selPaths();
if (paths.length == 0) {
draw.path.push({obj:[{type:'text2',text:['<><>'],rect:[100,100,200,100]}],selected:true});
paths = [draw.path.last()];
}
for (var p = 0; p < paths.length; p++) {
if (!un(paths[p].isInput)) continue;
paths[p].isInput = {type:'drag',value:"",shuffle:true};
var obj = paths[p].obj[0];
if (obj.type == 'text2') {
var color = !un(obj.box) && !un(obj.box.color) ? obj.box.color : '#CFF';
obj.box = {type:'loose',borderWidth:4,borderColor:'#000',color:color,radius:8};
obj.align = [0,0];
}
updateBorder(paths[p]);
}
drawCanvasPaths();
}
},
dragArea:{
drawButton: function(ctx,size) {
drawArrow({ctx:ctx,startX:10,startY:10,finX:19,finY:19,lineWidth:2,arrowLength:8,fillArrow:true,color:'#000'});
text({ctx:ctx,text:[''],align:[0,0],rect:[20,20,25,25],box:{type:'loose',color:'#FFF',borderWidth:4,borderColor:'#666',radius:3,dash:[5,5]}});
},
click: function() {
var paths = selPaths();
if (paths.length == 0) {
draw.path.push({obj:[{type:'text2',text:['<><>'],rect:[100,100,200,100]}],selected:true});
paths = [draw.path.last()];
}
for (var p = 0; p < paths.length; p++) {
if (!un(paths[p].isInput)) continue;
paths[p].isInput = {type:'dragArea',value:"",snap:false};
var obj = paths[p].obj[0];
if (obj.type == 'text2') {
var color = !un(obj.box) && !un(obj.box.color) ? obj.box.color : '#FFF';
obj.box = {type:'loose',borderWidth:4,borderColor:'#333',color:color,radius:8,dash:[15,10]};
}
updateBorder(paths[p]);
}
drawCanvasPaths();
}
},
addKeyboard:{
drawButton: function(ctx,size) {
roundedRect(ctx,3,3,49,49,8,6,'#000','#F0F');
roundedRect(ctx,2.5+9,2.5+9,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+21,2.5+9,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+33,2.5+9,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+9,2.5+21,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+21,2.5+21,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+33,2.5+21,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+9,2.5+33,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+21,2.5+33,8,8,3,2,'#000','#AFF');
roundedRect(ctx,2.5+33,2.5+33,8,8,3,2,'#000','#AFF');
},
click: function() {
/*if (!un(pages[pIndex].keyboard)) {
delete pages[pIndex].keyboard;
Notifier.info('Keyboard removed');
} else {
pages[pIndex].keyboard = {keyArray:[
['1','2','3'],
['4','5','6'],
['7','8','9'],
['-','0','delete']
]};
console.log(pages[pIndex].keyboard);
Notifier.info('Keyboard added');
}*/
}
},
checkButton:{
drawButton: function(ctx,size) {
roundedRect(ctx,3,10,49,35,8,6,'#000','#6F9');
text({context:ctx,left:size*8/55,width:size*(55-16)/55,top:size*15/55,textArray:['<><><>Check']});
},
click: function() {
draw.path.push({obj:[{type:'text2',align:[0,0],text:['<><>Check Answer'],rect:[20,700-80,260,60],box:{type:'loose',color:'#6F9',borderColor:'#000',borderWidth:4,radius:10}}],selected:true,isInput:{type:'check'}});
updateBorder(draw.path.last());
drawCanvasPaths();
}
},
feedback:{
drawButton: function(ctx,size) {
text({context:ctx,left:size*8/55,width:size*(55-16)/55,top:size*15/55,textArray:['<><><>Feedback']});
},
click: function() {
draw.path.push({obj:[{type:'feedback',rect:[300,700-80,880,60]}],selected:true});
updateBorder(draw.path.last());
drawCanvasPaths();
}
}
},
update: function() {
var changed = false;
draw.objs(function(obj) {
if (typeof obj !== 'object') return;
if (!un(obj.interact) && !un(obj.interact.update)) {
changed = true;
if (typeof obj.interact.update == 'function') {
obj.interact.update(obj);
} else if (obj.interact.update instanceof Array) {
for (var i = 0; i < obj.interact.update.length; i++) {
draw.interact.processFuncObject(obj,obj.interact.update[i]);
}
}
}
});
if (changed === true) drawCanvasPaths();
},
click: function() {
var obj = draw.currCursor.obj;
if (typeof obj.interact.click == 'function') {
if (obj.type === 'table2') {
var rows = obj.heights.length;
var cols = obj.widths.length;
var top = obj.top;
var row = 0;
for (var r = 0; r < rows; r++) {
if (draw.mouse[1] > top) row = r;
top += obj.heights[r];
}
var left = obj.left;
var col = 0;
for (var c = 0; c < cols; c++) {
if (draw.mouse[0] > left) col = c;
left += obj.widths[c];
}
var cell = obj.cells[row][col];
obj.interact.click(cell);
} else {
obj.interact.click(obj);
}
drawCanvasPaths();
} else if (obj.interact.click instanceof Array) {
for (var i = 0; i < obj.interact.click.length; i++) {
draw.interact.processFuncObject(obj,obj.interact.click[i]);
}
drawCanvasPaths();
}
draw.interact.update();
},
processFuncObject: function(obj,funcObject) {
// get object to act upon
var obj2 = un(funcObject.id) || funcObject.id == 'self' ? obj : draw.getObjById(funcObject.id);
// get property object
var property = draw.interact.getPropertyObject(obj2,funcObject.property);
if (typeof property !== 'object') return;
// get value
if (!un(funcObject.value)) {
var value = funcObject.value;
} else if (!un(funcObject.condition)) {
var conditionObj = un(funcObject.condition.id) || funcObject.condition.id == 'self' ? obj2 : draw.getObjById(funcObject.condition.id);
var conditionProperty = draw.interact.getPropertyObject(conditionObj,funcObject.condition.property);
var conditionValue = conditionProperty.get(conditionObj);
var value = funcObject.condition.default;
for (var v = 0; v < funcObject.condition.value.length; v++) {
if (funcObject.condition.value[v][0] == conditionValue) {
value = funcObject.condition.value[v][1];
break;
}
}
}
// apply change
if (!un(value)) {
property.set(obj2,value);
} else if (property.type instanceof Array) {
property.cycle(obj2);
} else if (property.type == 'boolean') {
property.set(obj2,!property.get(obj2));
} else if (property.type == 'number') {
if (!un(funcObject.increment)) {
property.increment(obj2,funcObject.increment);
}
} else if (property.type == 'color') {
}
},
getPropertyObject: function(obj,property) {
if (!un(draw.obj.properties[property])) {
return draw.obj.properties[property];
} else if (!un(draw[obj.type].properties) && !un(draw[obj.type].properties[property])) {
return draw[obj.type].properties[property];
}
return null;
},
dragReset: function(path) {
if (un(path._initialPos)) return;
positionPath(path,path._initialPos[0],path._initialPos[1]);
if (!un(path.interact) && !un(path.interact._dragAreaHit)) {
var dragAreaHit = path.interact._dragAreaHit;
delete path.interact._dragAreaHit;
delete dragAreaHit.obj.interact._dragHit;
if (typeof dragAreaHit.obj.interact.onUndrop === 'function') {
dragAreaHit.obj.interact.onUndrop(dragAreaHit.obj,path);
}
}
},
dragResetAll: function() {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
draw.interact.dragReset(path);
}
},
dragStart: function(e) {
updateMouse(e);
changeDrawMode('selectDrag');
draw.drag = draw.currCursor;
var path = draw.drag.path;
draw.drag.path._interacting = true;
if (path.interact.moveToFront == true) {
//draw.qTable.updateAllPaths();
var index = draw.path.indexOf(path);
draw.path.splice(index,1);
draw.path.push(path);
}
if (un(path.tightBorder)) updateBorder(path);
if (un(path._initialPos) && !un(path.tightBorder)) {
path._initialPos = [path.tightBorder[0],path.tightBorder[1]];
}
draw.drag.offset = [draw.mouse[0]-path.tightBorder[0],draw.mouse[1]-path.tightBorder[1]];
draw.drag.startMouse = [draw.mouse[0],draw.mouse[1]];
draw.drag.startPos = [path.tightBorder[0],path.tightBorder[1]];
addListenerMove(window,draw.interact.dragMove);
addListenerEnd(window,draw.interact.dragStop);
draw.cursorCanvas.style.cursor = draw.cursors.move2;
draw.drag.dragAreas = [];
draw.objs(function(obj) {
if (!un(obj.interact) && (obj.interact.type == 'dragArea' || obj.interact.dragArea == true)) {
process(obj.interact);
} else if (!un(obj.isInput) && (obj.isInput.type == 'dragArea' || obj.isInput.dragArea == true)) {
process(obj.isInput);
}
function process(interact) {
if (!un(interact._dragHit)) {
if (interact._dragHit == draw.drag.path) {
delete interact._dragHit;
if (typeof interact.onUndrop == 'function') {
interact.onUndrop(obj,draw.drag.path);
}
} else {
return;
}
}
var snap = boolean(interact.snap,false);
var rect = obj.rect;
var center = [rect[0]+0.5*rect[2],rect[1]+0.5*rect[3]];
draw.drag.dragAreas.push({rect:rect,center:center,snap:snap,obj:obj});
}
});
draw.selectedCanvas = draw.drawCanvas[1];
if (!un(path.interact) && typeof path.interact.onDragStart == 'function') {
path.interact.onDragStart(path);
}
drawCanvasPaths();
},
dragMove: function(e) {
updateMouse(e);
var path = draw.drag.path;
var obj = draw.drag.obj || draw.drag.path.obj[0];
if (draw.drag.dragType == 'circle') {
var p = draw.drag.path;
var circle = draw.drag.circle;
if (!un(circle.interact) && typeof circle.interact.checkAllowDrag == 'function' && circle.interact.checkAllowDrag(circle,obj,draw.mouse) == false) return;
var c = draw.drag.center;
var r = draw.drag.radius;
var a = getAngleFromAToB(c,[draw.mouse[0],draw.mouse[1]]);
var pos = [c[0]+r*Math.cos(a),c[1]+r*Math.sin(a)];
var dx = pos[0]-(p.border[0]+0.5*p.border[2]);
var dy = pos[1]-(p.border[1]+0.5*p.border[3]);
repositionPath(p,dx,dy);
drawSelectedPaths();
} else if (draw.drag.dragType == 'lineSegment') {
var p = draw.drag.path;
var pos = closestPointOnLineSegment([draw.mouse[0],draw.mouse[1]],draw.drag.lineSegment.startPos,draw.drag.lineSegment.finPos);
var dx = pos[0]-(p.border[0]+0.5*p.border[2]);
var dy = pos[1]-(p.border[1]+0.5*p.border[3]);
repositionPath(p,dx,dy);
drawSelectedPaths();
} else {
var path = draw.drag.path;
if (!un(obj.interact) && typeof obj.interact.checkAllowDrag == 'function' && obj.interact.checkAllowDrag(obj,pos) == false) return;
if (!un(path.interact) && typeof path.interact.checkAllowDrag == 'function' && path.interact.checkAllowDrag(path,pos) == false) return;
var pos2 = clone(draw.mouse);
pos2[0] -= draw.drag.offset[0];
pos2[1] -= draw.drag.offset[1];
if (!un(path.interact) && !un(path.interact.dragRect)) {
var dragRect = path.interact.dragRect;
pos2[0] = Math.max(pos2[0],dragRect[0]);
pos2[0] = Math.min(pos2[0],dragRect[0]+dragRect[2]-path.tightBorder[2]);
pos2[1] = Math.max(pos2[1],dragRect[1]);
pos2[1] = Math.min(pos2[1],dragRect[1]+dragRect[3]-path.tightBorder[3])
} else {
pos2[0] = Math.max(pos2[0],draw.drawArea[0]);
pos2[0] = Math.min(pos2[0],draw.drawArea[0]+draw.drawArea[2]-path.tightBorder[2]);
pos2[1] = Math.max(pos2[1],draw.drawArea[1]);
pos2[1] = Math.min(pos2[1],draw.drawArea[1]+draw.drawArea[3]-path.tightBorder[3])
}
var posRel = [pos2[0]-draw.drag.startPos[0],pos2[1]-draw.drag.startPos[1]];
resizeCanvas2(draw.selectedCanvas,(posRel[0]+draw.drawRelPos[0])*draw.scale,(posRel[1]+draw.drawRelPos[1])*draw.scale);
path._dragPos = [pos2[0],pos2[1]];
//repositionPath(path,pos[0]-path.tightBorder[0],pos[1]-path.tightBorder[1]);
updateBorder(path);
var pos4 = [path._dragPos[0]+0.5*path.tightBorder[2],path._dragPos[1]+0.5*path.tightBorder[3]]; // centre of dragObj
delete draw.drag.path.interact._dragAreaHit;
for (d = 0; d < draw.drag.dragAreas.length; d++) {
var dragArea = draw.drag.dragAreas[d];
if (dist(pos4[0],pos4[1],dragArea.center[0],dragArea.center[1]) < 40) {
draw.drag.path.interact._dragAreaHit = dragArea;
dragArea.obj.interact._dragHit = draw.drag.path;
if (dragArea.snap === true) {
var path2 = draw.getPathOfObj(dragArea.obj);
var border2 = path2.tightBorder;
var pos3 = [border2[0]+0.5*border2[2],border2[1]+0.5*border2[3]]; // center of dragArea
var posNew = [pos3[0]-0.5*path.tightBorder[2],pos3[1]-0.5*path.tightBorder[3]];
var posRel = [posNew[0]-draw.drag.startPos[0],posNew[1]-draw.drag.startPos[1]];
resizeCanvas2(draw.selectedCanvas,(posRel[0]+draw.drawRelPos[0])*draw.scale,(posRel[1]+draw.drawRelPos[1])*draw.scale);
path._dragPos = [posNew[0],posNew[1]];
}
if (typeof dragArea.obj.interact.onDrop == 'function') {
dragArea.obj.interact.onDrop(dragArea.obj,draw.drag.path);
}
} else if (dragArea.obj.interact._dragHit == draw.drag.path) {
delete dragArea.obj.interact._dragHit;
delete draw.drag.path.interact._dragAreaHit;
if (typeof dragArea.obj.interact.onUndrop == 'function') {
dragArea.obj.interact.onUndrop(dragArea.obj,draw.drag.path);
}
}
}
}
if (!un(path.interact) && typeof path.interact.onDragMove == 'function') {
path.interact.onDragMove(path);
}
if (!un(obj.interact) && typeof obj.interact.onDragMove == 'function') {
obj.interact.onDragMove(obj);
}
draw.interact.update();
},
dragStop: function(e) {
changeDrawMode();
calcCursorPositions();
var path = draw.drag.path;
delete path._interacting;
delete path.interact._match;
if (!un(path.interact._dragAreaHit) && !un(path.interact._dragAreaHit.obj) && !un(path.interact._dragAreaHit.obj.interact) && !un(path.interact._dragAreaHit.obj.interact.value)) {
if (path.interact._dragAreaHit.obj.interact.value == path.interact.value) {
path.interact._match = true;
}
}
delete draw.drag;
resizeCanvas2(draw.selectedCanvas,draw.drawRelPos[0],draw.drawRelPos[1]);
if (!un(path._dragPos)) positionPath(path,path._dragPos[0],path._dragPos[1]);
delete draw.selectedCanvas;
delete path._dragPos;
delete draw.selectedCanvases;
draw.interact.update();
drawCanvasPaths();
removeListenerMove(window,draw.interact.dragMove);
removeListenerEnd(window,draw.interact.dragStop);
if (!un(path.interact) && typeof path.interact.onDragStop == 'function') {
path.interact.onDragStop(path);
}
draw.cursorCanvas.style.cursor = draw.cursors.move1;
},
animation:false,
startAnimation: function(func) {
draw.interact._frame = -1;
draw.interact._func = func;
draw.interact.animation = true;
window.requestAnimationFrame(draw.interact.animationStep);
},
stopAnimation: function() {
draw.interact.animation = false;
},
animationStep: function() {
if (draw.interact.animation == false) {
delete draw.interact._frame;
delete draw.interact._func;
return;
}
draw.interact._frame++;
var nextFrame = draw.interact._func(draw.interact._frame);
drawCanvasPaths();
if (nextFrame == false) {
delete draw.interact._frame;
delete draw.interact._func;
draw.interact.animation = false;
} else {
window.requestAnimationFrame(draw.interact.animationStep);
}
},
setFeedback: function(feedback,color) {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (obj.type == 'feedback') {
obj._feedback = feedback;
obj._color = color;
}
}
}
drawCanvasPaths();
},
clearFeedback: function(feedback,color) {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (obj.type == 'feedback') {
delete obj._feedback;
delete obj._color;
}
}
}
drawCanvasPaths();
},
checkPage: function(setFeedback) {
var inputs = [];
var dragCheckMode = 'none';
var dragCanvasCount = 0;
var dragAreaCount = 0;
var dragSnapAreaCount = 0;
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (un(path.isInput)) continue;
if (path.isInput.type == 'drag') {
dragCanvasCount++;
} else if (path.isInput.type == 'dragArea') {
if (path.isInput.snap == true) {
dragSnapAreaCount++;
} else {
dragAreaCount++;
}
}
}
if (dragCanvasCount > 0) {
if (dragSnapAreaCount > 0) {
dragCheckMode = 'dragArea';
} else {
dragCheckMode = 'dragCanvas';
}
}
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (un(path.isInput)) continue;
if (path.isInput.type == 'text') {
inputs.push({type:'text',path:path});
} else if (path.isInput.type == 'drag' && dragCheckMode == 'dragCanvas') {
inputs.push({type:'drag',path:path});
} else if (path.isInput.type == 'dragArea' && dragCheckMode == 'dragArea') {
inputs.push({type:'dragArea',path:path});
} else if (path.isInput.type == 'select') {
inputs.push({type:'select',path:path});
}
}
var checkVars = {check:true,a:[],qs:inputs.length};
var correct = 0;
var max = inputs.length;
for (var q = 0; q < max; q++) {
var input = inputs[q];
if (input.type == 'text') {
} else if (input.type == 'select') {
} else if (input.type == 'drag') {
var check = true;
if (un(input.path._dragAreaHit)) {
checkVars.check = false;
checkVars.fb = "You need to drag all the boxes into position.";
} else if (input.path._dragHit._match !== true) {
check = false;
}
if (check == true) correct++;
checkVars.a[q] = {type:'dragArea',check:check};
} else if (input.type == 'dragArea') {
var check = true;
if (un(input.path._dragHit)) {
checkVars.check = false;
checkVars.fb = "You need to drag boxes into all the positions.";
} else if (input.path._dragHit._match !== true) {
check = false;
}
if (check == true) correct++;
checkVars.a[q] = {type:'dragArea',check:check};
}
}
/*if (drags.length > 0) {
if (dragSnapAreaCount > 0) { // check by dragArea
for (var i = 0; i < dragAreas.length; i++) {
var dragArea = dragAreas[i];
console.log(dragArea);
if (un(dragArea._dragHit) || dragArea._dragHit._match !== true) {
errorCount++;
}
}
} else { // check by drags
for (var i = 0; i < drags.length; i++) {
var drag = drags[i];
console.log(drag);
if (drag._match !== true) {
errorCount++;
}
}
}
}*/
if (!un(checkVars.fb)) {
var feedback = checkVars.fb;
var color = '#C60';
} else {
var wrong = max-correct;
if (wrong == 1) {
var feedback = '1 answer is incorrect.';
var color = '#C60';
} else if (wrong > 1) {
var feedback = wrong+' answers are incorrect.';
var color = '#C60';
} else {
var feedback = 'All correct! Well done.';
var color = '#060';
}
}
if (boolean(setFeedback,true) == true) draw.interact.setFeedback(feedback,color);
return checkVars;
}
};
draw.obj = {
properties:{
visible:{
type:'boolean',
get: function(obj) {
return boolean(obj.visible,true);
},
set: function(obj,value) {
obj.visible = value;
}
}
}
};
function o(id) {
return draw.getObjById(id);
}
draw.objsOfType = function(type) {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
var found = false;
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (obj.type == type) {
console.log(obj);
found = true;
}
}
path.selected = found;
}
drawCanvasPaths();
}
draw.animate = function(onmove,onend,onframe) {
if (!un(draw._animation) && !un(draw._animation.stop)) draw._animation.stop();
if (un(onmove)) onmove = function() {};
if (un(onend)) onend = function() {};
if (un(onframe)) onframe = drawSelectedPaths;
draw._animation = {
onmove:onmove,
onframe:onframe,
onend:onend
};
draw._animation.frame = function() {
draw._animation.onframe();
draw._animation.frameID = window.requestAnimationFrame(draw._animation.frame);
}
draw._animation.stop = function(e) {
if (un(draw._animation)) return;
if (!un(e)) e.stopPropagation();
draw._animation.onend(e);
draw._animation.onframe();
window.cancelAnimationFrame(draw._animation.frameID);
document.removeEventListener("touchmove", draw._animation.onmove);
document.removeEventListener("mousemove", draw._animation.onmove);
document.removeEventListener("touchend", draw._animation.stop);
document.removeEventListener("mouseup", draw._animation.stop);
delete draw._animation;
if (draw.mode === 'edit' && !un(draw.contextMenu)) draw.contextMenu.update();
}
document.addEventListener("touchmove", draw._animation.onmove, false);
document.addEventListener("mousemove", draw._animation.onmove, false);
document.addEventListener("touchend", draw._animation.stop, true);
document.addEventListener("mouseup", draw._animation.stop, true);
draw._animation.frameID = window.requestAnimationFrame(draw._animation.frame);
}
draw.togglePathDraggable = function() {
var path = draw.currCursor.path;
if (un(path.interact)) path.interact = {};
path.interact.draggable = !path.interact.draggable;
updateBorder(path);
drawSelectCanvas();
}
function drawClickSelect() {
cursorPosHighlight(true);
var pathNum = draw.currCursor.pathNum;
if (!shiftOn) deselectAllPaths(false);
draw.path[pathNum].selected = !draw.path[pathNum].selected;
draw.controlPanel.clear();
calcCursorPositions();
drawCanvasPaths();
};
function drawClickStartSelectRect() {
if (shiftOn == false) {
deselectAllPaths(true);
} else {
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
if (getPathVis(path) && path.selected == true) {
path._preSelected = true;
}
}
}
draw.startX = draw.mouse[0];
draw.startY = draw.mouse[1];
changeDrawMode('selectRect');
draw.selectRect = [draw.mouse[0],draw.mouse[1],0,0];
//addListenerMove(window,selectRectMove);
//addListenerEnd(window,selectRectStop);
draw.animate(selectRectMove,selectRectStop,drawSelectCanvas);
};
function selectRectMove(e) {
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.selectRect[2] = x - draw.startX;
draw.selectRect[3] = y - draw.startY;
if (draw.selectRect[0] < x) {
var selectLeft = draw.selectRect[0];
var selectRight = x;
} else {
var selectLeft = x;
var selectRight = draw.selectRect[0];
}
if (draw.selectRect[1] < y) {
var selectTop = draw.selectRect[1];
var selectBottom = y;
} else {
var selectTop = y;
var selectBottom = draw.selectRect[1];
}
for (var i = 0; i < draw.path.length; i++) {
var path = draw.path[i];
//if (un(path.border)) continue;
//if (getPathVis(path) && path.border[0] >= selectLeft && path.border[4] <= selectRight && path.border[1] >= selectTop && path.border[5] <= selectBottom) {
if (un(path._center)) continue;
if (path._preSelected == true) continue;
if (getPathVis(path) && path._center[0] >= selectLeft && path._center[0] <= selectRight && path._center[1] >= selectTop && path._center[1] <= selectBottom) {
path.selected = true;
} else {
path.selected = false;
}
}
//drawSelectCanvas();
//drawSelectCanvas2();
}
function selectRectStop(e) {
changeDrawMode();
for (var p = 0; p < draw.path.length; p++) {
delete draw.path[p]._preSelected;
if (draw.path[p].selected == true) {
drawCanvasPaths();
break;
}
}
drawSelectCanvas2();
draw.startX = null;
draw.startY = null;
//removeListenerMove(window,selectRectMove);
//removeListenerEnd(window,selectRectStop);
}
function drawClickStartZoomRect() {
draw.startX = draw.mouse[0];
draw.startY = draw.mouse[1];
changeDrawMode('zoomRect');
draw.zoomRect = [draw.mouse[0],draw.mouse[1],0,0];
//addListenerMove(window,zoomRectMove);
//addListenerEnd(window,zoomRectStop);
draw.animate(zoomRectMove,zoomRectStop,drawSelectCanvas2);
};
function zoomRectMove(e) {
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.zoomRect[2] = x - draw.startX;
draw.zoomRect[3] = y - draw.startY;
//drawSelectCanvas2();
}
function zoomRectStop(e) {
changeDrawMode();
setZoomRect(draw.zoomRect);
drawSelectCanvas2();
//removeListenerMove(window,zoomRectMove);
//removeListenerEnd(window,zoomRectStop);
}
function changeDrawScale(scale) {
if (un(scale)) scale = 1;
draw.scale = scale;
var canvases = clone(draw.drawCanvas);
canvases.push(draw.cursorCanvas);
canvases.push(draw.toolsCanvas);
/*var w = Math.max(draw.drawArea[2],draw.drawArea[2]*draw.scale);
var h = Math.max(draw.drawArea[3],draw.drawArea[3]*draw.scale);
//console.log(w,h);
for (var c = 0; c < canvases.length; c++) {
var canvas = canvases[c];
resizeCanvas3(canvas,undefined,undefined,w,h);
}*/
drawCanvasPaths();
drawToolsCanvas();
}
function setZoomRect(rect) {
//console.log(rect);
var xScale = 1200 / rect[2];
var yScale = 700 / rect[3];
var scale = Math.min(xScale,yScale);
var xOffset = (1200 - scale*rect[2])/2;
var yOffset = (700 - scale*rect[3])/2;
//console.log(xScale,yScale,scale);
//console.log(xOffset,yOffset);
//console.log(-rect[0]*scale,-rect[1]*scale);
changeDrawScale(scale);
changeDrawRelPos(-rect[0]*scale,-rect[1]*scale);
/*
if (rect[2]/rect[3] > 12/7) {
var w = 1200;
var h = w * (rect[3]/rect[2]);
} else {
var h = 700;
var w = h * (rect[2]/rect[3]);
}
var rect2 = [(1200-w)/2,(700-h)/2,w,h];
var sf = rect2[2] / rect[2];
*/
/*
var ctx = draw.cursorCanvas.ctx;
ctx.scale(draw.scale,draw.scale);
ctx.clear();
ctx.fillStyle = colorA('#000',0.75);
ctx.fillRect(0,0,ctx.data[102],ctx.data[103]);
ctx.clearRect(rect[0],rect[1],rect[2],rect[3]);
ctx.setTransform(1,0,0,1,0,0);
*/
}
function drawClickStartDragObject() {
changeDrawMode('selectDrag');
draw.undo.saveState();
cursorPosHighlight(true);
draw.cursorCanvas.style.cursor = draw.cursors.move2;
draw.startDragX = draw.mouse[0];
draw.startDragY = draw.mouse[1];
draw.selectedCanvases = [];
draw.selectedPaths = getSelectedPaths();
draw.selPaths = selPaths();
//draw.selectedPathNums = selPathNums();
draw.selectedCanvases.push(draw.drawCanvas[1],draw.drawCanvas[draw.drawCanvas.length-1]);
if (!un(draw.gridMenu) && draw.gridMenu.showing == true) {
draw.prevX = mouse.x;
draw.prevY = mouse.y;
}
draw.dragX = draw.mouse[0];
draw.dragY = draw.mouse[1];
draw.prev = clone(draw.mouse);
draw.dragSnapped = false;
draw.dragOffsetX = draw.mouse[0] - draw.path[draw.selectedPaths[0]].tightBorder[0];
draw.dragOffsetY = draw.mouse[1] - draw.path[draw.selectedPaths[0]].tightBorder[1];
addListenerMove(window,selectDragMove);
addListenerEnd(window,selectDragStop);
};
function selectDragMove(e) {
updateMouse(e);
var paths = draw.selPaths;
if (altOn == true && paths.length == 1 && paths[0].obj.length == 1) {
var obj = paths[0].obj[0];
if (!un(draw[obj.type]) && !un(draw[obj.type].altDragMove)) {
var dx = draw.mouse[0] - draw.prev[0];
var dy = draw.mouse[1] - draw.prev[1];
draw[obj.type].altDragMove(obj,dx,dy);
drawSelectedPaths();
updateBorder(paths[0]);
drawSelectCanvas();
draw.prev = clone(draw.mouse);
return;
}
}
//var x = mouse.x + draw.drawRelPos[0] + draw.drawArea[0] - draw.startDragX;
//var y = mouse.y + draw.drawRelPos[1] + draw.drawArea[1] - draw.startDragY;
var x = draw.mouse[0] - draw.startDragX;
var y = draw.mouse[1] - draw.startDragY;
draw.dragSnapped = false;
if (snapToObj2On) {
var obj = sel();
if (obj.type == 'circle' || obj.type == 'point') {
/*var x2 = x + obj.center[0] - draw.drawRelPos[0];
var y2 = y + obj.center[1] - draw.drawRelPos[1];
var snapPos = snapToObj2([x2,y2]);
x = snapPos[0] - obj.center[0] + draw.drawRelPos[0];
y = snapPos[1] - obj.center[1] + draw.drawRelPos[1];
*/
var pos2 = drawPosToCanvasPos([x+obj.center[0],y+obj.center[1]]);
var snapPos = snapToObj2(pos2);
snapPos = canvasPosToDrawPos([snapPos[0]-obj.center[0],snapPos[1]-obj.center[1]]);
x = snapPos[0];
y = snapPos[1];
draw.dragSnapped = true;
} else if (obj.type == 'text2') {
var xLeft = obj.rect[0]+x-draw.drawRelPos[0];
var xCenter = obj.rect[0]+0.5*obj.rect[2]+x-draw.drawRelPos[0];
var xRight = obj.rect[0]+obj.rect[2]+x-draw.drawRelPos[0];
var yTop = obj.rect[1]+y-draw.drawRelPos[1];
var yMiddle = obj.rect[1]+0.5*obj.rect[3]+y-draw.drawRelPos[1];
var yBottom = obj.rect[1]+obj.rect[3]+y-draw.drawRelPos[1];
var found = false;
if (un(draw.savedTextAlign)) {
draw.savedTextArray = clone(obj.text);
draw.savedTextAlign = clone(obj.align);
}
for (var p = 0; p < draw.path.length; p++) {
if (found == true) break;
var path2 = draw.path[p];
for (var o = 0; o < path2.obj.length; o++) {
if (found == true) break;
var obj2 = path2.obj[o];
if (obj2.type == 'table2') {
var x2 = obj2.left;
var y2 = obj2.top;
var xFound = yFound = false;
for (var w = 0; w < obj2.widths.length; w++) {
var width = obj2.widths[w];
if (Math.abs(x2+(width/2)-xCenter) < draw.snapTolerance) {
x2 += width/2;
xFound = true;
break;
} else {
x2 += width;
}
}
if (xFound == true) {
for (var h = 0; h < obj2.heights.length; h++) {
var height = obj2.heights[h];
if (Math.abs(y2+(height/2)-yMiddle) < draw.snapTolerance) {
y2 += height/2;
yFound = true;
break;
} else {
y2 += height;
}
}
}
if (xFound == true && yFound == true) {
x += x2 - xCenter;
y += y2 - yMiddle;
found = true;
obj.align = [0,0];
break;
}
}
if (un(obj2._textSnapPos)) continue;
for (var q = 0; q < obj2._textSnapPos.length; q++) {
if (found == true) break;
var pos = obj2._textSnapPos[q];
if (arraysEqual(pos.align,[-1,0])) {
if (dist(pos.pos[0],pos.pos[1],xLeft,yMiddle) < draw.snapTolerance) {
x += pos.pos[0] - xLeft;
y += pos.pos[1] - yMiddle;
obj.align = [-1,0];
found = true;
break;
}
} else if (arraysEqual(pos.align,[-1,-1])) {
if (dist(pos.pos[0],pos.pos[1],xLeft,yTop) < draw.snapTolerance) {
x += pos.pos[0] - xLeft;
y += pos.pos[1] - yTop;
found = true;
obj.align = [-1,-1];
break;
}
} else if (arraysEqual(pos.align,[0,-1])) {
if (dist(pos.pos[0],pos.pos[1],xCenter,yTop) < draw.snapTolerance) {
x += pos.pos[0] - xCenter;
y += pos.pos[1] - yTop;
found = true;
obj.align = [0,-1];
break;
}
} else if (arraysEqual(pos.align,[1,-1])) {
if (dist(pos.pos[0],pos.pos[1],xRight,yTop) < draw.snapTolerance) {
x += pos.pos[0] - xRight;
y += pos.pos[1] - yTop;
found = true;
obj.align = [1,-1];
break;
}
} else if (arraysEqual(pos.align,[1,0])) {
if (dist(pos.pos[0],pos.pos[1],xRight,yMiddle) < draw.snapTolerance) {
x += pos.pos[0] - xRight;
y += pos.pos[1] - yMiddle;
found = true;
obj.align = [1,0];
break;
}
} else if (arraysEqual(pos.align,[1,1])) {
if (dist(pos.pos[0],pos.pos[1],xRight,yBottom) < draw.snapTolerance) {
x += pos.pos[0] - xRight;
y += pos.pos[1] - yBottom;
found = true;
obj.align = [1,1];
break;
}
} else if (arraysEqual(pos.align,[0,1])) {
if (dist(pos.pos[0],pos.pos[1],xCenter,yBottom) < draw.snapTolerance) {
x += pos.pos[0] - xCenter;
y += pos.pos[1] - yBottom;
found = true;
obj.align = [0,1];
break;
}
} else if (arraysEqual(pos.align,[-1,1])) {
if (dist(pos.pos[0],pos.pos[1],xLeft,yBottom) < draw.snapTolerance) {
x += pos.pos[0] - xLeft;
y += pos.pos[1] - yBottom;
found = true;
obj.align = [-1,1];
break;
}
}
}
}
}
if (found == true) {
obj.text = removeTagsOfType(obj.text,'align');
draw.dragSnapped = true;
drawCanvasPaths();
} else {
obj.text = draw.savedTextArray;
obj.align = draw.savedTextAlign;
}
}
} else if (shiftOn == true && snapBordersOn == true) {
var snapDiff = snapBorders(draw.selectedPaths[0],draw.mouse[0]-draw.dragOffsetX,draw.mouse[1]-draw.dragOffsetY);
x += snapDiff[0];
y += snapDiff[1];
draw.dragSnapped = true;
}
for (var c = 0; c < draw.selectedCanvases.length; c++) {
if (!un(draw.div)) {
var w = (1200/1235)*canvas.getBoundingClientRect().width*draw.div.zoom;
var h = w*(1700/1200);
draw.selectedCanvases[c].style.left = ((w/1200)*(x+draw.drawRelPos[0])*draw.scale)+'px';
draw.selectedCanvases[c].style.top = ((h/1700)*(y+draw.drawRelPos[1])*draw.scale)+'px';
} else {
resizeCanvas2(draw.selectedCanvases[c],(x+draw.drawRelPos[0])*draw.scale,(y+draw.drawRelPos[1])*draw.scale);
}
}
if (!un(draw.gridMenu) && draw.gridMenu.showing == true) {
var dx = draw.mouse[0] - draw.prevX;
var dy = draw.mouse[1] - draw.prevY;
draw.gridMenu.move(dx,dy);
draw.prevX = draw.mouse[0];
draw.prevY = draw.mouse[1];
}
draw.dragX = x;
draw.dragY = y;
}
function selectDragStop(e) {
updateMouse(e);
draw.undo.saveState();
removeListenerMove(window,selectDragMove);
removeListenerEnd(window,selectDragStop);
changeDrawMode();
draw.cursorCanvas.style.cursor = draw.cursors.move1;
if (altOn == true) return;
if (draw.dragSnapped == true) {
var dx = draw.dragX;// - draw.drawRelPos[0];
var dy = draw.dragY;// - draw.drawRelPos[1];
} else {
var dx = draw.mouse[0] - draw.startDragX;
var dy = draw.mouse[1] - draw.startDragY;
}
for (var c = 0; c < draw.selectedCanvases.length; c++) {
if (!un(draw.div)) {
draw.selectedCanvases[c].style.left = '0px';
draw.selectedCanvases[c].style.top = '0px';
} else {
resizeCanvas2(draw.selectedCanvases[c],draw.drawRelPos[0],draw.drawRelPos[1]);
}
}
draw.selectedCanvases = [];
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].selected == true) {
repositionPath(draw.path[i],dx,dy,0,0);
}
}
gridSnapObjects();
drawCanvasPaths();
delete draw.selectedPathNums;
delete draw.savedTextArray;
delete draw.savedTextAlign;
draw.undo.saveState();
}
function drawClickStartResizeObject() {
changeDrawMode('selectResize');
cursorPosHighlight(true);
draw.cursorCanvas.style.cursor = draw.cursors.nw;
draw.prevX = draw.mouse[0];
draw.prevY = draw.mouse[1];
draw.resizePathNum = draw.currCursor.pathNum;
//addListenerMove(window,selectResizeMove);
//addListenerEnd(window,selectResizeStop);
draw.animate(selectResizeMove,selectResizeStop,function() {
drawSelectedPaths();
drawSelectCanvas();
});
}
function selectResizeMove(e) {
updateMouse(e);
var dw = draw.mouse[0] - draw.prevX;
var dh = draw.mouse[1] - draw.prevY;
repositionPath(draw.path[draw.resizePathNum],0,0,dw,dh);
//drawSelectedPaths();
//drawSelectCanvas();
draw.prevX = draw.mouse[0];
draw.prevY = draw.mouse[1];
}
function selectResizeStop(e) {
changeDrawMode('prev');
draw.cursorCanvas.style.cursor = draw.cursors.move1;
gridSnapObjects();
draw.prevX = null;
draw.prevY = null;
delete draw.resizePathNum;
//removeListenerMove(window,selectResizeMove);
//removeListenerEnd(window,selectResizeStop);
}
function drawClickStartResizePath() {
changeDrawMode('selectResize');
draw._path = draw.path[draw.currCursor.pathNum];
//console.log(draw._path);
draw.cursorCanvas.style.cursor = draw.cursors.nw;
//addListenerMove(window,selectResizePathMove);
//addListenerEnd(window,selectResizePathStop);
draw.animate(selectResizePathMove,selectResizePathStop,function() {
drawSelectedPaths();
drawSelectCanvas();
});
}
function selectResizePathMove(e) {
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
var sfx = (x-draw._path.tightBorder[0])/draw._path.tightBorder[2];
var sfy = (y-draw._path.tightBorder[1])/draw._path.tightBorder[3];
draw.scalePath(draw._path,Math.min(sfx,sfy),draw._path.tightBorder);
updateBorder(draw._path);
//drawCanvasPaths();
//drawSelectCanvas2();
}
function selectResizePathStop(e) {
changeDrawMode('prev');
draw.cursorCanvas.style.cursor = draw.cursors.move1;
delete draw._pathNum;
//removeListenerMove(window,selectResizePathMove);
//removeListenerEnd(window,selectResizePathStop);
}
draw.rotateStart = function(e) {
changeDrawMode('selectRotate');
cursorPosHighlight(true);
draw.cursorCanvas.style.cursor = draw.cursors.rotate;
draw.currPath = draw.path[draw.currCursor.pathNum];
addListenerMove(window,draw.rotateMove);
addListenerEnd(window,draw.rotateStop);
}
draw.rotateMove = function(e) {
updateMouse(e);
var x = draw.mouse[0];
var y = draw.mouse[1];
draw.currPath.rotation = getAngleTwoPoints([draw.currPath.border[0]+0.5*draw.currPath.border[2],draw.currPath.border[1]+0.5*draw.currPath.border[3]],[x,y]) + Math.PI/2;
drawSelectedPaths();
drawSelectCanvas();
}
draw.rotateStop = function(e) {
changeDrawMode('prev');
draw.cursorCanvas.style.cursor = draw.cursors.move1;
delete draw.currPath;
removeListenerMove(window,draw.rotateMove);
removeListenerEnd(window,draw.rotateStop);
}
function drawClickAppear() {
var pathNum = draw.currCursor.pathNum;
var path = draw.path[pathNum];
if (un(path.appear)) {
path.appear = {};
} else if (boolean(path.appear.reversible,false) == false) {
path.appear.reversible = true;
} else {
delete path.appear;
}
updateBorder(path);
drawCanvasPaths();
}
function drawClickAppearMoveStart() {
changeDrawMode('appearMove');
draw.cursorCanvas.style.cursor = draw.cursors.move2;
draw.appearMoveMode = true;
draw.selPath = draw.path[draw.currCursor.pathNum];
//addListenerMove(window,drawClickAppearMoveMove);
//addListenerEnd(window,drawClickAppearMoveStop);
draw.animate(drawClickAppearMoveMove,drawClickAppearMoveStop,drawSelectCanvas2);
}
function drawClickAppearMoveMove(e) {
updateMouse(e);
draw.selPath.appear.pos = [round(draw.mouse[0],10),round(draw.mouse[1],10)];
delete draw.selPath.appear.center;
//drawSelectCanvas2();
}
function drawClickAppearMoveStop(e) {
changeDrawMode();
delete draw.selPath;
delete draw.appearMoveMode;
drawSelectCanvas2();
//removeListenerMove(window,drawClickAppearMoveMove);
//removeListenerEnd(window,drawClickAppearMoveStop);
}
function drawClickTrigger() {
var pathNum = draw.currCursor.pathNum;
var path = draw.path[pathNum];
//* just handles showAns at present
if (!un(path.trigger) && arraysEqual(path.trigger,[false])) {
delete path.trigger;
} else {
path.trigger = [false];
}
//*/
/*var prevVis = true;
if (typeof path.trigger == 'undefined') path.trigger = [];
for (var l = 0; l <= draw.triggerNum; l++) {
if (typeof path.trigger[l] == 'boolean') {
prevVis = path.trigger[l];
}
}
path.trigger[draw.triggerNum] = !prevVis;
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
var prevVis = true;
if (un(obj.trigger)) obj.trigger = [];
for (var l = 0; l <= draw.triggerNum; l++) {
if (typeof obj.trigger[l] == 'boolean') {
prevVis = obj.trigger[l];
}
}
obj.trigger[draw.triggerNum] = !prevVis;
}
if (!un(draw.triggerSlider) && draw.ansMode !== true && draw.triggerNum == draw.triggerNumMax) {
draw.triggerNumMax++;
draw.triggerSlider.max = draw.triggerNumMax;
draw.triggerSlider.sliderData[100] = draw.triggerSlider.left + (draw.triggerNum / draw.triggerNumMax) * draw.triggerSlider.width;
resize();
}*/
drawCanvasPaths();
}
function drawClickOrderPlus() {
if (!un(draw.currCursor.pathNum)) {
var pathNum = draw.currCursor.pathNum;
} else {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
var pathNum = p;
break;
}
}
}
if (un(pathNum)) return;
if (ctrlOn == true) {
bringToFront([draw.path[pathNum]]);
} else {
bringForward(pathNum);
}
}
function drawClickOrderMinus() {
if (!un(draw.currCursor.pathNum)) {
var pathNum = draw.currCursor.pathNum;
} else {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
var pathNum = p;
break;
}
}
}
if (un(pathNum)) return;
if (ctrlOn == true) {
sendToBack([draw.path[pathNum]]);
} else {
sendBackward();
}
}
function bringForward(pathNum) {
if (un(pathNum)) pathNum = selPathNum();
if (pathNum == -1 || pathNum == draw.path.length-1) return;
var path = draw.path[pathNum];
draw.path[pathNum] = draw.path[pathNum+1];
draw.path[pathNum+1] = path;
draw.currCursor.pathNum++;
updateBorder(draw.path[pathNum]);
updateBorder(draw.path[pathNum+1]);
calcCursorPositions();
drawCanvasPaths();
}
function sendBackward(pathNum) {
if (un(pathNum)) pathNum = selPathNum();
if (pathNum == -1 || pathNum == 0) return;
var path = draw.path[pathNum];
draw.path[pathNum] = draw.path[pathNum-1];
draw.path[pathNum-1] = path;
draw.currCursor.pathNum--;
updateBorder(draw.path[pathNum-1]);
updateBorder(draw.path[pathNum]);
calcCursorPositions();
drawCanvasPaths();
}
function sendToBack(paths) {
var applyToAllSel = un(paths) ? true : false;
if (un(paths)) paths = [];
for (var p = draw.path.length-1; p >= 0; p--) {
if (applyToAllSel == true && draw.path[p].selected == true) paths.push(draw.path[p]);
if (paths.includes(draw.path[p])) draw.path.splice(p,1);
}
for (var p = paths.length-1; p >= 0; p--) {
draw.path.unshift(paths[p]);
}
calcCursorPositions();
drawCanvasPaths();
}
function bringToFront(paths) {
var applyToAllSel = un(paths) ? true : false;
if (un(paths)) paths = [];
for (var p = draw.path.length-1; p >= 0; p--) {
if (applyToAllSel == true && draw.path[p].selected == true) paths.push(draw.path[p]);
if (paths.includes(draw.path[p])) draw.path.splice(p,1);
}
for (var p = paths.length-1; p >= 0; p--) {
draw.path.push(paths[p]);
}
calcCursorPositions();
drawCanvasPaths();
}
function drawClickDelete() {
if (!un(textEdit) && textEdit.obj !== null) textEdit.endInput();
var pathNum = draw.currCursor.pathNum;
if (draw.path[pathNum].selected == true) removePathObject(pathNum);
for (var p = 0; p < draw.path.length; p++) {
updateBorder(draw.path[p]);
}
calcCursorPositions();
drawCanvasPaths();
cursorPosHighlight(true);
}
draw.movePathToFront = function(path) {
var index = draw.path.indexOf(path);
if (index === -1) return;
draw.path.splice(index,1);
draw.path.push(path);
drawCanvasPaths();
}
draw.checkPathsForID = function(paths,id) {
if (un(paths)) paths = draw.path;
for (var p = 0; p < paths.length; p++) {
if (paths[p].id === id) return true;
}
return false;
}
draw.getUniquePathID = function(paths,id) {
if (un(paths)) paths = draw.path;
var id2 = id;
var num = 2;
while (draw.checkPathsForID(paths,id2) === true) {
id2 = id+'_'+num;
num++;
}
return id2;
}
draw.checkObjsForID = function(paths,id) {
if (un(paths)) paths = draw.path;
for (var p = 0; p < paths.length; p++) {
for (var o = 0; o < paths[p].obj.length; o++) {
if (paths[p].obj[o].id === id) return true;
}
}
return false;
}
draw.getUniqueObjID = function(paths,id) {
if (un(paths)) paths = draw.path;
var id2 = id;
var num = 2;
while (draw.checkObjsForID(paths,id2) === true) {
id2 = id+'_'+num;
num++;
}
return id2;
}
function cutPaths(e) {
copyPaths(e);
deletePaths();
}
function copyPaths(e) {
draw.pathClipboard = [];
var path = draw.path;
for (var p = 0; p < path.length; p++) {
if (path[p].selected) {
draw.pathClipboard.push(clone(path[p]));
}
}
if (typeof mode === 'string' && mode === 'edit') {
//var paths = draw.stringifyDrawPaths({currFilename:currFilename, paths:draw.pathClipboard}, false)
var paths = stringify({currFilename:currFilename, paths:draw.pathClipboard});
paths = obfuscate(paths);
updateClipboard(paths);
}
function updateClipboard(newClip) {
navigator.clipboard.writeText(newClip).then(function() {
Notifier.success('copied to clipboard');
}, function() {
});
}
function stringify(obj) {
var circular = [];
var str = stringify(obj);
return str;
function stringify(obj) {
var str = "";
if (circular.indexOf(obj) > -1) return "null";
if (obj instanceof Array) {
for (var i = 0; i < obj.length; i++) {
if (typeof obj[i] == 'object') {
circular.push(obj);
break;
}
}
str += "[";
for (var i = 0; i < obj.length; i++) {
if (obj.hasOwnProperty(i) !== true) continue;
//if (typeof obj[i] === 'function' && ['last','ran','max','min','sortOn','shuffle','isEmpty','alphanumSort'].includes(i)) continue;
str += stringify(obj[i])+',';
}
if (str.slice(-1) == ',') str = str.slice(0,-1);
str += "]";
} else if (typeof obj == 'object') {
for (var key in obj) {
if (typeof obj[key] == 'object') {
circular.push(obj);
break;
}
}
str += "{";
for (var key in obj) {
if (obj.hasOwnProperty(key) !== true) continue;
if (key.indexOf('_') === 0) continue;
if (['borderButtons','border','tightBorder','selected','ctx','qBox',"data","cursorData","textLoc","cursorPos","cursorMap","allMap","canvas","ctx","cursorCanvas","cursorctx","startText","startRichText","startTags","stringJS","currBackColor","preText","postText"].includes(key)) continue;
var value = stringify(obj[key]);
if (value == '') continue;
str += '"'+key+'":'+value+",";
}
if (str.slice(-1) == ',') str = str.slice(0,-1);
str += "}";
} else if (typeof obj == 'function') {
var funcStr = obj.toString().replace(/\r?\n|\r|\t/g,"");
str += JSON.stringify(funcStr);
} else if (typeof obj == 'number') {
str += String(Number(obj.toFixed(3)));
} else if (typeof obj == 'string') {
var escapeString = replaceAll(obj,"\"","\\\"");
str += '"'+escapeString+'"';
} else if (typeof obj == 'boolean') {
str += obj;
} else {
if (typeof obj !== 'undefined') console.log('draw.stringify type not included: ',typeof obj,obj);
str += 'null';
}
return str;
}
}
function obfuscate(str) {
var bytes = [];
for (var i = 0; i < str.length; i++) {
var charCode = str.charCodeAt(i);
charCode = String("00000" + charCode).slice(-5);
bytes.push(charCode);
}
return bytes.join('');
}
}
function pastePaths(e) {
deselectAllPaths(false);
/*if (!un(draw.pathClipboard) && draw.pathClipboard.length > 0) {
var paths = clonePaths2(draw.pathClipboard);
if (shiftOn === false) {
var top;
for (var c = 0; c < paths.length; c++) {
var path = paths[c];
if (un(top)) {
top = path.tightBorder[1];
} else {
top = Math.min(top,path.tightBorder[1])
}
}
for (var c = 0; c < paths.length; c++) {
var path = paths[c];
positionPath(path,path.tightBorder[0],40-draw.drawRelPos[1]+path.tightBorder[1]-top);
}
}
for (var c = 0; c < paths.length; c++) {
var path = paths[c];
if (typeof path.id === 'string') {
path.id = draw.getUniquePathID(draw.path,path.id);
}
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (typeof obj.id === 'string') {
obj.id = draw.getUniqueObjID(draw.path,obj.id);
}
}
draw.path.push(path);
}
calcCursorPositions();
drawCanvasPaths();
}*/
if (typeof mode === 'string' && mode === 'edit') {
navigator.clipboard.readText().then(function(clipText) {
var json = deobfuscate(clipText);
try {
var clipObj = parse(json);
//if (clipObj.currFilename !== currFilename) {
Notifier.success('pasted from clipboard');
var paths = draw.convertLoadedPaths(clipObj.paths);
var top;
for (var p = 0; p < paths.length; p++) {
var path = paths[p];
path.selected = true;
updateBorder(path);
if (un(top)) {
top = path.tightBorder[1];
} else {
top = Math.min(top,path.tightBorder[1])
}
}
if (shiftOn === false) {
for (var c = 0; c < paths.length; c++) {
var path = paths[c];
positionPath(path,path.tightBorder[0],40-draw.drawRelPos[1]+path.tightBorder[1]-top);
}
}
for (var c = 0; c < paths.length; c++) {
var path = paths[c];
if (typeof path.id === 'string') {
path.id = draw.getUniquePathID(draw.path,path.id);
}
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (typeof obj.id === 'string') {
obj.id = draw.getUniqueObjID(draw.path,obj.id);
}
}
draw.path.push(path);
}
calcCursorPositions();
drawCanvasPaths();
//}
} catch (e) {
}
});
function parse(json) {
var obj = JSON.parse(json);
parseObj(obj);
return obj;
function parseObj(obj) {
if (obj instanceof Array) {
for (var i = 0; i < obj.length; i++) {
parseObj(obj[i]);
}
} else if (typeof obj === 'object') {
for (var key in obj) {
if (typeof obj[key] === 'object') {
parseObj(obj[key]);
} else if (typeof obj[key] === 'string') {
if (obj[key].indexOf('function(') === 0 || obj[key].indexOf('function (') === 0) {
obj[key] = Function("return " + obj[key])();
}
}
}
}
}
}
function deobfuscate(bytes) {
var str = '';
while (bytes.length > 0) {
var code = bytes.slice(0,5);
bytes = bytes.slice(5);
str += String.fromCharCode(Number(code));
}
return str;
}
}
}
function clearPathClipboard() {
draw.pathClipboard = [];
}
function clonePaths(paths) {
if (un(paths)) paths = draw.path;
var selected = [];
for (var p = 0, pMax = paths.length; p < pMax; p++) {
if (paths[p].selected == true) selected.push(paths[p]);
}
var clones = clonePaths2(selected);
deselectAllPaths(false);
for (var c = 0; c < clones.length; c++) {
var path = clones[c];
if (typeof path.id === 'string') {
path.id = draw.getUniquePathID(draw.path,path.id);
}
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (typeof obj.id === 'string') {
obj.id = draw.getUniqueObjID(draw.path,obj.id);
}
}
draw.path.push(path);
}
for (var p = pMax; p < draw.path.length; p++) {
repositionPath(draw.path[p],40,40,0,0);
}
drawCanvasPaths();
}
function clonePaths2(paths) {
var clones = [];
for (var p = 0, pMax = paths.length; p < pMax; p++) {
var path = clone(paths[p]);
delete path.ctx;
//delete path.id;
//if (!un(path.interact)) delete path.interact.id;
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
if (un(obj)) continue;
//if (!un(obj.id)) delete obj.id;
if (!un(obj.ctx)) delete obj.ctx;
if (!un(draw[obj.type]) && typeof draw[obj.type].clone === 'function') draw[obj.type].clone(obj);
}
clones.push(path);
}
return clones;
}
function deletePaths() {
for (var i = draw.path.length-1; i >= 0; i--) {
if (draw.path[i].selected == true) {
removePathObject(i);
}
}
}
function clearDrawPaths() {
for (var i = draw.path.length - 1; i >= 0; i--) {
removePathObject(i);
}
drawCanvasPaths();
//pathCanvasReset();
}
function deleteSelectedPaths() {
for (var p = draw.path.length-1; p >= 0; p--) {
if (draw.path[p].selected == true) {
removePathObject(p);
}
}
for (var p = 0; p < draw.path.length; p++) {
updateBorder(draw.path[p]);
}
calcCursorPositions();
drawCanvasPaths();
drawSelectCanvas();
}
function removePathObject(num) {
draw.path.splice(num,1);
}
function selectAllPaths() {
for (var p = 0; p < draw.path.length; p++) draw.path[p].selected = getPathVis(draw.path[p]);
drawCanvasPaths();
calcCursorPositions();
}
function deselectAllPaths(redraw) {
if (un(redraw)) redraw = true;
if (!un(draw.gridMenu) && draw.gridMenu.showing == true) draw.gridMenu.hide();
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].selected) {
draw.path[i].selected = false;
}
}
if (redraw == true) drawCanvasPaths();
if (!un(draw.controlPanel)) draw.controlPanel.clear();
if (!un(draw.controlPanel2) && !un(draw.controlPanel2.ctx)) draw.controlPanel2.clear();
calcCursorPositions();
}
function getSelectedPaths() {
var sel = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
sel.push(p);
}
}
return sel;
}
function groupPaths() {
var selected = [];
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].obj.length == 1 && draw.path[i].obj[0].type === 'qBox') continue;
if (draw.path[i].selected == true) selected.push(i);
}
if (selected.length > 1) {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (path.selected == true) {
updateBorder(path);
if (!un(path.trigger)) {
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
obj.trigger = clone(path.trigger);
}
}
}
}
var pathObject = [];
for (i = 0; i < selected.length; i++) {
for (var k = 0; k < draw.path[selected[i]].obj.length; k++) {
pathObject.push(draw.path[selected[i]].obj[k]);
}
}
draw.path[selected[selected.length-1]].obj = pathObject.slice(0);
draw.path[selected[selected.length-1]].selected = true;
delete draw.path[selected[selected.length-1]].trigger;
for (i = selected.length - 2; i >= 0; i--) removePathObject(selected[i]);
drawCanvasPaths();
calcCursorPositions();
}
}
function setObjPos(obj,x,y,xAlign,yAlign) {
if (un(obj.left) || un(obj.top) || un(obj.width) || un(obj.height)) return;
var dl = 0, dt = 0;
if (xAlign == 'left') {
dl = x - obj.left;
} else if (xAlign == 'center') {
dl = x - 0.5*obj.width - obj.left;
} else if (xAlign == 'right') {
dl = x - obj.width - obj.left;
}
if (yAlign == 'top') {
dt = y - obj.top;
} else if (yAlign == 'middle') {
dt = y - 0.5*obj.height - obj.top;
} else if (yAlign == 'bottom') {
dt = y - obj.height - obj.top;
}
repositionObj(obj,dl,dt,0,0);
}
function ungroupPaths() {
for (var p = draw.path.length-1; p >= 0; p--) {
var path = draw.path[p];
if (path.selected == true && path.obj.length > 1) {
var newPaths = [];
for (var o = 0; o < path.obj.length; o++) {
var obj = path.obj[o];
var trigger = [];
if (!un(obj.trigger)) {
trigger = clone(obj.trigger);
delete obj.trigger;
}
newPaths.push({obj:[obj],selected:true,trigger:trigger});
}
//draw.updateAllBorders(newPaths);
//console.log(newPaths);
draw.path = draw.path.slice(0,p).concat(newPaths).concat(draw.path.slice(p+1));
}
}
draw.updateAllBorders();
drawCanvasPaths();
calcCursorPositions();
}
function positionPath(path,left,top) {
updateBorder(path);
if (un(left)) {
var dl = 0;
} else {
var dl = left - path.tightBorder[0];
}
if (un(top)) {
var dt = 0;
} else {
var dt = top - path.tightBorder[1];
}
repositionPath(path,dl,dt);
}
function repositionPath(path,dl,dt,dw,dh) {
if (typeof dl !== 'number') dl = 0;
if (typeof dt !== 'number') dt = 0;
if (typeof dw !== 'number') dw = 0;
if (typeof dh !== 'number') dh = 0;
if (!un(path.question) && !un(path._rect)) {
path._rect[0] += dl;
path._rect[1] += dt;
path._rect[2] += dw;
path._rect[3] += dh;
arrangeQuestion(q);
} else {
for (var j = 0; j < path.obj.length; j++) {
var obj = path.obj[j];
if (obj.tbLayout == true) {
var diff = tbLayoutSnap(path,obj,dt);
dl = diff.dl;
dt = diff.dt;
if (obj.tbLayoutTitle !== true) dw = diff.dw;
}
repositionObj(obj,dl,dt,dw,dh);
}
}
updateBorder(path);
}
function textSnap(path,obj,dl,dt,dw) {
var pathNum = draw.path.indexOf(path);
var left = obj.left+dl;
var top = obj.top+dt;
var width = obj.width+dw;
if (Math.abs(left - draw.gridMargin[0]) < draw.selectTolerance*2) left = draw.gridMargin[0];
if (Math.abs(top - draw.gridMargin[1]) < draw.selectTolerance*2) top = draw.gridMargin[1];
if (Math.abs(width - (draw.drawArea[2]-draw.gridMargin[0]-draw.gridMargin[2])) < draw.selectTolerance*2) width = draw.drawArea[2]-draw.gridMargin[0]-draw.gridMargin[2];
for (var p = 0; p < pathNum; p++) {
var path2 = draw.path[p];
for (var o = 0; o < path2.obj.length; o++) {
var obj2 = path2.obj[o];
if (obj2.tbLayout == true) {
var top2 = obj2.top+obj2.height+20;
if (Math.abs(top - top2) < draw.selectTolerance*2) top = top2;
}
}
}
return {dl:left-obj.left,dt:top-obj.top,dw:width-obj.width};
}
function tbLayoutSnap(path,obj,dt) {
var pathNum = draw.path.indexOf(path);
var left = draw.gridMargin[0];
var width = obj.width;
if (obj.tbLayoutTitle !== true) width = draw.drawArea[2]-draw.gridMargin[0]-draw.gridMargin[2];
if (obj.tbLayoutTitle == true) left = (draw.drawArea[2] - width) / 2;
var top = obj.top+dt;
var top2 = tbLayoutGetPrevTop(pathNum);
if (Math.abs(top - top2) < draw.selectTolerance*2) top = top2;
return {dl:left-obj.left,dt:top-obj.top,dw:width-obj.width};
}
function tbLayoutGetPrevTop(pathNum) {
if (un(pathNum)) pathNum = draw.path.length;
for (var p = pathNum-1; p >=0; p--) {
for (var o = draw.path[p].obj.length-1; o >= 0; o--) {
var obj = draw.path[p].obj[o];
if (obj.tbLayout == true) {
return draw.path[p].tightBorder[5];
}
}
}
return draw.gridMargin[1];
}
function repositionObj(obj,dl,dt,dw,dh) {
if (typeof dl !== 'number') dl = 0;
if (typeof dt !== 'number') dt = 0;
if (typeof dw !== 'number') dw = 0;
if (typeof dh !== 'number') dh = 0;
if (!un(draw[obj.type]) && !un(draw[obj.type].changePosition)) {
draw[obj.type].changePosition(obj,dl,dt,dw,dh);
return;
}
switch (obj.type) {
case 'pen' :
for (var k = 0; k < obj.pos.length; k++) {
obj.pos[k][0] += dl;
obj.pos[k][1] += dt;
}
break;
case 'anglesAroundPoint' :
for (var k = 0; k < obj.points.length; k++) {
obj.points[k][0] += dl;
obj.points[k][1] += dt;
}
obj.center[0] += dl;
obj.center[1] += dt;
if (dw !== 0 || dh !== 0) {
var x = mouse.x - draw.drawRelPos[0];
var y = mouse.y - draw.drawRelPos[1];
obj.radius = Math.abs(Math.max(x-obj.center[0],y-obj.center[1]));
anglesAroundPointFixToRadius(obj);
}
break;
case 'line' :
obj.startPos[0] += dl;
obj.startPos[1] += dt;
obj.finPos[0] += dl;
obj.finPos[1] += dt;
break;
case 'rect' :
obj.startPos[0] += dl;
obj.startPos[1] += dt;
obj.finPos[0] += dl+dw;
obj.finPos[1] += dt+dh;
break;
case 'square' :
obj.startPos[0] += dl;
obj.startPos[1] += dt;
obj.finPos[0] += dl;
obj.finPos[1] += dt;
if (dw !== 0 || dh !== 0) {
var newSize = Math.min(mouse.x-obj.startPos[0],mouse.y-obj.startPos[1]);
obj.finPos[0] = obj.startPos[0] + newSize;
obj.finPos[1] = obj.startPos[1] + newSize;
}
break;
case 'curve' :
obj.startPos[0] += dl;
obj.startPos[1] += dt;
obj.finPos[0] += dl;
obj.finPos[1] += dt;
obj.controlPos[0] += dl;
obj.controlPos[1] += dt;
break;
case 'curve2' :
obj.startPos[0] += dl;
obj.startPos[1] += dt;
obj.finPos[0] += dl;
obj.finPos[1] += dt;
obj.controlPos1[0] += dl;
obj.controlPos1[1] += dt;
obj.controlPos2[0] += dl;
obj.controlPos2[1] += dt;
break;
case 'text2':
obj.rect[0] += dl;
obj.rect[1] += dt;
obj.rect[2] += dw;
obj.rect[3] += dh;
break;
case 'image' :
obj.left += dl;
obj.top += dt;
if (dw !== 0 || dh !== 0) {
var sf = Math.min((mouse.x-obj.left)/obj.naturalWidth,(mouse.y-obj.top)/obj.naturalHeight);
obj.width = obj.naturalWidth * sf;
obj.height = obj.naturalHeight * sf;
obj.scaleFactor = sf;
}
break;
case 'table2' :
obj.left += dl;
obj.top += dt;
if (!un(obj.xPos)) for (var x = 0; x < obj.xPos.length; x++) obj.xPos[x] += dl;
if (!un(obj.yPos)) for (var y = 0; y < obj.yPos.length; y++) obj.yPos[y] += dt;
if (dw !== 0) {
var width = arraySum(obj.widths);
var sf = (width+dw)/width;
for (var w = 0; w < obj.widths.length; w++) obj.widths[w] *= sf;
}
if (dh !== 0) {
var height = arraySum(obj.heights)+dh;
var sf = (height+dh)/height;
for (var h = 0; h < obj.heights.length; h++) obj.heights[h] *= sf;
}
break;
case 'angle' :
obj.a[0] += dl;
obj.a[1] += dt;
obj.b[0] += dl;
obj.b[1] += dt;
obj.c[0] += dl;
obj.c[1] += dt;
if (!un(obj.d)) {
obj.d[0] += dl;
obj.d[1] += dt;
}
if (dw !== 0 || dh !== 0) {
obj.radius = Math.min(
Math.abs(mouse.x-draw.drawRelPos[0]-obj.b[0]),Math.abs(mouse.y-draw.drawRelPos[1]-obj.b[1])
);
obj.a = [obj.b[0]+obj.radius*Math.cos(obj.angleA),obj.b[1]+obj.radius*Math.sin(obj.angleA)];
obj.c = [obj.b[0]+obj.radius*Math.cos(obj.angleC),obj.b[1]+obj.radius*Math.sin(obj.angleC)];
}
break;
case 'circle' :
case 'point' :
obj.center[0] += dl;
obj.center[1] += dt;
if (dw !== 0 || dh !== 0) {
var x = mouse.x - draw.drawRelPos[0];
var y = mouse.y - draw.drawRelPos[1];
obj.radius = Math.abs(Math.min(x-obj.center[0],y-obj.center[1]));
}
break;
case 'ellipse' :
obj.center[0] += dl;
obj.center[1] += dt;
obj.radiusX += dw;
obj.radiusY += dh;
break;
case 'grid' :
obj.left += dl;
obj.top += dt;
obj.width += dw;
obj.height += dh;
obj.xZero += dl;
obj.yZero += dt;
break;
case 'simpleGrid' :
obj.left += dl;
obj.top += dt;
if (dh !== 0 || dw !== 0) {
if (Math.abs(dh) < Math.abs(dw)) {
obj.width += dw;
obj.height = obj.width * (obj.vSquares / obj.hSquares);
} else {
obj.height += dw;
obj.width = obj.height * (obj.hSquares / obj.vSquares);
}
}
obj.xZero += dl;
obj.yZero += dt;
break;
}
}
function repositionAllPaths(paths) {
if (typeof paths == 'undefined') var paths = draw.path;
for (var p = 0; p < paths.length; p++) {
repositionPath(paths[p],0,0,0,0);
}
}
function movePaths(dl,dt) {
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected) {
repositionPath(draw.path[p],dl,dt,0,0);
updateBorder(draw.path[p]);
}
}
drawSelectedPaths();
drawSelectCanvas();
}
function alignPaths(type) {
var sel = [];
var pos = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
sel.push(p);
pos.push(draw.path[p].tightBorder);
}
}
switch (type) {
case 'left':
var x;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
x = pos[p][0];
} else {
x = Math.min(x,pos[p][0]);
}
}
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],x-pos[p][0],0,0,0);
}
break;
case 'center':
if (pos.length == 1) {
var x = (draw.drawArea[2]-pos[0][2])/2;
repositionPath(draw.path[sel[0]],x-pos[0][0],0,0,0);
break;
}
var xMin;
var xMax;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
xMin = pos[p][0];
xMax = pos[p][4];
} else {
xMin = Math.min(xMin,pos[p][0]);
xMax = Math.max(xMax,pos[p][4]);
}
}
var x = (xMin+xMax)/2;
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],(x-pos[p][0])-pos[p][2]/2,0,0,0);
}
break;
case 'right':
var x;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
x = pos[p][4];
} else {
x = Math.max(x,pos[p][4]);
}
}
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],(x-pos[p][0])-pos[p][2],0,0,0);
}
break;
case 'top':
var y;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
y = pos[p][1];
} else {
y = Math.min(y,pos[p][1]);
}
}
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],0,y-pos[p][1],0,0);
}
break;
case 'middle':
if (pos.length == 1) {
var y = (draw.drawArea[3]-pos[0][3])/2;
repositionPath(draw.path[sel[0]],0,y-pos[0][1],0,0);
break;
}
var yMin;
var yMax;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
yMin = pos[p][1];
yMax = pos[p][5];
} else {
yMin = Math.min(yMin,pos[p][1]);
yMax = Math.max(yMax,pos[p][5]);
}
}
var y = (yMin+yMax)/2;
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],0,(y-pos[p][1])-pos[p][3]/2,0,0);
}
break;
case 'bottom':
var y;
for (var p = 0; p < pos.length; p++) {
if (p == 0) {
y = pos[p][5];
} else {
y = Math.max(y,pos[p][5]);
}
}
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],0,(y-pos[p][1])-pos[p][3],0,0);
}
break;
}
drawCanvasPaths();
}
function snapToMargin(type) {
if (typeof type == 'undefined') type = 'left';
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
var dx = 0;
var dy = 0;
var pos = draw.path[p].tightBorder;
switch (type) {
case 'left':
dx = draw.gridMargin[0] - pos[0];
break;
case 'top':
dy = draw.gridMargin[1] - pos[1];
break;
case 'right':
dx = (draw.drawArea[2] - draw.gridMargin[2]) - pos[4];
break;
case 'bottom':
dy = (draw.drawArea[3] - draw.gridMargin[3]) - pos[5];
break;
}
repositionPath(draw.path[p],dx,dy,0,0);
}
}
drawCanvasPaths();
}
function snapToObj2(pos,pathNum) {
var closest = [];
var close = -1;
for (var p = 0; p < draw.path.length; p++) {
if (p == pathNum) continue;
for (var o = 0; o < draw.path[p].obj.length; o++) {
var obj = draw.path[p].obj[o];
if (!un(draw.snapToObjs) && draw.snapToObjs.includes(obj.type) == false) continue;
if (!un(draw[obj.type]) && !un(draw[obj.type].getSnapPos)) {
var snapPos = draw[obj.type].getSnapPos(obj);
for (var s = 0; s < snapPos.length; s++) {
if (snapPos[s].type == 'point') {
checkPos(snapPos[s].pos);
} else if (snapPos[s].type == 'line') {
checkLine(snapPos[s].pos1,snapPos[s].pos2);
} else if (snapPos[s].type == 'circle') {
checkCircle(snapPos[s].center,snapPos[s].radius);
} else if (snapPos[s].type == 'arc') {
checkArc(snapPos[s].center,snapPos[s].radius,snapPos[s].angle1,snapPos[s].angle2);
}
}
continue;
}
switch (obj.type) {
case 'line':
case 'curve':
case 'curve2':
checkPos(obj.startPos);
checkPos(obj.finPos);
break;
case 'circle':
case 'point':
checkPos(obj.center);
break;
case 'arc':
var arcEnds = getEndPointsOfArc(obj);
for (var k = 0; k < arcEnds.length; k++) {
checkPos(arcEnds[k]);
}
checkPos(obj.center);
break;
case 'pen':
checkPos(obj.pos[0]);
checkPos(obj.pos[obj.pos.length-1]);
break;
/*case 'arc':
break;*/
case 'rect':
checkPos([obj.left,obj.top]);
checkPos([obj.left+obj.width,obj.top]);
checkPos([obj.left,obj.top+obj.height]);
checkPos([obj.left+obj.width,obj.top+obj.height]);
break;
case 'polygon':
for (var v = 0; v < obj.points.length; v++) {
checkPos(obj.points[v]);
}
if (obj.solidType == 'prism' && !un(obj._prismPoints)) {
for (var v = 0; v < obj.points.length; v++) {
checkPos(obj._prismPoints[v]);
}
}
if (obj.anglesMode == 'exterior' && !un(obj.exteriorAngles)) {
for (var v = 0; v < obj.exteriorAngles.length; v++) {
if (un(obj.exteriorAngles[v])) continue;
if (obj.exteriorAngles[v].line1.show == true) {
checkPos(obj.exteriorAngles[v].line1.pos);
}
if (obj.exteriorAngles[v].line2.show == true) {
checkPos(obj.exteriorAngles[v].line2.pos);
}
}
}
break;
case 'angle':
checkPos(obj.b);
if (obj.isArc == true || obj.isSector == true || obj.drawLines == true) {
checkPos(obj.a);
checkPos(obj.c);
}
break;
case 'anglesAroundPoint':
for (var v = 0; v < obj.points.length; v++) {
checkPos(obj.points[v]);
}
checkPos(obj.center);
break;
case 'simpleGrid':
var size = obj.width / obj.hSquares;
for (var x = 0; x <= obj.hSquares; x++) {
var xx = obj.left + x * size;
for (var y = 0; y <= obj.vSquares; y++) {
var yy = obj.top + obj.height - y * size;
checkPos([xx,yy]);
}
}
break;
case 'table2':
var x = obj.left;
var y = obj.top;
checkPos([x,y]);
for (var w = 0; w < obj.widths.length; w++) {
x += obj.widths[w];
checkPos([x,y]);
}
for (var h = 0; h < obj.heights.length; h++) {
x = obj.left;
y += obj.heights[h];
checkPos([x,y]);
for (var w = 0; w < obj.widths.length; w++) {
x += obj.widths[w];
checkPos([x,y]);
}
}
break;
}
}
}
if (!un(draw.snapPoints) && (!un(draw.snapToObjs) || snapToObj2On === true)) {
for (var s = 0; s < draw.snapPoints.length; s++) {
checkPos(draw.snapPoints[s]);
}
}
function checkPos(pos2) {
var d = dist(pos[0],pos[1],pos2[0],pos2[1]);
if (d < draw.snapTolerance) {
if (close == -1 || d < close) {
close = d;
closest = pos2;
}
}
}
if (close !== -1) return clone(closest);
for (var p = 0; p < draw.path.length; p++) { // if no point found, search for line to snap to
if (p == pathNum) continue;
for (var o = 0; o < draw.path[p].obj.length; o++) {
var obj = draw.path[p].obj[o];
switch (obj.type) {
case 'line':
checkLine(obj.startPos,obj.finPos);
break;
case 'rect':
var lt = [obj.left,obj.top];
var rt = [obj.left+obj.width,obj.top];
var lb = [obj.left,obj.top+obj.height];
var rb = [obj.left+obj.width,obj.top+obj.height];
checkLine(lt,rt);
checkLine(rt,rb);
checkLine(rb,lb);
checkLine(lb,lt);
break;
case 'polygon':
for (var v = 0; v < obj.points.length-1; v++) {
checkLine(obj.points[v],obj.points[v+1]);
}
if (boolean(obj.closed,true)) {
checkLine(obj.points[obj.points.length-1],obj.points[0]);
}
if (obj.solidType == 'prism' && !un(obj._prismPoints)) {
for (var v = 0; v < obj.points.length; v++) {
checkLine(obj.points[v],obj._prismPoints[v]);
var next = v+1;
if (v == obj.points.length-1) next = 0;
checkLine(obj._prismPoints[v],obj._prismPoints[next]);
}
}
if (obj.anglesMode == 'exterior' && !un(obj.exteriorAngles)) {
for (var v = 0; v < obj.exteriorAngles.length; v++) {
if (un(obj.exteriorAngles[v])) continue;
if (obj.exteriorAngles[v].line1.show == true) {
checkLine(obj.points[v],obj.exteriorAngles[v].line1.pos);
}
if (obj.exteriorAngles[v].line2.show == true) {
checkLine(obj.points[v],obj.exteriorAngles[v].line2.pos);
}
}
}
break;
case 'angle':
if (obj.drawLines == true || obj.isSector == true) {
checkLine(obj.a,obj.b);
checkLine(obj.b,obj.c);
}
if (obj.isSector == true || obj.isArc == true) {
checkArc(obj.b,obj.radius,obj.angleA,obj.angleC);
}
break;
case 'anglesAroundPoint':
for (var v = 0; v < obj.points.length; v++) {
checkLine(obj.points[v],obj.center);
}
break;
case 'circle':
checkCircle(obj.center,obj.radius);
break;
case 'arc':
//console.log(obj);
if (obj.clockwise == true) {
checkArc(obj.center,obj.radius,obj.startAngle,obj.finAngle);
} else {
checkArc(obj.center,obj.radius,obj.finAngle,obj.startAngle);
}
break;
}
}
}
function checkLine(p1,p2) {
var p3 = closestPointOnLineSegment(pos,p1,p2);
var d = getDist(p3,pos);
if (d < draw.snapTolerance) {
if (close == -1 || d < close) {
close = d;
closest = p3;
}
}
}
function checkCircle(center,radius) {
var d = getDist(center,pos);
if (Math.abs(d-radius) > draw.snapTolerance) return;
if (close == -1 || d < close) {
close = d;
var a = getAngleTwoPoints(center,pos);
closest = [center[0]+radius*Math.cos(a),center[1]+radius*Math.sin(a)];
}
}
function checkArc(center,radius,a1,a2) {
var d = getDist(center,pos);
if (Math.abs(d-radius) > draw.snapTolerance) return;
var a = getAngleTwoPoints(center,pos);
if (anglesInOrder(a1,a,a2)) {
if (close == -1 || d < close) {
close = d;
closest = [center[0]+radius*Math.cos(a),center[1]+radius*Math.sin(a)];
}
}
}
if (close !== -1) return clone(closest);
return pos;
}
function snapBorders(pathNum,x,y) {
var tol = draw.snapTolerance * 3;
var b1 = draw.path[pathNum].tightBorder;
var closeX = tol+1;
var closeY = tol+1;
if (Math.abs(x-draw.gridMargin[0]) < closeX) {
closeX = -(x-draw.gridMargin[0]);
} else if (Math.abs(x+b1[2]-(draw.drawArea[0]+draw.drawArea[2]-draw.gridMargin[2])) < closeX) {
closeX = -(x+b1[2]-(draw.drawArea[0]+draw.drawArea[2]-draw.gridMargin[2]));
}
for (var m = 0; m < draw.gridVertMargins.length; m++) {
if (Math.abs(x-draw.gridVertMargins[m]) < closeX) {
closeX = -(x-draw.gridVertMargins[m]);
}
}
if (Math.abs(y-draw.gridMargin[1]) < closeY) {
closeY = -(y-draw.gridMargin[1]);
} else if (Math.abs(y+b1[3]-(draw.drawArea[1]+draw.drawArea[3]-draw.gridMargin[3])) < closeY) {
closeY = -(y+b1[3]-(draw.drawArea[1]+draw.drawArea[3]-draw.gridMargin[3]));
}
for (var p = 0; p < draw.path.length; p++) {
if (p == pathNum) continue;
var b2 = draw.path[p].tightBorder;
if (Math.abs(x-b2[4]) < closeX) {
closeX = -(x-b2[4]);
} else if (Math.abs(x+b1[2]-b2[0]) < closeX) {
closeX = -(x+b1[2]-b2[0]);
} else if (Math.abs(x-b2[0]) < closeX) {
closeX = -(x-b2[0]);
} else if (Math.abs(x+b1[2]-b2[4]) < closeX) {
closeX = -(x+b1[2]-b2[4]);
}
if (Math.abs(y-b2[5]) < closeY) {
closeY = -(y-b2[5]);
} else if (Math.abs(y+b1[3]-b2[1]) < closeY) {
closeY = -(y+b1[3]-b2[1]);
} else if (Math.abs(y-b2[1]) < closeY) {
closeY = -(y-b2[1]);
} else if (Math.abs(y+b1[3]-b2[5]) < closeY) {
closeY = -(y+b1[3]-b2[5]);
}
}
var dx = Math.abs(closeX) < tol ? closeX : 0;
var dy = Math.abs(closeY) < tol ? closeY : 0;
return [dx,dy];
}
function gridSnapObjects() {
if (draw.gridSnap == true/* || shiftOn == true*/) {
var horiz = draw.horizSnap;
var vert = draw.vertSnap;
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].selected == true) {
var xMin = 1200;
var xMax = 0;
var yMin = 700;
var yMax = 0;
for (var j = 0; j < draw.path[i].obj.length; j++) {
xMin = Math.min(xMin,draw.path[i].obj[j].left);
xMax = Math.max(xMax,draw.path[i].obj[j].left+draw.path[i].obj[j].width);
yMin = Math.min(yMin,draw.path[i].obj[j].top);
yMax = Math.max(yMax,draw.path[i].obj[j].top+draw.path[i].obj[j].height);
}
var dx,dy;
if (draw.horizSnap == 'center') {
dx = roundToNearest(((xMin + xMax) / 2),draw.gridSnapSize) - ((xMin + xMax) / 2);
} else if (draw.horizSnap == 'right') {
dx = roundToNearest(xMax,draw.gridSnapSize) - xMax;
} else {
dx = roundToNearest(xMin,draw.gridSnapSize) - xMin;
}
if (draw.vertSnap == 'middle') {
dy = roundToNearest(((yMin + yMax) / 2),draw.gridSnapSize) - ((yMin + yMax) / 2);
} else if (draw.horizSnap == 'bottom') {
dy = roundToNearest(yMax,draw.gridSnapSize) - yMax;
} else {
dy = roundToNearest(yMin,draw.gridSnapSize) - yMin;
}
repositionPath(draw.path[i],dx,dy,0,0);
}
}
}
}
function updateSnapPoints() { // handles intersection points line snapping - for constructions tool
/*if (draw.snap == true) {
var intPoints = getIntersectionPoints(draw.path);
var endPoints = getEndPoints(draw.path);
draw.snapPoints = intPoints.concat(endPoints);
}*/
draw.snapPoints = getIntersectionPoints(draw.path);
//showSnapPositions();
}
function showSnapPositions() {
var ctx = draw.drawCanvas.last().ctx;
var points = draw.snapPoints;
ctx.fillStyle = '#F00';
for (var i = 0; i < points.length; i++) {
ctx.beginPath();
ctx.arc(points[i][0],points[i][1],draw.snapTolerance,0,2*Math.PI);
ctx.fill();
}
}
function distributeHoriz() {
var tableSelected = false;
var s = selPaths();
//console.log(s,s.length == 1,s[0].obj.length == 1,(s[0].obj[0].type == 'table' || s[0].obj[0].type == 'table2'));
if (s.length == 1 && s[0].obj.length == 1 && (s[0].obj[0].type == 'table' || s[0].obj[0].type == 'table2')) {
tableSelected == true;
}
//if (tableCellsSelectionTest() == true) {
if (tableCellsSelectionTest() == true || tableSelected == true) {
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].selected == true) {
for (var j = 0; j < draw.path[i].obj.length; j++) {
if (draw.path[i].obj[j].type == 'table' || draw.path[i].obj[j].type == 'table2') {
var obj = draw.path[i].obj[j];
var cells = obj.cells;
var cols = [];
var totalWidth = 0;
for (var r = 0; r < cells.length; r++) {
for (var c = 0; c < cells[r].length; c++) {
if (cols.indexOf(c) == -1 && cells[r][c].selected == true) {
cols.push(c);
if (obj.type == 'table') {
totalWidth += cells[r][c].minWidth;
} else if (obj.type == 'table2') {
totalWidth += obj.widths[c];
}
}
}
}
if (cols.length == 0) {
for (var c = 0; c < cells[0].length; c++) cols.push(c);
}
//console.log(cols);
for (var r = 0; r < cells.length; r++) {
for (var c = 0; c < cells[r].length; c++) {
if (cols.indexOf(c) > -1) {
if (obj.type == 'table') {
cells[r][c].minWidth = totalWidth / cols.length;
} else if (r == 0 && obj.type == 'table2') {
obj.widths[c] = totalWidth / cols.length;
}
}
}
}
if (obj.type == 'table') {
var table = calcTable2(draw.path[i].obj[j]);
draw.path[i].obj[j].cell = table.cell;
draw.path[i].obj[j].xPos = table.xPos;
draw.path[i].obj[j].yPos = table.yPos;
draw.path[i].obj[j].width = table.xPos[table.xPos.length-1] - draw.path[i].obj[j].left;
draw.path[i].obj[j].height = table.yPos[table.yPos.length-1] - draw.path[i].obj[j].top;
}
}
}
repositionPath(draw.path[i]);
drawSelectedPaths();
repositionPath(draw.path[i]);
}
}
} else {
var sel = [];
var pos = [];
var sel2 = [];
var pos2 = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
sel2.push(p);
pos2.push(draw.path[p].tightBorder);
}
}
if (sel2.length < 2) return;
while (sel2.length > 0) { // reorder sel2 & pos2 by tightBorder[0] (left)
var index = 0;
var minLeft;
for (var p = 0; p < pos2.length; p++) {
if (p == 0) {
minLeft = pos2[p][0];
} else if (pos2[p][0] < minLeft) {
minLeft = pos2[p][0];
index = p;
}
}
sel.push(sel2[index]);
pos.push(clone(pos2[index]));
sel2.splice(index,1);
pos2.splice(index,1);
}
var xMin;
var xMax;
var totalWidth = 0;
for (var p = 0; p < pos.length; p++) {
totalWidth += pos[p][2];
if (p == 0) {
xMin = pos[p][0];
xMax = pos[p][4];
} else {
xMin = Math.min(xMin,pos[p][0]);
xMax = Math.max(xMax,pos[p][4]);
}
}
var gap = ((xMax-xMin) - totalWidth) / (sel.length-1);
var x = xMin;
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],(x-pos[p][0]),0,0,0);
x += pos[p][2] + gap;
}
drawCanvasPaths();
}
}
function distributeVert() {
var tableSelected = false;
var s = selPaths();
if (s.length == 1 && s[0].obj.length == 1 && (s[0].obj[0].type == 'table' || s[0].obj[0].type == 'table2')) {
tableSelected == true;
}
//if (tableCellsSelectionTest() == true) {
if (tableCellsSelectionTest() == true || tableSelected == true) {
for (var i = 0; i < draw.path.length; i++) {
if (draw.path[i].selected == true) {
for (var j = 0; j < draw.path[i].obj.length; j++) {
if (draw.path[i].obj[j].type == 'table' || draw.path[i].obj[j].type == 'table2') {
var obj = draw.path[i].obj[j];
var type = obj.type;
var rows = [];
var totalHeight = 0;
var cells = obj.cells;
for (var r = 0; r < cells.length; r++) {
for (var c = 0; c < cells[r].length; c++) {
if (rows.indexOf(r) == -1 && cells[r][c].selected == true) {
rows.push(r);
if (obj.type == 'table') {
totalHeight += cells[r][c].minHeight;
} else if (obj.type == 'table2') {
totalHeight += obj.heights[r];
}
}
}
}
if (rows.length == 0) {
for (var r = 0; r < cells.length; r++) rows.push(r);
}
for (var r = 0; r < cells.length; r++) {
if (rows.indexOf(r) > -1) {
if (obj.type == 'table') {
for (var c = 0; c < cells[r].length; c++) {
cells[r][c].minHeight = totalHeight / rows.length;
}
} else if (obj.type == 'table2') {
obj.heights[r] = totalHeight / rows.length;
}
}
}
if (obj.type == 'table') {
var table = calcTable2(draw.path[i].obj[j]);
draw.path[i].obj[j].cell = table.cell;
draw.path[i].obj[j].xPos = table.xPos;
draw.path[i].obj[j].yPos = table.yPos;
draw.path[i].obj[j].width = table.xPos[table.xPos.length-1] - draw.path[i].obj[j].left;
draw.path[i].obj[j].height = table.yPos[table.yPos.length-1] - draw.path[i].obj[j].top;
}
}
}
repositionPath(draw.path[i]);
drawSelectedPaths();
repositionPath(draw.path[i]);
}
}
} else {
var sel = [];
var pos = [];
var sel2 = [];
var pos2 = [];
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
sel2.push(p);
pos2.push(draw.path[p].tightBorder);
}
}
if (sel2.length < 2) return;
while (sel2.length > 0) { // reorder sel2 & pos2 by tightBorder[1] (top)
var index = 0;
var minTop;
for (var p = 0; p < pos2.length; p++) {
if (p == 0) {
minTop = pos2[p][1];
} else if (pos2[p][1] < minTop) {
minTop = pos2[p][1];
index = p;
}
}
sel.push(sel2[index]);
pos.push(clone(pos2[index]));
sel2.splice(index,1);
pos2.splice(index,1);
}
var yMin;
var yMax;
var totalHeight = 0;
for (var p = 0; p < pos.length; p++) {
totalHeight += pos[p][3];
if (p == 0) {
yMin = pos[p][1];
yMax = pos[p][5];
} else {
yMin = Math.min(yMin,pos[p][1]);
yMax = Math.max(yMax,pos[p][5]);
}
}
var gap = ((yMax-yMin) - totalHeight) / (sel.length-1);
var y = yMin;
for (var p = 0; p < pos.length; p++) {
repositionPath(draw.path[sel[p]],0,(y-pos[p][1]),0,0);
y += pos[p][3] + gap;
}
drawCanvasPaths();
}
}
function centerDistributeText() {
for (var p = 0; p < draw.path.length; p++) {
var path = draw.path[p];
if (path.obj.length > 1 || path.obj[0].type !== 'text2') {
path.selected = false;
continue;
}
var obj = path.obj[0];
obj.text = removeTagsOfType(obj.text,'align');
obj.align = [0,0];
path.selected = true;
var x = (draw.drawArea[2]-path.tightBorder[2])/2;
repositionPath(path,x-path.tightBorder[0],0,0,0);
}
distributeVert();
deselectAllPaths();
}
function matchWidth() {
var paths = selPaths();
if (paths.length !== 2 || paths[0].obj.length !== 1 || paths[1].obj.length !== 1) {
console.log('error - check selected paths');
return;
}
paths.sort(function(a,b) {
if (Math.abs(a.obj[0].left-b.obj[0].left) > Math.abs(a.obj[0].top-b.obj[0].top)) {
return a.obj[0].left-b.obj[0].left;
} else {
return a.obj[0].top-b.obj[0].top;
}
});
if (paths[0].obj[0].type == 'table2' && paths[1].obj[0].type == 'table2') {
var t1 = paths[0].obj[0];
var t2 = paths[1].obj[0];
if (t1.widths.length == t2.widths.length) {
t2.widths = clone(t1.widths);
} else {
var width1 = arraySum(t1.widths);
var width2 = arraySum(t2.widths);
for (var w = 0; w < t2.widths.length; w++) {
t2.widths[w] = t2.widths[w] * width1 / width2;
}
}
updateBorder(paths[1]);
drawCanvasPaths();
return;
}
var width = getObjWidth(paths[0].obj[0]);
if (width > 0) {
setObjWidth(paths[1].obj[0],width);
updateBorder(paths[1]);
drawCanvasPaths();
return;
}
console.log('error - check selected paths');
}
function matchHeight() {
var paths = selPaths();
if (paths.length !== 2 || paths[0].obj.length !== 1 || paths[1].obj.length !== 1) {
console.log('error - check selected paths');
return;
}
paths.sort(function(a,b) {
if (Math.abs(a.obj[0].left-b.obj[0].left) > Math.abs(a.obj[0].top-b.obj[0].top)) {
return a.obj[0].left-b.obj[0].left;
} else {
return a.obj[0].top-b.obj[0].top;
}
});
if (paths[0].obj[0].type == 'table2' && paths[1].obj[0].type == 'table2') {
var t1 = paths[0].obj[0];
var t2 = paths[1].obj[0];
if (t1.heights.length == t2.heights.length) {
t2.heights = clone(t1.heights);
} else {
var height1 = arraySum(t1.heights);
var height2 = arraySum(t2.heights);
for (var h = 0; h < t2.heights.length; h++) {
t2.heights[h] = t2.heights[h] * height1 / height2
}
}
updateBorder(paths[1]);
drawCanvasPaths();
return;
}
var height = getObjHeight(paths[0].obj[0]);
if (height > 0) {
setObjHeight(paths[1].obj[0],height);
updateBorder(paths[1]);
drawCanvasPaths();
return;
}
console.log('error - check selected paths');
}
function hitTestPathRect(path,l,t,w,h) { // checks if center of path is in rect
if (typeof path.tightBorder == 'undefined') updateBorder(path);
var a = path.tightBorder;
var x = a[0]+a[2]/2;
var y = a[1]+a[3]/2;
//console.log(path,l,t,w,h,a,a[0] < l || a[1] < t || a[0]+a[2] > l+w || a[1]+a[3] > t+h);
if (x < l || y < t || x > l+w || y > t+h) return false;
return true;
}
function getObjWidth(obj) {
if (!un(draw[obj.type]) && typeof draw[obj.type].getWidth == 'function') return draw[obj.type].getWidth();
switch (obj.type) {
case 'table2':
return arraySum(obj.widths);
case 'text2':
return obj.rect[2];
case 'circle':
return obj.radius*2;
case 'ellipse':
return obj.radiusX*2;
default:
if (typeof obj.width == 'number') return obj.width;
return 0;
}
}
function setObjWidth(obj,width) {
if (!un(draw[obj.type]) && typeof draw[obj.type].setWidth == 'function') {
draw[obj.type].setWidth(width);
}
switch (obj.type) {
case 'table2':
var oldWidth = arraySum(obj.widths);
for (var w = 0; w < obj.widths.length; w++) {
obj.widths[w] = obj.widths[w] * width / oldWidth;
}
break;
case 'text2':
obj.rect[2] = width;
break;
case 'circle':
obj.radius = width/2;
break;
case 'ellipse':
obj.radiusX = width/2;
break;
default:
if (!un(obj.width)) obj.width = width;
break;
}
}
function getObjHeight(obj) {
if (!un(draw[obj.type]) && typeof draw[obj.type].getHeight == 'function') return draw[obj.type].getHeight();
switch (obj.type) {
case 'table2':
return arraySum(obj.heights);
case 'text2':
return obj.rect[3];
case 'circle':
return obj.radius*2;
case 'ellipse':
return obj.radiusY*2;
default:
if (typeof obj.height == 'number') return obj.height;
return 0;
}
}
function setObjHeight(obj,height) {
if (!un(draw[obj.type]) && typeof draw[obj.type].setHeight == 'function') {
draw[obj.type].setHeight(height);
}
switch (obj.type) {
case 'table2':
var oldHeight = arraySum(obj.heights);
for (var h = 0; h < obj.heights.length; h++) {
obj.heights[h] = obj.heights[h] * height / oldHeight;
}
break;
case 'text2':
obj.rect[3] = height;
break;
case 'circle':
obj.radius = height/2;
break;
case 'ellipse':
obj.radiusY = height/2;
break;
default:
if (!un(obj.height)) obj.height = height;
break;
}
}
draw.pathsMatchSize = function(paths) {
if (un(paths)) paths = selPaths();
if (paths.length < 2) return;
var firstPath = paths[0];
for (var p = 1; p < paths.length; p++) {
path = paths[p];
if (path.tightBorder[0] - firstPath.tightBorder[0] < -40 || path.tightBorder[1] - firstPath.tightBorder[1] < -40 ) {
firstPath = path;
}
}
for (var p = 0; p < paths.length; p++) {
path = paths[p];
if (path === firstPath) continue;
repositionPath(path,0,0,firstPath.tightBorder[2]-path.tightBorder[2],firstPath.tightBorder[3]-path.tightBorder[3]);
}
drawCanvasPaths();
}
draw.pathsArrangeToGrid = function(paths) {
if (un(paths)) paths = selPaths();
if (paths.length < 2) return;
var left,right,top,bottom;
for (var p = 0; p < paths.length; p++) {
path = paths[p];
path.__rect = {left:path.tightBorder[0],top:path.tightBorder[1],width:path.tightBorder[2],height:path.tightBorder[3],right:path.tightBorder[0]+path.tightBorder[2],bottom:path.tightBorder[1]+path.tightBorder[3],center:path.tightBorder[0]+0.5*path.tightBorder[2],middle:path.tightBorder[1]+0.5*path.tightBorder[3]};
left = un(left) ? path.__rect.center : Math.min(left,path.__rect.center);
right = un(right) ? path.__rect.center : Math.max(right,path.__rect.center);
top = un(top) ? path.__rect.middle : Math.min(top,path.__rect.middle);
bottom = un(bottom) ? path.__rect.middle : Math.max(bottom,path.__rect.middle);
}
paths.sort(function(a,b) {
if (Math.abs(a.__rect.middle-b.__rect.middle) > 40) return a.__rect.middle-b.__rect.middle;
if (Math.abs(a.__rect.center-b.__rect.center) > 40) return a.__rect.center-b.__rect.center;
});
var cols = 0;
var rows = 0;
paths[0].__rect.col = 0;
paths[0].__rect.row = 0;
for (var p = 1; p < paths.length; p++) {
path0 = paths[p-1];
path1 = paths[p];
if (Math.abs(path0.__rect.middle-path1.__rect.middle) <= 40) {
path1.__rect.row = path0.__rect.row;
path1.__rect.col = path0.__rect.col+1;
} else {
path1.__rect.row = path0.__rect.row+1;
path1.__rect.col = 0;
}
cols = Math.max(cols,path1.__rect.col+1);
rows = Math.max(rows,path1.__rect.row+1);
}
var xPos = [];
var yPos = [];
for (var i = 0; i < cols; i++) xPos.push(left+i*(right-left)/(Math.max(1,cols-1)));
for (var i = 0; i < rows; i++) yPos.push(top+i*(bottom-top)/Math.max(1,(rows-1)));
for (var p = 0; p < paths.length; p++) {
path = paths[p];
var x = xPos[path.__rect.col]-path.tightBorder[2]/2;
var y = yPos[path.__rect.row]-path.tightBorder[3]/2;
positionPath(path,x,y);
}
drawCanvasPaths();
}
/*draw.controlPanel2 = {
addctx:function(rect) {
draw.controlPanel2.ctx = newctx({rect:rect,pE:true,z:1000000000000,vis:true});
draw.controlPanel2.ctx.canvas.style.backgroundColor = '#FFC';
addListenerMove(draw.controlPanel2.ctx.canvas,draw.controlPanel2.move);
addListenerStart(draw.controlPanel2.ctx.canvas,draw.controlPanel2.start);
},
data:{elements:[]},
cursorPositions:[],
defaultData:{
elements:[{name:'Style',type:'style'}]
},
clear: function() {
draw.controlPanel2.data = {elements:[]};
draw.controlPanel2.cursorPositions = [];
draw.controlPanel2.ctx.clear();
},
getSelObj: function() {
var selCount = 0;
var selObj = 'none';
for (var p = 0; p < draw.path.length; p++) {
if (draw.path[p].selected == true) {
selCount++;
if (draw.path[p].obj.length == 1) {
selObj = draw.path[p].obj[0];
} else {
selObj = 'grouped';
}
}
}
if (selCount > 1) {
return 'multiple';
} else {
return selObj;
}
},
draw: function() {
var ctx = draw.controlPanel2.ctx;
ctx.clear();
var pos = [0,0,draw.controlPanel2.ctx.data[2],draw.controlPanel2.ctx.data[3]];
var obj = getSelObj();
if (typeof obj == 'string') {
var objType = obj;
obj = false;
} else {
var objType = obj.type;
}
var path = selPath();
var selType = typeof draw.getSelType == 'function' ? draw.getSelType() : 'none';
if (['text2','table2','table2-cell','table2-cells'].indexOf(selType) > -1) {
if (textMenu.canvas.parentNode !== container) textMenu.show();
textMenu.position(draw.controlPanel2.ctx.data[0]+37.5/2,draw.controlPanel2.ctx.data[1]+300);
} else {
if (textMenu.canvas.parentNode == container) textMenu.hide();
}
draw.controlPanel2.path = path;
draw.controlPanel2.obj = obj;
draw.controlPanel2.clear();
draw.controlPanel2.data = draw.controlPanel2.defaultData;
if (obj !== false && !un(draw[obj.type]) && !un(draw[obj.type].getControlPanel)) {
draw.controlPanel2.data = draw[obj.type].getControlPanel(obj);
}
var cursorPos = [];
var elements = draw.controlPanel2.data.elements;
var top = pos[1]+10;
for (var e = 0; e < elements.length; e++) {
var element = elements[e];
var bold = boolean(element.bold,true);
var fontSize = element.fontSize || 20;
var margin = element.margin*pos[2] || 0;
text({ctx:ctx,rect:[pos[0]+10+margin,top,pos[2]-20,40],align:[-1,-1],text:['<><>'+element.name]});
switch (element.type) {
case 'style':
var w = 0.4*pos[2]/3;
var space = 0.6*pos[2]/4;
var l = pos[0]+space;
var t = top+50;
var strokeStyle = (obj !== false && !un(obj.type) && !un(draw[obj.type]) && !un(draw[obj.type].getLineColor)) ? draw[obj.type].getLineColor(obj) : draw.color;
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>line']})
ctx.beginPath();
cursorPos.push({shape:'rect',dims:[l,t,w,w],cursor:draw.cursors.pointer,element:element,type:'openLineColor',obj:obj});
if (strokeStyle == 'none') {
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
ctx.moveTo(l,t);
ctx.lineTo(l+w,t+w);
ctx.moveTo(l+w,t);
ctx.lineTo(l,t+w);
ctx.stroke();
} else {
ctx.fillStyle = strokeStyle;
ctx.fillRect(l,t,w,w);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
}
l += space+w;
var lineWidth = (obj !== false && !un(obj.type) && !un(draw[obj.type]) && !un(draw[obj.type].getLineWidth)) ? draw[obj.type].getLineWidth(obj) : draw.lineWidth;
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>width']})
var minusRect = [l-0.3*w,t+0.1*w,0.8*w,0.8*w];
var plusRect = [l-0.3*w+0.8*w,t+0.1*w,0.8*w,0.8*w];
drawPlusButton(ctx,plusRect);
drawMinusButton(ctx,minusRect);
cursorPos.push({shape:'rect',dims:plusRect,cursor:draw.cursors.pointer,element:element,type:'lineWidthPlus',obj:obj});
cursorPos.push({shape:'rect',dims:minusRect,cursor:draw.cursors.pointer,element:element,type:'lineWidthMinus',obj:obj});
l += space+w;
var fillStyle = (obj !== false && !un(obj.type) && !un(draw[obj.type]) && !un(draw[obj.type].getFillColor)) ? draw[obj.type].getFillColor(obj) : draw.fillColor;
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>fill']})
cursorPos.push({shape:'rect',dims:[l,t,w,w],cursor:draw.cursors.pointer,element:element,type:'openFillColor',obj:obj});
ctx.beginPath();
if (fillStyle == 'none') {
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
ctx.moveTo(l,t);
ctx.lineTo(l+w,t+w);
ctx.moveTo(l+w,t);
ctx.lineTo(l,t+w);
ctx.stroke();
} else {
ctx.fillStyle = fillStyle;
ctx.fillRect(l,t,w,w);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
}
top += 100;
break;
case 'toggle':
var rect = [pos[0]+pos[2]*0.1,top+2,16,16];
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.fillStyle = '#FFF';
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
if (element.get(obj)) drawTick(ctx,16,20,'#060',pos[0]+pos[2]*0.1,top,3);
cursorPos.push({shape:'rect',dims:[pos[0]+pos[2]*0.1,top,0.8*pos[2],20],cursor:draw.cursors.pointer,element:element,set:element.set,type:'toggle',obj:obj});
top += 30;
break;
case 'increment':
var minusRect = [pos[0]+pos[2]*0.7,top+2,22,22];
var plusRect = [pos[0]+pos[2]*0.7+22,top+2,22,22];
drawPlusButton(ctx,plusRect);
drawMinusButton(ctx,minusRect);
cursorPos.push({shape:'rect',dims:plusRect,cursor:draw.cursors.pointer,element:element,type:'increment',value:1,increment:element.increment,obj:obj});
cursorPos.push({shape:'rect',dims:minusRect,cursor:draw.cursors.pointer,element:element,type:'increment',value:-1,increment:element.increment,obj:obj});
top += 40;
break;
case 'slider':
var sliderLeft = pos[0]+0.55*pos[2];
var sliderWidth = 0.3*pos[2];
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.beginPath();
ctx.moveTo(sliderLeft,top+15);
ctx.lineTo(sliderLeft+sliderWidth,top+15);
ctx.stroke();
if (typeof element.value == 'string') {
var value = obj[element.value];
} else if (typeof element.value == 'function') {
var value = element.value(obj);
} else if (!un(element.get)) {
var value = element.get(obj);
}
var xPos = sliderLeft + sliderWidth*(value-element.min)/(element.max-element.min);
ctx.fillStyle = '#00F';
ctx.beginPath();
ctx.arc(xPos,top+15,8,0,2*Math.PI);
ctx.fill();
cursorPos.push({shape:'circle',dims:[xPos,top+15,8],cursor:draw.cursors.pointer,element:element,type:'slider',obj:obj,sliderLeft:sliderLeft,sliderWidth:sliderWidth});
top += 30;
break;
case 'multiSelect':
var cells = [], rows = 0, cols = 0, heights = [], widths = [];
var selected = element.get(obj);
for (var r = 0; r < element.options.length; r++) {
cells[r] = [];
rows++;
heights.push(30);
for (var c = 0; c < element.options[r].length; c++) {
var txt = !un(element.options[r][c]) ? element.options[r][c] : '';
cells[r][c] = {};
if (text !== '' && selected.toLowerCase() == txt.toLowerCase()) {
cells[r][c].color = '#3FF';
}
cells[r][c].text = ['<>'+txt];
cols = Math.max(cols,c);
}
}
for (var c = 0; c < cols+1; c++) widths.push(0.8*pos[2]/(cols+1));
var table = drawTable3({ctx:ctx,left:pos[0]+pos[2]*0.1,top:top+30,widths:widths,heights:heights,cells:cells,outerBorder:{width:2,color:'#000',dash:[]},innerBorder:{width:1,color:'#000',dash:[]}});
for (var r = 0; r < table.cell.length; r++) {
for (var c = 0; c < table.cell[r].length; c++) {
var cell = table.cell[r][c];
cursorPos.push({shape:'rect',dims:[cell.left,cell.top,cell.width,cell.height],cursor:draw.cursors.pointer,element:element,set:element.set,type:'multiSelect',value:element.options[r][c],obj:obj});
}
}
top += (rows+1)*30+10;
break;
case 'tableBorder':
top += 30;
break;
case 'lineDec':
top += 30;
ctx.translate(10,0);
var selected = 0;
if (obj.endStart == 'open' && obj.endStartSize == 10) selected = 1;
if (obj.endStart == 'closed' && obj.endStartSize == 10) selected = 2;
if (obj.endStart == 'open' && obj.endStartSize == 15) selected = 3;
if (obj.endStart == 'closed' && obj.endStartSize == 15) selected = 4;
for (var i = 0; i < 5; i++) {
ctx.fillStyle = i == selected ? '#66F' : '#CCF';
ctx.fillRect(0,i*40+top,60,40);
var kind = ['none','open','closed','open','closed'][i];
var size = [0,10,10,15,15][i];
cursorPos.push({shape:'rect',dims:[10,i*40+top,60,40],cursor:draw.cursors.pointer,type:'lineDecEndStart',kind:kind,size:size,obj:obj});
}
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(20,i*40+20+top);
ctx.lineTo(60,i*40+20+top);
}
ctx.stroke();
drawArrow({context:ctx,startX:60,startY:top+60,finX:20,finY:top+60,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:60,startY:top+100,finX:20,finY:top+100,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
drawArrow({context:ctx,startX:60,startY:top+140,finX:20,finY:top+140,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:60,startY:top+180,finX:20,finY:top+180,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
ctx.translate(-10,0);
ctx.translate(70,0);
var selected = 0;
if (obj.endMid == 'dash' && obj.endMidSize == 10) selected = 1;
if (obj.endMid == 'dash2' && obj.endMidSize == 10) selected = 2;
if (obj.endMid == 'open' && obj.endMidSize == 15) selected = 3;
if (obj.endMid == 'open2' && obj.endMidSize == 15) selected = 4;
for (var i = 0; i < 5; i++) {
ctx.fillStyle = i == selected ? '#66F' : '#CCF';
ctx.fillRect(0,i*40+top,60,40);
var kind = ['none','dash','dash2','open','open2'][i];
var size = [0,10,10,15,15][i];
cursorPos.push({shape:'rect',dims:[70,i*40+top,60,40],cursor:draw.cursors.pointer,type:'lineDecEndMid',kind:kind,size:size,obj:obj});
}
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(0,i*40+20+top);
ctx.lineTo(60,i*40+20+top);
}
ctx.stroke();
drawDash(ctx,0,top+60,60,top+60,8);
drawDoubleDash(ctx,0,top+100,60,top+100,8);
drawParallelArrow({context:ctx,startX:0,startY:top+140,finX:60,finY:top+140,arrowLength:10,lineWidth:3});
drawParallelArrow({context:ctx,startX:0,startY:top+180,finX:60,finY:top+180,arrowLength:10,lineWidth:3,numOfArrows:2});
ctx.translate(-70,0);
ctx.translate(130,0);
var selected = 0;
if (obj.endFin == 'open' && obj.endFinSize == 10) selected = 1;
if (obj.endFin == 'closed' && obj.endFinSize == 10) selected = 2;
if (obj.endFin == 'open' && obj.endFinSize == 15) selected = 3;
if (obj.endFin == 'closed' && obj.endFinSize == 15) selected = 4;
for (var i = 0; i < 5; i++) {
ctx.fillStyle = i == selected ? '#66F' : '#CCF';
ctx.fillRect(0,i*40+top,60,40);
var kind = ['none','open','closed','open','closed'][i];
var size = [0,10,10,15,15][i];
cursorPos.push({shape:'rect',dims:[130,i*40+top,60,40],cursor:draw.cursors.pointer,type:'lineDecEndFin',kind:kind,size:size,obj:obj});
}
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(0,i*40+20+top);
ctx.lineTo(40,i*40+20+top);
}
ctx.stroke();
drawArrow({context:ctx,startX:0,startY:top+60,finX:40,finY:top+60,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:0,startY:top+100,finX:40,finY:top+100,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
drawArrow({context:ctx,startX:0,startY:top+140,finX:40,finY:top+140,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:0,startY:top+180,finX:40,finY:top+180,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
ctx.translate(-130,0);
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 6; i++) {
ctx.moveTo(10,i*40+top);
ctx.lineTo(190,i*40+top);
}
for (var i = 0; i < 4; i++) {
ctx.moveTo(10+i*60,top);
ctx.lineTo(10+i*60,top+200);
}
ctx.stroke();
top += 200+10;
break;
case 'curveDec':
top += 30;
ctx.translate(10,0);
var selected = 0;
if (obj.endStart == 'open' && obj.endStartSize == 10) selected = 1;
if (obj.endStart == 'closed' && obj.endStartSize == 10) selected = 2;
if (obj.endStart == 'open' && obj.endStartSize == 15) selected = 3;
if (obj.endStart == 'closed' && obj.endStartSize == 15) selected = 4;
for (var i = 0; i < 5; i++) {
ctx.fillStyle = i == selected ? '#66F' : '#CCF';
ctx.fillRect(0,i*40+top,60,40);
var kind = ['none','open','closed','open','closed'][i];
var size = [0,10,10,15,15][i];
cursorPos.push({shape:'rect',dims:[10,i*40+top,60,40],cursor:draw.cursors.pointer,type:'lineDecEndStart',kind:kind,size:size,obj:obj});
}
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(20,i*40+20+top);
ctx.lineTo(60,i*40+20+top);
}
ctx.stroke();
drawArrow({context:ctx,startX:60,startY:top+60,finX:20,finY:top+60,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:60,startY:top+100,finX:20,finY:top+100,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
drawArrow({context:ctx,startX:60,startY:top+140,finX:20,finY:top+140,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:60,startY:top+180,finX:20,finY:top+180,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
ctx.translate(-10,0);
ctx.translate(70,0);
var selected = 0;
if (obj.endFin == 'open' && obj.endFinSize == 10) selected = 1;
if (obj.endFin == 'closed' && obj.endFinSize == 10) selected = 2;
if (obj.endFin == 'open' && obj.endFinSize == 15) selected = 3;
if (obj.endFin == 'closed' && obj.endFinSize == 15) selected = 4;
for (var i = 0; i < 5; i++) {
ctx.fillStyle = i == selected ? '#66F' : '#CCF';
ctx.fillRect(0,i*40+top,60,40);
var kind = ['none','open','closed','open','closed'][i];
var size = [0,10,10,15,15][i];
cursorPos.push({shape:'rect',dims:[70,i*40+top,60,40],cursor:draw.cursors.pointer,type:'lineDecEndFin',kind:kind,size:size,obj:obj});
}
ctx.lineWidth = 3;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 5; i++) {
ctx.moveTo(0,i*40+20+top);
ctx.lineTo(40,i*40+20+top);
}
ctx.stroke();
drawArrow({context:ctx,startX:0,startY:top+60,finX:40,finY:top+60,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:0,startY:top+100,finX:40,finY:top+100,arrowLength:10,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
drawArrow({context:ctx,startX:0,startY:top+140,finX:40,finY:top+140,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3});
drawArrow({context:ctx,startX:0,startY:top+180,finX:40,finY:top+180,arrowLength:15,color:'#000',lineWidth:2,arrowLineWidth:3,fillArrow:true});
ctx.translate(-70,0);
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.beginPath();
for (var i = 0; i < 6; i++) {
ctx.moveTo(10,i*40+top);
ctx.lineTo(130,i*40+top);
}
for (var i = 0; i < 3; i++) {
ctx.moveTo(10+i*60,top);
ctx.lineTo(10+i*60,top+200);
}
ctx.stroke();
top += 200+10;
break;
}
}
if (!un(draw.controlPanel2.colorMenu)) {
var type = draw.controlPanel2.colorMenu.type;
var pos2 = draw.controlPanel2.colorMenu.pos;
var width = 30, padding = 10, rows = 6, cols = 4;
if (draw.drawArea[0]+draw.drawArea[2]-pos2[0] < width*cols+2*padding) {
pos2[0] = draw.drawArea[0]+draw.drawArea[2]-(width*cols+2*padding);
}
roundedRect(ctx,pos2[0],pos2[1],width*cols+2*padding,width*rows+2*padding,5,2,'#000','#FFF');
cursorPos.push({shape:'rect',dims:[pos2[0],pos2[1],width*cols+2*padding,width*rows+2*padding],cursor:draw.cursors.default});
var colors = [
['none','#F00','#F99','#FCC'],
['#000','#090','#9F9','#CFC'],
['#666','#00F','#99F','#CCF'],
['#999','#FF0','#FF9','#FFC'],
['#CCC','#F0F','#F9F','#FCF'],
['#FFF','#0FF','#9FF','#CFF'],
]
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
for (var r = 0; r < colors.length; r++) {
var t = pos2[1]+padding+r*width;
for (var c = 0; c < colors[r].length; c++) {
var l = pos2[0]+padding+c*width;
if (colors[r][c] == 'none') {
ctx.beginPath();
ctx.moveTo(l,t);
ctx.lineTo(l+width,t+width);
ctx.moveTo(l+width,t);
ctx.lineTo(l,t+width);
ctx.stroke();
} else {
ctx.fillStyle = colors[r][c];
ctx.fillRect(l,t,width,width);
}
ctx.strokeRect(l,t,width,width);
cursorPos.push({shape:'rect',dims:[l,t,width,width],cursor:draw.cursors.pointer,element:element,type:type,color:colors[r][c],obj:obj});
}
}
}
cursorPos.unshift({shape:'rect',dims:[pos[0],pos[1],pos[2],top+10-pos[1]],cursor:draw.cursors.default});
draw.controlPanel2.cursorPositions = cursorPos;
function drawPlusButton(ctx,rect,fillStyle) {
if (un(fillStyle)) fillStyle = '#CCC';
ctx.fillStyle = fillStyle;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
ctx.beginPath();
ctx.moveTo(rect[0]+0.25*rect[2],rect[1]+0.5*rect[3]);
ctx.lineTo(rect[0]+0.75*rect[2],rect[1]+0.5*rect[3]);
ctx.moveTo(rect[0]+0.5*rect[2],rect[1]+0.25*rect[3]);
ctx.lineTo(rect[0]+0.5*rect[2],rect[1]+0.75*rect[3]);
ctx.stroke();
}
function drawMinusButton(ctx,rect,fillStyle) {
if (un(fillStyle)) fillStyle = '#CCC';
ctx.fillStyle = fillStyle;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
ctx.beginPath();
ctx.moveTo(rect[0]+0.25*rect[2],rect[1]+0.5*rect[3]);
ctx.lineTo(rect[0]+0.75*rect[2],rect[1]+0.5*rect[3]);
ctx.stroke();
}
},
move:function(e) {
updateMouse(e);
delete draw.controlPanel2.currCursor;
draw.controlPanel2.ctx.canvas.style.cursor = 'default';
var x = mouse.x - draw.controlPanel2.ctx.data[0];
var y = mouse.y - draw.controlPanel2.ctx.data[1];
for (var p = 0; p < draw.controlPanel2.cursorPositions.length; p++) {
var pos = draw.controlPanel2.cursorPositions[p];
if (draw.cursorPosHitTest(pos,x,y) == true) {
draw.controlPanel2.currCursor = pos;
draw.controlPanel2.ctx.canvas.style.cursor = pos.cursor;
}
}
},
start: function(e) {
if (un(draw.controlPanel2.currCursor)) return;
var obj = draw.controlPanel2.obj;
var element = draw.controlPanel2.currCursor.element;
var type = draw.controlPanel2.currCursor.type;
if (type == 'slider') {
draw.drag = {prev:[mouse.x,mouse.y],element:element,obj:obj,sliderLeft:draw.controlPanel2.currCursor.sliderLeft,sliderWidth:draw.controlPanel2.currCursor.sliderWidth};
addListenerMove(window,draw.controlPanel2.move2);
addListenerEnd(window,draw.controlPanel2.stop);
draw.drawCanvas[draw.drawCanvas.length-2].style.cursor = draw.controlPanel2.currCursor.cursor;
} else if (type == 'multiSelect') {
draw.controlPanel2.currCursor.set(obj,draw.controlPanel2.currCursor.value);
drawSelectedPaths();
} else if (type == 'openLineColor') {
if (!un(draw.controlPanel2.colorMenu) && draw.controlPanel2.colorMenu.type == 'lineColor') {
delete draw.controlPanel2.colorMenu;
} else {
var dims = draw.controlPanel2.currCursor.dims;
draw.controlPanel2.colorMenu = {type:'lineColor',pos:[0,dims[1]+dims[3]]};
}
} else if (type == 'openFillColor') {
if (!un(draw.controlPanel2.colorMenu) && draw.controlPanel2.colorMenu.type == 'fillColor') {
delete draw.controlPanel2.colorMenu;
} else {
var dims = draw.controlPanel2.currCursor.dims;
draw.controlPanel2.colorMenu = {type:'fillColor',pos:[0,dims[1]+dims[3]]};
}
} else if (type == 'lineColor') {
draw.setObjStrokeStyle(obj,draw.controlPanel2.currCursor.color);
if (obj == false) draw.color = draw.controlPanel2.currCursor.color;
delete draw.controlPanel2.colorMenu;
} else if (type == 'fillColor') {
draw.setObjFillStyle(obj,draw.controlPanel2.currCursor.color);
if (obj == false) draw.fillColor = draw.controlPanel2.currCursor.color;
delete draw.controlPanel2.colorMenu;
} else if (type == 'lineWidthPlus') {
if (obj !== false) {
if (!un(draw[obj.type]) && !un(draw[obj.type].getLineWidth)) {
var width = draw[obj.type].getLineWidth(obj);
draw[obj.type].setLineWidth(obj,Math.min(8,width+1));
} else if (!un(obj.thickness)) {
obj.thickness = Math.min(8,obj.thickness+1);
} else if (!un(obj.lineWidth)) {
obj.lineWidth = Math.min(8,obj.lineWidth+1);
}
} else {
draw.thickness = Math.min(8,draw.thickness+1);
}
} else if (type == 'lineWidthMinus') {
if (obj !== false) {
if (!un(draw[obj.type]) && !un(draw[obj.type].getLineWidth)) {
var width = draw[obj.type].getLineWidth(obj);
draw[obj.type].setLineWidth(obj,Math.max(1,width-1));
} else if (!un(obj.thickness)) {
obj.thickness = Math.max(1,obj.thickness-1);
} else if (!un(obj.lineWidth)) {
obj.lineWidth = Math.max(1,obj.lineWidth-1);
}
} else {
draw.thickness = Math.max(1,draw.thickness-1);
}
} else if (type == 'toggle') {
draw.controlPanel2.currCursor.set(obj);
} else if (type == 'increment') {
draw.controlPanel2.currCursor.increment(obj,draw.controlPanel2.currCursor.value);
} else if (type == 'lineDecEndStart') {
obj.endStart = draw.controlPanel2.currCursor.kind;
obj.endStartSize = draw.controlPanel2.currCursor.size;
} else if (type == 'lineDecEndMid') {
obj.endMid = draw.controlPanel2.currCursor.kind;
obj.endMidSize = draw.controlPanel2.currCursor.size;
} else if (type == 'lineDecEndFin') {
obj.endFin = draw.controlPanel2.currCursor.kind;
obj.endFinSize = draw.controlPanel2.currCursor.size;
}
if (['openLineColor','openFillColor'].includes(type) == false) {
delete draw.controlPanel2.colorMenu;
}
drawCanvasPaths();
drawSelectCanvas();
calcCursorPositions();
},
move2: function(e) {
updateMouse(e);
var x = mouse.x - draw.controlPanel2.ctx.data[0];
var y = mouse.y - draw.controlPanel2.ctx.data[1];
var obj = draw.drag.obj;
var element = draw.drag.element;
if (element.type == 'slider') {
var value = bound(element.min+(element.max-element.min)*(x-draw.drag.sliderLeft)/draw.drag.sliderWidth,element.min,element.max,element.step);
if (!un(element.set)) {
element.set(obj,value);
} else {
obj[element.value] = value;
}
}
drawCanvasPaths();
},
stop: function(e) {
delete draw.drag;
removeListenerMove(window,draw.controlPanel2.move2);
removeListenerEnd(window,draw.controlPanel2.stop);
}
};
*/
draw.setObjFillStyle = function(obj,color) {
if (obj == false || un(obj.type)) return;
if (!un(draw[obj.type]) && !un(draw[obj.type].setFillColor)) {
draw[obj.type].setFillColor(obj,color);
return;
}
if (!un(obj.fillColor)) {
obj.fillColor = color;
} else if (!un(obj.fillStyle)) {
obj.fillStyle = color;
}
if (['table2'].indexOf(obj.type) > -1) {
var selCount = draw.table2.countSelectedCells(obj);
var cells = selCount == 0 ? draw.table2.getAllCells(obj) : draw.table2.getSelectedCells(obj);
for (var c = 0; c < cells.length; c++) {
var cell = cells[c];
if (!un(cell.box)) {
cell.box.color = color;
} else {
if (color !== 'none') {
cell.box = {
color:color,
lineColor:'none',
borderWidth:3,
borderRadius:0,
show:true
}
}
}
}
}
}
draw.setObjStrokeStyle = function(obj,color) {
if (obj == false || un(obj.type)) return;
if (!un(draw[obj.type]) && !un(draw[obj.type].setLineColor)) {
draw[obj.type].setLineColor(obj,color);
return;
}
if (!un(obj.color)) {
obj.color = color;
} else if (!un(obj.lineColor)) {
obj.lineColor = color;
} else if (!un(obj.strokeStyle)) {
obj.strokeStyle = color;
}
if (['table2'].indexOf(obj.type) > -1) {
var selCount = draw.table2.countSelectedCells(obj);
var cells = selCount == 0 ? draw.table2.getAllCells(obj) : draw.table2.getSelectedCells(obj);
for (var c = 0; c < cells.length; c++) {
var cell = cells[c];
if (!un(cell.box)) {
cell.box.borderColor = color;
} else {
if (color !== 'none') {
cell.box = {
color:'none',
borderColor:color,
borderWidth:3,
borderRadius:0,
show:true
}
}
}
}
}
}
draw.controlPanel = {
data:{elements:[]},
cursorPositions:[],
clear: function() {
draw.controlPanel.data = {elements:[]};
draw.controlPanel.cursorPositions = [];
},
draw: function(ctx,obj,path,controlPanelData,pos) {
if (draw.mode === 'interact') return;
draw.controlPanel.path = path;
draw.controlPanel.obj = obj;
draw.controlPanel.clear();
if (!un(controlPanelData)) {
draw.controlPanel.data = controlPanelData;
} else {
if (un(draw[obj.type]) || un(draw[obj.type].getControlPanel)) return;
draw.controlPanel.data = draw[obj.type].getControlPanel(obj);
}
var cursorPos = [];
var elements = draw.controlPanel.data.elements;
var width = draw.controlPanel.data.width || 200;
if (un(pos)) {
if (draw.drawArea[0]+draw.drawArea[2]-path.border[4] >= width) {
var pos = [path.border[4],path.border[1],width];
} else {
var pos = [path.border[0]-width,path.border[1],width];
}
}
var top = pos[1]+10;
for (var e = 0; e < elements.length; e++) {
var element = elements[e];
var bold = boolean(element.bold,true);
var fontSize = element.fontSize || 20;
var margin = element.margin*pos[2] || 0;
text({ctx:ctx,rect:[pos[0]+10+margin,top,pos[2]-20,40],align:[-1,-1],text:['<><>'+element.name]});
switch (element.type) {
case 'style':
var w = 0.4*pos[2]/3;
var space = 0.6*pos[2]/4;
var l = pos[0]+space;
var t = top+50;
var strokeStyle = draw[obj.type].getLineColor(obj);
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>line']})
ctx.beginPath();
cursorPos.push({shape:'rect',dims:[l,t,w,w],cursor:draw.cursors.pointer,element:element,type:'openLineColor',obj:obj,func:draw.controlPanel.start});
if (strokeStyle == 'none') {
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
ctx.moveTo(l,t);
ctx.lineTo(l+w,t+w);
ctx.moveTo(l+w,t);
ctx.lineTo(l,t+w);
ctx.stroke();
} else {
ctx.fillStyle = strokeStyle;
ctx.fillRect(l,t,w,w);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
}
l += space+w;
var fillStyle = draw[obj.type].getLineWidth(obj);
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>width']})
var minusRect = [l-0.3*w,t+0.1*w,0.8*w,0.8*w];
var plusRect = [l-0.3*w+0.8*w,t+0.1*w,0.8*w,0.8*w];
drawPlusButton(ctx,plusRect);
drawMinusButton(ctx,minusRect);
cursorPos.push({shape:'rect',dims:plusRect,cursor:draw.cursors.pointer,element:element,type:'lineWidthPlus',obj:obj,func:draw.controlPanel.start});
cursorPos.push({shape:'rect',dims:minusRect,cursor:draw.cursors.pointer,element:element,type:'lineWidthMinus',obj:obj,func:draw.controlPanel.start});
l += space+w;
var fillStyle = draw[obj.type].getFillColor(obj);
text({ctx:ctx,align:[0,-1],rect:[l,top+25,w,w],text:['<>fill']})
cursorPos.push({shape:'rect',dims:[l,t,w,w],cursor:draw.cursors.pointer,element:element,type:'openFillColor',obj:obj,func:draw.controlPanel.start});
ctx.beginPath();
if (fillStyle == 'none') {
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
ctx.moveTo(l,t);
ctx.lineTo(l+w,t+w);
ctx.moveTo(l+w,t);
ctx.lineTo(l,t+w);
ctx.stroke();
} else {
ctx.fillStyle = fillStyle;
ctx.fillRect(l,t,w,w);
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(l,t,w,w);
}
top += 90;
break;
case 'toggle':
var rect = [pos[0]+pos[2]*0.1,top+2,16,16];
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.fillStyle = '#FFF';
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
if (element.get(obj)) drawTick(ctx,16,20,'#060',pos[0]+pos[2]*0.1,top,3);
cursorPos.push({shape:'rect',dims:[pos[0]+pos[2]*0.1,top,0.8*pos[2],20],cursor:draw.cursors.pointer,element:element,set:element.set,type:'toggle',obj:obj,func:draw.controlPanel.start});
top += 30;
break;
case 'increment':
var minusRect = [pos[0]+pos[2]*0.7,top+2,22,22];
var plusRect = [pos[0]+pos[2]*0.7+22,top+2,22,22];
drawPlusButton(ctx,plusRect);
drawMinusButton(ctx,minusRect);
cursorPos.push({shape:'rect',dims:plusRect,cursor:draw.cursors.pointer,element:element,type:'increment',value:1,increment:element.increment,obj:obj,func:draw.controlPanel.start});
cursorPos.push({shape:'rect',dims:minusRect,cursor:draw.cursors.pointer,element:element,type:'increment',value:-1,increment:element.increment,obj:obj,func:draw.controlPanel.start});
top += 40;
break;
case 'slider':
var sliderLeft = pos[0]+0.55*pos[2];
var sliderWidth = 0.3*pos[2];
ctx.lineWidth = 2;
ctx.strokeStyle = '#000';
ctx.beginPath();
ctx.moveTo(sliderLeft,top+15);
ctx.lineTo(sliderLeft+sliderWidth,top+15);
ctx.stroke();
if (typeof element.value == 'string') {
var value = obj[element.value];
} else if (typeof element.value == 'function') {
var value = element.value(obj);
} else if (!un(element.get)) {
var value = element.get(obj);
}
var xPos = sliderLeft + sliderWidth*(value-element.min)/(element.max-element.min);
ctx.fillStyle = '#00F';
ctx.beginPath();
ctx.arc(xPos,top+15,8,0,2*Math.PI);
ctx.fill();
cursorPos.push({shape:'circle',dims:[xPos,top+15,8],cursor:draw.cursors.pointer,element:element,type:'slider',obj:obj,func:draw.controlPanel.start,sliderLeft:sliderLeft,sliderWidth:sliderWidth});
top += 30;
break;
case 'multiSelect':
var cells = [], rows = 0, cols = 0, heights = [], widths = [];
var selected = element.get(obj);
for (var r = 0; r < element.options.length; r++) {
cells[r] = [];
rows++;
heights.push(30);
for (var c = 0; c < element.options[r].length; c++) {
var txt = !un(element.options[r][c]) ? element.options[r][c] : '';
cells[r][c] = {};
if (text !== '' && selected.toLowerCase() == txt.toLowerCase()) {
cells[r][c].color = '#3FF';
}
cells[r][c].text = ['<>'+txt];
cols = Math.max(cols,c);
}
}
for (var c = 0; c < cols+1; c++) widths.push(0.8*pos[2]/(cols+1));
var table = drawTable3({ctx:ctx,left:pos[0]+pos[2]*0.1,top:top+30,widths:widths,heights:heights,cells:cells,outerBorder:{width:2,color:'#000',dash:[]},innerBorder:{width:1,color:'#000',dash:[]}});
for (var r = 0; r < table.cell.length; r++) {
for (var c = 0; c < table.cell[r].length; c++) {
var cell = table.cell[r][c];
cursorPos.push({shape:'rect',dims:[cell.left,cell.top,cell.width,cell.height],cursor:draw.cursors.pointer,element:element,set:element.set,type:'multiSelect',value:element.options[r][c],obj:obj,func:draw.controlPanel.start});
}
}
top += (rows+1)*30+10;
break;
}
}
if (!un(draw.controlPanel.colorMenu)) {
var type = draw.controlPanel.colorMenu.type;
var pos2 = draw.controlPanel.colorMenu.pos;
var width = 30, padding = 10, rows = 6, cols = 4;
if (draw.drawArea[0]+draw.drawArea[2]-pos2[0] < width*cols+2*padding) {
pos2[0] = draw.drawArea[0]+draw.drawArea[2]-(width*cols+2*padding);
}
roundedRect(ctx,pos2[0],pos2[1],width*cols+2*padding,width*rows+2*padding,5,2,'#000','#FFF');
cursorPos.push({shape:'rect',dims:[pos2[0],pos2[1],width*cols+2*padding,width*rows+2*padding],cursor:draw.cursors.default});
var colors = [
['none','#F00','#F99','#FCC'],
['#000','#090','#9F9','#CFC'],
['#666','#00F','#99F','#CCF'],
['#999','#FF0','#FF9','#FFC'],
['#CCC','#F0F','#F9F','#FCF'],
['#FFF','#0FF','#9FF','#CFF'],
]
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
for (var r = 0; r < colors.length; r++) {
var t = pos2[1]+padding+r*width;
for (var c = 0; c < colors[r].length; c++) {
var l = pos2[0]+padding+c*width;
if (colors[r][c] == 'none') {
ctx.beginPath();
ctx.moveTo(l,t);
ctx.lineTo(l+width,t+width);
ctx.moveTo(l+width,t);
ctx.lineTo(l,t+width);
ctx.stroke();
} else {
ctx.fillStyle = colors[r][c];
ctx.fillRect(l,t,width,width);
}
ctx.strokeRect(l,t,width,width);
cursorPos.push({shape:'rect',dims:[l,t,width,width],cursor:draw.cursors.pointer,element:element,type:type,color:colors[r][c],obj:obj,func:draw.controlPanel.start});
}
}
}
ctx.globalCompositeOperation = 'destination-over';
roundedRect(ctx,pos[0],pos[1],pos[2],top+10-pos[1],0,3,'#000','#FFC');
ctx.globalCompositeOperation = 'source-over';
cursorPos.unshift({shape:'rect',dims:[pos[0],pos[1],pos[2],top+10-pos[1]],cursor:draw.cursors.default});
draw.controlPanel.cursorPositions = cursorPos;
function drawPlusButton(ctx,rect,fillStyle) {
if (un(fillStyle)) fillStyle = '#CCC';
ctx.fillStyle = fillStyle;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
ctx.beginPath();
ctx.moveTo(rect[0]+0.25*rect[2],rect[1]+0.5*rect[3]);
ctx.lineTo(rect[0]+0.75*rect[2],rect[1]+0.5*rect[3]);
ctx.moveTo(rect[0]+0.5*rect[2],rect[1]+0.25*rect[3]);
ctx.lineTo(rect[0]+0.5*rect[2],rect[1]+0.75*rect[3]);
ctx.stroke();
}
function drawMinusButton(ctx,rect,fillStyle) {
if (un(fillStyle)) fillStyle = '#CCC';
ctx.fillStyle = fillStyle;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.fillRect(rect[0],rect[1],rect[2],rect[3]);
ctx.strokeRect(rect[0],rect[1],rect[2],rect[3]);
ctx.beginPath();
ctx.moveTo(rect[0]+0.25*rect[2],rect[1]+0.5*rect[3]);
ctx.lineTo(rect[0]+0.75*rect[2],rect[1]+0.5*rect[3]);
ctx.stroke();
}
},
start: function() {
var obj = draw.controlPanel.obj;
var element = draw.currCursor.element;
var type = draw.currCursor.type;
if (type == 'slider') {
draw.drag = {prev:[mouse.x,mouse.y],element:element,obj:obj,sliderLeft:draw.currCursor.sliderLeft,sliderWidth:draw.currCursor.sliderWidth};
draw.animate(draw.controlPanel.move,draw.controlPanel.stop,drawCanvasPaths);
//addListenerMove(window,draw.controlPanel.move);
//addListenerEnd(window,draw.controlPanel.stop);
draw.drawCanvas[draw.drawCanvas.length-2].style.cursor = draw.currCursor.cursor;
} else if (type == 'multiSelect') {
draw.currCursor.set(obj,draw.currCursor.value);
drawSelectedPaths();
} else if (type == 'openLineColor') {
if (!un(draw.controlPanel.colorMenu) && draw.controlPanel.colorMenu.type == 'lineColor') {
delete draw.controlPanel.colorMenu;
} else {
var dims = draw.currCursor.dims;
draw.controlPanel.colorMenu = {type:'lineColor',pos:[dims[0],dims[1]+dims[3]]};
}
} else if (type == 'openFillColor') {
if (!un(draw.controlPanel.colorMenu) && draw.controlPanel.colorMenu.type == 'fillColor') {
delete draw.controlPanel.colorMenu;
} else {
var dims = draw.currCursor.dims;
draw.controlPanel.colorMenu = {type:'fillColor',pos:[dims[0],dims[1]+dims[3]]};
}
} else if (type == 'lineColor') {
draw[obj.type].setLineColor(obj,draw.currCursor.color);
delete draw.controlPanel.colorMenu;
} else if (type == 'fillColor') {
draw[obj.type].setFillColor(obj,draw.currCursor.color);
delete draw.controlPanel.colorMenu;
} else if (type == 'lineWidthPlus') {
var width = draw[obj.type].getLineWidth(obj);
draw[obj.type].setLineWidth(obj,Math.min(8,width+1));
} else if (type == 'lineWidthMinus') {
var width = draw[obj.type].getLineWidth(obj);
draw[obj.type].setLineWidth(obj,Math.max(1,width-1));
} else if (type == 'toggle') {
draw.currCursor.set(obj);
} else if (type == 'increment') {
draw.currCursor.increment(obj,draw.currCursor.value);
}
if (['openLineColor','openFillColor'].includes(type) == false) {
delete draw.controlPanel.colorMenu;
}
drawCanvasPaths();
drawSelectCanvas();
calcCursorPositions();
},
move: function(e) {
updateMouse(e);
var obj = draw.drag.obj;
var element = draw.drag.element;
if (element.type == 'slider') {
var value = bound(element.min+(element.max-element.min)*(mouse.x-draw.drag.sliderLeft)/draw.drag.sliderWidth,element.min,element.max,element.step);
if (!un(element.set)) {
element.set(obj,value);
} else {
obj[element.value] = value;
}
}
//drawCanvasPaths();
},
stop: function(e) {
delete draw.drag;
//removeListenerMove(window,draw.controlPanel.move);
//removeListenerEnd(window,draw.controlPanel.stop);
}
};
function angleStyleIncrement(angle) {
angle.style = (angle.style+1) % 7;
switch (angle.style) {
case 0:
angle.drawCurve = false;
angle.numOfCurves = 1;
angle.fill = false;
break;
case 1:
angle.drawCurve = true;
angle.numOfCurves = 1;
angle.fill = false;
break;
case 2:
angle.drawCurve = true;
angle.numOfCurves = 2;
angle.fill = false;
break;
case 3:
angle.drawCurve = true;
angle.numOfCurves = 3;
angle.fill = false;
break;
case 4:
angle.drawCurve = true;
angle.numOfCurves = 1;
angle.fill = true;
angle.fillColor = '#CFC';
break;
case 5:
angle.drawCurve = true;
angle.numOfCurves = 1;
angle.fill = true;
angle.fillColor = '#FCF';
break;
case 6:
angle.drawCurve = true;
angle.numOfCurves = 1;
angle.fill = true;
angle.fillColor = '#CCF';
break;
}
return angle;
}
/****************************/
/* PROTRACTOR RULER COMPASS */
/****************************/
function getRelPos(pos) {
if (un(pos)) pos = [mouse.x,mouse.y];
return [pos[0]-draw.drawRelPos[0],pos[1]-draw.drawRelPos[1]];
//return [(pos[0]-draw.drawRelPos[0])/draw.scale,(pos[1]-draw.drawRelPos[1])/draw.scale];
}
function drawClickProtractorStartMove() {
moveToolToFront('protractor');
draw.cursorCanvas.style.cursor = draw.cursors.move1;
draw.animate(protractorDragMove,protractorDragStop,drawToolsCanvas);
changeDrawMode('protractorMove');
}
function protractorDragMove(e) {
updateMouse(e);
var center = [
draw.mouse[0]-draw.protractor.relSelPoint[0],
draw.mouse[1]-draw.protractor.relSelPoint[1]
];
center = snapToObj2(center,-1);
draw.protractor.center[0] = center[0];
draw.protractor.center[1] = center[1];
//drawToolsCanvas();
}
function protractorDragStop(e) {
changeDrawMode('prev');
}
function drawClickProtractorStartRotate() {
moveToolToFront('protractor');
draw.animate(protractorRotateMove,protractorRotateStop,drawToolsCanvas);
changeDrawMode('protractorRotate');
}
function protractorRotateMove(e) {
updateMouse(e);
draw.protractor.angle += measureAngle({c:draw.mouse,b:[draw.protractor.center[0],draw.protractor.center[1]],a:[draw.protractor.prevX,draw.protractor.prevY],angleType:'radians'});
draw.protractor.prevX = draw.mouse[0];
draw.protractor.prevY = draw.mouse[1];
}
function protractorRotateStop(e) {
changeDrawMode('prev');
}
function drawClickRulerStartMove() {
moveToolToFront('ruler');
//addListenerMove(window,rulerDragMove);
//addListenerEnd(window,rulerDragStop);
draw.animate(rulerDragMove,rulerDragStop,drawToolsCanvas);
changeDrawMode('rulerMove');
}
function rulerDragMove(e) {
updateMouse(e);
draw.ruler.left += draw.mouse[0]-draw.ruler.prevX;
draw.ruler.top += draw.mouse[1]-draw.ruler.prevY;
recalcRulerValues();
//drawToolsCanvas();
draw.ruler.prevX = draw.mouse[0];
draw.ruler.prevY = draw.mouse[1];
}
function rulerDragStop(e) {
changeDrawMode('prev');
}
function drawClickRulerStartRotate1() {
moveToolToFront('ruler');
//addListenerMove(window,rulerRotateMove1);
//addListenerEnd(window,rulerRotateStop);
draw.animate(rulerRotateMove1,rulerRotateStop,drawToolsCanvas);
changeDrawMode('rulerRotate');
}
function drawClickRulerStartRotate2() {
moveToolToFront('ruler');
//addListenerMove(window,rulerRotateMove2);
//addListenerEnd(window,rulerRotateStop);
draw.animate(rulerRotateMove2,rulerRotateStop,drawToolsCanvas);
changeDrawMode('rulerRotate');
}
function rulerRotateMove1(e) {
updateMouse(e);
dAngle = measureAngle({c:draw.mouse,b:[draw.ruler.centerX2,draw.ruler.centerY2],a:[draw.ruler.prevX,draw.ruler.prevY],angleType:'radians'});
draw.ruler.angle += dAngle;
draw.ruler.left = (draw.ruler.centerX2 - 0.98*draw.ruler.length*Math.cos(draw.ruler.angle));
draw.ruler.top = (draw.ruler.centerY2 - 0.98*draw.ruler.length*Math.sin(draw.ruler.angle));
recalcRulerValues();
//drawToolsCanvas();
draw.ruler.prevX = draw.mouse[0];
draw.ruler.prevY = draw.mouse[1];
}
function rulerRotateMove2(e) {
updateMouse(e);
draw.ruler.angle += measureAngle({c:draw.mouse,b:[draw.ruler.centerX1,draw.ruler.centerY1],a:[draw.ruler.prevX,draw.ruler.prevY],angleType:'radians'});
recalcRulerValues();
//drawToolsCanvas();
draw.ruler.prevX = draw.mouse[0];
draw.ruler.prevY = draw.mouse[1];
}
function rulerRotateStop(e) {
changeDrawMode('prev');
}
function drawClickRulerRotate180() {
moveToolToFront('ruler');
draw.ruler.angle += Math.PI;
draw.ruler.left += 2*draw.ruler.centerRel[0];
draw.ruler.top += 2*draw.ruler.centerRel[1];
recalcRulerValues();
drawToolsCanvas();
}
function drawClickRulerStartDraw1() {
//console.log('drawClickRulerStartDraw1');
moveToolToFront('ruler');
draw.drawing = true;
drawCanvasPaths();
var obj = {
type:'line',
color:draw.color,
thickness:draw.thickness,
startPos:[draw.startX,draw.startY]
};
if (!un(draw.dash) && draw.dash.length > 0) obj.dash = clone(draw.dash);
draw.path.push({obj:[obj],selected:false});
//addListenerMove(window,rulerDrawMove1);
//addListenerEnd(window,lineDrawStop);
draw.animate(rulerDrawMove1,lineDrawStop,drawSelectedPaths);
}
function rulerDrawMove1(e) {
updateMouse(e);
var newPos = closestPointOnLineSegment(draw.mouse,draw.ruler.edgePos1,draw.ruler.edgePos2);
draw.path[draw.path.length-1].obj[0].finPos = newPos;
//drawSelectedPaths();
}
function drawClickRulerStartDraw2() {
//console.log('drawClickRulerStartDraw2');
moveToolToFront('ruler');
draw.drawing = true;
drawCanvasPaths();
var obj = {
type:'line',
color:draw.color,
thickness:draw.thickness,
startPos:[draw.startX,draw.startY]
};
if (!un(draw.dash) && draw.dash.length > 0) obj.dash = clone(draw.dash);
draw.path.push({obj:[obj],selected:false});
//addListenerMove(window,rulerDrawMove2);
//addListenerEnd(window,lineDrawStop);
draw.animate(rulerDrawMove2,lineDrawStop,drawSelectedPaths);
}
function rulerDrawMove2(e) {
updateMouse(e);
var newPos = closestPointOnLineSegment(draw.mouse,draw.ruler.edgePos3,draw.ruler.edgePos4);
draw.path[draw.path.length-1].obj[0].finPos = newPos;
//drawSelectedPaths();
}
function drawClickCompassLock() {
moveToolToFront('compass');
draw.compass.radiusLocked = !draw.compass.radiusLocked;
drawToolsCanvas();
}
function drawClickCompassStartDraw(e) {
updateMouse(e);
moveToolToFront('compass');
draw.compass.mode = 'draw';
draw.drawing = true;
changeDrawMode('compassDraw');
var obj = {
type:'arc',
color:draw.color,
thickness:draw.thickness,
center:draw.compass.center1.slice(0),
radius:draw.compass.radius,
startAngle:draw.compass.angle,
finAngle:draw.compass.angle,
clockwise:true
};
if (!un(draw.dash) && draw.dash.length > 0) obj.dash = clone(draw.dash);
draw.path.push({obj:[obj],selected:false});
drawCanvasPaths();
//addListenerMove(window,compassDrawMove);
//addListenerEnd(window,compassDrawStop);
draw.animate(compassDrawMove,compassDrawStop,function() {
drawSelectedPaths();
drawToolsCanvas();
});
}
function compassDrawMove(e) {
updateMouse(e);
var dAngle = measureAngle({c:draw.mouse,b:[draw.compass.center1[0],draw.compass.center1[1]],a:[draw.compass.prevX,draw.compass.prevY],angleType:'radians'});
if (dAngle > Math.PI) {
draw.compass.angle -= dAngle = 2*Math.PI-dAngle;
} else {
draw.compass.angle += dAngle;
}
var angle = (draw.compass.angle%(2*Math.PI));
if (angle < 0) angle += 2*Math.PI;
if (angle > 0.5 * Math.PI && angle < 1.5 * Math.PI) {
draw.compass.drawOn = 'left';
} else {
draw.compass.drawOn = 'right';
}
draw.compass.center3[0] = draw.compass.center1[0]+draw.compass.radius*Math.cos(draw.compass.angle);
draw.compass.center3[1] = draw.compass.center1[1]+draw.compass.radius*Math.sin(draw.compass.angle);
/*var snapNewCenter3 = snapToObj2(draw.compass.center3,-1);
if (snapNewCenter3[0] !== draw.compass.center3[0] || snapNewCenter3[1] !== draw.compass.center3[1]) {
draw.compass.angle = getAngleFromAToB(snapNewCenter3,draw.compass.center1);
var angle = (draw.compass.angle%(2*Math.PI));
if (angle < 0) angle += 2*Math.PI;
if (angle > 0.5 * Math.PI && angle < 1.5 * Math.PI) {
draw.compass.drawOn = 'left';
} else {
draw.compass.drawOn = 'right';
}
draw.compass.center3[0] = draw.compass.center1[0]+draw.compass.radius*Math.cos(draw.compass.angle);
draw.compass.center3[1] = draw.compass.center1[1]+draw.compass.radius*Math.sin(draw.compass.angle);
}*/
if (draw.compass.drawOn == 'right') {
draw.compass.center2[0] = draw.compass.center1[0]+0.5*draw.compass.radius*Math.cos(draw.compass.angle)+draw.compass.h*Math.sin(draw.compass.angle);
draw.compass.center2[1] = draw.compass.center1[1]+0.5*draw.compass.radius*Math.sin(draw.compass.angle)-draw.compass.h*Math.cos(draw.compass.angle);
} else {
draw.compass.center2[0] = draw.compass.center1[0]+0.5*draw.compass.radius*Math.cos(draw.compass.angle)-draw.compass.h*Math.sin(draw.compass.angle);
draw.compass.center2[1] = draw.compass.center1[1]+0.5*draw.compass.radius*Math.sin(draw.compass.angle)+draw.compass.h*Math.cos(draw.compass.angle);
}
var mp1 = midpoint(draw.compass.center1[0],draw.compass.center1[1],draw.compass.center3[0],draw.compass.center3[1]);
var mp2 = midpoint(draw.compass.center2[0],draw.compass.center2[1],mp1[0],mp1[1]);
draw.compass.lockCenter = mp2;
draw.path[draw.path.length-1].obj[0].startAngle = Math.min(draw.path[draw.path.length-1].obj[0].startAngle,draw.compass.angle);
draw.path[draw.path.length-1].obj[0].finAngle = Math.max(draw.path[draw.path.length-1].obj[0].finAngle,draw.compass.angle);
recalcCompassValues();
//drawSelectedPaths();
//drawToolsCanvas();
draw.compass.prevX = draw.mouse[0];
draw.compass.prevY = draw.mouse[1];
}
function compassDrawStop(e) {
//removeListenerMove(window,compassDrawMove);
//removeListenerEnd(window,compassDrawStop);
draw.compass.mode = 'none';
draw.drawing = false;
changeDrawMode('prev');
recalcCompassValues();
drawToolsCanvas();
// simplify angles to between 0 and 360
var angle1 = draw.path[draw.path.length-1].obj[0].startAngle;
var angle2 = draw.path[draw.path.length-1].obj[0].finAngle;
if (angle1 > angle2) {
draw.path[draw.path.length-1].obj[0].clockwise = true;
} else {
draw.path[draw.path.length-1].obj[0].clockwise = false;
}
if (Math.abs(angle1 - angle2) > 2 * Math.PI) {
draw.path[draw.path.length-1].obj[0].startAngle = 0;
draw.path[draw.path.length-1].obj[0].finAngle = 2 * Math.PI;
draw.path[draw.path.length-1].obj[0].clockwise = true;
} else {
while (angle1 < 0) {angle1 += 2 * Math.PI;}
while (angle2 < 0) {angle2 += 2 * Math.PI;}
while (angle1 > 2 * Math.PI) {angle1 -= 2 * Math.PI;}
while (angle2 > 2 * Math.PI) {angle2 -= 2 * Math.PI;}
if (draw.path[draw.path.length-1].obj[0].clockwise == true) {
draw.path[draw.path.length-1].obj[0].startAngle = angle1;
draw.path[draw.path.length-1].obj[0].finAngle = angle2;
} else {
draw.path[draw.path.length-1].obj[0].startAngle = angle2;
draw.path[draw.path.length-1].obj[0].finAngle = angle1;
}
}
//console.log(draw.path[draw.path.length-1].startAngle,draw.path[draw.path.length-1].finAngle,draw.path[draw.path.length-1].clockwise);
drawCanvasPaths();
delete draw.compass.dragRelPos;
}
function drawClickCompassStartMove1(e) {
moveToolToFront('compass');
draw.compass.mode = 'move1';
changeDrawMode('compassMove1');
updateSnapPoints(); // update intersection points
draw.animate(compassMove1Move,compassMoveStop,drawToolsCanvas);
//addListenerMove(window,compassMove1Move);
//addListenerEnd(window,compassMoveStop);
draw.cursorCanvas.style.cursor = 'url("/i2/cursors/closedhand.cur"), auto';
}
function drawClickCompassStartMove2(e) {
updateMouse(e);
draw.compass.dragRelPos = [draw.compass.center3[0]-draw.mouse[0],draw.compass.center3[1]-draw.mouse[1]];
moveToolToFront('compass');
draw.compass.mode = 'move2';
changeDrawMode('compassMove2');
updateSnapPoints(); // update intersection points
draw.compass.pointerEvents = 'auto';
draw.animate(compassMove2Move,compassMoveStop,drawToolsCanvas);
//addListenerMove(window,compassMove2Move);
//addListenerEnd(window,compassMoveStop);
draw.cursorCanvas.style.cursor = 'url("/i2/cursors/closedhand.cur"), auto';
}
function compassMove1Move(e) {
updateMouse(e);
var center1 = [
draw.mouse[0]-draw.compass.relSelPoint[0],
draw.mouse[1]-draw.compass.relSelPoint[1]
];
if (snapToObj2On || draw.snapLinesTogether) {
center1 = snapToObj2(center1);
}
draw.compass.center1 = center1;
draw.compass.center2 = [center1[0]+draw.compass.relCenter2[0],center1[1]+draw.compass.relCenter2[1]];
draw.compass.center3 = [center1[0]+draw.compass.relCenter3[0],center1[1]+draw.compass.relCenter3[1]];
draw.compass.lockCenter = [center1[0]+draw.compass.relLockCenter[0],center1[1]+draw.compass.relLockCenter[1]];
//drawToolsCanvas();
}
function compassMove2Move(e) {
updateMouse(e);
var newcenter3 = [draw.mouse[0]+draw.compass.dragRelPos[0],draw.mouse[1]+draw.compass.dragRelPos[1]];
if (draw.compass.radiusLocked == false) {
newcenter3 = snapToObj2(newcenter3,-1);
var newRadius = Math.sqrt(Math.pow(newcenter3[0]-draw.compass.center1[0],2)+Math.pow(newcenter3[1]-draw.compass.center1[1],2));
if (newRadius <= 1.85 * draw.compass.armLength) {
draw.compass.center3[0] = newcenter3[0];
draw.compass.center3[1] = newcenter3[1];
draw.compass.radius = newRadius;
if (draw.compass.center3[0] >= draw.compass.center1[0]) {
draw.compass.angle = Math.atan((draw.compass.center3[1]-draw.compass.center1[1])/(draw.compass.center3[0]-draw.compass.center1[0]));
} else {
draw.compass.angle = Math.PI + Math.atan((draw.compass.center3[1]-draw.compass.center1[1])/(draw.compass.center3[0]-draw.compass.center1[0]));
}
} else {
if (newcenter3[0] >= draw.compass.center1[0]) {
draw.compass.angle = Math.atan((newcenter3[1]-draw.compass.center1[1])/(newcenter3[0]-draw.compass.center1[0]));
} else {
draw.compass.angle = Math.PI + Math.atan((newcenter3[1]-draw.compass.center1[1])/(newcenter3[0]-draw.compass.center1[0]));
}
draw.compass.center3[0] = draw.compass.center1[0] + 1.85 * draw.compass.armLength * Math.cos(draw.compass.angle);
draw.compass.center3[1] = draw.compass.center1[1] + 1.85 * draw.compass.armLength * Math.sin(draw.compass.angle);
draw.compass.radius = 1.85 * draw.compass.armLength;
}
} else {
var snapNewCenter3 = snapToObj2(newcenter3,-1);
var pos = clone(draw.mouse);
if (Math.abs(dist(snapNewCenter3,draw.compass.center1) - draw.compass.radius) < 0.1) {
pos = [pos[0]-draw.compass.dragRelPos[0],pos[1]-draw.compass.dragRelPos[1]];
}
var dAngle = measureAngle({c:pos,b:[draw.compass.center1[0],draw.compass.center1[1]],a:[draw.compass.prevX,draw.compass.prevY],angleType:'radians'});
if (dAngle > Math.PI) {
draw.compass.angle -= (2*Math.PI-dAngle);
} else {
draw.compass.angle += dAngle;
}
draw.compass.center3[0] = draw.compass.center1[0] + draw.compass.radius * Math.cos(draw.compass.angle);
draw.compass.center3[1] = draw.compass.center1[1] + draw.compass.radius * Math.sin(draw.compass.angle);
}
var angle = (draw.compass.angle%(2*Math.PI));
if (angle < 0) angle += 2*Math.PI;
if (angle > 0.5 * Math.PI && angle < 1.5 * Math.PI) {
draw.compass.drawOn = 'left';
} else {
draw.compass.drawOn = 'right';
}
draw.compass.h = Math.sqrt(Math.pow(draw.compass.armLength,2)-Math.pow(0.5*draw.compass.radius,2));
if (draw.compass.drawOn == 'right') {
draw.compass.center2[0] = draw.compass.center1[0]+0.5*draw.compass.radius*Math.cos(draw.compass.angle)+draw.compass.h*Math.sin(draw.compass.angle);
draw.compass.center2[1] = draw.compass.center1[1]+0.5*draw.compass.radius*Math.sin(draw.compass.angle)-draw.compass.h*Math.cos(draw.compass.angle);
} else {
draw.compass.center2[0] = draw.compass.center1[0]+0.5*draw.compass.radius*Math.cos(draw.compass.angle)-draw.compass.h*Math.sin(draw.compass.angle);
draw.compass.center2[1] = draw.compass.center1[1]+0.5*draw.compass.radius*Math.sin(draw.compass.angle)+draw.compass.h*Math.cos(draw.compass.angle);
}
var mp1 = midpoint(draw.compass.center1[0],draw.compass.center1[1],draw.compass.center3[0],draw.compass.center3[1]);
var mp2 = midpoint(draw.compass.center2[0],draw.compass.center2[1],mp1[0],mp1[1]);
draw.compass.lockCenter = mp2;
recalcCompassValues();
//drawToolsCanvas();
draw.compass.prevX = draw.mouse[0];
draw.compass.prevY = draw.mouse[1];
}
function compassMoveStop(e) {
//removeListenerMove(window,compassMove1Move);
//removeListenerMove(window,compassMove2Move);
//removeListenerEnd(window,compassMoveStop);
draw.cursorCanvas.style.cursor = draw.cursors.move1;
draw.compass.mode = 'none';
changeDrawMode('prev');
recalcCompassValues();
delete draw.compass.dragRelPos;
}