😡 component removing 👈
This commit is contained in:
parent
6e93a23ec2
commit
d7d20b2360
BIN
src/assets/or_gate.png
Normal file
BIN
src/assets/or_gate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
src/assets/xor_gate.png
Normal file
BIN
src/assets/xor_gate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -8,8 +8,8 @@
|
|||
<link rel='stylesheet' href='style.css'>
|
||||
</head>
|
||||
|
||||
<body ondragstart="return false;" ondrop="return false;">
|
||||
hello world
|
||||
<body ondragstart="return false;" ondrop="return false;" oncontextmenu="return false">
|
||||
loading
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,7 +1,7 @@
|
|||
@import "./toastr.scss";
|
||||
@import "./modal.scss";
|
||||
|
||||
$mdc-theme-primary: orange / 2;
|
||||
$mdc-theme-primary: orange;
|
||||
$mdc-theme-secondary: #feeae6;
|
||||
$mdc-theme-on-primary: white;
|
||||
$mdc-theme-surface: black;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { Singleton } from "@eix/utils";
|
||||
import { activationFunction, activationFunctionParam } from "./interfaces"
|
||||
import { toActivationFunction } from "./toActivation";
|
||||
|
||||
@Singleton
|
||||
export class FunctionStore {
|
||||
functions = new Map<string, activationFunction>()
|
||||
|
||||
private storageKeyword: string
|
||||
|
||||
constructor(name="activation") {
|
||||
this.storageKeyword =`/${name}`
|
||||
for (let i in localStorage) {
|
||||
if (i.indexOf(this.storageKeyword) == 0)
|
||||
this.register(i.substr(this.storageKeyword.length), localStorage[i])
|
||||
}
|
||||
}
|
||||
|
||||
register(name: string, activation: activationFunctionParam) {
|
||||
this.functions.set(name, toActivationFunction(activation))
|
||||
localStorage[`${this.storageKeyword.substr(1)}/${name}`] = activation
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from "./toActivation"
|
|
@ -1,4 +0,0 @@
|
|||
export type activationInput = any[]
|
||||
export type activationOutput = boolean
|
||||
export type activationFunctionParam = ( (data:activationInput) => activationOutput ) | string
|
||||
export type activationFunction = (data:activationInput) => activationOutput
|
|
@ -1,8 +0,0 @@
|
|||
import { activationFunctionParam, activationFunction } from "./interfaces";
|
||||
|
||||
export const toActivationFunction = (original: activationFunctionParam) => {
|
||||
const stringified = (typeof original == "string") ? original : original.toString()
|
||||
const final = new Function(`return ${stringified}`) as () => activationFunction
|
||||
|
||||
return final()
|
||||
}
|
|
@ -11,6 +11,7 @@ import { alertOptions } from "../componentManager/alertOptions";
|
|||
import { WireManager } from "../wires";
|
||||
import { runCounter } from "./runCounter";
|
||||
import { Material } from "./material";
|
||||
import { manager } from "../../main";
|
||||
|
||||
export class Component {
|
||||
private static store = new ComponentTemplateStore()
|
||||
|
@ -76,9 +77,9 @@ export class Component {
|
|||
this.subscriptions.push(subscription)
|
||||
})
|
||||
|
||||
this.activate()
|
||||
|
||||
this.material = new Material(data.material.mode, data.material.data)
|
||||
|
||||
this.activate()
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
|
@ -110,16 +111,29 @@ export class Component {
|
|||
}
|
||||
|
||||
handleClick(e: MouseEvent) {
|
||||
const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY)
|
||||
console.log(e.button)
|
||||
|
||||
this.mouserDelta = this.position.value.map((value, index) =>
|
||||
mousePosition[index] - value
|
||||
)
|
||||
this.clicked = true
|
||||
this.clickedChanges.next(this.clicked)
|
||||
if (e.button === 0) {
|
||||
const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY)
|
||||
|
||||
this.activate(1)
|
||||
this.activate(0)
|
||||
this.mouserDelta = this.position.value.map((value, index) =>
|
||||
mousePosition[index] - value
|
||||
)
|
||||
this.clicked = true
|
||||
this.clickedChanges.next(this.clicked)
|
||||
|
||||
this.activate(1)
|
||||
this.activate(0)
|
||||
}
|
||||
|
||||
else if (e.button === 2){
|
||||
manager.components = manager.components.filter(val => val !== this)
|
||||
manager.wireManager.wires
|
||||
.filter(val => val.input.of === this || val.output.of === this)
|
||||
.forEach(val => val.dispose())
|
||||
manager.wireManager.update.next(true)
|
||||
manager.update()
|
||||
}
|
||||
}
|
||||
|
||||
handlePinClick(e: MouseEvent, pin: Pin) {
|
||||
|
|
|
@ -11,7 +11,9 @@ export class Material {
|
|||
private static images: {
|
||||
[key: string]: string
|
||||
} = {
|
||||
and: require("../../../assets/and_gate.jpg")
|
||||
and: require("../../../assets/and_gate.jpg"),
|
||||
or: require("../../../assets/or_gate.png"),
|
||||
xor: require("../../../assets/xor_gate.png")
|
||||
}
|
||||
|
||||
private static cached = new Map()
|
||||
|
|
|
@ -26,13 +26,13 @@ export class ComponentManager {
|
|||
public svgs = new Subject<SVGTemplateResult>()
|
||||
public placeholder = new BehaviorSubject("Create simulation")
|
||||
public barAlpha = new BehaviorSubject<string>("0");
|
||||
public wireManager = new WireManager()
|
||||
|
||||
private temporaryCommnad = ""
|
||||
private onTop: Component
|
||||
private clicked = false
|
||||
|
||||
private screen = new Screen()
|
||||
private wireManager = new WireManager()
|
||||
private templateStore = new ComponentTemplateStore()
|
||||
private settings = new Settings()
|
||||
private standard: {
|
||||
|
@ -53,7 +53,7 @@ export class ComponentManager {
|
|||
private palleteEvent = new KeyboardInput("p")
|
||||
private shiftEvent = new KeyboardInput("shift")
|
||||
private refreshEvent = new KeyboardInput("r")
|
||||
private clearEvent = new KeyboardInput("c")
|
||||
private clearEvent = new KeyboardInput("delete")
|
||||
private upEvent = new KeyboardInput("up")
|
||||
private downEvent = new KeyboardInput("down")
|
||||
|
||||
|
@ -99,6 +99,17 @@ export class ComponentManager {
|
|||
public gates = this.templateStore.store.lsChanges
|
||||
public saves = this.store.lsChanges
|
||||
|
||||
public file: {
|
||||
[key: string]: () => void
|
||||
} = {
|
||||
clear: () => this.clear(),
|
||||
clean: () => this.smartClear(),
|
||||
save: () => this.save(),
|
||||
refresh: () => this.refresh(),
|
||||
download: () => download(this,[],[]),
|
||||
delete: () => this.delete(this.name)
|
||||
}
|
||||
|
||||
constructor() {
|
||||
runCounter.increase()
|
||||
|
||||
|
@ -158,12 +169,6 @@ export class ComponentManager {
|
|||
this.inputMode = "command"
|
||||
this.placeholder.next("Command palette")
|
||||
}
|
||||
else if (this.clearEvent.value) {
|
||||
if (this.shiftEvent.value)
|
||||
this.clear()
|
||||
else
|
||||
this.smartClear()
|
||||
}
|
||||
else if (this.saveEvent.value) {
|
||||
this.save()
|
||||
}
|
||||
|
@ -171,6 +176,12 @@ export class ComponentManager {
|
|||
this.refresh()
|
||||
}
|
||||
}
|
||||
else if (this.clearEvent.value) {
|
||||
if (this.shiftEvent.value)
|
||||
this.clear()
|
||||
else
|
||||
this.smartClear()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -104,6 +104,32 @@ export class ComponentTemplateStore {
|
|||
data: "and"
|
||||
}
|
||||
})
|
||||
this.store.set("or", {
|
||||
inputs: 2,
|
||||
outputs: 1,
|
||||
name: "or",
|
||||
version: "1.0.0",
|
||||
activation: `
|
||||
ctx.outputs[0].value = ctx.inputs[0].value || ctx.inputs[1].value
|
||||
`.trim(),
|
||||
material: {
|
||||
mode: "standard_image",
|
||||
data: "or"
|
||||
}
|
||||
})
|
||||
this.store.set("xor", {
|
||||
inputs: 2,
|
||||
outputs: 1,
|
||||
name: "xor",
|
||||
version: "1.0.0",
|
||||
activation: `
|
||||
ctx.outputs[0].value = (ctx.inputs[0].value || ctx.inputs[1].value) && !(ctx.inputs[0].value && ctx.inputs[1].value)
|
||||
`.trim(),
|
||||
material: {
|
||||
mode: "standard_image",
|
||||
data: "xor"
|
||||
}
|
||||
})
|
||||
this.store.set("true", {
|
||||
inputs: 0,
|
||||
outputs: 1,
|
||||
|
@ -161,7 +187,7 @@ export class ComponentTemplateStore {
|
|||
onclick: `
|
||||
ctx.outputs[0].memory.value = !ctx.outputs[0].memory.value
|
||||
if (ctx.outputs[0].memory.value)
|
||||
ctx.color("#880000")
|
||||
ctx.color("#550000")
|
||||
else
|
||||
ctx.color("red")
|
||||
`
|
||||
|
|
|
@ -36,12 +36,16 @@ export const modal = (options: Partial<confirmModalOptions>) => new Promise((res
|
|||
${content}
|
||||
</div>
|
||||
<footer class="mdc-dialog__actions">
|
||||
<button type="button" class="mdc-button mdc-dialog__button" id="no-${id}">
|
||||
<span class="mdc-button__label">${no}</span>
|
||||
</button>
|
||||
<button type="button" class="mdc-button mdc-dialog__button" id="yes-${id}">
|
||||
<span class="mdc-button__label">${yes}</span>
|
||||
</button>
|
||||
${(no !== "") ?
|
||||
html`<button type="button" class="mdc-button mdc-dialog__button" id="no-${id}">
|
||||
<span class="mdc-button__label">${no}</span>
|
||||
</button>` : no
|
||||
}
|
||||
${(yes !== "") ?
|
||||
html`<button type="button" class="mdc-button mdc-dialog__button" id="yes-${id}">
|
||||
<span class="mdc-button__label">${yes}</span>
|
||||
</button>` : yes
|
||||
}
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,5 +11,7 @@ export class Wire {
|
|||
public dispose(){
|
||||
this.output.unbind(this.input)
|
||||
this.input.pair = null
|
||||
this.input.update()
|
||||
this.output.update()
|
||||
}
|
||||
}
|
|
@ -51,6 +51,12 @@ export class WireManager {
|
|||
return true
|
||||
}
|
||||
|
||||
private remove(target: Wire) {
|
||||
target.dispose()
|
||||
this.wires = this.wires.filter(val => val !== target)
|
||||
this.update.next(true)
|
||||
}
|
||||
|
||||
get svg() {
|
||||
return this.wires.map(val => {
|
||||
const i = val.input.of
|
||||
|
@ -61,6 +67,8 @@ export class WireManager {
|
|||
y1=${subscribe(i.piny(false,i.outputPins.indexOf(val.input)))}
|
||||
y2=${subscribe(o.piny(true,o.inputPins.indexOf(val.output)))}
|
||||
stroke=${subscribe(val.input.svgColor)}
|
||||
stroke-width=10
|
||||
@click=${() => this.remove(val)}
|
||||
>
|
||||
</line>
|
||||
`})
|
||||
|
|
|
@ -2,17 +2,47 @@ import { render, html, svg } from "lit-html"
|
|||
import { subscribe } from "lit-rx"
|
||||
import { Screen } from "./common/screen.ts";
|
||||
import { Component } from "./common/component";
|
||||
import { FunctionStore } from "./common/activation/activationStore";
|
||||
import { ComponentManager } from "./common/componentManager";
|
||||
import { map } from "rxjs/operators";
|
||||
import { MDCMenu } from '@material/menu';
|
||||
import { error } from "toastr"
|
||||
import { modal } from "./common/modals";
|
||||
|
||||
const screen = new Screen()
|
||||
|
||||
const manager = new ComponentManager()
|
||||
export const manager = new ComponentManager()
|
||||
manager.save()
|
||||
manager.update()
|
||||
|
||||
window.onerror = (message: string, url: string, lineNumber: number): boolean => {
|
||||
error(message,"",{
|
||||
...manager.alertOptions,
|
||||
onclick: () => modal({
|
||||
no: "",
|
||||
yes: "close",
|
||||
title: "Error",
|
||||
content: html`
|
||||
<table>
|
||||
<tr>
|
||||
<td>Url:</td>
|
||||
<td>${url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Message:</td>
|
||||
<td>${message}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Line:</td>
|
||||
<td>${lineNumber}</td>
|
||||
</tr>
|
||||
</table>
|
||||
`
|
||||
})
|
||||
})
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleEvent = <T>(e: T, func: (e: T) => any) => {
|
||||
if (manager.barAlpha.value == "0")
|
||||
func(e)
|
||||
|
@ -75,6 +105,12 @@ render(html`
|
|||
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">add</i>
|
||||
<span class="mdc-list-item__text">Add logic gate</span>
|
||||
</a>
|
||||
<a class="mdc-list-item" href="#" id="openFile" @click=${() => {
|
||||
menus[2].open = true
|
||||
}}>
|
||||
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">insert_drive_file</i>
|
||||
<span class="mdc-list-item__text">File</span>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
@ -86,7 +122,7 @@ render(html`
|
|||
<span class="mdc-list-item__text"> ${val} </span>
|
||||
<span class="material-icons mdc-list-item__meta" @click=${() => manager.delete(val)}> delete </span>
|
||||
</li>`
|
||||
))))}
|
||||
))))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -96,14 +132,29 @@ render(html`
|
|||
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.add(val)}>
|
||||
<span class="mdc-list-item__text"> ${val} </span>
|
||||
</li>`
|
||||
))))}
|
||||
))))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="mdc-menu mdc-menu-surface mdc-theme--primary-bg mdc-theme--on-primary" id="fileMenu">
|
||||
<ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
||||
${[...Object.keys(manager.file)].sort().map(key => html`
|
||||
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.file[key]()}>
|
||||
<span class="mdc-list-item__text"> ${key} </span>
|
||||
</li>`
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
`, document.body)
|
||||
|
||||
const menus = [new MDCMenu(document.querySelector('#saveMenu')), new MDCMenu(document.querySelector('#gateMenu'))]
|
||||
const menus = [
|
||||
new MDCMenu(document.querySelector('#saveMenu')),
|
||||
new MDCMenu(document.querySelector('#gateMenu')),
|
||||
new MDCMenu(document.querySelector('#fileMenu'))
|
||||
]
|
||||
menus.forEach(menu => menu.hoistMenuToBody())
|
||||
menus[0].setAnchorElement(document.querySelector(`#openSimulation`))
|
||||
menus[1].setAnchorElement(document.querySelector("#openGates"))
|
||||
menus[2].setAnchorElement(document.querySelector("#openFile"))
|
||||
|
||||
manager.update()
|
Loading…
Reference in a new issue