Browse Source

Blended modeling demo also has automated + manual parsing and rendering

Joeri Exelmans 2 years ago
parent
commit
68531e6d8e
4 changed files with 426 additions and 553 deletions
  1. 284 500
      pnpm-lock.yaml
  2. 49 13
      src/frontend/correspondence.tsx
  3. 85 26
      src/frontend/demo_bm.tsx
  4. 8 14
      src/frontend/demo_corr.tsx

File diff suppressed because it is too large
+ 284 - 500
pnpm-lock.yaml


+ 49 - 13
src/frontend/correspondence.tsx

@@ -1,5 +1,6 @@
 import * as React from "react";
 import * as Mantine from "@mantine/core";
+import * as Icons from "@tabler/icons";
 
 import {newVersionedModel, VersionedModelState} from "./versioned_model";
 import {TrivialParser} from "../parser/trivial_parser";
@@ -145,35 +146,70 @@ export function newCorrespondence({generateUUID, primitiveRegistry, cs, as}) {
       gotoVersionOrig(corrVersion);
       asReducer.gotoVersion(asVersion);
     };
-    const getParseRenderButtons = (csState: VersionedModelState, asState: VersionedModelState) => {
-      const parseButton =
-        <Mantine.Button compact
-          disabled={parseMap.has(csState.version)}
-          onClick={() => parseExistingVersion(csState.version)}
+    const getParseButton = (csVersion, dir: "left"|"right" = "right") => {
+      return <Mantine.Button compact
+          disabled={parseMap.has(csVersion)}
+          onClick={() => parseExistingVersion(csVersion)}
+          rightIcon={dir === "right" ? <Icons.IconChevronsRight/>: null}
+          leftIcon={dir === "left" ? <Icons.IconChevronsLeft/>: null}
         >Parse</Mantine.Button>;
-      const renderButton =
-        <Mantine.Button compact
-          disabled={renderMap.has(asState.version)}
-          onClick={() => renderExistingVersion(asState.version)}
+    };
+    const getRenderButton = (asVersion, dir: "left"|"right" = "left") => {
+      return <Mantine.Button compact
+          disabled={renderMap.has(asVersion)}
+          onClick={() => renderExistingVersion(asVersion)}
+          rightIcon={dir === "right" ? <Icons.IconChevronsRight/>: null}
+          leftIcon={dir === "left" ? <Icons.IconChevronsLeft/>: null}
         >Render</Mantine.Button>;
-      return {parseButton, renderButton};
+    };
+    const getCaptionWithParseButton = (autoParseState, setAutoParseState, csVersion, dir: "left"|"right" = "right") => {
+      const sw = <Mantine.Switch label="Auto"
+        labelPosition={dir}
+        checked={autoParseState}
+        onChange={(event) => setAutoParseState(event.currentTarget.checked)}
+      />;
+      const button = getParseButton(csVersion, dir);
+      if (dir === "left") {
+        return <Mantine.Group>{button}{sw}</Mantine.Group>;
+      }
+      else {
+        return <Mantine.Group>{sw}{button}</Mantine.Group>;
+      }
+    };
+    const getCaptionWithRenderButton = (autoRenderState, setAutoRenderState, asVersion, dir: "left"|"right" = "left") => {
+      const sw = <Mantine.Switch label="Auto"
+        labelPosition={dir}
+        checked={autoRenderState}
+        onChange={(event) => setAutoRenderState(event.currentTarget.checked)}
+      />
+      const button = getRenderButton(asVersion, dir);
+      if (dir === "left") {
+        return <Mantine.Group>{button}{sw}</Mantine.Group>;
+      }
+      else {
+        return <Mantine.Group>{sw}{button}</Mantine.Group>;
+      }
     };
 
     return {
       parse,
       render,
+      parseExistingVersion,
+      renderExistingVersion,
       gotoVersion,
       undo,
       redo,
-      getParseRenderButtons,
+      getParseButton,
+      getRenderButton,
+      getCaptionWithParseButton,
+      getCaptionWithRenderButton,
     };
   }
 
-
   return {
     initialState,
     getCurrentVersion,
     getReducer,
     getReactComponents,
   };
-}
+}

+ 85 - 26
src/frontend/demo_bm.tsx

@@ -1,5 +1,5 @@
 import * as React from "react";
-import {SimpleGrid, Text, Title, Group, Stack, Button, Space, Textarea, Tabs, HoverCard, ActionIcon, Center} from "@mantine/core";
+import {SimpleGrid, Text, Title, Group, Stack, Button, Space, Textarea, Tabs, HoverCard, ActionIcon, Center, Switch, Grid} from "@mantine/core";
 
 import {PrimitiveRegistry} from "../onion/primitive_delta";
 import {mockUuid} from "../onion/test_helpers";
@@ -27,6 +27,11 @@ export function getDemoBM() {
     const [corr1State, setCorr1State] = React.useState<VersionedModelState>(corr1.initialState);
     const [corr2State, setCorr2State] = React.useState<VersionedModelState>(corr2.initialState);
 
+    const [autoParse1, setAutoParse1] = React.useState<boolean>(true);
+    const [autoParse2, setAutoParse2] = React.useState<boolean>(true);
+    const [autoRender1, setAutoRender1] = React.useState<boolean>(false);
+    const [autoRender2, setAutoRender2] = React.useState<boolean>(false);
+
     const asReducer = as.getReducer(setAsState);
     const cs1Reducer = cs1.getReducer(setCs1State);
     const cs2Reducer = cs2.getReducer(setCs2State);
@@ -35,8 +40,13 @@ export function getDemoBM() {
 
     const asComponents = as.getReactComponents(asState, {
       onUserEdit: (deltas, description) => {
-        corr1Reducer.render(deltas, description);
-        corr2Reducer.render(deltas, description);
+        const newVersion = asReducer.createAndGotoNewVersion(deltas, description);
+        if (autoRender1) {
+          corr1Reducer.renderExistingVersion(newVersion);
+        }
+        if (autoRender2) {
+          corr2Reducer.renderExistingVersion(newVersion);
+        }
       },
       onUndoClicked: asReducer.undo,
       onRedoClicked: asReducer.redo,
@@ -44,13 +54,23 @@ export function getDemoBM() {
     });
 
     const cs1Components = cs1.getReactComponents(cs1State, {
-      onUserEdit: corr1Reducer.parse,
+      onUserEdit: (deltas, description) => {
+        const newVersion = cs1Reducer.createAndGotoNewVersion(deltas, description);
+        if (autoParse1) {
+          corr1Reducer.parseExistingVersion(newVersion);
+        }
+      },
       onUndoClicked: cs1Reducer.undo,
       onRedoClicked: cs1Reducer.redo,
       onVersionClicked: cs1Reducer.gotoVersion,
     });
     const cs2Components = cs2.getReactComponents(cs2State, {
-      onUserEdit: corr2Reducer.parse,
+      onUserEdit: (deltas, description) => {
+        const newVersion = cs2Reducer.createAndGotoNewVersion(deltas, description);
+        if (autoParse2) {
+          corr2Reducer.parseExistingVersion(newVersion);
+        }
+      },
       onUndoClicked: cs2Reducer.undo,
       onRedoClicked: cs2Reducer.redo,
       onVersionClicked: cs2Reducer.gotoVersion,
@@ -71,46 +91,85 @@ export function getDemoBM() {
     const corrTabs = ["state", "history", "dependencyL1", "dependencyL0"];
     const asTabs = ["state", "history", "dependencyL1", "dependencyL0"];
 
-    return (<>
-      <SimpleGrid cols={5}>
-        <div>
-          <Title order={4}>Concrete Syntax 1</Title>
+    function centeredCaption(text) {
+      return <Center><Title order={4}>{text}</Title></Center>;
+    }
+
+    return (<div style={{minWidth:2200}}>
+      <Grid columns={5} grow>
+        <Grid.Col span={1}>
+          {centeredCaption("Concrete Syntax 1")}
+        </Grid.Col>
+        <Grid.Col span={1}>
+          {centeredCaption("Correspondence 1")}
+        </Grid.Col>
+        <Grid.Col span={1}>
+          {centeredCaption("Abstract Syntax")}
+        </Grid.Col>
+        <Grid.Col span={1}>
+          {centeredCaption("Correspondence 2")}
+        </Grid.Col>
+        <Grid.Col span={1}>
+          {centeredCaption("Concrete Syntax 2")}
+        </Grid.Col>
+
+        <Grid.Col span={1}>
+          <Group position="right">
+            {corr1Reducer.getCaptionWithParseButton(autoParse1, setAutoParse1, cs1.getCurrentVersion())}
+          </Group>
+        </Grid.Col>
+        <Grid.Col span={1}>
+        </Grid.Col>
+        <Grid.Col span={1}>
+          <Group position="apart">
+            {corr1Reducer.getCaptionWithRenderButton(autoRender1, setAutoRender1, as.getCurrentVersion())}
+            {corr2Reducer.getCaptionWithRenderButton(autoRender2, setAutoRender2, as.getCurrentVersion(), "right")}
+          </Group>
+        </Grid.Col>
+        <Grid.Col span={1}>
+        </Grid.Col>
+        <Grid.Col span={1}>
+          <Group position="left">
+            {corr2Reducer.getCaptionWithParseButton(autoParse2, setAutoParse2, cs2.getCurrentVersion(), "left")}
+          </Group>
+        </Grid.Col>
+
+        <Grid.Col span={1}>
           <Stack>
             {cs1Components.makeTabs("editor", csTabs)}
             {cs1Components.makeTabs("history", csTabs)}
+            <Center>{cs1Components.undoRedoButtons}</Center>
           </Stack>
-        </div>
-        <div>
-          <Title order={4}>Correspondence 1</Title>
+        </Grid.Col>
+        <Grid.Col span={1}>
           <Stack>
             {corr1Components.makeTabs("state", corrTabs)}
             {corr1Components.makeTabs("history", corrTabs)}
+            <Center>{corr1Components.undoRedoButtons}</Center>
           </Stack>
-          <Center>{corr1Components.undoRedoButtons}</Center>
-        </div>
-        <div>
-          <Title order={4}>Abstract Syntax</Title>
+        </Grid.Col>
+        <Grid.Col span={1}>
           <Stack>
             {asComponents.makeTabs("state", asTabs)}
             {asComponents.makeTabs("history", asTabs)}
+            <Center>{asComponents.undoRedoButtons}</Center>
           </Stack>
-        </div>
-        <div>
-          <Title order={4}>Correspondence 2</Title>
+        </Grid.Col>
+        <Grid.Col span={1}>
           <Stack>
             {corr2Components.makeTabs("state", corrTabs)}
             {corr2Components.makeTabs("history", corrTabs)}
+            <Center>{corr2Components.undoRedoButtons}</Center>
           </Stack>
-          <Center>{corr2Components.undoRedoButtons}</Center>
-        </div>
-        <div>
-          <Title order={4}>Concrete Syntax 2</Title>
+        </Grid.Col>
+        <Grid.Col span={1}>
           <Stack>
             {cs2Components.makeTabs("editor", csTabs)}
             {cs2Components.makeTabs("history", csTabs)}
+            <Center>{cs2Components.undoRedoButtons}</Center>
           </Stack>
-        </div>
-      </SimpleGrid>
-    </>);
+        </Grid.Col>
+      </Grid>
+    </div>);
   }
 }

+ 8 - 14
src/frontend/demo_corr.tsx

@@ -66,20 +66,15 @@ export function getDemoCorr() {
     const corrTabs = ["state", "history", "dependencyL1", "dependencyL0"];
     const asTabs = ["state", "history", "dependencyL1", "dependencyL0"];
 
-    const {parseButton, renderButton} = corrReducer.getParseRenderButtons(csState, asState);
-
     const undoButtonHelpText = "Use the Undo/Redo buttons or the History panel to navigate to any version.";
 
-    return (<>
-          <Group position="right">
-          </Group>
+    return (<div style={{minWidth:1300}}>
       <SimpleGrid cols={3}>
         <div>
-          <Group position="center">
+          <Group position="apart">
             <Title order={4}>Concrete Syntax</Title>
-            <Switch label="Auto-parse"
-              checked={autoParse} onChange={(event) => setAutoParse(event.currentTarget.checked)}/>
-            {parseButton}
+            {corrReducer.getCaptionWithParseButton(
+              autoParse, setAutoParse, cs.getCurrentVersion())}
           </Group>
           <Space h="sm" />
           <Stack>
@@ -112,11 +107,10 @@ export function getDemoCorr() {
           </Stack>
         </div>
         <div>
-          <Group position="center">
+          <Group position="apart">
+            {corrReducer.getCaptionWithRenderButton(
+              autoRender, setAutoRender, as.getCurrentVersion())}
             <Title order={4}>Abstract Syntax</Title>
-            <Switch label="Auto-render"
-              checked={autoRender} onChange={(event) => setAutoRender(event.currentTarget.checked)}/>
-            {renderButton}
           </Group>
           <Space h="sm" />
           <Stack>
@@ -130,6 +124,6 @@ export function getDemoCorr() {
           </Stack>
         </div>
       </SimpleGrid>
-    </>);
+    </div>);
   }
 }