🔭 implemented adding gates and smart clearing 1️⃣
This commit is contained in:
parent
cbc9c1ec0f
commit
ce5005f704
|
@ -18,13 +18,14 @@ import { modal } from "../modals";
|
||||||
import { map } from "rxjs/operators";
|
import { map } from "rxjs/operators";
|
||||||
import { persistent } from "../store/persistent";
|
import { persistent } from "../store/persistent";
|
||||||
|
|
||||||
|
const defaultName = "default"
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
export class ComponentManager {
|
export class ComponentManager {
|
||||||
public components: Component[] = []
|
public components: Component[] = []
|
||||||
public svgs = new Subject<SVGTemplateResult>()
|
public svgs = new Subject<SVGTemplateResult>()
|
||||||
public placeholder = new BehaviorSubject("Create simulation")
|
public placeholder = new BehaviorSubject("Create simulation")
|
||||||
public saves = new BehaviorSubject<string[]>(["hello world"])
|
public barAlpha = new BehaviorSubject<string>("0");
|
||||||
|
|
||||||
private temporaryCommnad = ""
|
private temporaryCommnad = ""
|
||||||
private onTop: Component
|
private onTop: Component
|
||||||
|
@ -34,6 +35,13 @@ export class ComponentManager {
|
||||||
private wireManager = new WireManager()
|
private wireManager = new WireManager()
|
||||||
private templateStore = new ComponentTemplateStore()
|
private templateStore = new ComponentTemplateStore()
|
||||||
private settings = new Settings()
|
private settings = new Settings()
|
||||||
|
private standard: {
|
||||||
|
offset: number
|
||||||
|
scale: [number, number]
|
||||||
|
} = {
|
||||||
|
offset: 50,
|
||||||
|
scale: [100, 100]
|
||||||
|
}
|
||||||
|
|
||||||
private commandHistoryStore = new Store<string>("commandHistory")
|
private commandHistoryStore = new Store<string>("commandHistory")
|
||||||
private store = new Store<ManagerState>("simulationStates")
|
private store = new Store<ManagerState>("simulationStates")
|
||||||
|
@ -49,7 +57,7 @@ export class ComponentManager {
|
||||||
private upEvent = new KeyboardInput("up")
|
private upEvent = new KeyboardInput("up")
|
||||||
private downEvent = new KeyboardInput("down")
|
private downEvent = new KeyboardInput("down")
|
||||||
|
|
||||||
@persistent<ComponentManager, string>("current", "main'")
|
@persistent<ComponentManager, string>(defaultName, "main")
|
||||||
public name: string
|
public name: string
|
||||||
public alertOptions = alertOptions
|
public alertOptions = alertOptions
|
||||||
|
|
||||||
|
@ -88,7 +96,8 @@ export class ComponentManager {
|
||||||
}
|
}
|
||||||
private inputMode: string
|
private inputMode: string
|
||||||
|
|
||||||
public barAlpha = new BehaviorSubject<string>("0");
|
public gates = this.templateStore.store.lsChanges
|
||||||
|
public saves = this.store.lsChanges
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
runCounter.increase()
|
runCounter.increase()
|
||||||
|
@ -150,7 +159,10 @@ export class ComponentManager {
|
||||||
this.placeholder.next("Command palette")
|
this.placeholder.next("Command palette")
|
||||||
}
|
}
|
||||||
else if (this.clearEvent.value) {
|
else if (this.clearEvent.value) {
|
||||||
this.clear()
|
if (this.shiftEvent.value)
|
||||||
|
this.clear()
|
||||||
|
else
|
||||||
|
this.smartClear()
|
||||||
}
|
}
|
||||||
else if (this.saveEvent.value) {
|
else if (this.saveEvent.value) {
|
||||||
this.save()
|
this.save()
|
||||||
|
@ -163,7 +175,6 @@ export class ComponentManager {
|
||||||
})
|
})
|
||||||
|
|
||||||
this.wireManager.update.subscribe(val => this.update())
|
this.wireManager.update.subscribe(val => this.update())
|
||||||
this.saves.next(this.store.ls())
|
|
||||||
if (this.saves.value.length === 0)
|
if (this.saves.value.length === 0)
|
||||||
this.save()
|
this.save()
|
||||||
|
|
||||||
|
@ -174,13 +185,14 @@ export class ComponentManager {
|
||||||
this.inputMode = "create"
|
this.inputMode = "create"
|
||||||
this.placeholder.next("Create simulation")
|
this.placeholder.next("Create simulation")
|
||||||
}
|
}
|
||||||
preInput() {
|
|
||||||
|
private preInput() {
|
||||||
const elem = <HTMLInputElement>document.getElementById("nameInput")
|
const elem = <HTMLInputElement>document.getElementById("nameInput")
|
||||||
elem.value = ""
|
elem.value = ""
|
||||||
this.barAlpha.next("1")
|
this.barAlpha.next("1")
|
||||||
}
|
}
|
||||||
|
|
||||||
async create() {
|
private async create() {
|
||||||
const elem = <HTMLInputElement>document.getElementById("nameInput")
|
const elem = <HTMLInputElement>document.getElementById("nameInput")
|
||||||
this.barAlpha.next("0")
|
this.barAlpha.next("0")
|
||||||
|
|
||||||
|
@ -204,8 +216,35 @@ All you work will be lost!`
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public add(template: string, position?: [number, number]) {
|
||||||
|
const pos = position ? position : [...Array(2)].fill(this.standard.offset * this.components.length) as [number, number]
|
||||||
|
|
||||||
|
this.components.push(new Component(template, pos, this.standard.scale))
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
public async delete(name: string) {
|
||||||
|
const res = await modal({
|
||||||
|
title: "Are you sure?",
|
||||||
|
content: html`Deleting a simulations is ireversible, and all work will be lost!`
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
if (this.name === name) {
|
||||||
|
if (this.saves.value.length > 1) {
|
||||||
|
this.switchTo(this.saves.value.find(val => val !== name))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let newName = (name === defaultName) ? `${defaultName}(1)` : defaultName
|
||||||
|
await this.createEmptySimulation(newName)
|
||||||
|
this.switchTo(newName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.store.delete(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public createEmptySimulation(name: string) {
|
public createEmptySimulation(name: string) {
|
||||||
console.log(name)
|
|
||||||
const create = () => {
|
const create = () => {
|
||||||
this.store.set(name, {
|
this.store.set(name, {
|
||||||
wires: [],
|
wires: [],
|
||||||
|
@ -230,8 +269,6 @@ All you work will be lost!`
|
||||||
}
|
}
|
||||||
|
|
||||||
public switchTo(name: string) {
|
public switchTo(name: string) {
|
||||||
console.log(`switching to ${name}`)
|
|
||||||
|
|
||||||
const data = this.store.get(name)
|
const data = this.store.get(name)
|
||||||
if (!data)
|
if (!data)
|
||||||
error(`An error occured when trying to load ${name}`, "", this.alertOptions)
|
error(`An error occured when trying to load ${name}`, "", this.alertOptions)
|
||||||
|
@ -260,7 +297,15 @@ All you work will be lost!`
|
||||||
"", this.alertOptions)
|
"", this.alertOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
public smartClear() {
|
||||||
|
this.components = this.components.filter(({ id }) =>
|
||||||
|
this.wireManager.wires.find(val => val.input.of.id == id || val.output.of.id == id)
|
||||||
|
)
|
||||||
|
this.update()
|
||||||
|
success("Succesfully cleared all unconnected components", "", this.alertOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
this.components = []
|
this.components = []
|
||||||
this.wireManager.dispose()
|
this.wireManager.dispose()
|
||||||
this.update()
|
this.update()
|
||||||
|
@ -269,8 +314,6 @@ All you work will be lost!`
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
console.log(this.name)
|
|
||||||
|
|
||||||
if (this.store.get(this.name)) {
|
if (this.store.get(this.name)) {
|
||||||
this.loadState(this.store.get(this.name))
|
this.loadState(this.store.get(this.name))
|
||||||
}
|
}
|
||||||
|
@ -424,7 +467,6 @@ All you work will be lost!`
|
||||||
this.commandHistoryStore.set(i.toString(), element)
|
this.commandHistoryStore.set(i.toString(), element)
|
||||||
}
|
}
|
||||||
this.store.set(this.name, this.state)
|
this.store.set(this.name, this.state)
|
||||||
this.saves.next(this.store.ls())
|
|
||||||
success(`Saved the simulation ${this.name} succesfully!`, "", this.alertOptions)
|
success(`Saved the simulation ${this.name} succesfully!`, "", this.alertOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,23 +1,40 @@
|
||||||
|
import { BehaviorSubject } from "rxjs";
|
||||||
|
|
||||||
export class Store<T> {
|
export class Store<T> {
|
||||||
constructor(private name: string){ }
|
public lsChanges = new BehaviorSubject<string[]>([])
|
||||||
|
|
||||||
|
constructor(private name: string){
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
update(){
|
||||||
|
this.lsChanges.next(this.ls())
|
||||||
|
}
|
||||||
|
|
||||||
get(key:string):T{
|
get(key:string):T{
|
||||||
const data = localStorage[`${this.name}/${key}`]
|
const data = localStorage[`${this.name}/${key}`]
|
||||||
|
|
||||||
if(data)
|
if(data)
|
||||||
return JSON.parse(data).value
|
return JSON.parse(data).value
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(key:string){
|
||||||
|
localStorage.removeItem(`${this.name}/${key}`)
|
||||||
|
this.update()
|
||||||
|
}
|
||||||
|
|
||||||
set(key:string,value:T){
|
set(key:string,value:T){
|
||||||
localStorage[`${this.name}/${key}`] = JSON.stringify({ value })
|
localStorage[`${this.name}/${key}`] = JSON.stringify({ value })
|
||||||
|
|
||||||
|
this.update()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
ls() {
|
ls() {
|
||||||
let keys = []
|
let keys = []
|
||||||
|
|
||||||
for (const i in localStorage){
|
for (const i in localStorage){
|
||||||
if (i.indexOf(this.name) == 0)
|
if (i.indexOf(this.name) == 0)
|
||||||
keys.push(i.substr(this.name.length + 1))
|
keys.push(i.substr(this.name.length + 1))
|
||||||
|
|
|
@ -11,8 +11,8 @@ import { WireState, WireStateVal } from "./interface";
|
||||||
export class WireManager {
|
export class WireManager {
|
||||||
public start: Pin
|
public start: Pin
|
||||||
public end: Pin
|
public end: Pin
|
||||||
|
|
||||||
private wires: Wire[] = []
|
public wires: Wire[] = []
|
||||||
|
|
||||||
public update = new Subject<boolean>()
|
public update = new Subject<boolean>()
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,6 @@ import { MDCMenu } from '@material/menu';
|
||||||
const screen = new Screen()
|
const screen = new Screen()
|
||||||
|
|
||||||
const manager = new ComponentManager()
|
const manager = new ComponentManager()
|
||||||
manager.components.push(new Component("and", [200, 100], [100, 100]))
|
|
||||||
// manager.components.push(new Component("not", [200, 500], [100, 100]))
|
|
||||||
// manager.components.push(new Component("true", [200, 500], [100, 100]))
|
|
||||||
// manager.components.push(new Component("false", [200, 500], [100, 100]))
|
|
||||||
manager.save()
|
manager.save()
|
||||||
manager.update()
|
manager.update()
|
||||||
|
|
||||||
|
@ -64,32 +60,50 @@ render(html`
|
||||||
<div class="mdc-drawer__content">
|
<div class="mdc-drawer__content">
|
||||||
<nav class="mdc-list">
|
<nav class="mdc-list">
|
||||||
<a class="mdc-list-item mdc-list-item--activated" href="#" aria-current="page" @click=${() => manager.prepareNewSimulation()}>
|
<a class="mdc-list-item mdc-list-item--activated" href="#" aria-current="page" @click=${() => manager.prepareNewSimulation()}>
|
||||||
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">add</i>
|
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">note_add</i>
|
||||||
<span class="mdc-list-item__text">Create new simulation</span>
|
<span class="mdc-list-item__text">Create new simulation</span>
|
||||||
</a>
|
</a>
|
||||||
<a class="mdc-list-item" href="#" id="openSimulation" @click=${() => {
|
<a class="mdc-list-item" href="#" id="openSimulation" @click=${() => {
|
||||||
menu.open = true
|
menus[0].open = true
|
||||||
}}>
|
}}>
|
||||||
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">folder_open</i>
|
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">folder_open</i>
|
||||||
<span class="mdc-list-item__text">Open simulation</span>
|
<span class="mdc-list-item__text">Open simulation</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="mdc-list-item" href="#" id="openGates" @click=${() => {
|
||||||
|
menus[1].open = true
|
||||||
|
}}>
|
||||||
|
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">add</i>
|
||||||
|
<span class="mdc-list-item__text">Add logic gate</span>
|
||||||
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div class="mdc-menu mdc-menu-surface mdc-theme--primary-bg mdc-theme--on-primary">
|
<div class="mdc-menu mdc-menu-surface mdc-theme--primary-bg mdc-theme--on-primary" id="saveMenu">
|
||||||
<ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
<ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
||||||
${subscribe(manager.saves.pipe(map(_ => _.map(val => html`
|
${subscribe(manager.saves.pipe(map(_ => _.map(val => html`
|
||||||
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.switchTo(val)}>
|
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.switchTo(val)}>
|
||||||
<span class="mdc-list-item__text"> ${val} </span>
|
<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>
|
||||||
|
|
||||||
|
<div class="mdc-menu mdc-menu-surface mdc-theme--primary-bg mdc-theme--on-primary" id="gateMenu">
|
||||||
|
<ul class="mdc-list" role="menu" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
||||||
|
${subscribe(manager.gates.pipe(map(_ => _.map(val => html`
|
||||||
|
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.add(val)}>
|
||||||
|
<span class="mdc-list-item__text"> ${val} </span>
|
||||||
</li>`
|
</li>`
|
||||||
))))}
|
))))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
`, document.body)
|
`, document.body)
|
||||||
|
|
||||||
const menu = new MDCMenu(document.querySelector('.mdc-menu'));
|
const menus = [new MDCMenu(document.querySelector('#saveMenu')), new MDCMenu(document.querySelector('#gateMenu'))]
|
||||||
menu.hoistMenuToBody()
|
menus.forEach(menu => menu.hoistMenuToBody())
|
||||||
menu.setAnchorElement(document.querySelector(`#openSimulation`))
|
menus[0].setAnchorElement(document.querySelector(`#openSimulation`))
|
||||||
|
menus[1].setAnchorElement(document.querySelector("#openGates"))
|
||||||
|
|
||||||
manager.update()
|
manager.update()
|
Loading…
Reference in a new issue