123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- import * as React from "react";
- import {SimpleGrid, Text, Title, Stack, Center, Image, Group, Space} from "@mantine/core";
- import {DeltaRegistry} from "onion/delta_registry";;
- import {mockUuid} from "../../util/test_helpers";
- import {OnionContext} from "../onion_context";
- import {VersionRegistry} from "onion/version";
- import {newOnion, undoButtonHelpText} from "../versioned_model/single_model";
- import {newCorrespondence, undoButtonHelpTextCorr} from "../versioned_model/correspondence";
- import {ModalManualRenderer, ManualRendererProps} from "../versioned_model/manual_renderer";
- import {InfoHoverCard} from "../info_hover_card";
- import corr_csImage from './assets/corr_cs.svg';
- import corr_asImage from './assets/corr_as.svg';
- import corr_corrImage from './assets/corr_corr.svg';
- import {Actionblock, Resultblock} from "./blocks";
- export const demo_Corr_description =
- <>
- <Title order={4}>
- Correspondence Model
- </Title>
- <Text>
- The different parts we have seen in the previous demos, are now in combined in different tabs in one column.
- The second row is just a copy of the upper one and shows exactly the same model(s). This allows the simultaneous observation of changes in the
- different models.
- </Text>
- <Text>
- The following figure shows the connection of the different models combined in the "Concrete Syntax" (CS)
- column.
- The two abstraction levels of Deltas L1 and L0 are combined as "CS Delta(s)" and the History is omitted in the
- figure.
- </Text>
- <Image src={corr_csImage}/>
- <Text>
- Analogously, the third column combines the different models shown in the first demo "Primitive Delta" into
- a single view, representing the "Abstract Syntax model" (AS).
- The difference to the Concrete Syntax in the first column is, that there is no additional "user-friendly"
- editor for editing the state. Instead, the state graph can be manipulated directly as already introduced in the first
- demo "Primitive Deltas". This way of manipulation is also illustrated in the following picture.
- </Text>
- <Image src={corr_asImage}/>
- <Text>
- Between the CS and AS the "Correspondence model" (Corr) encapsulates and connects the Deltas of the CS and
- AS models as visualized in the following picture.
- </Text>
- <Image src={corr_corrImage}/>
- <Text>
- The creation of Deltas of the Correspondence model and AS Deltas is triggered by the "Parsing" process.
- Parsing can either be automatically started after each user interaction or interactively at specific points
- in time, simulated by pressing the "Parse >>" button in the upper right corner of the first column.
- </Text>
- <Text>
- In turn, changes to the AS model are taken into account in the rendering process. Since the CS can contain
- information the AS does not contain, such as layout information, some user interaction
- may be required to add this missing information. This process is not automatically triggered by default.
- </Text>
- <Text>
- Common to all these three models (CS, Corr, AS) is the central foundation in Deltas encoding any change of
- the state graph. On this generic basis all other functionality is built on: conflict detection, versioning,
- undo/redo, etc. That is also the reason why these features can be presented in a homogeneous way for each of
- the models.
- </Text>
- <Text>
- This demo focuses on the parsing (CS → AS) and rendering (AS → CS).
- </Text>
- <Actionblock>
- 1. Create a Rountangle!
- </Actionblock>
- <Resultblock>
- Below the rountangle editor, the new State graph of the CS is shown.
- </Resultblock>
- <Resultblock>
- Automatic parsing recognizes this rountangle as a state in the AS with ID = 2 and connects both via the
- Correspondence model by introducing a "connection node" with ID = 1.
- </Resultblock>
- <Resultblock>
- As visualized in the above picture, the Correspondence model contains the complete CS and AS model plus some
- more information relevant to maintain the relations between elements contained in the AS and the CS.
- </Resultblock>
- <Actionblock>
- 2. Draw a second Rountangle and move and resize it such that the new rountangle completely surrounds the
- first one!
- </Actionblock>
- <Resultblock>
- The parser recognizes the (visual) containment relation between the two rountangles and translates this to a
- "has-parent" relation between the two (abstract) states. Again, you can find this relation also in the correspondence
- model.
- </Resultblock>
- <Actionblock>
- 3. Create a new State in the AS by a right click in the canvas!
- </Actionblock>
- <Actionblock>
- 4. Press the "<< Render"-button at the top!
- </Actionblock>
- <Resultblock>
- The rendering process detects missing information while it tries to create a CS model for the new state.
- </Resultblock>
- <Resultblock>
- A new dialog appears where one can position and resize the new rectangle.
- </Resultblock>
- <Resultblock>
- The system does not allow any position/size whose parsing would result in a different AS (e.g., additional or missing "hasParent" relation).
- </Resultblock>
- <Actionblock>
- 5. Position the new state according to the given constraints!
- </Actionblock>
- <Resultblock>
- Your CS model is updated and the rountangles are visualized accordingly.
- </Resultblock>
- {/* TODO: remove z-index!
- TODO: deleted nodes/Rountangles are still considered in the "Missing information"-dialog
- TODO: everywhere: Arrows with directions!
- */}
- </>;
- export function getDemoCorr() {
- const deltaRegistry = new DeltaRegistry();
- const generateUUID = mockUuid();
- const versionRegistry = new VersionRegistry();
- const as = newOnion({readonly: false, deltaRegistry, versionRegistry});
- const cs = newOnion({readonly: false, deltaRegistry, versionRegistry});
- const corr = newCorrespondence({deltaRegistry, generateUUID, versionRegistry});
- // returns functional react component
- return function () {
- const onionAs = as.useOnion(reducer => ({
- onUserEdit: (deltas, description) => {
- const newVersion = onionAs.reducer.createAndGotoNewVersion(deltas, description);
- if (autoRender) {
- onionCorr.reducer.renderExistingVersion(newVersion, setManualRendererState);
- }
- },
- }));
- const onionCs = cs.useOnion(reducer => ({
- onUserEdit: (deltas, description) => {
- const newVersion = reducer.createAndGotoNewVersion(deltas, description);
- if (autoParse) {
- onionCorr.reducer.parseExistingVersion(newVersion);
- }
- },
- }));
- const onionCorr = corr.useCorrespondence(onionCs, onionAs);
- const [autoParse, setAutoParse] = React.useState<boolean>(true);
- const [autoRender, setAutoRender] = React.useState<boolean>(false);
- const [manualRendererState, setManualRendererState] = React.useState<null | ManualRendererProps>(null);
- const csTabs = ["editor", "state", "merge", "deltaL1", "deltaL0"];
- const corrTabs = ["state", "merge", "deltaL1", "deltaL0"];
- const asTabs = ["state", "merge", "deltaL1", "deltaL0"];
- return (<div style={{minWidth: 1300}}>
- <OnionContext.Provider value={{generateUUID, deltaRegistry}}>
- <ModalManualRenderer manualRendererState={manualRendererState}/>
- <SimpleGrid cols={3}>
- <div>
- <Group position="apart">
- <Title order={4}>Concrete Syntax</Title>
- {onionCorr.components.getCaptionWithParseButton(
- autoParse, setAutoParse)}
- </Group>
- <Space h="sm"/>
- <Stack>
- {onionCs.components.makeTabs("editor", csTabs)}
- {onionCs.components.makeTabs("merge", csTabs)}
- <Center>
- {onionCs.components.undoRedoButtons}
- <Space w="sm"/>
- <InfoHoverCard>
- {undoButtonHelpText}
- </InfoHoverCard>
- </Center>
- </Stack>
- </div>
- <div>
- <Group position="center">
- <Title order={4}>Correspondence</Title>
- </Group>
- <Space h="sm"/>
- <Stack>
- {onionCorr.components.makeTabs("state", corrTabs)}
- {onionCorr.components.makeTabs("merge", corrTabs)}
- <Center>
- {onionCorr.components.undoRedoButtons}
- <Space w="sm"/>
- <InfoHoverCard>
- {undoButtonHelpText}
- <Space h="sm"/>
- {undoButtonHelpTextCorr}
- </InfoHoverCard>
- </Center>
- </Stack>
- </div>
- <div>
- <Group position="apart">
- {onionCorr.components.getCaptionWithRenderButton(
- autoRender, setAutoRender, setManualRendererState)}
- <Title order={4}>Abstract Syntax</Title>
- </Group>
- <Space h="sm"/>
- <Stack>
- {onionAs.components.makeTabs("state", asTabs)}
- {onionAs.components.makeTabs("merge", asTabs)}
- <Center>
- {onionAs.components.undoRedoButtons}
- <Space w="sm"/>
- <InfoHoverCard>
- {undoButtonHelpText}
- </InfoHoverCard>
- </Center>
- </Stack>
- </div>
- </SimpleGrid>
- </OnionContext.Provider>
- </div>);
- }
- }
|