😡 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'>
|
<link rel='stylesheet' href='style.css'>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body ondragstart="return false;" ondrop="return false;">
|
<body ondragstart="return false;" ondrop="return false;" oncontextmenu="return false">
|
||||||
hello world
|
loading
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -1,7 +1,7 @@
|
||||||
@import "./toastr.scss";
|
@import "./toastr.scss";
|
||||||
@import "./modal.scss";
|
@import "./modal.scss";
|
||||||
|
|
||||||
$mdc-theme-primary: orange / 2;
|
$mdc-theme-primary: orange;
|
||||||
$mdc-theme-secondary: #feeae6;
|
$mdc-theme-secondary: #feeae6;
|
||||||
$mdc-theme-on-primary: white;
|
$mdc-theme-on-primary: white;
|
||||||
$mdc-theme-surface: black;
|
$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 { WireManager } from "../wires";
|
||||||
import { runCounter } from "./runCounter";
|
import { runCounter } from "./runCounter";
|
||||||
import { Material } from "./material";
|
import { Material } from "./material";
|
||||||
|
import { manager } from "../../main";
|
||||||
|
|
||||||
export class Component {
|
export class Component {
|
||||||
private static store = new ComponentTemplateStore()
|
private static store = new ComponentTemplateStore()
|
||||||
|
@ -76,9 +77,9 @@ export class Component {
|
||||||
this.subscriptions.push(subscription)
|
this.subscriptions.push(subscription)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.activate()
|
|
||||||
|
|
||||||
this.material = new Material(data.material.mode, data.material.data)
|
this.material = new Material(data.material.mode, data.material.data)
|
||||||
|
|
||||||
|
this.activate()
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
|
@ -110,6 +111,9 @@ export class Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick(e: MouseEvent) {
|
handleClick(e: MouseEvent) {
|
||||||
|
console.log(e.button)
|
||||||
|
|
||||||
|
if (e.button === 0) {
|
||||||
const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY)
|
const mousePosition = Component.screen.getWorldPosition(e.clientX, e.clientY)
|
||||||
|
|
||||||
this.mouserDelta = this.position.value.map((value, index) =>
|
this.mouserDelta = this.position.value.map((value, index) =>
|
||||||
|
@ -122,6 +126,16 @@ export class Component {
|
||||||
this.activate(0)
|
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) {
|
handlePinClick(e: MouseEvent, pin: Pin) {
|
||||||
Component.wireManager.add(pin)
|
Component.wireManager.add(pin)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,9 @@ export class Material {
|
||||||
private static images: {
|
private static images: {
|
||||||
[key: string]: string
|
[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()
|
private static cached = new Map()
|
||||||
|
|
|
@ -26,13 +26,13 @@ export class ComponentManager {
|
||||||
public svgs = new Subject<SVGTemplateResult>()
|
public svgs = new Subject<SVGTemplateResult>()
|
||||||
public placeholder = new BehaviorSubject("Create simulation")
|
public placeholder = new BehaviorSubject("Create simulation")
|
||||||
public barAlpha = new BehaviorSubject<string>("0");
|
public barAlpha = new BehaviorSubject<string>("0");
|
||||||
|
public wireManager = new WireManager()
|
||||||
|
|
||||||
private temporaryCommnad = ""
|
private temporaryCommnad = ""
|
||||||
private onTop: Component
|
private onTop: Component
|
||||||
private clicked = false
|
private clicked = false
|
||||||
|
|
||||||
private screen = new Screen()
|
private screen = new Screen()
|
||||||
private wireManager = new WireManager()
|
|
||||||
private templateStore = new ComponentTemplateStore()
|
private templateStore = new ComponentTemplateStore()
|
||||||
private settings = new Settings()
|
private settings = new Settings()
|
||||||
private standard: {
|
private standard: {
|
||||||
|
@ -53,7 +53,7 @@ export class ComponentManager {
|
||||||
private palleteEvent = new KeyboardInput("p")
|
private palleteEvent = new KeyboardInput("p")
|
||||||
private shiftEvent = new KeyboardInput("shift")
|
private shiftEvent = new KeyboardInput("shift")
|
||||||
private refreshEvent = new KeyboardInput("r")
|
private refreshEvent = new KeyboardInput("r")
|
||||||
private clearEvent = new KeyboardInput("c")
|
private clearEvent = new KeyboardInput("delete")
|
||||||
private upEvent = new KeyboardInput("up")
|
private upEvent = new KeyboardInput("up")
|
||||||
private downEvent = new KeyboardInput("down")
|
private downEvent = new KeyboardInput("down")
|
||||||
|
|
||||||
|
@ -99,6 +99,17 @@ export class ComponentManager {
|
||||||
public gates = this.templateStore.store.lsChanges
|
public gates = this.templateStore.store.lsChanges
|
||||||
public saves = this.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() {
|
constructor() {
|
||||||
runCounter.increase()
|
runCounter.increase()
|
||||||
|
|
||||||
|
@ -158,12 +169,6 @@ export class ComponentManager {
|
||||||
this.inputMode = "command"
|
this.inputMode = "command"
|
||||||
this.placeholder.next("Command palette")
|
this.placeholder.next("Command palette")
|
||||||
}
|
}
|
||||||
else if (this.clearEvent.value) {
|
|
||||||
if (this.shiftEvent.value)
|
|
||||||
this.clear()
|
|
||||||
else
|
|
||||||
this.smartClear()
|
|
||||||
}
|
|
||||||
else if (this.saveEvent.value) {
|
else if (this.saveEvent.value) {
|
||||||
this.save()
|
this.save()
|
||||||
}
|
}
|
||||||
|
@ -171,6 +176,12 @@ export class ComponentManager {
|
||||||
this.refresh()
|
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"
|
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", {
|
this.store.set("true", {
|
||||||
inputs: 0,
|
inputs: 0,
|
||||||
outputs: 1,
|
outputs: 1,
|
||||||
|
@ -161,7 +187,7 @@ export class ComponentTemplateStore {
|
||||||
onclick: `
|
onclick: `
|
||||||
ctx.outputs[0].memory.value = !ctx.outputs[0].memory.value
|
ctx.outputs[0].memory.value = !ctx.outputs[0].memory.value
|
||||||
if (ctx.outputs[0].memory.value)
|
if (ctx.outputs[0].memory.value)
|
||||||
ctx.color("#880000")
|
ctx.color("#550000")
|
||||||
else
|
else
|
||||||
ctx.color("red")
|
ctx.color("red")
|
||||||
`
|
`
|
||||||
|
|
|
@ -36,12 +36,16 @@ export const modal = (options: Partial<confirmModalOptions>) => new Promise((res
|
||||||
${content}
|
${content}
|
||||||
</div>
|
</div>
|
||||||
<footer class="mdc-dialog__actions">
|
<footer class="mdc-dialog__actions">
|
||||||
<button type="button" class="mdc-button mdc-dialog__button" id="no-${id}">
|
${(no !== "") ?
|
||||||
|
html`<button type="button" class="mdc-button mdc-dialog__button" id="no-${id}">
|
||||||
<span class="mdc-button__label">${no}</span>
|
<span class="mdc-button__label">${no}</span>
|
||||||
</button>
|
</button>` : no
|
||||||
<button type="button" class="mdc-button mdc-dialog__button" id="yes-${id}">
|
}
|
||||||
|
${(yes !== "") ?
|
||||||
|
html`<button type="button" class="mdc-button mdc-dialog__button" id="yes-${id}">
|
||||||
<span class="mdc-button__label">${yes}</span>
|
<span class="mdc-button__label">${yes}</span>
|
||||||
</button>
|
</button>` : yes
|
||||||
|
}
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,5 +11,7 @@ export class Wire {
|
||||||
public dispose(){
|
public dispose(){
|
||||||
this.output.unbind(this.input)
|
this.output.unbind(this.input)
|
||||||
this.input.pair = null
|
this.input.pair = null
|
||||||
|
this.input.update()
|
||||||
|
this.output.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -51,6 +51,12 @@ export class WireManager {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private remove(target: Wire) {
|
||||||
|
target.dispose()
|
||||||
|
this.wires = this.wires.filter(val => val !== target)
|
||||||
|
this.update.next(true)
|
||||||
|
}
|
||||||
|
|
||||||
get svg() {
|
get svg() {
|
||||||
return this.wires.map(val => {
|
return this.wires.map(val => {
|
||||||
const i = val.input.of
|
const i = val.input.of
|
||||||
|
@ -61,6 +67,8 @@ export class WireManager {
|
||||||
y1=${subscribe(i.piny(false,i.outputPins.indexOf(val.input)))}
|
y1=${subscribe(i.piny(false,i.outputPins.indexOf(val.input)))}
|
||||||
y2=${subscribe(o.piny(true,o.inputPins.indexOf(val.output)))}
|
y2=${subscribe(o.piny(true,o.inputPins.indexOf(val.output)))}
|
||||||
stroke=${subscribe(val.input.svgColor)}
|
stroke=${subscribe(val.input.svgColor)}
|
||||||
|
stroke-width=10
|
||||||
|
@click=${() => this.remove(val)}
|
||||||
>
|
>
|
||||||
</line>
|
</line>
|
||||||
`})
|
`})
|
||||||
|
|
|
@ -2,17 +2,47 @@ import { render, html, svg } from "lit-html"
|
||||||
import { subscribe } from "lit-rx"
|
import { subscribe } from "lit-rx"
|
||||||
import { Screen } from "./common/screen.ts";
|
import { Screen } from "./common/screen.ts";
|
||||||
import { Component } from "./common/component";
|
import { Component } from "./common/component";
|
||||||
import { FunctionStore } from "./common/activation/activationStore";
|
|
||||||
import { ComponentManager } from "./common/componentManager";
|
import { ComponentManager } from "./common/componentManager";
|
||||||
import { map } from "rxjs/operators";
|
import { map } from "rxjs/operators";
|
||||||
import { MDCMenu } from '@material/menu';
|
import { MDCMenu } from '@material/menu';
|
||||||
|
import { error } from "toastr"
|
||||||
|
import { modal } from "./common/modals";
|
||||||
|
|
||||||
const screen = new Screen()
|
const screen = new Screen()
|
||||||
|
|
||||||
const manager = new ComponentManager()
|
export const manager = new ComponentManager()
|
||||||
manager.save()
|
manager.save()
|
||||||
manager.update()
|
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) => {
|
const handleEvent = <T>(e: T, func: (e: T) => any) => {
|
||||||
if (manager.barAlpha.value == "0")
|
if (manager.barAlpha.value == "0")
|
||||||
func(e)
|
func(e)
|
||||||
|
@ -75,6 +105,12 @@ render(html`
|
||||||
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">add</i>
|
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">add</i>
|
||||||
<span class="mdc-list-item__text">Add logic gate</span>
|
<span class="mdc-list-item__text">Add logic gate</span>
|
||||||
</a>
|
</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>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
@ -99,11 +135,26 @@ render(html`
|
||||||
))))}
|
))))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</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)
|
`, 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.forEach(menu => menu.hoistMenuToBody())
|
||||||
menus[0].setAnchorElement(document.querySelector(`#openSimulation`))
|
menus[0].setAnchorElement(document.querySelector(`#openSimulation`))
|
||||||
menus[1].setAnchorElement(document.querySelector("#openGates"))
|
menus[1].setAnchorElement(document.querySelector("#openGates"))
|
||||||
|
menus[2].setAnchorElement(document.querySelector("#openFile"))
|
||||||
|
|
||||||
manager.update()
|
manager.update()
|
Loading…
Reference in a new issue