class CanvasTools { constructor() { } textSize(ctx,text,fontStyle) { ctx.save(); ctx.font = fontStyle; let tHeight = Math.round(ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent); let tWidth = Math.round(ctx.measureText(text).width); ctx.restore(); return { width: tWidth, height: tHeight }; } drawBorderBox(ctx,x,y,drawWidth,drawHeight,borderWidth=1,borderColor="#000",fillColor="#f7e979",shadowColor = "transparent") { ctx.save(); ctx.beginPath(); ctx.fillStyle = borderColor; if (shadowColor != "transparent") { ctx.shadowBlur = "6"; ctx.shadowColor = shadowColor; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.stroke(); } ctx.fillRect(x,y,drawWidth,drawHeight); ctx.fillStyle = fillColor; ctx.fillRect(x+borderWidth,y+borderWidth,drawWidth-(borderWidth*2),drawHeight-(borderWidth*2)); ctx.restore(); } drawTextCentered(ctx,x,y,x2,y2,text,fontStyle="24px Console",fontColor = "#555", Overline = false) { ctx.save(); ctx.font = fontStyle; ctx.fillStyle = fontColor; let textSize = this.textSize(ctx,text,fontStyle); let tHeight = ctx.measureText(text).actualBoundingBoxAscent + ctx.measureText(text).actualBoundingBoxDescent; let tX = x+((x2/2)-(ctx.measureText(text).width/2)); let tY = y+tHeight+((y2/2)-(tHeight/2)); if (Overline) { ctx.strokeStyle = fontColor; ctx.beginPath(); ctx.moveTo(tX,tY-textSize.height-1); ctx.lineTo(tX+textSize.width,tY-textSize.height-1); ctx.stroke(); } ctx.fillText(text,tX,tY); ctx.restore(); } drawText(ctx,x,y,text,fontStyle="24px Console",fontColor = "#555",Overline = false) { let textSize = this.textSize(ctx,text,fontStyle); ctx.save(); ctx.font = fontStyle; ctx.fillStyle = fontColor; ctx.fillText(text,x,y); if (Overline) { ctx.strokeStyle = fontColor; ctx.beginPath(); ctx.moveTo(x,y-textSize.height-2); ctx.lineTo(x+textSize.width,y-textSize.height-2); ctx.stroke(); } ctx.restore(); } } class ContainerConnection { constructor(fromElementContainer,toElementContainer,fromElement,toElement,input) { this.fromElementContainer = fromElementContainer; this.toElementContainer = toElementContainer; this.fromElement = fromElement; this.toElement = toElement; this.Input = input; } toJSON(key) { return { fromElement: (this.fromElement) ? this.fromElement.Designator : null, toElement: (this.toElement) ? this.toElement.Designator : null, Input: parseInt(this.Input) }; } } class elementContainer { constructor() { this.Elements = new Array(); this.Selected = false; this.Inputs = new Array(); this.Outputs = new Array(); this.StaticImages = {}; this.ICOutputs = 0; } isSelected(element) { if (this.Selected) { for (let a = 0; a < this.Selected.length; a++) { if (this.Selected[a] == element) return true; } } return false; } isHigh(element,input) { let isHigh = false; for (let a = 0; a < this.Elements.length; a++) { let conn = this.Elements[a].ConnectsTo(element,input); if (conn !== false) { if (this.Elements[a].getOutput(conn)) isHigh = true; } } return isHigh; } clearRedraw() { for (let a = 0; a < this.Elements.length; a++) { this.Elements[a].redraw = false; } } toJSON(key) { let elements = new Array(); for (let a = 0; a < this.Elements.length; a++) { elements.push(this.Elements[a].toJSON()); } return elements; } AddElement(element) { let designatorNumber = 1; let designatorTest = element.Name + designatorNumber; let unused = false; while (!unused) { let foundMatch = false; for (let a=0;a < this.Elements.length;a++) { if (this.Elements[a].Designator == designatorTest) foundMatch = true; } if (foundMatch) { designatorNumber++; designatorTest = element.Name + designatorNumber; } else { unused = true; element.Designator = designatorTest; if (logicEngine.ActiveContainer === this) { element.clearStatic(); element.drawElement(0, 0, element.StaticCtx); } this.Elements.push(element); } } } DeleteElement(element) { // Can pass object or Designator, or array if (Array.isArray(element)) { let returnval = false; for (let a = 0; a < element.length; a++) { for (let b = 0; b < this.Elements.length; b++) { if ((this.Elements[b] == element[a]) || (this.Elements[b].Designator == element[a])) { this.Elements[b].Delete(); this.Elements.splice(b, 1); b--; returnval = true; } } } return returnval; } else { for (let a = 0; a < this.Elements.length; a++) { if ((this.Elements[a] == element) || (this.Elements[a].Designator == element)) { this.Elements[a].Delete(); this.Elements.splice(a, 1); return true; } } return false; } } HasElement(element) { // Can pass object or Designator for (let a = 0; a < this.Elements.length; a++) { if ((this.Elements[a] == element) || (this.Elements[a].Designator == element)) { return this.Elements[a]; } } return false; } Disconnect(element) { if (!element) return false; if (Array.isArray(element)) { for (let a = 0; a < this.Elements.length; a++) { for (let b = 0; b < element.length; b++) { this.Elements[a].Disconnect(element[b]); } } } else { for (let a = 0; a < this.Elements.length; a++) { this.Elements[a].Disconnect(element); } } } DrawAll(ctx,settings) { let ICOuts = 0; if (!logicEngine.Settings.TopConnections && !logicEngine.Settings.HideConnections) { for (let a = 0; a < this.Elements.length; a++) { // Not ideal to loop twice but we need the connections drawn all at once to prevent layer issues this.Elements[a].drawConnections(ctx, settings); } } for (let a = 0; a < this.Elements.length; a++) { if (this.Elements[a] instanceof ICOutput) ICOuts++; if (this.Elements[a].isVisible()) { ctx.save(); if (this.isSelected(this.Elements[a])) this.Elements[a].drawBorderBox(ctx, this.Elements[a].X - 2, this.Elements[a].Y - 2, this.Elements[a].Width + 4, this.Elements[a].Height + 4, 1, "rgba(100,200,255,0.25)", "rgba(100,200,255,0.25)"); //this.Elements[a].drawElement(this.Elements[a].X, this.Elements[a].Y, ctx); ctx.drawImage(this.Elements[a].StaticCanvas,this.Elements[a].X,this.Elements[a].Y); ctx.restore(); } } this.ICOutputs = ICOuts; if (!this.Selected) { if (this.Selected.length == 1) { let PropertiesBox = document.getElementById("PropertiesBox"); if (PropertiesBox.style.display != "none") PropertiesBox.style.display = "none"; } } if (logicEngine.Settings.TopConnections && !logicEngine.Settings.HideConnections) { for (let a = 0; a < this.Elements.length; a++) { // Not ideal to loop twice but we need the connections drawn all at once to prevent layer issues this.Elements[a].drawConnections(ctx, settings); } } } SelectWithin(x1,y1,x2,y2) { let selectedArray = new Array(); for (let a = 0; a < this.Elements.length; a++) { if ((this.Elements[a].X >= x1) && ((this.Elements[a].X + this.Elements[a].Width) <= x2) && (this.Elements[a].Y >= y1) && ((this.Elements[a].Y + this.Elements[a].Height) <= y2)) selectedArray.push(this.Elements[a]); } this.Selected = selectedArray; } Select(element) { this.Selected = new Array(element); let PropertiesBox = document.getElementById("PropertiesBox"); let PropertiesBoxTitle = document.getElementById("PropertiesBoxTitle"); let PropertiesBoxContent = document.getElementById("PropertiesBoxContent"); PropertiesBoxTitle.innerText = this.Selected[0].Designator + " Properties"; let contentString = "
" + this.Selected[0].Properties[a].Name + " | "; switch (this.Selected[0].Properties[a].Type) { case "button": contentString += ""; break; case "int": contentString += ""; break; case "string": contentString += ''; break; case "color": contentString += ''; break; case "list": contentString += ''; break; } contentString += " |