integrated circuit deleting
This commit is contained in:
parent
ce325167c2
commit
431af8f68c
|
@ -15,4 +15,5 @@ body {
|
||||||
|
|
||||||
background-color: $bg;
|
background-color: $bg;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ const allSimulationSubject = new BehaviorSubject<string[]>([])
|
||||||
*
|
*
|
||||||
* It also has the side effect of sorting the simulation names.
|
* It also has the side effect of sorting the simulation names.
|
||||||
*/
|
*/
|
||||||
const updateSimulationList = () => {
|
export const updateSimulationList = () => {
|
||||||
allSimulationSubject.next(allSimulations().sort())
|
allSimulationSubject.next(allSimulations().sort())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Icon from '@material-ui/core/Icon'
|
import Icon from '@material-ui/core/Icon'
|
||||||
import IconButton from '@material-ui/core/IconButton'
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
import { LogicGateProps } from './LogicGate'
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
||||||
|
|
||||||
const AddGate = ({ template }: LogicGateProps) => {
|
const AddGate = ({ template }: LogicGateProps) => {
|
||||||
|
|
28
src/modules/logic-gates/components/DeleteGate.tsx
Normal file
28
src/modules/logic-gates/components/DeleteGate.tsx
Normal 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
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Icon from '@material-ui/core/Icon'
|
import Icon from '@material-ui/core/Icon'
|
||||||
import IconButton from '@material-ui/core/IconButton'
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
import { LogicGateProps } from './LogicGate'
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
import { randomItem } from '../../internalisation/helpers/randomItem'
|
import { randomItem } from '../../internalisation/helpers/randomItem'
|
||||||
|
|
||||||
const GateInfo = ({ template }: LogicGateProps) => {
|
const GateInfo = ({ template }: LogicGateProps) => {
|
||||||
|
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Icon from '@material-ui/core/Icon'
|
import Icon from '@material-ui/core/Icon'
|
||||||
import { LogicGateProps } from './LogicGate'
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
|
|
||||||
const GateSettings = ({ template }: LogicGateProps) => {
|
const GateSettings = ({ template }: LogicGateProps) => {
|
||||||
const tags = template.tags
|
const tags = template.tags
|
||||||
|
|
|
@ -1,38 +1,14 @@
|
||||||
import './LogicGate.scss'
|
import './LogicGate.scss'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { GateTemplate } from '../../simulation/types/GateTemplate'
|
|
||||||
import GateInfo from './GateInfo'
|
import GateInfo from './GateInfo'
|
||||||
import GateSettings from './GateSettings'
|
import GateSettings from './GateSettings'
|
||||||
import AddGate from './AddGate'
|
import AddGate from './AddGate'
|
||||||
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
||||||
import { repeat } from '../../vector2/helpers/repeat'
|
import DeleteGateIcon from './DeleteGate'
|
||||||
|
import GatePreview from './GatePreview'
|
||||||
export interface LogicGateProps {
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
template: GateTemplate
|
|
||||||
}
|
|
||||||
|
|
||||||
const gradientSmoothness = 10
|
|
||||||
|
|
||||||
const LogicGate = ({ template }: 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 rawName = template.metadata.name
|
||||||
const name = `${rawName[0].toUpperCase()}${rawName.substr(1)}`
|
const name = `${rawName[0].toUpperCase()}${rawName.substr(1)}`
|
||||||
|
|
||||||
|
@ -43,7 +19,7 @@ const LogicGate = ({ template }: LogicGateProps) => {
|
||||||
className="gate-preview"
|
className="gate-preview"
|
||||||
onClick={() => addGateFromTemplate(template)}
|
onClick={() => addGateFromTemplate(template)}
|
||||||
>
|
>
|
||||||
{gatePreview}
|
<GatePreview template={template} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
|
@ -54,6 +30,7 @@ const LogicGate = ({ template }: LogicGateProps) => {
|
||||||
<GateInfo template={template} />
|
<GateInfo template={template} />
|
||||||
<GateSettings template={template} />
|
<GateSettings template={template} />
|
||||||
<AddGate template={template} />
|
<AddGate template={template} />
|
||||||
|
<DeleteGateIcon template={template} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
5
src/modules/logic-gates/types/LogicGateProps.tsx
Normal file
5
src/modules/logic-gates/types/LogicGateProps.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { GateTemplate } from '../../simulation/types/GateTemplate'
|
||||||
|
|
||||||
|
export interface LogicGateProps {
|
||||||
|
template: GateTemplate
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import { toast } from 'react-toastify'
|
||||||
import { createToastArguments } from '../../toasts/helpers/createToastArguments'
|
import { createToastArguments } from '../../toasts/helpers/createToastArguments'
|
||||||
import { CurrentLanguage } from '../../internalisation/stores/currentLanguage'
|
import { CurrentLanguage } from '../../internalisation/stores/currentLanguage'
|
||||||
import { compileIc } from '../../integrated-circuits/helpers/compileIc'
|
import { compileIc } from '../../integrated-circuits/helpers/compileIc'
|
||||||
|
import { updateLogicGateList } from '../../logic-gates/subjects/LogicGateList'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits a simulation by:
|
* Inits a simulation by:
|
||||||
|
@ -34,6 +35,7 @@ export const initSimulation = (name: string, mode: simulationMode) => {
|
||||||
|
|
||||||
if (mode === 'ic') {
|
if (mode === 'ic') {
|
||||||
compileIc(state.simulation)
|
compileIc(state.simulation)
|
||||||
|
updateLogicGateList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -5,12 +5,27 @@ import { initSimulation } from '../../saving/helpers/initSimulation'
|
||||||
import { defaultSimulationName } from '../../saving/constants'
|
import { defaultSimulationName } from '../../saving/constants'
|
||||||
import { randomItem } from '../../internalisation/helpers/randomItem'
|
import { randomItem } from '../../internalisation/helpers/randomItem'
|
||||||
import { switchTo } from '../../saving/helpers/switchTo'
|
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
|
||||||
|
|
||||||
|
if (toDelete === renderer.simulation.name) {
|
||||||
const others = saveStore.ls()
|
const others = saveStore.ls()
|
||||||
removeElement(others, current)
|
removeElement(others, toDelete)
|
||||||
|
|
||||||
if (!others.length) {
|
if (!others.length) {
|
||||||
initSimulation(defaultSimulationName, 'project')
|
initSimulation(defaultSimulationName, 'project')
|
||||||
|
@ -18,7 +33,61 @@ export const deleteSimulation = (renderer: SimulationRenderer) => {
|
||||||
|
|
||||||
const switchTarget = randomItem(others)
|
const switchTarget = randomItem(others)
|
||||||
switchTo(switchTarget)
|
switchTo(switchTarget)
|
||||||
|
}
|
||||||
|
|
||||||
// actually delete simulation
|
// 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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,12 @@ export class LocalStore<T> {
|
||||||
|
|
||||||
public delete(key = 'index') {
|
public delete(key = 'index') {
|
||||||
const all = this.getAll()
|
const all = this.getAll()
|
||||||
|
const last = all[key]
|
||||||
|
|
||||||
delete all[key]
|
delete all[key]
|
||||||
|
|
||||||
localStorage.setItem(this.name, JSON.stringify(all))
|
localStorage.setItem(this.name, JSON.stringify(all))
|
||||||
|
|
||||||
|
return last
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue