Clean up 'prompt user for info' modals (#58)

This commit is contained in:
Kurt Hutten
2023-03-13 09:22:05 +11:00
committed by GitHub
parent eebddb0ce2
commit 1de21b8bdd
6 changed files with 491 additions and 309 deletions

View File

@ -0,0 +1,236 @@
import { useEffect, useState, useRef } from 'react'
import { abstractSyntaxTree, Value } from '../lang/abstractSyntaxTree'
import { executor } from '../lang/executor'
import { findUniqueName } from '../lang/modifyAst'
import { findAllPreviousVariables, PrevVariable } from '../lang/queryAst'
import { lexer } from '../lang/tokeniser'
import { useStore } from '../useStore'
export const AvailableVars = ({
onVarClick,
prevVariables,
}: {
onVarClick: (a: string) => void
prevVariables: PrevVariable<any>[]
}) => {
return (
<ul className="flex flex-col">
{prevVariables.length &&
prevVariables.map(({ key, value }) => (
<li key={key}>
<button
className="flex w-full justify-between items-center rounded-md hover:bg-gray-100 max-w-xs"
onClick={() => onVarClick(key)}
>
<span className="font-[monospace] text-gray-800">{key}</span>{' '}
<span className="font-[monospace] text-gray-600 w-24 text-start font-bold">
{value}
</span>
</button>
</li>
))}
</ul>
)
}
export const addToInputHelper =
(
inputRef: React.RefObject<HTMLInputElement>,
setValue: (a: string) => void
) =>
(varName: string) => {
const selectionStart = inputRef.current?.selectionStart
let selectionEnd = inputRef.current?.selectionEnd
let newValue = ''
if (
typeof selectionStart === 'number' &&
typeof selectionEnd === 'number'
) {
newValue = stringSplice(
inputRef.current?.value || '',
selectionStart,
selectionEnd,
varName
)
selectionEnd = selectionStart + varName.length
} else {
newValue = inputRef.current?.value + varName
}
setValue(newValue)
inputRef.current?.focus()
setTimeout(() => {
// run in the next render cycle
const _selectionEnd =
typeof selectionEnd === 'number' ? selectionEnd : newValue.length
inputRef.current?.setSelectionRange(_selectionEnd, _selectionEnd)
})
}
function stringSplice(str: string, index: number, count: number, add: string) {
return str.slice(0, index) + (add || '') + str.slice(index + count)
}
export function useCalc({
value,
initialVariableName: valueName = '',
}: {
value: string
initialVariableName?: string
}): {
inputRef: React.RefObject<HTMLInputElement>
valueNode: Value | null
calcResult: string
prevVariables: PrevVariable<any>[]
newVariableName: string
isNewVariableNameUnique: boolean
newVariableInsertIndex: number
setNewVariableName: (a: string) => void
} {
const { ast, programMemory, selectionRange } = useStore((s) => ({
ast: s.ast,
programMemory: s.programMemory,
selectionRange: s.selectionRanges[0],
}))
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>
>({
variables: [],
insertIndex: 0,
bodyPath: [],
})
const [valueNode, setValueNode] = useState<Value | null>(null)
const [calcResult, setCalcResult] = useState('NAN')
const [newVariableName, setNewVariableName] = useState('')
const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true)
useEffect(() => {
setTimeout(() => {
inputRef.current && inputRef.current.focus()
inputRef.current &&
inputRef.current.setSelectionRange(0, String(value).length)
}, 100)
if (ast) {
setNewVariableName(findUniqueName(ast, valueName))
}
}, [])
useEffect(() => {
const allVarNames = Object.keys(programMemory.root)
if (allVarNames.includes(newVariableName)) {
setIsNewVariableNameUnique(false)
} else {
setIsNewVariableNameUnique(true)
}
}, [newVariableName])
useEffect(() => {
if (!ast || !programMemory || !selectionRange) return
const varInfo = findAllPreviousVariables(ast, programMemory, selectionRange)
setAvailableVarInfo(varInfo)
}, [ast, programMemory, selectionRange])
useEffect(() => {
try {
const code = `const __result__ = ${value}\nshow(__result__)`
const ast = abstractSyntaxTree(lexer(code))
const _programMem: any = { root: {} }
availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
})
const programMemory = executor(ast, _programMem)
const resultDeclaration = ast.body.find(
(a) =>
a.type === 'VariableDeclaration' &&
a.declarations?.[0]?.id?.name === '__result__'
)
const init =
resultDeclaration?.type === 'VariableDeclaration' &&
resultDeclaration?.declarations?.[0]?.init
const result = programMemory?.root?.__result__?.value
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
init && setValueNode(init)
} catch (e) {
setCalcResult('NAN')
setValueNode(null)
}
}, [value])
return {
valueNode,
calcResult,
prevVariables: availableVarInfo.variables,
newVariableInsertIndex: availableVarInfo.insertIndex,
newVariableName,
isNewVariableNameUnique,
setNewVariableName,
inputRef,
}
}
export const CalcResult = ({ calcResult }: { calcResult: string }) => {
return (
<div className="font-[monospace] pl-4 text-gray-600">
<span
className={`${
calcResult === 'NAN' ? 'bg-pink-200' : ''
} px-2 py-0.5 rounded`}
>
= {calcResult}
</span>
</div>
)
}
export const CreateNewVariable = ({
newVariableName,
isNewVariableNameUnique,
setNewVariableName,
shouldCreateVariable,
setShouldCreateVariable,
}: {
isNewVariableNameUnique: boolean
newVariableName: string
setNewVariableName: (a: string) => void
shouldCreateVariable: boolean
setShouldCreateVariable: (a: boolean) => void
}) => {
return (
<>
<label
htmlFor="create-new-variable"
className="block text-sm font-medium text-gray-700 mt-3 font-mono"
>
Create new variable
</label>
<div className="mt-1 flex flex-1">
<input
type="checkbox"
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 flex-shrink"
checked={shouldCreateVariable}
onChange={(e) => {
setShouldCreateVariable(e.target.checked)
}}
/>
<input
type="text"
disabled={!shouldCreateVariable}
name="create-new-variable"
id="create-new-variable"
className={`shadow-sm font-[monospace] focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 flex-shrink-0 ${
!shouldCreateVariable ? 'opacity-50' : ''
}`}
value={newVariableName}
onChange={(e) => {
setNewVariableName(e.target.value)
}}
/>
</div>
{!isNewVariableNameUnique && (
<div className="bg-pink-200 rounded px-2 py-0.5 text-xs">
Sorry, that's not a unique variable name. Please try something else
</div>
)}
</>
)
}

View File

@ -0,0 +1,142 @@
import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTree'
import {
AvailableVars,
addToInputHelper,
useCalc,
CalcResult,
CreateNewVariable,
} from './AvailableVarsHelpers'
export const SetAngleLengthModal = ({
isOpen,
onResolve,
onReject,
value: initialValue,
valueName,
}: {
isOpen: boolean
onResolve: (a: {
value: string
valueNode: Value
variableName?: string
newVariableInsertIndex: number
}) => void
onReject: (a: any) => void
value: number
valueName: string
}) => {
const [value, setValue] = useState(String(initialValue))
const [shouldCreateVariable, setShouldCreateVariable] = useState(false)
const {
prevVariables,
calcResult,
valueNode,
isNewVariableNameUnique,
newVariableName,
setNewVariableName,
inputRef,
newVariableInsertIndex,
} = useCalc({ value, initialVariableName: valueName })
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={onReject}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900 capitalize"
>
Set {valueName}
</Dialog.Title>
<div className="block text-sm font-medium text-gray-700 mt-3 font-mono capitalize">
Available Variables
</div>
<AvailableVars
prevVariables={prevVariables}
onVarClick={addToInputHelper(inputRef, setValue)}
/>
<label
htmlFor="val"
className="block text-sm font-medium text-gray-700 mt-3 font-mono capitalize"
>
{valueName} Value
</label>
<div className="mt-1">
<input
ref={inputRef}
type="text"
name="val"
id="val"
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1"
value={value}
onChange={(e) => {
setValue(e.target.value)
}}
/>
</div>
<CalcResult calcResult={calcResult} />
<CreateNewVariable
setNewVariableName={setNewVariableName}
newVariableName={newVariableName}
isNewVariableNameUnique={isNewVariableNameUnique}
shouldCreateVariable={shouldCreateVariable}
setShouldCreateVariable={setShouldCreateVariable}
/>
<div className="mt-4">
<button
type="button"
disabled={calcResult === 'NAN' || !isNewVariableNameUnique}
className={`inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 ${
calcResult === 'NAN' || !isNewVariableNameUnique
? 'opacity-50 cursor-not-allowed'
: ''
}`}
onClick={() =>
valueNode &&
onResolve({
value,
valueNode,
newVariableInsertIndex,
variableName: shouldCreateVariable
? newVariableName
: undefined,
})
}
>
Add constraining value
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)
}

View File

@ -1,272 +0,0 @@
import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState, useRef, useEffect } from 'react'
import { abstractSyntaxTree, Value } from '../lang/abstractSyntaxTree'
import { executor } from '../lang/executor'
import { findUniqueName } from '../lang/modifyAst'
import { PrevVariable } from '../lang/queryAst'
import { lexer } from '../lang/tokeniser'
import { useStore } from '../useStore'
export const SetAngleLengthModal = ({
isOpen,
onResolve,
onReject,
prevVariables,
value: initialValue,
valueName,
}: {
isOpen: boolean
onResolve: (a: {
value: string
valueNode: Value
variableName?: string
}) => void
onReject: (a: any) => void
prevVariables: PrevVariable<number>[]
value: number
valueName: string
}) => {
const { ast, programMemory } = useStore((s) => ({
ast: s.ast,
programMemory: s.programMemory,
}))
const [value, setValue] = useState(String(initialValue))
const [calcResult, setCalcResult] = useState('NAN')
const [shouldCreateVariable, setShouldCreateVariable] = useState(false)
const [newVariableName, setNewVariableName] = useState('')
const [isNewVariableNameUnique, setIsNewVariableNameUnique] = useState(true)
const [valueNode, setValueNode] = useState<any>(null)
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
setTimeout(() => {
inputRef.current && inputRef.current.focus()
inputRef.current &&
inputRef.current.setSelectionRange(0, String(value).length)
}, 100)
if (ast) {
setNewVariableName(findUniqueName(ast, valueName))
}
}, [])
useEffect(() => {
const allVarNames = Object.keys(programMemory.root)
if (allVarNames.includes(newVariableName)) {
setIsNewVariableNameUnique(false)
} else {
setIsNewVariableNameUnique(true)
}
}, [newVariableName])
useEffect(() => {
try {
const code = `const __result__ = ${value}\nshow(__result__)`
const ast = abstractSyntaxTree(lexer(code))
const _programMem: any = { root: {} }
prevVariables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
})
const programMemory = executor(ast, _programMem)
const resultDeclaration = ast.body.find(
(a) =>
a.type === 'VariableDeclaration' &&
a.declarations?.[0]?.id?.name === '__result__'
)
const init =
resultDeclaration?.type === 'VariableDeclaration' &&
resultDeclaration?.declarations?.[0]?.init
console.log(init)
setCalcResult(programMemory?.root?.__result__?.value || 'NAN')
setValueNode(init)
} catch (e) {
setCalcResult('NAN')
setValueNode(null)
}
}, [value])
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={onReject}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 text-gray-900 capitalize"
>
Set {valueName}
</Dialog.Title>
<div className="block text-sm font-medium text-gray-700 mt-3 font-mono capitalize">
Available Variables
</div>
<ul className="flex flex-col">
{prevVariables.length &&
prevVariables.map(({ key, value }) => (
<li key={key}>
<button
className="flex w-full justify-between items-center rounded-md hover:bg-gray-100 max-w-xs"
onClick={(e) => {
const selectionStart =
inputRef.current?.selectionStart
let selectionEnd = inputRef.current?.selectionEnd
let newValue = ''
if (
typeof selectionStart === 'number' &&
typeof selectionEnd === 'number'
) {
newValue = stringSplice(
inputRef.current?.value || '',
selectionStart,
selectionEnd,
key
)
selectionEnd = selectionStart + key.length
} else {
newValue = inputRef.current?.value + key
}
setValue(newValue)
inputRef.current?.focus()
setTimeout(() => {
// run in the next render cycle
const _selectionEnd =
typeof selectionEnd === 'number'
? selectionEnd
: newValue.length
inputRef.current?.setSelectionRange(
_selectionEnd,
_selectionEnd
)
})
}}
>
<span className="font-[monospace] text-gray-800">
{key}
</span>{' '}
<span className="font-[monospace] text-gray-600 w-24 text-start font-bold">
{value}
</span>
</button>
</li>
))}
</ul>
<label
htmlFor="val"
className="block text-sm font-medium text-gray-700 mt-3 font-mono capitalize"
>
{valueName} Value
</label>
<div className="mt-1">
<input
ref={inputRef}
type="text"
name="val"
id="val"
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1"
value={value}
onChange={(e) => {
setValue(e.target.value)
}}
/>
</div>
<div className="font-[monospace] pl-4 text-gray-600">
<span
className={`${
calcResult === 'NAN' ? 'bg-pink-200' : ''
} px-2 py-0.5 rounded`}
>
= {calcResult}
</span>
</div>
<label
htmlFor="val"
className="block text-sm font-medium text-gray-700 mt-3 font-mono"
>
Create new variable
</label>
<div className="mt-1 flex flex-1">
<input
type="checkbox"
name="val"
id="val"
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 flex-shrink"
checked={shouldCreateVariable}
onChange={(e) => {
setShouldCreateVariable(e.target.checked)
}}
/>
<input
type="text"
disabled={!shouldCreateVariable}
name="val"
id="val"
className={`shadow-sm font-[monospace] focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono pl-1 flex-shrink-0 ${
!shouldCreateVariable ? 'opacity-50' : ''
}`}
value={newVariableName}
onChange={(e) => {
setNewVariableName(e.target.value)
}}
/>
</div>
{!isNewVariableNameUnique && (
<div className="bg-pink-200 rounded px-2 py-0.5 text-xs">
Sorry, that's not a unique variable name. Please try
something else
</div>
)}
<div className="mt-4">
<button
type="button"
disabled={calcResult === 'NAN' || !isNewVariableNameUnique}
className={`inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 ${
calcResult === 'NAN' || !isNewVariableNameUnique
? 'opacity-50 cursor-not-allowed'
: ''
}`}
onClick={() =>
onResolve({
value,
valueNode,
variableName: shouldCreateVariable
? newVariableName
: undefined,
})
}
>
Add constraining value
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)
}
function stringSplice(str: string, index: number, count: number, add: string) {
return str.slice(0, index) + (add || '') + str.slice(index + count)
}

View File

@ -1,28 +1,55 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTree'
import {
AvailableVars,
addToInputHelper,
useCalc,
CalcResult,
CreateNewVariable,
} from './AvailableVarsHelpers'
export const GetInfoModal = ({ export const GetInfoModal = ({
isOpen, isOpen,
onResolve, onResolve,
onReject, onReject,
// fields: initialFields,
segName: initialSegName, segName: initialSegName,
isSegNameEditable, isSegNameEditable,
value: initialValue, value: initialValue,
initialVariableName,
}: { }: {
isOpen: boolean isOpen: boolean
onResolve: (a: any) => void onResolve: (a: {
value: string
segName: string
valueNode: Value
variableName?: string
newVariableInsertIndex: number
}) => void
onReject: (a: any) => void onReject: (a: any) => void
segName: string segName: string
isSegNameEditable: boolean isSegNameEditable: boolean
value: number value: number
initialVariableName: string
}) => { }) => {
const [segName, setSegName] = useState(initialSegName) const [segName, setSegName] = useState(initialSegName)
const [value, setValue] = useState(initialValue) const [value, setValue] = useState(String(initialValue))
const [shouldCreateVariable, setShouldCreateVariable] = useState(false)
const {
prevVariables,
inputRef,
calcResult,
valueNode,
setNewVariableName,
newVariableName,
isNewVariableNameUnique,
newVariableInsertIndex,
} = useCalc({ value, initialVariableName })
return ( return (
<Transition appear show={isOpen} as={Fragment}> <Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={onResolve}> <Dialog as="div" className="relative z-10" onClose={onReject}>
<Transition.Child <Transition.Child
as={Fragment} as={Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
@ -53,6 +80,13 @@ export const GetInfoModal = ({
> >
Constraint details Constraint details
</Dialog.Title> </Dialog.Title>
<div className="block text-sm font-medium text-gray-700 mt-3 font-mono capitalize">
Available Variables
</div>
<AvailableVars
prevVariables={prevVariables}
onVarClick={addToInputHelper(inputRef, setValue)}
/>
<label <label
htmlFor="val" htmlFor="val"
className="block text-sm font-medium text-gray-700 mt-3 font-mono" className="block text-sm font-medium text-gray-700 mt-3 font-mono"
@ -61,16 +95,18 @@ export const GetInfoModal = ({
</label> </label>
<div className="mt-1"> <div className="mt-1">
<input <input
type="number" type="text"
name="val" name="val"
id="val" id="val"
ref={inputRef}
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono" className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono"
value={value} value={value}
onChange={(e) => { onChange={(e) => {
setValue(Number(e.target.value)) setValue(e.target.value)
}} }}
/> />
</div> </div>
<CalcResult calcResult={calcResult} />
<label <label
htmlFor="segName" htmlFor="segName"
className="block text-sm font-medium text-gray-700 mt-3 font-mono" className="block text-sm font-medium text-gray-700 mt-3 font-mono"
@ -90,12 +126,30 @@ export const GetInfoModal = ({
}} }}
/> />
</div> </div>
<CreateNewVariable
setNewVariableName={setNewVariableName}
newVariableName={newVariableName}
isNewVariableNameUnique={isNewVariableNameUnique}
shouldCreateVariable={shouldCreateVariable}
setShouldCreateVariable={setShouldCreateVariable}
/>
<div className="mt-4"> <div className="mt-4">
<button <button
type="button" type="button"
className="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2" className="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
onClick={() => onResolve({ segName, value })} onClick={() =>
valueNode &&
onResolve({
segName,
value,
valueNode,
newVariableInsertIndex,
variableName: shouldCreateVariable
? newVariableName
: undefined,
})
}
> >
Add constraining value Add constraining value
</button> </button>

View File

@ -12,7 +12,7 @@ import {
getTransformInfos, getTransformInfos,
transformAstSketchLines, transformAstSketchLines,
} from '../../lang/std/sketchcombos' } from '../../lang/std/sketchcombos'
import { SetAngleLengthModal } from '../SetAngleModal' import { SetAngleLengthModal } from '../SetAngleLengthModal'
import { import {
createIdentifier, createIdentifier,
createVariableDeclaration, createVariableDeclaration,
@ -69,16 +69,10 @@ export const SetAngleLength = ({
programMemory, programMemory,
referenceSegName: '', referenceSegName: '',
}) })
const availableVarInfo = findAllPreviousVariables(
modifiedAst,
programMemory,
selectionRanges[0]
)
try { try {
const { valueNode, variableName } = await getModalInfo({ const { valueNode, variableName, newVariableInsertIndex } =
await getModalInfo({
value: valueUsedInTransform, value: valueUsedInTransform,
prevVariables: availableVarInfo.variables,
valueName: angleOrLength === 'setAngle' ? 'angle' : 'length', valueName: angleOrLength === 'setAngle' ? 'angle' : 'length',
} as any) } as any)
@ -95,7 +89,7 @@ export const SetAngleLength = ({
if (variableName) { if (variableName) {
const newBody = [..._modifiedAst.body] const newBody = [..._modifiedAst.body]
newBody.splice( newBody.splice(
availableVarInfo.insertIndex, newVariableInsertIndex,
0, 0,
createVariableDeclaration(variableName, valueNode) createVariableDeclaration(variableName, valueNode)
) )

View File

@ -12,8 +12,11 @@ import {
transformSecondarySketchLinesTagFirst, transformSecondarySketchLinesTagFirst,
getTransformInfos, getTransformInfos,
} from '../../lang/std/sketchcombos' } from '../../lang/std/sketchcombos'
import { GetInfoModal } from '../GetInfoModal' import { GetInfoModal } from '../SetHorVertDistanceModal'
import { createLiteral } from '../../lang/modifyAst' import {
createIdentifier,
createVariableDeclaration,
} from '../../lang/modifyAst'
const getModalInfo = create(GetInfoModal as any) const getModalInfo = create(GetInfoModal as any)
@ -87,25 +90,50 @@ export const SetHorzDistance = ({
transformInfos, transformInfos,
programMemory, programMemory,
}) })
const { segName, value }: { segName: string; value: number } = const {
await getModalInfo({ segName,
value,
valueNode,
variableName,
newVariableInsertIndex,
}: {
segName: string
value: number
valueNode: Value
variableName?: string
newVariableInsertIndex: number
} = await getModalInfo({
segName: tagInfo?.tag, segName: tagInfo?.tag,
isSegNameEditable: !tagInfo?.isTagExisting, isSegNameEditable: !tagInfo?.isTagExisting,
value: valueUsedInTransform, value: valueUsedInTransform,
initialVariableName:
horOrVert === 'setHorzDistance' ? 'xDis' : 'yDis',
} as any) } as any)
if (segName === tagInfo?.tag && value === valueUsedInTransform) { if (segName === tagInfo?.tag && value === valueUsedInTransform) {
updateAst(modifiedAst) updateAst(modifiedAst)
} else { } else {
// transform again but forcing certain values // transform again but forcing certain values
const { modifiedAst } = transformSecondarySketchLinesTagFirst({ const { modifiedAst: _modifiedAst } =
transformSecondarySketchLinesTagFirst({
ast, ast,
selectionRanges, selectionRanges,
transformInfos, transformInfos,
programMemory, programMemory,
forceSegName: segName, forceSegName: segName,
forceValueUsedInTransform: createLiteral(value), forceValueUsedInTransform: variableName
? createIdentifier(variableName)
: valueNode,
}) })
updateAst(modifiedAst) if (variableName) {
const newBody = [..._modifiedAst.body]
newBody.splice(
newVariableInsertIndex,
0,
createVariableDeclaration(variableName, valueNode)
)
_modifiedAst.body = newBody
}
updateAst(_modifiedAst)
} }
} }
}} }}