|
@@ -16,7 +16,7 @@ import {Delta} from "../onion/delta";
|
|
|
import {TrivialParser} from "../parser/trivial_parser";
|
|
|
|
|
|
import {d3Types, Graph} from "./graph"
|
|
|
-import {EditableGraph, GraphType, NodeType, LinkType} from "./editable_graph";
|
|
|
+import {EditableGraph, UserEditCallback, SetNodePositionCallback, GraphType, NodeType, LinkType} from "./editable_graph";
|
|
|
import {D3StateManipulator} from "./d3_state_manipulator";
|
|
|
import {RountangleEditor} from "./rountangleEditor/RountangleEditor";
|
|
|
import {
|
|
@@ -58,53 +58,32 @@ interface VersionedModelState {
|
|
|
historyGraph: HistoryGraphType; // the state of what is displayed in the middle panel
|
|
|
dependencyGraphL1: DependencyGraphType; // the state of what is displayed in the rightmost panel
|
|
|
dependencyGraphL0: DependencyGraphType; // the state of what is displayed in the rightmost panel
|
|
|
+ manipulator: D3StateManipulator;
|
|
|
+ graphDeltaExecutor: GraphDeltaExecutor;
|
|
|
+ versionRegistry: VersionRegistry;
|
|
|
+ compositeLevel: CompositeLevel;
|
|
|
}
|
|
|
|
|
|
-const initialModel: VersionedModelState = {
|
|
|
- version: initialVersion,
|
|
|
- graph: emptyGraph,
|
|
|
- historyGraph: initialHistoryGraph,
|
|
|
- dependencyGraphL1: emptyGraph,
|
|
|
- dependencyGraphL0: emptyGraph,
|
|
|
-};
|
|
|
-
|
|
|
export interface VersionedModelProps {
|
|
|
title: string;
|
|
|
generateUUID: () => UUID;
|
|
|
+ // compositeLevel: CompositeLevel;
|
|
|
|
|
|
readonly?: boolean;
|
|
|
|
|
|
+ onUserEdit?: UserEditCallback;
|
|
|
+ setNextNodePosition: SetNodePositionCallback;
|
|
|
+
|
|
|
state: VersionedModelState;
|
|
|
setState: (callback: (VersionedModelState) => VersionedModelState) => void;
|
|
|
}
|
|
|
|
|
|
class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
- readonly manipulator: D3StateManipulator;
|
|
|
- readonly graphDeltaExecutor: GraphDeltaExecutor;
|
|
|
- readonly compositeLevel: CompositeLevel;
|
|
|
- readonly versionRegistry: VersionRegistry;
|
|
|
-
|
|
|
readonly textarearef: React.RefObject<HTMLTextAreaElement>;
|
|
|
|
|
|
constructor(props) {
|
|
|
super(props);
|
|
|
-
|
|
|
- console.log(props);
|
|
|
-
|
|
|
- // 'Glue' callback
|
|
|
- const setGraph = (callback: (GraphType) => GraphType) => {
|
|
|
- this.props.setState(({graph, ...rest}) => ({
|
|
|
- graph: callback(graph),
|
|
|
- ...rest,
|
|
|
- }));
|
|
|
- };
|
|
|
-
|
|
|
this.textarearef = React.createRef();
|
|
|
-
|
|
|
- this.manipulator = new D3StateManipulator(setGraph);
|
|
|
- this.graphDeltaExecutor = new GraphDeltaExecutor(this.manipulator);
|
|
|
- this.compositeLevel = new CompositeLevel();
|
|
|
- this.versionRegistry = new VersionRegistry();
|
|
|
}
|
|
|
|
|
|
render() {
|
|
@@ -122,8 +101,9 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
throw new Error("Could not find path to clicked version!");
|
|
|
}
|
|
|
|
|
|
- this.manipulator.x = 0;
|
|
|
- this.manipulator.y = 0;
|
|
|
+ // this.manipulator.x = 0;
|
|
|
+ // this.manipulator.y = 0;
|
|
|
+ this.props.setNextNodePosition(0,0);
|
|
|
|
|
|
for (const [linkType, delta] of path) {
|
|
|
if (linkType === 'p') {
|
|
@@ -144,92 +124,90 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
}
|
|
|
|
|
|
const undo = deltaToUndo => {
|
|
|
- this.manipulator.x = 0;
|
|
|
- this.manipulator.y = 0;
|
|
|
- this.graphDeltaExecutor.unexec(deltaToUndo);
|
|
|
- this.props.setState(({dependencyGraphL0: prevDepGraphL0, dependencyGraphL1: prevDepGraphL1, ...rest}) => ({
|
|
|
- dependencyGraphL1: setDeltaInactive(prevDepGraphL1, deltaToUndo),
|
|
|
- dependencyGraphL0: deltaToUndo.deltas.reduce((prevDepGraphL0, delta) => setDeltaInactive(prevDepGraphL0, delta), prevDepGraphL0),
|
|
|
- ...rest,
|
|
|
- }));
|
|
|
+ // this.props.setNextNodePosition(0,0);
|
|
|
+ // this.graphDeltaExecutor.unexec(deltaToUndo);
|
|
|
+ // this.props.setState(({dependencyGraphL0: prevDepGraphL0, dependencyGraphL1: prevDepGraphL1, ...rest}) => ({
|
|
|
+ // dependencyGraphL1: setDeltaInactive(prevDepGraphL1, deltaToUndo),
|
|
|
+ // dependencyGraphL0: deltaToUndo.deltas.reduce((prevDepGraphL0, delta) => setDeltaInactive(prevDepGraphL0, delta), prevDepGraphL0),
|
|
|
+ // ...rest,
|
|
|
+ // }));
|
|
|
};
|
|
|
const redo = deltaToRedo => {
|
|
|
- this.manipulator.x = 0;
|
|
|
- this.manipulator.y = 0;
|
|
|
- this.graphDeltaExecutor.exec(deltaToRedo);
|
|
|
- this.props.setState(({dependencyGraphL0: prevDepGraphL0, dependencyGraphL1: prevDepGraphL1, ...rest}) => ({
|
|
|
- dependencyGraphL1: setDeltaActive(prevDepGraphL1, deltaToRedo),
|
|
|
- dependencyGraphL0: deltaToRedo.deltas.reduce((prevDepGraphL0, delta) => setDeltaActive(prevDepGraphL0, delta), prevDepGraphL0),
|
|
|
- ...rest,
|
|
|
- }));
|
|
|
+ // this.props.setNextNodePosition(0,0);
|
|
|
+ // this.graphDeltaExecutor.exec(deltaToRedo);
|
|
|
+ // this.props.setState(({dependencyGraphL0: prevDepGraphL0, dependencyGraphL1: prevDepGraphL1, ...rest}) => ({
|
|
|
+ // dependencyGraphL1: setDeltaActive(prevDepGraphL1, deltaToRedo),
|
|
|
+ // dependencyGraphL0: deltaToRedo.deltas.reduce((prevDepGraphL0, delta) => setDeltaActive(prevDepGraphL0, delta), prevDepGraphL0),
|
|
|
+ // ...rest,
|
|
|
+ // }));
|
|
|
};
|
|
|
|
|
|
const onUndoClicked = (parentVersion, deltaToUndo) => {
|
|
|
- undo(deltaToUndo);
|
|
|
- this.props.setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
|
|
|
- version: parentVersion,
|
|
|
- historyGraph: setCurrentVersion(prevHistoryGraph, prevVersion, parentVersion),
|
|
|
- ...rest,
|
|
|
- }));
|
|
|
+ // undo(deltaToUndo);
|
|
|
+ // this.props.setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
|
|
|
+ // version: parentVersion,
|
|
|
+ // historyGraph: setCurrentVersion(prevHistoryGraph, prevVersion, parentVersion),
|
|
|
+ // ...rest,
|
|
|
+ // }));
|
|
|
};
|
|
|
const onRedoClicked = (childVersion, deltaToRedo) => {
|
|
|
- redo(deltaToRedo);
|
|
|
- this.props.setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
|
|
|
- version: childVersion,
|
|
|
- historyGraph: setCurrentVersion(prevHistoryGraph, prevVersion, childVersion),
|
|
|
- ...rest,
|
|
|
- }));
|
|
|
+ // redo(deltaToRedo);
|
|
|
+ // this.props.setState(({historyGraph: prevHistoryGraph, version: prevVersion, ...rest}) => ({
|
|
|
+ // version: childVersion,
|
|
|
+ // historyGraph: setCurrentVersion(prevHistoryGraph, prevVersion, childVersion),
|
|
|
+ // ...rest,
|
|
|
+ // }));
|
|
|
};
|
|
|
|
|
|
|
|
|
const onMergeClicked = () => {
|
|
|
- const text = this.textarearef.current?.value;
|
|
|
- if (text) {
|
|
|
- const lines = text.split('\n');
|
|
|
-
|
|
|
- const versionIds: Buffer[] = lines.map(s => {
|
|
|
- try {
|
|
|
- return Buffer.from(s, 'base64');
|
|
|
- } catch (e) {
|
|
|
- return Buffer.alloc(0);
|
|
|
- }
|
|
|
- }).filter(buf => buf.length !== 0);
|
|
|
-
|
|
|
- let versionsToMerge;
|
|
|
- try {
|
|
|
- versionsToMerge = versionIds.map((buf: Buffer) => {
|
|
|
- return this.versionRegistry.lookup(buf);
|
|
|
- });
|
|
|
- } catch (e) {
|
|
|
- alert("Input error:" + e.toString());
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const mergedVersions = this.versionRegistry.merge(versionsToMerge);
|
|
|
-
|
|
|
- console.log("mergedVersions:", mergedVersions);
|
|
|
-
|
|
|
- const add = v => {
|
|
|
- this.props.setState(({historyGraph: prevHistoryGraph, ...rest}) => {
|
|
|
- return {
|
|
|
- historyGraph: appendToHistoryGraph(prevHistoryGraph, v),
|
|
|
- ...rest,
|
|
|
- };
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- // add all mergedVersions (and their parents) to history graph:
|
|
|
- // this may be overkill (and not so scalable), but it does the job :)
|
|
|
- mergedVersions.forEach(v => {
|
|
|
- const addParents = v => {
|
|
|
- v.parents.forEach(([v]) => {
|
|
|
- addParents(v);
|
|
|
- });
|
|
|
- add(v);
|
|
|
- }
|
|
|
- addParents(v);
|
|
|
- });
|
|
|
- }
|
|
|
+ // const text = this.textarearef.current?.value;
|
|
|
+ // if (text) {
|
|
|
+ // const lines = text.split('\n');
|
|
|
+
|
|
|
+ // const versionIds: Buffer[] = lines.map(s => {
|
|
|
+ // try {
|
|
|
+ // return Buffer.from(s, 'base64');
|
|
|
+ // } catch (e) {
|
|
|
+ // return Buffer.alloc(0);
|
|
|
+ // }
|
|
|
+ // }).filter(buf => buf.length !== 0);
|
|
|
+
|
|
|
+ // let versionsToMerge;
|
|
|
+ // try {
|
|
|
+ // versionsToMerge = versionIds.map((buf: Buffer) => {
|
|
|
+ // return this.props.versionRegistry.lookup(buf);
|
|
|
+ // });
|
|
|
+ // } catch (e) {
|
|
|
+ // alert("Input error:" + e.toString());
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // const mergedVersions = this.props.versionRegistry.merge(versionsToMerge);
|
|
|
+
|
|
|
+ // console.log("mergedVersions:", mergedVersions);
|
|
|
+
|
|
|
+ // const add = v => {
|
|
|
+ // this.props.setState(({historyGraph: prevHistoryGraph, ...rest}) => {
|
|
|
+ // return {
|
|
|
+ // historyGraph: appendToHistoryGraph(prevHistoryGraph, v),
|
|
|
+ // ...rest,
|
|
|
+ // };
|
|
|
+ // });
|
|
|
+ // };
|
|
|
+
|
|
|
+ // // add all mergedVersions (and their parents) to history graph:
|
|
|
+ // // this may be overkill (and not so scalable), but it does the job :)
|
|
|
+ // mergedVersions.forEach(v => {
|
|
|
+ // const addParents = v => {
|
|
|
+ // v.parents.forEach(([v]) => {
|
|
|
+ // addParents(v);
|
|
|
+ // });
|
|
|
+ // add(v);
|
|
|
+ // }
|
|
|
+ // addParents(v);
|
|
|
+ // });
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
function makeInfoHoverCardIcon(contents) {
|
|
@@ -247,46 +225,22 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- const onUserEdit = (deltas: PrimitiveDelta[], description: string) => {
|
|
|
- const composite = this.compositeLevel.createCompositeWithCustomDescription(deltas, description);
|
|
|
- const newVersion = this.versionRegistry.createVersion(this.props.state.version, composite);
|
|
|
-
|
|
|
- this.props.setState(({historyGraph: prevHistoryGraph, version: prevVersion, dependencyGraphL0: prevDepGraphL0, dependencyGraphL1: prevDepGraphL1, ...rest}) => {
|
|
|
- return {
|
|
|
- version: newVersion,
|
|
|
-
|
|
|
- // add new version to history graph + highlight the new version as the current version:
|
|
|
- historyGraph: setCurrentVersion(appendToHistoryGraph(prevHistoryGraph, newVersion), prevVersion, newVersion),
|
|
|
-
|
|
|
- // add the composite delta to the L1-graph + highlight it as 'active':
|
|
|
- dependencyGraphL1: addDeltaAndActivate(prevDepGraphL1, composite),
|
|
|
-
|
|
|
- // add the primitive L0-deltas to the L0-graph + highlight them as 'active':
|
|
|
- dependencyGraphL0: composite.deltas.reduce((prevDepGraphL0, delta) => addDeltaAndActivate(prevDepGraphL0, delta), prevDepGraphL0),
|
|
|
-
|
|
|
- ...rest,
|
|
|
- };
|
|
|
- });
|
|
|
-
|
|
|
- this.graphDeltaExecutor.exec(composite);
|
|
|
- };
|
|
|
-
|
|
|
const makeConcreteSyntaxTabs = defaultTab => (
|
|
|
<Tabs defaultValue={defaultTab}>
|
|
|
{this.props.readonly?(
|
|
|
<Tabs.List>
|
|
|
- <Tabs.Tab value="state">Graph State</Tabs.Tab>
|
|
|
- <Tabs.Tab value="history">History Graph</Tabs.Tab>
|
|
|
- <Tabs.Tab value="dependencyL1">Delta Graph (L1)</Tabs.Tab>
|
|
|
- <Tabs.Tab value="dependencyL0">Delta Graph (L0)</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="state">State</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="history">History</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="dependencyL1">Deltas (L1)</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="dependencyL0">Deltas (L0)</Tabs.Tab>
|
|
|
</Tabs.List>
|
|
|
):(
|
|
|
<Tabs.List>
|
|
|
<Tabs.Tab value="editor">Editor</Tabs.Tab>
|
|
|
- <Tabs.Tab value="state">Graph State</Tabs.Tab>
|
|
|
- <Tabs.Tab value="history">History Graph</Tabs.Tab>
|
|
|
- <Tabs.Tab value="dependencyL1">Delta Graph (L1)</Tabs.Tab>
|
|
|
- <Tabs.Tab value="dependencyL0">Delta Graph (L0)</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="state">State</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="history">History</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="dependencyL1">Deltas (L1)</Tabs.Tab>
|
|
|
+ <Tabs.Tab value="dependencyL0">Deltas (L0)</Tabs.Tab>
|
|
|
</Tabs.List>
|
|
|
)}
|
|
|
|
|
@@ -302,11 +256,11 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
):(
|
|
|
<EditableGraph
|
|
|
graph={this.props.state.graph}
|
|
|
- graphDeltaExecutor={this.graphDeltaExecutor}
|
|
|
+ graphDeltaExecutor={this.props.state.graphDeltaExecutor}
|
|
|
forces={historyGraphForces}
|
|
|
generateUUID={this.props.generateUUID}
|
|
|
- setNextNodePosition={(x,y)=>{this.manipulator.x = x; this.manipulator.y = y;}}
|
|
|
- onUserEdit={onUserEdit} />
|
|
|
+ setNextNodePosition={this.props.setNextNodePosition}
|
|
|
+ onUserEdit={this.props.onUserEdit} />
|
|
|
)}
|
|
|
</Tabs.Panel>
|
|
|
|
|
@@ -317,8 +271,8 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
<RountangleEditor
|
|
|
graph={this.props.state.graph}
|
|
|
generateUUID={this.props.generateUUID}
|
|
|
- onUserEdit={onUserEdit}
|
|
|
- graphDeltaExecutor={this.graphDeltaExecutor} />
|
|
|
+ onUserEdit={this.props.onUserEdit}
|
|
|
+ graphDeltaExecutor={this.props.state.graphDeltaExecutor} />
|
|
|
</Tabs.Panel>
|
|
|
|
|
|
<Tabs.Panel value="dependencyL1">
|
|
@@ -349,16 +303,18 @@ class VersionedModel extends React.Component<VersionedModelProps, {}> {
|
|
|
<>
|
|
|
<Title order={4}>{this.props.title}</Title>
|
|
|
<Stack>
|
|
|
- {makeConcreteSyntaxTabs(this.props.readonly?"state":"editor")}
|
|
|
- {makeConcreteSyntaxTabs("history")}
|
|
|
+ {/*{makeConcreteSyntaxTabs(this.props.readonly?"state":"editor")}*/}
|
|
|
+ {/*{makeConcreteSyntaxTabs("history")}*/}
|
|
|
+ {makeConcreteSyntaxTabs("state")}
|
|
|
+ {makeConcreteSyntaxTabs("dependencyL0")}
|
|
|
</Stack>
|
|
|
|
|
|
- <Textarea size="xs" label="Versions to merge:" ref={this.textarearef}
|
|
|
+{/* <Textarea size="xs" label="Versions to merge:" ref={this.textarearef}
|
|
|
autosize placeholder="Right-click on version in History Graph to add it to this textbox"></Textarea>
|
|
|
<Button onClick={() => {if (this.textarearef.current) this.textarearef.current.value = "";}}>CLEAR</Button>
|
|
|
|
|
|
<Button onClick={onMergeClicked}>MERGE</Button>
|
|
|
- </>
|
|
|
+*/} </>
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -369,49 +325,133 @@ interface AppState {
|
|
|
as: VersionedModelState;
|
|
|
}
|
|
|
|
|
|
-export function makeApp() {
|
|
|
- const generateUUID = mockUuid();
|
|
|
+// const initialModel: VersionedModelState =
|
|
|
+
|
|
|
+
|
|
|
+export class App extends React.Component<{}, AppState> {
|
|
|
+ generateUUID = mockUuid();
|
|
|
+ // csLvl = new CompositeLevel();
|
|
|
+ // corrLvl = new CompositeLevel();
|
|
|
+ // asLvl = new CompositeLevel();
|
|
|
+ // versionRegistry = new VersionRegistry();
|
|
|
+ parser: TrivialParser;
|
|
|
+
|
|
|
+ setCsState(callback) {
|
|
|
+ return this.setState(({cs, ...rest}) => ({cs: callback(cs), ...rest}));
|
|
|
+ }
|
|
|
+ setCorrState(callback) {
|
|
|
+ return this.setState(({corr, ...rest}) => ({corr: callback(corr), ...rest}));
|
|
|
+ }
|
|
|
+ setAsState(callback) {
|
|
|
+ return this.setState(({as, ...rest}) => ({as: callback(as), ...rest}));
|
|
|
+ }
|
|
|
+
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+
|
|
|
+ const makeModelState = (setState) => {
|
|
|
+ // 'Glue' callback
|
|
|
+ const setGraph = (callback: (GraphType) => GraphType) => {
|
|
|
+ setState(({graph, ...rest}) => ({
|
|
|
+ graph: callback(graph),
|
|
|
+ ...rest,
|
|
|
+ }));
|
|
|
+ };
|
|
|
+ const manipulator = new D3StateManipulator(setGraph);
|
|
|
+ return {
|
|
|
+ version: initialVersion,
|
|
|
+ graph: emptyGraph,
|
|
|
+ historyGraph: initialHistoryGraph,
|
|
|
+ dependencyGraphL1: emptyGraph,
|
|
|
+ dependencyGraphL0: emptyGraph,
|
|
|
+ compositeLevel: new CompositeLevel(),
|
|
|
+ versionRegistry: new VersionRegistry(),
|
|
|
+ manipulator,
|
|
|
+ graphDeltaExecutor: new GraphDeltaExecutor(manipulator),
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ this.state = {
|
|
|
+ cs: makeModelState(this.setCsState.bind(this)),
|
|
|
+ corr: makeModelState(this.setCorrState.bind(this)),
|
|
|
+ as: makeModelState(this.setAsState.bind(this)),
|
|
|
+ };
|
|
|
+
|
|
|
+ this.parser = new TrivialParser(this.generateUUID, this.state.corr.versionRegistry,
|
|
|
+ {
|
|
|
+ csLvl: this.state.cs.compositeLevel,
|
|
|
+ asLvl: this.state.as.compositeLevel,
|
|
|
+ corrLvl: this.state.corr.compositeLevel,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ render() {
|
|
|
+ // const execChanges = ({version, historyGraph, dependencyGraphL0, dependencyGraphL1, ...rest}: VersionedModelState, newVersion: Version, composite: CompositeDelta) => {
|
|
|
+ const execChanges = ({version, historyGraph, dependencyGraphL1, dependencyGraphL0, ...rest}: VersionedModelState, newVersion: Version, composite: CompositeDelta) => {
|
|
|
+ return {
|
|
|
+ version: newVersion,
|
|
|
|
|
|
- // functional component:
|
|
|
- return function App() {
|
|
|
- const [cs, setCs] = React.useState<VersionedModelState>(initialModel);
|
|
|
- const [corr, setCorr] = React.useState<VersionedModelState>(initialModel);
|
|
|
- const [as, setAs] = React.useState<VersionedModelState>(initialModel);
|
|
|
+ // // add new version to history graph + highlight the new version as the current version:
|
|
|
+ historyGraph: setCurrentVersion(appendToHistoryGraph(historyGraph, newVersion), version, newVersion),
|
|
|
|
|
|
- const [corrVersion, setCorrVersion] = React.useState<Version>(initialVersion);
|
|
|
+ // // add the composite delta to the L1-graph + highlight it as 'active':
|
|
|
+ dependencyGraphL1: addDeltaAndActivate(dependencyGraphL1, composite),
|
|
|
|
|
|
- const handleNewCsVersion = (cs: Version) => {
|
|
|
-
|
|
|
+ // // add the primitive L0-deltas to the L0-graph + highlight them as 'active':
|
|
|
+ dependencyGraphL0: composite.deltas.reduce(
|
|
|
+ (graph, delta) => {
|
|
|
+ return addDeltaAndActivate(graph, delta);
|
|
|
+ }, dependencyGraphL0),
|
|
|
+
|
|
|
+ ...rest,
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
- // const undoButtons = corrVersion.parents.map(([parentVersion,deltaToUndo]) => {
|
|
|
- // return (
|
|
|
- // <div key={fullVersionId(parentVersion)}>
|
|
|
- // <Button fullWidth={true} compact={true} leftIcon={<IconPlayerTrackPrev size={18}/>} onClick={onUndoClicked.bind(null, parentVersion,deltaToUndo)}>
|
|
|
- // UNDO {deltaToUndo.getDescription()}
|
|
|
- // </Button>
|
|
|
- // <Space h="xs"/>
|
|
|
- // </div>
|
|
|
- // );
|
|
|
- // });
|
|
|
- // const redoButtons = corrVersion.children.map(([childVersion,deltaToRedo]) => {
|
|
|
- // return (
|
|
|
- // <div key={fullVersionId(childVersion)}>
|
|
|
- // <Button style={{width: "100%"}} compact={true} rightIcon={<IconPlayerTrackNext size={18}/>} onClick={onRedoClicked.bind(null, childVersion,deltaToRedo)}>
|
|
|
- // REDO {deltaToRedo.getDescription()}
|
|
|
- // </Button>
|
|
|
- // <Space h="xs"/>
|
|
|
- // </div>
|
|
|
- // );
|
|
|
- // });
|
|
|
+ const onCsEdit = (deltas: PrimitiveDelta[], description: string) => {
|
|
|
+ const csComposite = this.state.cs.compositeLevel.createComposite(deltas, description);
|
|
|
+ const newCsVersion = this.state.cs.versionRegistry.createVersion(this.state.cs.version, csComposite);
|
|
|
+
|
|
|
+ const newCorrVersion = this.parser.parse(newCsVersion, this.state.corr.version);
|
|
|
+ const corrComposite = newCorrVersion.parents.find(([parentVersion, d]) => parentVersion === this.state.corr.version)?.[1] as CompositeDelta;
|
|
|
+ const newAsVersion = newCorrVersion.getEmbedded("as")?.embedded as Version;
|
|
|
+ const asComposite = newAsVersion!.parents.find(([parentVersion, d]) => parentVersion === this.state.as.version)?.[1] as CompositeDelta;
|
|
|
+
|
|
|
+ this.state.cs.graphDeltaExecutor.exec(csComposite);
|
|
|
+ this.state.corr.graphDeltaExecutor.exec(corrComposite);
|
|
|
+ this.state.as.graphDeltaExecutor.exec(asComposite);
|
|
|
+
|
|
|
+ // Update state:
|
|
|
+ this.setState(({cs, corr, as}) => {
|
|
|
+ const result = {
|
|
|
+ cs: execChanges(cs, newCsVersion, csComposite),
|
|
|
+ corr: execChanges(corr, newCorrVersion, corrComposite),
|
|
|
+ as: execChanges(as, newAsVersion, asComposite),
|
|
|
+ };
|
|
|
+ return result;
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
return (<>
|
|
|
<Grid grow>
|
|
|
<Grid.Col span={1}>
|
|
|
- <VersionedModel title="Concrete Syntax" generateUUID={generateUUID} state={cs} setState={setCs} />
|
|
|
+ <VersionedModel title="Concrete Syntax"
|
|
|
+ generateUUID={this.generateUUID}
|
|
|
+ // compositeLevel={this.state.cs.compositeLevel}
|
|
|
+ // versionRegistry={this.state.cs.versionRegistry}
|
|
|
+ state={this.state.cs}
|
|
|
+ setState={this.setCsState.bind(this)}
|
|
|
+ setNextNodePosition={(x,y)=>{this.state.cs.manipulator.x = x; this.state.cs.manipulator.y = y;}}
|
|
|
+ // onNewVersion={handleNewCsVersion}
|
|
|
+ onUserEdit={onCsEdit} />
|
|
|
</Grid.Col>
|
|
|
<Grid.Col span={1}>
|
|
|
- <VersionedModel title="Correspondence" generateUUID={generateUUID} state={corr} setState={setCorr} readonly />
|
|
|
+ <VersionedModel title="Correspondence" readonly
|
|
|
+ generateUUID={this.generateUUID}
|
|
|
+ // compositeLevel={this.state.corr.compositeLevel}
|
|
|
+ // versionRegistry={this.state.corr.versionRegistry}
|
|
|
+ setNextNodePosition={(x,y)=>{this.state.corr.manipulator.x = x; this.state.corr.manipulator.y = y;}}
|
|
|
+ state={this.state.corr}
|
|
|
+ setState={this.setCorrState.bind(this)} />
|
|
|
|
|
|
{/* <SimpleGrid cols={2}>
|
|
|
<div>
|
|
@@ -424,10 +464,65 @@ export function makeApp() {
|
|
|
*/}
|
|
|
</Grid.Col>
|
|
|
<Grid.Col span={1}>
|
|
|
- <VersionedModel title="Abstract Syntax" generateUUID={generateUUID} state={as} setState={setAs} />
|
|
|
+ <VersionedModel title="Abstract Syntax"
|
|
|
+ generateUUID={this.generateUUID}
|
|
|
+ // compositeLevel={this.state.as.compositeLevel}
|
|
|
+ // versionRegistry={this.state.as.versionRegistry}
|
|
|
+ setNextNodePosition={(x,y)=>{this.state.as.manipulator.x = x; this.state.as.manipulator.y = y;}}
|
|
|
+ state={this.state.as}
|
|
|
+ setState={this.setAsState.bind(this)}
|
|
|
+ />
|
|
|
</Grid.Col>
|
|
|
</Grid>
|
|
|
</>);
|
|
|
- };
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+// export function makeApp() {
|
|
|
+// const generateUUID = mockUuid();
|
|
|
+
|
|
|
+// function createModelState() {
|
|
|
+// const [state, setState] = React.useState
|
|
|
+// return {
|
|
|
+
|
|
|
+// lvl: new CompositeLevel(),
|
|
|
+// registry: new VersionRegistry(),
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// // functional component:
|
|
|
+// return function App() {
|
|
|
+// const [cs, setCs] = React.useState<VersionedModelState>(initialModel);
|
|
|
+// const [corr, setCorr] = React.useState<VersionedModelState>(initialModel);
|
|
|
+// const [as, setAs] = React.useState<VersionedModelState>(initialModel);
|
|
|
+
|
|
|
+// const [corrVersion, setCorrVersion] = React.useState<Version>(initialVersion);
|
|
|
+
|
|
|
+
|
|
|
+// // const undoButtons = corrVersion.parents.map(([parentVersion,deltaToUndo]) => {
|
|
|
+// // return (
|
|
|
+// // <div key={fullVersionId(parentVersion)}>
|
|
|
+// // <Button fullWidth={true} compact={true} leftIcon={<IconPlayerTrackPrev size={18}/>} onClick={onUndoClicked.bind(null, parentVersion,deltaToUndo)}>
|
|
|
+// // UNDO {deltaToUndo.getDescription()}
|
|
|
+// // </Button>
|
|
|
+// // <Space h="xs"/>
|
|
|
+// // </div>
|
|
|
+// // );
|
|
|
+// // });
|
|
|
+// // const redoButtons = corrVersion.children.map(([childVersion,deltaToRedo]) => {
|
|
|
+// // return (
|
|
|
+// // <div key={fullVersionId(childVersion)}>
|
|
|
+// // <Button style={{width: "100%"}} compact={true} rightIcon={<IconPlayerTrackNext size={18}/>} onClick={onRedoClicked.bind(null, childVersion,deltaToRedo)}>
|
|
|
+// // REDO {deltaToRedo.getDescription()}
|
|
|
+// // </Button>
|
|
|
+// // <Space h="xs"/>
|
|
|
+// // </div>
|
|
|
+// // );
|
|
|
+// // });
|
|
|
+
|
|
|
+// };
|
|
|
+// }
|
|
|
+
|