🔭 implemented adding gates and smart clearing 1️⃣

This commit is contained in:
Matei Adriel 2019-06-03 22:10:46 +00:00
parent cbc9c1ec0f
commit ce5005f704
4 changed files with 103 additions and 30 deletions

View file

@ -18,13 +18,14 @@ import { modal } from "../modals";
import { map } from "rxjs/operators";
import { persistent } from "../store/persistent";
const defaultName = "default"
@Singleton
export class ComponentManager {
public components: Component[] = []
public svgs = new Subject<SVGTemplateResult>()
public placeholder = new BehaviorSubject("Create simulation")
public saves = new BehaviorSubject<string[]>(["hello world"])
public barAlpha = new BehaviorSubject<string>("0");
private temporaryCommnad = ""
private onTop: Component
@ -34,6 +35,13 @@ export class ComponentManager {
private wireManager = new WireManager()
private templateStore = new ComponentTemplateStore()
private settings = new Settings()
private standard: {
offset: number
scale: [number, number]
} = {
offset: 50,
scale: [100, 100]
}
private commandHistoryStore = new Store<string>("commandHistory")
private store = new Store<ManagerState>("simulationStates")
@ -49,7 +57,7 @@ export class ComponentManager {
private upEvent = new KeyboardInput("up")
private downEvent = new KeyboardInput("down")
@persistent<ComponentManager, string>("current", "main'")
@persistent<ComponentManager, string>(defaultName, "main")
public name: string
public alertOptions = alertOptions
@ -88,7 +96,8 @@ export class ComponentManager {
}
private inputMode: string
public barAlpha = new BehaviorSubject<string>("0");
public gates = this.templateStore.store.lsChanges
public saves = this.store.lsChanges
constructor() {
runCounter.increase()
@ -150,7 +159,10 @@ export class ComponentManager {
this.placeholder.next("Command palette")
}
else if (this.clearEvent.value) {
this.clear()
if (this.shiftEvent.value)
this.clear()
else
this.smartClear()
}
else if (this.saveEvent.value) {
this.save()
@ -163,7 +175,6 @@ export class ComponentManager {
})
this.wireManager.update.subscribe(val => this.update())
this.saves.next(this.store.ls())
if (this.saves.value.length === 0)
this.save()
@ -174,13 +185,14 @@ export class ComponentManager {
this.inputMode = "create"
this.placeholder.next("Create simulation")
}
preInput() {
private preInput() {
const elem = <HTMLInputElement>document.getElementById("nameInput")
elem.value = ""
this.barAlpha.next("1")
}
async create() {
private async create() {
const elem = <HTMLInputElement>document.getElementById("nameInput")
this.barAlpha.next("0")
@ -204,8 +216,35 @@ All you work will be lost!`
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) {
console.log(name)
const create = () => {
this.store.set(name, {
wires: [],
@ -230,8 +269,6 @@ All you work will be lost!`
}
public switchTo(name: string) {
console.log(`switching to ${name}`)
const data = this.store.get(name)
if (!data)
error(`An error occured when trying to load ${name}`, "", this.alertOptions)
@ -260,7 +297,15 @@ All you work will be lost!`
"", 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.wireManager.dispose()
this.update()
@ -269,8 +314,6 @@ All you work will be lost!`
}
refresh() {
console.log(this.name)
if (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.store.set(this.name, this.state)
this.saves.next(this.store.ls())
success(`Saved the simulation ${this.name} succesfully!`, "", this.alertOptions)
}
}

View file

@ -1,23 +1,40 @@
import { BehaviorSubject } from "rxjs";
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{
const data = localStorage[`${this.name}/${key}`]
if(data)
return JSON.parse(data).value
return null
}
delete(key:string){
localStorage.removeItem(`${this.name}/${key}`)
this.update()
}
set(key:string,value:T){
localStorage[`${this.name}/${key}`] = JSON.stringify({ value })
this.update()
return this
}
ls() {
let keys = []
for (const i in localStorage){
if (i.indexOf(this.name) == 0)
keys.push(i.substr(this.name.length + 1))

View file

@ -11,8 +11,8 @@ import { WireState, WireStateVal } from "./interface";
export class WireManager {
public start: Pin
public end: Pin
private wires: Wire[] = []
public wires: Wire[] = []
public update = new Subject<boolean>()

View file

@ -10,10 +10,6 @@ import { MDCMenu } from '@material/menu';
const screen = new Screen()
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.update()
@ -64,32 +60,50 @@ render(html`
<div class="mdc-drawer__content">
<nav class="mdc-list">
<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>
</a>
<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>
<span class="mdc-list-item__text">Open simulation</span>
</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>
</div>
</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">
${subscribe(manager.saves.pipe(map(_ => _.map(val => html`
<li class= "mdc-list-item" role = "menuitem" @click=${() => manager.switchTo(val)}>
<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>`
))))}
</ul>
</div>
`, document.body)
const menu = new MDCMenu(document.querySelector('.mdc-menu'));
menu.hoistMenuToBody()
menu.setAnchorElement(document.querySelector(`#openSimulation`))
const menus = [new MDCMenu(document.querySelector('#saveMenu')), new MDCMenu(document.querySelector('#gateMenu'))]
menus.forEach(menu => menu.hoistMenuToBody())
menus[0].setAnchorElement(document.querySelector(`#openSimulation`))
menus[1].setAnchorElement(document.querySelector("#openGates"))
manager.update()