diff --git a/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/AnnotationFactory.tsx b/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/AnnotationFactory.tsx new file mode 100644 index 000000000..9ff9cf673 --- /dev/null +++ b/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/AnnotationFactory.tsx @@ -0,0 +1,20 @@ +import { BackendTypeRole } from "visualiser-debugger/Types/annotationType"; +import { LinkedListNodeAnnotation } from "./LinkedListAnnotation"; +import { assertUnreachable } from "visualiser-debugger/Component/Visualizer/Util/util"; +import { TypeAnnotationProp } from "../TypeAnnotation"; +import { TreeNodeAnnotation } from "./BinaryTreeAnnotation"; +export function AnnotationFactory (backendRole: BackendTypeRole, { + typeDeclaration, + }: TypeAnnotationProp) : JSX.Element | null { + switch(backendRole){ + case BackendTypeRole.LinkedList: + return + case BackendTypeRole.BinaryTree: + return + case BackendTypeRole.Empty: + return null; + default: + assertUnreachable(backendRole); +} + return null; +} \ No newline at end of file diff --git a/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/BinaryTreeAnnotation.tsx b/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/BinaryTreeAnnotation.tsx new file mode 100644 index 000000000..41752fbeb --- /dev/null +++ b/client/src/visualiser-debugger/Component/Configuration/RoleAnnotation/BinaryTreeAnnotation.tsx @@ -0,0 +1,197 @@ +import { BackendTypeDeclaration, isNativeTypeName, isPointerType, isStructTypeName } from 'visualiser-debugger/Types/backendType'; +import styles from 'styles/Configuration.module.css'; +import * as RadioGroup from '@radix-ui/react-radio-group'; +import { BinaryTreeAnnotation, DataStructureType, PossibleBinaryTreeAnnotation } from '../../../Types/annotationType'; +import { AnnotationComponent, AnnotationProp } from './AnnotationComponentBase'; +import { useEffect, useState } from 'react'; +import { useGlobalStore } from 'visualiser-debugger/Store/globalStateStore'; +import ConfigurationSelect from '../ConfigurationSelect'; + +export const createPossibleTreeTypeDecl = ( + typeDecl: BackendTypeDeclaration +) : PossibleBinaryTreeAnnotation | null => { + if (!('fields' in typeDecl)) { + return null; + } + + if (!isStructTypeName(typeDecl.typeName)) { + return null; + } + + const possibleTypeDecl: PossibleBinaryTreeAnnotation = { + typeName: typeDecl.typeName, + possibleValues: [], + possibleLefts: [], + possibleRights: [], + }; + if (typeDecl.fields === undefined) { + return null; + } + typeDecl.fields.forEach((field) => { + if (isNativeTypeName(field.typeName)) { + possibleTypeDecl.possibleValues.push({ + name: field.name, + typeName: field.typeName, + }); + } + if ( + isPointerType(field.typeName) && + isStructTypeName(field.typeName.slice(0, -1)) && + field.name.includes('left') + ) { + possibleTypeDecl.possibleLefts.push({ + name: field.name, + typeName: field.typeName, + }); + } + if ( + isPointerType(field.typeName) && + isStructTypeName(field.typeName.slice(0, -1)) && + field.name.includes('right') + ) { + possibleTypeDecl.possibleRights.push({ + name: field.name, + typeName: field.typeName, + }); + } + }); + + if ( + possibleTypeDecl.possibleValues.length >= 1 && + possibleTypeDecl.possibleLefts.length >= 1 && + possibleTypeDecl.possibleRights.length >= 1 + ) { + return possibleTypeDecl; + } + return null; +} + +export const TreeNodeAnnotation: AnnotationComponent = ({ backendType }: AnnotationProp) => { + const [possibleTypeDeclForTree, setPossibleTypeDeclForTree] = + useState(createPossibleTreeTypeDecl(backendType)); + const { updateUserAnnotation, visualizer } = useGlobalStore(); + const [nodeAnnotation, setNodeAnnotation] = useState(null); + const handleUpdateNodeAnnotation = (newAnnotation: BinaryTreeAnnotation) => { + updateUserAnnotation({ + stackAnnotation: visualizer.userAnnotation.stackAnnotation, + typeAnnotation: { + ...visualizer.userAnnotation.typeAnnotation, + [backendType.typeName]: newAnnotation, + }, + }); + } + const handleTreeNodeAnnotation = (possibleTypeAnnotation: PossibleBinaryTreeAnnotation | null) => { + if (possibleTypeAnnotation === null) return; + setPossibleTypeDeclForTree(possibleTypeAnnotation); + const newAnnotation: BinaryTreeAnnotation = { + typeName: backendType.typeName as `struct ${string}`, + type: DataStructureType.BinaryTree, + value: { + name: possibleTypeAnnotation.possibleValues[0].name, + typeName: possibleTypeAnnotation.possibleValues[0].typeName, + }, + left: { + name: possibleTypeAnnotation.possibleLefts[0].name, + typeName: possibleTypeAnnotation.possibleLefts[0].typeName, + }, + right: { + name: possibleTypeAnnotation.possibleRights[0].name, + typeName: possibleTypeAnnotation.possibleRights[0].typeName, + }, + + } + setNodeAnnotation(newAnnotation); + handleUpdateNodeAnnotation(newAnnotation); + } + + useEffect(() => { + handleTreeNodeAnnotation(possibleTypeDeclForTree); + } , [possibleTypeDeclForTree]); + + useEffect(() => { + const possibleTypeDecls = createPossibleTreeTypeDecl(backendType); + setPossibleTypeDeclForTree(possibleTypeDecls); + }, [backendType]); + + const handleUpdateNodeData = (newNodeData: string, newNodeDataType: string) => { + if (isNativeTypeName(newNodeDataType)) { + const newAnnotation: BinaryTreeAnnotation = { + ...nodeAnnotation, + value: { + name: newNodeData, + typeName: newNodeDataType, + }, + } as BinaryTreeAnnotation; + setNodeAnnotation(newAnnotation); + handleUpdateNodeAnnotation(newAnnotation); + } + }; + + const handleUpdateLeftData = (newLeftData: string, newLeftDataType: string) => { + if (isPointerType(newLeftDataType) && isStructTypeName(newLeftDataType.slice(0, -1))) { + const newAnnotation: BinaryTreeAnnotation = { + ...nodeAnnotation, + left: { + name: newLeftData, + typeName: newLeftDataType, + }, + } as BinaryTreeAnnotation; + setNodeAnnotation(newAnnotation); + handleUpdateNodeAnnotation(newAnnotation); + } + } + + const handleUpdateRightData = (newRightData: string, newRightDataType: string) => { + if (isPointerType(newRightDataType) && isStructTypeName(newRightDataType.slice(0, -1))) { + const newAnnotation: BinaryTreeAnnotation = { + ...nodeAnnotation, + right: { + name: newRightData, + typeName: newRightDataType, + }, + } as BinaryTreeAnnotation; + setNodeAnnotation(newAnnotation); + handleUpdateNodeAnnotation(newAnnotation); + } + } + + if (!possibleTypeDeclForTree) { + return ( + + + Error: No possible{' '} + {/* where is the styles.highlightLinkedList */} + binary tree annotation can be made. + + + ); + } + return ( + + + + Node Data + + + + + Left Child + + + + Right Child + + + + + ); +} \ No newline at end of file diff --git a/client/src/visualiser-debugger/Component/Configuration/StackVarDeclaration.tsx b/client/src/visualiser-debugger/Component/Configuration/StackVarDeclaration.tsx index c4fb4af90..35c664829 100644 --- a/client/src/visualiser-debugger/Component/Configuration/StackVarDeclaration.tsx +++ b/client/src/visualiser-debugger/Component/Configuration/StackVarDeclaration.tsx @@ -33,7 +33,7 @@ export const StackVarAnnotation: React.FC = ({ // Annotate by default if the variable contains a pointer useEffect(() => { - if (selectedRole === StackVariableRole.LinkedListPointer) { + if (selectedRole === StackVariableRole.LinkedListPointer || selectedRole === StackVariableRole.BinaryTreePointer) { const newStackAnnotation = { [name]: memoryValue.typeName, }; @@ -84,7 +84,7 @@ export const StackVarAnnotation: React.FC = ({ type="button" onClick={() => { setSelectedRole(role[1]); - if (role[1] === StackVariableRole.LinkedListPointer) { + if (role[1] === StackVariableRole.LinkedListPointer || role[1] === StackVariableRole.BinaryTreePointer) { updateStackAnnotation({ [name]: memoryValue.typeName }); } else { updateStackAnnotation({ [name]: null }); diff --git a/client/src/visualiser-debugger/Component/Configuration/TypeAnnotation.tsx b/client/src/visualiser-debugger/Component/Configuration/TypeAnnotation.tsx index 41773bb96..185fae207 100644 --- a/client/src/visualiser-debugger/Component/Configuration/TypeAnnotation.tsx +++ b/client/src/visualiser-debugger/Component/Configuration/TypeAnnotation.tsx @@ -6,10 +6,12 @@ import { MotionCollapse } from './MotionCollapse'; import './typeAnnotation.css'; import { BackendTypeRole } from '../../Types/annotationType'; import { - LinkedListNodeAnnotation, createPossibleLinkedListTypeDecl, } from './RoleAnnotation/LinkedListAnnotation'; import { BackendTypeDeclaration } from '../../Types/backendType'; +import { AnnotationFactory } from './RoleAnnotation/AnnotationFactory'; +import { createPossibleTreeTypeDecl } from './RoleAnnotation/BinaryTreeAnnotation'; + export type TypeAnnotationProp = { typeDeclaration: BackendTypeDeclaration; @@ -26,8 +28,11 @@ export const TypeAnnotation: React.FC = ({ if (createPossibleLinkedListTypeDecl(typeDeclaration) !== null) { setSelectedRole(BackendTypeRole.LinkedList); } + if (createPossibleTreeTypeDecl(typeDeclaration) !== null) { + setSelectedRole(BackendTypeRole.BinaryTree); + } }, []); - + const annotation = AnnotationFactory(selectedRole, {typeDeclaration}); return ( @@ -95,9 +100,9 @@ export const TypeAnnotation: React.FC = ({ - - - + {/* should this be true??? */} + + {annotation} ); diff --git a/client/src/visualiser-debugger/Types/annotationType.ts b/client/src/visualiser-debugger/Types/annotationType.ts index 630995301..c1fabd0ba 100644 --- a/client/src/visualiser-debugger/Types/annotationType.ts +++ b/client/src/visualiser-debugger/Types/annotationType.ts @@ -136,11 +136,13 @@ export type PossibleStructAnnotation = { export enum BackendTypeRole { LinkedList = 'Linked List Node', + BinaryTree = 'Binary Tree Node', Empty = 'Not Visualized', } export enum StackVariableRole { LinkedListPointer = 'Linked List Node', + BinaryTreePointer = 'Binary Tree Node', Empty = 'Not Visualized', } @@ -155,3 +157,19 @@ export type PossibleLinkedListAnnotation = { typeName: PointerType['typeName']; }[]; }; + +export type PossibleBinaryTreeAnnotation = { + typeName: StructType['typeName']; + possibleValues: { + name: Name; + typeName: NativeTypeName; + }[]; + possibleLefts: { + name: Name; + typeName: PointerType['typeName']; + }[]; + possibleRights: { + name: Name; + typeName: PointerType['typeName']; + }[]; +}; \ No newline at end of file