integrated circuit deleting

This commit is contained in:
Matei Adriel 2019-07-28 19:22:07 +03:00
parent ce325167c2
commit 431af8f68c
12 changed files with 154 additions and 42 deletions

View file

@ -15,4 +15,5 @@ body {
background-color: $bg;
overflow-y: auto;
overflow-x: hidden;
}

View file

@ -34,7 +34,7 @@ const allSimulationSubject = new BehaviorSubject<string[]>([])
*
* It also has the side effect of sorting the simulation names.
*/
const updateSimulationList = () => {
export const updateSimulationList = () => {
allSimulationSubject.next(allSimulations().sort())
}

View file

@ -1,7 +1,7 @@
import React from 'react'
import Icon from '@material-ui/core/Icon'
import IconButton from '@material-ui/core/IconButton'
import { LogicGateProps } from './LogicGate'
import { LogicGateProps } from '../types/LogicGateProps'
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
const AddGate = ({ template }: LogicGateProps) => {

View file

@ -0,0 +1,28 @@
import React from 'react'
import Icon from '@material-ui/core/Icon'
import IconButton from '@material-ui/core/IconButton'
import { LogicGateProps } from '../types/LogicGateProps'
import { deleteGateFromMemory } from '../../simulation-actions/helpers/deleteSimulation'
import { getRendererSafely } from '../helpers/getRendererSafely'
const DeleteGateIcon = ({ template }: LogicGateProps) => {
if (template.tags.includes('base')) {
return <></>
} else {
return (
<IconButton
aria-label="delete"
onClick={() =>
deleteGateFromMemory(
getRendererSafely(),
template.metadata.name
)
}
>
<Icon>delete</Icon>
</IconButton>
)
}
}
export default DeleteGateIcon

View file

@ -1,7 +1,7 @@
import React from 'react'
import Icon from '@material-ui/core/Icon'
import IconButton from '@material-ui/core/IconButton'
import { LogicGateProps } from './LogicGate'
import { LogicGateProps } from '../types/LogicGateProps'
import { randomItem } from '../../internalisation/helpers/randomItem'
const GateInfo = ({ template }: LogicGateProps) => {

View file

@ -0,0 +1,27 @@
import React from 'react'
import { LogicGateProps } from '../types/LogicGateProps'
import { repeat } from '../../vector2/helpers/repeat'
const gradientSmoothness = 10
const GatePreview = ({ template }: LogicGateProps) => {
const { fill } = template.material
return template.material.type === 'image' ? (
<img src={fill} alt={template.metadata.name} />
) : (
<div
style={{
backgroundColor: fill,
backgroundImage: `linear-gradient(-60deg,${[
...Object.values(template.material.colors)
.map(color => repeat(color, gradientSmoothness))
.flat(),
...repeat(fill, gradientSmoothness)
].join(',')})`
}}
/>
)
}
export default GatePreview

View file

@ -1,6 +1,6 @@
import React from 'react'
import Icon from '@material-ui/core/Icon'
import { LogicGateProps } from './LogicGate'
import { LogicGateProps } from '../types/LogicGateProps'
const GateSettings = ({ template }: LogicGateProps) => {
const tags = template.tags

View file

@ -1,38 +1,14 @@
import './LogicGate.scss'
import React from 'react'
import { GateTemplate } from '../../simulation/types/GateTemplate'
import GateInfo from './GateInfo'
import GateSettings from './GateSettings'
import AddGate from './AddGate'
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
import { repeat } from '../../vector2/helpers/repeat'
export interface LogicGateProps {
template: GateTemplate
}
const gradientSmoothness = 10
import DeleteGateIcon from './DeleteGate'
import GatePreview from './GatePreview'
import { LogicGateProps } from '../types/LogicGateProps'
const LogicGate = ({ template }: LogicGateProps) => {
const { fill } = template.material
const gatePreview =
template.material.type === 'image' ? (
<img src={fill} alt={template.metadata.name} />
) : (
<div
style={{
backgroundColor: fill,
backgroundImage: `linear-gradient(-60deg,${[
...Object.values(template.material.colors)
.map(color => repeat(color, gradientSmoothness))
.flat(),
...repeat(fill, gradientSmoothness)
].join(',')})`
}}
/>
)
const rawName = template.metadata.name
const name = `${rawName[0].toUpperCase()}${rawName.substr(1)}`
@ -43,7 +19,7 @@ const LogicGate = ({ template }: LogicGateProps) => {
className="gate-preview"
onClick={() => addGateFromTemplate(template)}
>
{gatePreview}
<GatePreview template={template} />
</div>
</section>
<section>
@ -54,6 +30,7 @@ const LogicGate = ({ template }: LogicGateProps) => {
<GateInfo template={template} />
<GateSettings template={template} />
<AddGate template={template} />
<DeleteGateIcon template={template} />
</div>
</section>
</div>

View file

@ -0,0 +1,5 @@
import { GateTemplate } from '../../simulation/types/GateTemplate'
export interface LogicGateProps {
template: GateTemplate
}

View file

@ -6,6 +6,7 @@ import { toast } from 'react-toastify'
import { createToastArguments } from '../../toasts/helpers/createToastArguments'
import { CurrentLanguage } from '../../internalisation/stores/currentLanguage'
import { compileIc } from '../../integrated-circuits/helpers/compileIc'
import { updateLogicGateList } from '../../logic-gates/subjects/LogicGateList'
/**
* Inits a simulation by:
@ -34,6 +35,7 @@ export const initSimulation = (name: string, mode: simulationMode) => {
if (mode === 'ic') {
compileIc(state.simulation)
updateLogicGateList()
}
return state

View file

@ -5,20 +5,89 @@ import { initSimulation } from '../../saving/helpers/initSimulation'
import { defaultSimulationName } from '../../saving/constants'
import { randomItem } from '../../internalisation/helpers/randomItem'
import { switchTo } from '../../saving/helpers/switchTo'
import { updateLogicGateList } from '../../logic-gates/subjects/LogicGateList'
import { getTemplateSafely } from '../../logic-gates/helpers/getTemplateSafely'
import { SimulationError } from '../../errors/classes/SimulationError'
import { templateStore } from '../../saving/stores/templateStore'
import { updateSimulationList } from '../../core/components/OpenSimulation'
export const deleteSimulation = (renderer: SimulationRenderer) => {
const current = renderer.simulation.name
/**
* Deletes the current simulation
*
* @param renderer The current renderer
*/
export const deleteSimulation = (
renderer: SimulationRenderer,
name?: string,
shouldDeleteIc = true
) => {
const toDelete = name ? name : renderer.simulation.name
const others = saveStore.ls()
removeElement(others, current)
if (toDelete === renderer.simulation.name) {
const others = saveStore.ls()
removeElement(others, toDelete)
if (!others.length) {
initSimulation(defaultSimulationName, 'project')
if (!others.length) {
initSimulation(defaultSimulationName, 'project')
}
const switchTarget = randomItem(others)
switchTo(switchTarget)
}
const switchTarget = randomItem(others)
switchTo(switchTarget)
// actually delete simulation
saveStore.delete(current)
const deleted = saveStore.delete(toDelete)
if (shouldDeleteIc && deleted.simulation.mode === 'ic') {
deleteGateFromMemory(renderer, toDelete, false)
} else {
updateLogicGateList()
}
updateSimulationList()
}
/**
* Deletes a gate from memory
*
* @param renderer The current renderer
* @param name The name of the gate
*
* @throws SimulationError if the gate cannot be deleted
*/
export const deleteGateFromMemory = (
renderer: SimulationRenderer,
name: string,
shouldDeleteSimulation = true
) => {
const template = getTemplateSafely(name)
if (template.tags.includes('base')) {
throw new SimulationError('Cannot delete base gate')
}
templateStore.delete(name)
if (shouldDeleteSimulation && saveStore.get(name)) {
deleteSimulation(renderer, name, false)
}
// delete all occurance of that gate
for (const simulationName of saveStore.ls()) {
const simulationState = saveStore.get(simulationName)
if (!simulationState) {
throw new SimulationError(
`Cannot find simulation ${simulationName}`
)
}
simulationState.simulation.gates = simulationState.simulation.gates.filter(
gate => gate.template !== name
)
saveStore.set(simulationName, simulationState)
}
updateLogicGateList()
}

View file

@ -53,9 +53,12 @@ export class LocalStore<T> {
public delete(key = 'index') {
const all = this.getAll()
const last = all[key]
delete all[key]
localStorage.setItem(this.name, JSON.stringify(all))
return last
}
}