integrated circuit deleting
This commit is contained in:
parent
ce325167c2
commit
431af8f68c
|
@ -15,4 +15,5 @@ body {
|
|||
|
||||
background-color: $bg;
|
||||
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.
|
||||
*/
|
||||
const updateSimulationList = () => {
|
||||
export const updateSimulationList = () => {
|
||||
allSimulationSubject.next(allSimulations().sort())
|
||||
}
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
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 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) => {
|
||||
|
|
|
@ -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 Icon from '@material-ui/core/Icon'
|
||||
import { LogicGateProps } from './LogicGate'
|
||||
import { LogicGateProps } from '../types/LogicGateProps'
|
||||
|
||||
const GateSettings = ({ template }: LogicGateProps) => {
|
||||
const tags = template.tags
|
||||
|
|
|
@ -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>
|
||||
|
|
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 { 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
|
||||
|
|
|
@ -5,12 +5,27 @@ 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
|
||||
|
||||
if (toDelete === renderer.simulation.name) {
|
||||
const others = saveStore.ls()
|
||||
removeElement(others, current)
|
||||
removeElement(others, toDelete)
|
||||
|
||||
if (!others.length) {
|
||||
initSimulation(defaultSimulationName, 'project')
|
||||
|
@ -18,7 +33,61 @@ export const deleteSimulation = (renderer: SimulationRenderer) => {
|
|||
|
||||
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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue