Files
modeling-app/src/useStore.ts

194 lines
4.7 KiB
TypeScript
Raw Normal View History

import create from 'zustand'
2022-11-26 08:34:23 +11:00
import { addLineHighlight, EditorView } from './editor/highlightextension'
import {
Program,
abstractSyntaxTree,
getNodeFromPath,
} from './lang/abstractSyntaxTree'
import { ProgramMemory, Position, PathToNode, Rotation } from './lang/executor'
import { recast } from './lang/recast'
import { asyncLexer } from './lang/tokeniser'
import { EditorSelection } from '@codemirror/state'
export type Range = [number, number]
export type Ranges = Range[]
export type TooTip =
| 'lineTo'
| 'line'
| 'angledLine'
| 'angledLineOfXLength'
| 'angledLineOfYLength'
| 'angledLineToX'
| 'angledLineToY'
| 'xLine'
| 'yLine'
| 'xLineTo'
| 'yLineTo'
export const toolTips: TooTip[] = [
'lineTo',
'line',
'angledLine',
'angledLineOfXLength',
'angledLineOfYLength',
'angledLineToX',
'angledLineToY',
'xLine',
'yLine',
'xLineTo',
'yLineTo',
]
export type GuiModes =
| {
mode: 'default'
}
| {
mode: 'sketch'
sketchMode: TooTip
isTooltip: true
rotation: Rotation
2023-01-04 01:28:26 +11:00
position: Position
id?: string
2022-12-06 05:40:05 +11:00
pathToNode: PathToNode
}
2022-12-06 05:40:05 +11:00
| {
mode: 'sketch'
sketchMode: 'sketchEdit'
rotation: Rotation
2023-01-04 01:28:26 +11:00
position: Position
2022-12-06 05:40:05 +11:00
pathToNode: PathToNode
2022-12-23 07:37:42 +11:00
}
| {
mode: 'sketch'
sketchMode: 'selectFace'
}
| {
2022-12-06 05:40:05 +11:00
mode: 'canEditSketch'
pathToNode: PathToNode
rotation: Rotation
2023-01-04 01:28:26 +11:00
position: Position
2022-12-23 07:37:42 +11:00
}
| {
mode: 'canEditExtrude'
pathToNode: PathToNode
rotation: Rotation
position: Position
}
interface StoreState {
2022-11-26 08:34:23 +11:00
editorView: EditorView | null
setEditorView: (editorView: EditorView) => void
highlightRange: [number, number]
setHighlightRange: (range: Range) => void
setCursor: (selections: Ranges) => void
selectionRanges: Ranges
setSelectionRanges: (range: Ranges) => void
guiMode: GuiModes
lastGuiMode: GuiModes
setGuiMode: (guiMode: GuiModes) => void
logs: string[]
addLog: (log: string) => void
resetLogs: () => void
ast: Program | null
setAst: (ast: Program | null) => void
updateAst: (ast: Program, focusPath?: PathToNode) => void
code: string
setCode: (code: string) => void
2022-11-28 19:43:20 +11:00
formatCode: () => void
2022-12-06 05:40:05 +11:00
errorState: {
isError: boolean
error: string
}
setError: (error?: string) => void
2023-01-04 01:28:26 +11:00
programMemory: ProgramMemory
setProgramMemory: (programMemory: ProgramMemory) => void
isShiftDown: boolean
setIsShiftDown: (isShiftDown: boolean) => void
}
export const useStore = create<StoreState>()((set, get) => ({
2022-11-26 08:34:23 +11:00
editorView: null,
setEditorView: (editorView) => {
set({ editorView })
},
highlightRange: [0, 0],
setHighlightRange: (highlightRange) => {
set({ highlightRange })
const editorView = get().editorView
if (editorView) {
editorView.dispatch({ effects: addLineHighlight.of(highlightRange) })
}
},
setCursor: (ranges: Ranges) => {
const { editorView } = get()
2023-01-06 09:07:22 +11:00
if (!editorView) return
editorView.dispatch({
selection: EditorSelection.create(
[...ranges.map(([start, end]) => EditorSelection.cursor(end))],
ranges.length - 1
),
2023-01-06 09:07:22 +11:00
})
},
selectionRanges: [[0, 0]],
setSelectionRanges: (selectionRanges) => {
set({ selectionRanges })
2022-11-26 08:34:23 +11:00
},
guiMode: { mode: 'default' },
lastGuiMode: { mode: 'default' },
setGuiMode: (guiMode) => {
set({ guiMode })
},
logs: [],
addLog: (log) => {
if (Array.isArray(log)) {
const cleanLog: any = log.map(({ __geoMeta, ...rest }) => rest)
set((state) => ({ logs: [...state.logs, cleanLog] }))
} else {
set((state) => ({ logs: [...state.logs, log] }))
}
},
resetLogs: () => {
set({ logs: [] })
},
ast: null,
setAst: (ast) => {
set({ ast })
},
updateAst: async (ast, focusPath) => {
const newCode = recast(ast)
const astWithUpdatedSource = abstractSyntaxTree(await asyncLexer(newCode))
set({ ast: astWithUpdatedSource, code: newCode })
if (focusPath) {
const { node } = getNodeFromPath<any>(astWithUpdatedSource, focusPath)
const { start, end } = node
if (!start || !end) return
setTimeout(() => {
get().setCursor([[start, end]])
})
}
},
code: '',
setCode: (code) => {
set({ code })
2022-11-28 19:43:20 +11:00
},
formatCode: async () => {
2022-11-28 19:43:20 +11:00
const code = get().code
const ast = abstractSyntaxTree(await asyncLexer(code))
const newCode = recast(ast)
2022-11-28 19:43:20 +11:00
set({ code: newCode, ast })
},
2022-12-06 05:40:05 +11:00
errorState: {
isError: false,
error: '',
},
setError: (error = '') => {
set({ errorState: { isError: !!error, error } })
2022-12-23 07:37:42 +11:00
},
2023-01-04 01:28:26 +11:00
programMemory: { root: {}, _sketch: [] },
setProgramMemory: (programMemory) => set({ programMemory }),
isShiftDown: false,
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
}))