diff --git a/README.md b/README.md index 2002c4c..f313df3 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,13 @@ To be decided, but at this moment this code is open source and free to use for n * You can now pan the work area, hold ctrl key while mouse dragging an empty area. * Right Click Menu * If an item is selected you can delete or disconnect them (BUG WIP: Doesn't disconnect IC's) +* Top menu + * New / Open / Save moved to File menu + * There is now a pan to center feature in View menu + * Create IC has been moved to Tools menu + * Help menu -> About opens the Welcome Window * Save dialog +* Fixed bug ### 0.3.10 * Added BCD and Decimal options to the 4 bit output display, as well as bit labels in inputs diff --git a/css/main.css b/css/main.css index ce78f70..59e51fa 100644 --- a/css/main.css +++ b/css/main.css @@ -281,7 +281,7 @@ textarea { } #top-bar { - height: 50px; + height: 80px; overflow: none; margin: 0px; padding: 0px; @@ -408,7 +408,7 @@ textarea { padding: 5px; } -#RightClickMenu { +#RightClickMenu, .top-menu-div { display: none; position: absolute; left: 0px; @@ -418,12 +418,52 @@ textarea { z-index: 9999999999; } -#RightClickMenu ul { +#top-menu { + border-bottom: 3px ridge #54545d; +} + +#top-menu a { + text-decoration: none; + width: 100%; + height: 100%; +} +#top-menu a:visited { + color: #ddd; +} +#top-menu ul { + margin: 0px; + padding: 0px; + font-size: 0.5em; +} + +#top-menu li { + display: inline-block; + cursor: default; + text-decoration: none; + list-style-type: none; + margin: 0px; + padding: 2px; + padding-left: 10px; + padding-right: 10px; +} + +.top-menu-div { + font-size: 2em; +} + +#top-menu li span { + display: inline-block; + padding-left: 10px; + float: right; +} + +#RightClickMenu ul, .top-menu-div ul { margin: 0px; padding: 0px; } -#RightClickMenu li { +#RightClickMenu li, .top-menu-div li { + display: block !important; cursor: default; text-decoration: none; list-style-type: none; @@ -433,19 +473,19 @@ textarea { padding-right: 30px; } -#RightClickMenu li:hover { +#RightClickMenu li:hover, .top-menu-div li:hover { background-color: #222222; } -#RightClickMenu .disabled { +#RightClickMenu .disabled, #top-menu .disabled { color: #777777; } -.rcm_seperator:hover { +.rcm_seperator:hover, .tfm_seperator:hover { background-color: transparent !important; } -.rcm_seperator { +.rcm_seperator, .tfm_seperator { height: 2px; margin-bottom: 7px; border-bottom: 2px groove #54545d; diff --git a/index.html b/index.html index e3652da..bd6ae89 100644 --- a/index.html +++ b/index.html @@ -28,24 +28,79 @@

Welcome to logic.parts, a free to use logic simulator for anyone to use. This is opensource software, you can find the project at https://www.mygit.space/MatCat.OpenSource/BrowserLogic. This is an early development project, so expect bugs and some things to not work :) If you would like to contribute please feel free to find me on IRC on Freenode in channel #LogicParts.


- + + +
-
-     -     - - +
+
    +
  • File +
    +
      +
    • New
    • +
    • Open
    • +
    • Save
    • +
    • Save As
    • +
    +
    +
  • +
  • Edit +
    +
      +
    • Undo
    • +
    • Redo
    • +
    • +
    • Cut
    • +
    • Copy
    • +
    • Paste
    • +
    • +
    • Delete
    • +
    • Disconnect
    • +
    • +
    • Select All
    • +
    +
    +
  • +
  • View +
    +
      +
    • Pan to Center
    • +
    • +
    • Show Grid
    • +
    • Snap to Grid
    • +
    • Grid Size
    • +
    +
    +
  • +
  • Tools +
    +
      +
    • Create IC
    • +
    +
    +
  • +
  • Help +
    + +
    +
  • +
-
- MatCat BrowserLogic +
+
+ MatCat BrowserLogic +
LOADING
-
diff --git a/js/elements.js b/js/elements.js index 74c83f2..4dac5f2 100644 --- a/js/elements.js +++ b/js/elements.js @@ -771,7 +771,7 @@ class ICElement extends Element { ctx.fill(); ctx.stroke(); let textSize = false; - if (ctx,this.InputConnections[a]) textSize = this.textSize(ctx,this.InputConnections[a].toElement.Properties[0].CurrentValue,"10px Console"); + if (ctx,this.Outputs[a]) textSize = this.textSize(ctx,this.Outputs[a].fromElement.Properties[0].CurrentValue,"10px Console"); this.drawText(ctx,(x+(this.Width-10)) - (textSize.width + 5 + (this.outputCircleRadius*2)),(firstY + (a*24)) + 5,this.Outputs[a].fromElement.Properties[0].CurrentValue,"10px Console","#000"); } ctx.restore(); diff --git a/js/globalfunctions.js b/js/globalfunctions.js index 25be5ea..a178de0 100644 --- a/js/globalfunctions.js +++ b/js/globalfunctions.js @@ -183,11 +183,21 @@ function disableSelectedRCMs(bool) { } } +function hideMenus() { + let tds = document.getElementsByClassName("top-menu-div"); + for (let a = 0; a < tds.length; a++) { + tds[a].setAttribute('style','display: none;'); + } + +} + function createSaveState(container = false) { let saveState = { Name: "LogicDesign", Version: Version, Timestamp: Date.now(), + PanX: logicEngine.Panning.OffsetX, + PanY: logicEngine.Panning.OffsetY, Elements: new Array() }; if (container.Elements.length > 0) saveState.Elements = container.Elements; @@ -299,5 +309,10 @@ function loadsave(savedata) { let saveName = document.getElementById("saveName"); saveName.value = savedata.Name; logicEngine.ActiveContainer = newContainer; + if (savedata.PanX) { + logicEngine.Panning.OffsetX = savedata.PanX; + logicEngine.Panning.OffsetY = savedata.PanY; + logicEngine.Ctx.translate(logicEngine.Panning.OffsetX,logicEngine.Panning.OffsetY); + } return true; } diff --git a/js/logicengine.js b/js/logicengine.js index a3dfdef..8c4c4ab 100644 --- a/js/logicengine.js +++ b/js/logicengine.js @@ -10,6 +10,8 @@ class LogicEngineSettings { this.ShadowColor = "#222"; this.InputCircleSize = 10; this.OutputCircleSize = 10; + this.ShowGrid = true; + this.SnapGrid = true; this.GridSize = 20; } } @@ -17,34 +19,40 @@ class LogicEngineSettings { class LogicEngine { Resize(evt) { let leftmenu = document.getElementById("left-menu"); - leftmenu.style.height = (window.innerHeight - 52) + "px"; + let topbar = document.getElementById("top-bar"); + console.log(topbar); + console.log("Top bar height " + topbar.scrollHeight); + leftmenu.style.height = (window.innerHeight - (topbar.scrollHeight + 2)) + "px"; this.Canvas.width = window.innerWidth - 205; - this.Canvas.height = window.innerHeight - 50; + this.Canvas.height = window.innerHeight - topbar.scrollHeight; this.Mouse = false; let gridPlane = document.getElementById("GridPlane"); + gridPlane.style.top = topbar.scrollHeight + "px"; + this.Canvas.style.top = topbar.scrollHeight + "px"; gridPlane.width = this.Canvas.width; gridPlane.height = this.Canvas.height; let Ctx = gridPlane.getContext("2d"); - Ctx.save(); - let gridWidth = this.Settings.GridSize; - for (let x = gridWidth;x < (this.Canvas.width); x+= gridWidth) { - Ctx.beginPath(); - Ctx.moveTo(x,0); - Ctx.lineTo(x,this.Canvas.height); - Ctx.strokeStyle = "#777"; - Ctx.lineWidth = "1"; - Ctx.stroke(); + if (this.Settings.ShowGrid) { + Ctx.save(); + let gridWidth = this.Settings.GridSize; + for (let x = gridWidth; x < (this.Canvas.width); x += gridWidth) { + Ctx.beginPath(); + Ctx.moveTo(x, 0); + Ctx.lineTo(x, this.Canvas.height); + Ctx.strokeStyle = "#777"; + Ctx.lineWidth = "1"; + Ctx.stroke(); + } + for (let y = gridWidth; y < (this.Canvas.height); y += gridWidth) { + Ctx.beginPath(); + Ctx.moveTo(0, y); + Ctx.lineTo(this.Canvas.width, y); + Ctx.lineWidth = "1"; + Ctx.strokeStyle = "#777"; + Ctx.stroke(); + } + Ctx.restore(); } - for (let y = gridWidth;y < (this.Canvas.height); y+= gridWidth) { - Ctx.beginPath(); - Ctx.moveTo(0,y); - Ctx.lineTo(this.Canvas.width,y); - Ctx.lineWidth = "1"; - Ctx.strokeStyle = "#777"; - Ctx.stroke(); - } - Ctx.restore(); - } PropertyChange(property) { @@ -54,32 +62,34 @@ class LogicEngine { } Mouse_Down(evt) { - let mousePos = getMousePos(this.Canvas, evt); - this.MouseDownTime = performance.now(); - let element = this.ActiveContainer.checkMouseBounds(mousePos); - if (element) { - this.MouseDown = true; - this.ActiveContainer.Select(element); - this.MovingElement = element; - this.MovingElementStartX = element.X; - this.MovingElementStartY = element.Y; - this.MovingElementMouseStartX = mousePos.x; - this.MovingElementMouseStartY = mousePos.y; - element.MouseDown(mousePos); - } else { - this.MouseDown = true; - this.ActiveLink = false; - if (this.ControlPressed) { - this.Panning.StartOffsetX = this.Panning.OffsetX; - this.Panning.StartOffsetY = this.Panning.OffsetY; - this.Panning.StartX = mousePos.x; - this.Panning.StartY = mousePos.y; + if (evt.which === 1) { + let mousePos = getMousePos(this.Canvas, evt); + this.MouseDownTime = performance.now(); + let element = this.ActiveContainer.checkMouseBounds(mousePos); + if (element) { + this.MouseDown = true; + this.ActiveContainer.Select(element); + this.MovingElement = element; + this.MovingElementStartX = element.X; + this.MovingElementStartY = element.Y; + this.MovingElementMouseStartX = mousePos.x; + this.MovingElementMouseStartY = mousePos.y; + element.MouseDown(mousePos); + } else { + this.MouseDown = true; + this.ActiveLink = false; + if (this.ControlPressed) { + this.Panning.StartOffsetX = this.Panning.OffsetX; + this.Panning.StartOffsetY = this.Panning.OffsetY; + this.Panning.StartX = mousePos.x; + this.Panning.StartY = mousePos.y; + } + } + if (this.ActiveContainer.Selected) { + disableSelectedRCMs(false); + } else { + disableSelectedRCMs(true); } - } - if (this.ActiveContainer.Selected) { - disableSelectedRCMs(false); - } else { - disableSelectedRCMs(true); } } @@ -93,7 +103,7 @@ class LogicEngine { } //console.log("Mouse Up"); } - if (!this.MovingElement) this.ActiveContainer.Selected = false; + if (!this.MovingElement && evt.which === 1) this.ActiveContainer.Selected = false; this.MovingElement = false; this.MouseDown = false; @@ -118,8 +128,8 @@ class LogicEngine { let diffyOffset = this.MovingElementMouseStartY - this.MovingElementStartY; let actualPosX = (this.MovingElementMouseStartX + xOffset) - diffxOffset; let actualPosY = (this.MovingElementMouseStartY + yOffset) - diffyOffset; - if (!this.ControlPressed) actualPosX = Math.round(actualPosX/this.Settings.GridSize)*this.Settings.GridSize; - if (!this.ControlPressed) actualPosY = Math.round(actualPosY/this.Settings.GridSize)*this.Settings.GridSize; + if (!this.ControlPressed && this.Settings.SnapGrid) actualPosX = Math.round(actualPosX/this.Settings.GridSize)*this.Settings.GridSize; + if (!this.ControlPressed && this.Settings.SnapGrid) actualPosY = Math.round(actualPosY/this.Settings.GridSize)*this.Settings.GridSize; this.MovingElement.X = actualPosX; this.MovingElement.Y = actualPosY; } @@ -227,12 +237,12 @@ class LogicEngine { this.Ctx.clearRect(0- this.Panning.OffsetX,0- this.Panning.OffsetY,this.Canvas.width,this.Canvas.height); this.ActiveContainer.DrawAll(this.Ctx,this.Settings); - let btn_CreateIC = document.getElementById("btn_CreateIC"); + let tfm_CreateIC = document.getElementById("tfm_CreateIC"); let rcm_CreateIC = document.getElementById("rcm_CreateIC"); - btn_CreateIC.disabled = true; + tfm_CreateIC.classList.add("disabled"); rcm_CreateIC.classList.add("disabled"); - if (this.ActiveContainer.ICOutputs > 0) btn_CreateIC.disabled = false; + if (this.ActiveContainer.ICOutputs > 0) tfm_CreateIC.classList.remove("disabled"); if (this.ActiveContainer.ICOutputs > 0) rcm_CreateIC.classList.remove("disabled"); if (this.ActiveLink) { let startX = this.ActiveLink.LinkOutLocation().x; diff --git a/js/main.js b/js/main.js index 2986ae8..c7f034f 100644 --- a/js/main.js +++ b/js/main.js @@ -28,6 +28,10 @@ window.addEventListener('keyup', function(evt) { window.addEventListener('mouseup', function(evt) { let rcm = document.getElementById("RightClickMenu"); rcm.style.display = "none"; + let tfms = document.getElementsByClassName("top-menu-div"); + for (let a = 0; a < tfms.length; a++) { + tfms[a].style.display = "none"; + } }, false); @@ -60,10 +64,15 @@ btn_CloseWelcome.addEventListener('click', function(evt) { } }, false); -let btn_CreateIC = document.getElementById("btn_CreateIC"); -btn_CreateIC.addEventListener('click', function(evt) { - let CreateICBox = document.getElementById("CreateICBox"); - CreateICBox.style.display = "block"; +let tfm_CreateIC = document.getElementById("tfm_CreateIC"); +tfm_CreateIC.addEventListener('click', function(evt) { + if (!tfm_CreateIC.classList.contains("disabled")) { + let CreateICBox = document.getElementById("CreateICBox"); + CreateICBox.style.display = "block"; + setTimeout(function () { + hideMenus() + }, 10); + } }); let rcm_CreateIC = document.getElementById("rcm_CreateIC"); @@ -102,9 +111,10 @@ ICDescription.addEventListener('input', function(evt){ if (ICName.value.length > 0 && ICDescription.value.length > 0) btn_CreateIC_Create.disabled = false; }); -let btn_New = document.getElementById("btn_New"); -btn_New.addEventListener('click', function(evt) { +let tfm_New = document.getElementById("tfm_New"); +tfm_New.addEventListener('click', function(evt) { logicEngine.ActiveContainer = new elementContainer(); + setTimeout(function(){hideMenus()},10); }); let rcm_New = document.getElementById("rcm_New"); @@ -124,13 +134,13 @@ rcm_Disconect.addEventListener('click', function(evt) { }); -let btn_Save = document.getElementById("btn_Save"); -btn_Save.addEventListener('click', function(evt) { - //download("mydeign.LogicParts",createSaveState(logicEngine.ActiveContainer)); +let tfm_Save = document.getElementById("tfm_Save"); +tfm_Save.addEventListener('click', function(evt) { let saveWindow = document.getElementById("SaveWindow"); saveWindow.style.display="block"; saveWindow.style.left = Math.round((window.innerWidth / 2) - (saveWindow.clientWidth/2)) + "px"; saveWindow.style.top = Math.round((window.innerHeight / 2) - (saveWindow.clientHeight/2)) + "px"; + setTimeout(function(){hideMenus()},10); }); let btn_SaveDesign = document.getElementById("btn_SaveDesign"); @@ -150,8 +160,9 @@ btn_Save_Cancel.addEventListener('click', function(evt) { }); let file_Load = document.getElementById("file_Load"); -let btn_Load = document.getElementById("btn_Load"); -btn_Load.addEventListener('click', function(evt) { +let tfm_Open = document.getElementById("tfm_Open"); +tfm_Open.addEventListener('click', function(evt) { + setTimeout(function(){hideMenus()},10); file_Load.click(); }); file_Load.addEventListener('change', function(evt) { @@ -184,14 +195,76 @@ file_Load.addEventListener('change', function(evt) { fread.readAsText(evt.target.files[0]); }, false); +let tfms = document.getElementsByClassName("top-menu-item"); +for (let a = 0; a < tfms.length; a++) { + tfms[a].addEventListener("click", function (evt) { + let tfm = document.getElementById(tfms[a].id + "Menu"); + let tfm_rect = tfms[a].getBoundingClientRect(); + tfm.style.left = (tfm_rect.left) + "px"; + tfm.style.top = (tfm_rect.top + tfm_rect.height) + "px"; + tfm.style.display = "block"; + }); +} + +let tfm_About = document.getElementById("tfm_About"); +tfm_About.addEventListener("click", function (evt) { + let WelcomeScreen = document.getElementById("WelcomeWindow"); + WelcomeScreen.style.display = "block"; + setTimeout(function(){hideMenus()},10); +}); + +let tfm_Pan2Center = document.getElementById("tfm_Pan2Center"); +tfm_Pan2Center.addEventListener("click", function (evt) { + logicEngine.Ctx.setTransform(1,0,0,1,0,0); + logicEngine.Panning.OffsetX = 0; + logicEngine.Panning.OffsetY = 0; + setTimeout(function(){hideMenus()},10); +}); + +let tfm_ShowGrid = document.getElementById("tfm_ShowGrid"); +tfm_ShowGrid.addEventListener("click", function (evt) { + if (logicEngine.Settings.ShowGrid) { + let sgSpan = tfm_ShowGrid.getElementsByTagName("span")[0]; + sgSpan.innerText = ""; + logicEngine.Settings.ShowGrid = false; + } else { + let sgSpan = tfm_ShowGrid.getElementsByTagName("span")[0]; + sgSpan.innerText = "✓"; + logicEngine.Settings.ShowGrid = true; + } + logicEngine.Resize(""); + //setTimeout(function(){hideMenus()},10); +}); + +let tfm_SnapGrid = document.getElementById("tfm_SnapGrid"); +tfm_SnapGrid.addEventListener("click", function (evt) { + if (logicEngine.Settings.SnapGrid) { + let sgSpan = tfm_SnapGrid.getElementsByTagName("span")[0]; + sgSpan.innerText = ""; + logicEngine.Settings.SnapGrid = false; + } else { + let sgSpan = tfm_SnapGrid.getElementsByTagName("span")[0]; + sgSpan.innerText = "✓"; + logicEngine.Settings.SnapGrid = true; + } + logicEngine.Resize(""); + //setTimeout(function(){hideMenus()},10); +}); + +let in_GridSize = document.getElementById("in_GridSize"); +in_GridSize.addEventListener("change", function (evt) { + logicEngine.Settings.GridSize = parseInt(in_GridSize.value); + logicEngine.Resize(""); + //setTimeout(function(){hideMenus()},10); +}); + + document.addEventListener( "contextmenu", function(evt) { evt.preventDefault(); let rcm = document.getElementById("RightClickMenu"); rcm.style.left = (evt.clientX-40) + "px"; rcm.style.top = (evt.clientY-25) + "px"; - console.log(rcm.style); rcm.style.display = "block"; - console.log(evt); });