demo_corr.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import * as React from "react";
  2. import {SimpleGrid, Text, Title, Stack, Center, Image, Group, Space} from "@mantine/core";
  3. import {DeltaRegistry} from "onion/delta_registry";;
  4. import {mockUuid} from "../../util/test_helpers";
  5. import {OnionContext} from "../onion_context";
  6. import {VersionRegistry} from "onion/version";
  7. import {newOnion, undoButtonHelpText} from "../versioned_model/single_model";
  8. import {newCorrespondence, undoButtonHelpTextCorr} from "../versioned_model/correspondence";
  9. import {ModalManualRenderer, ManualRendererProps} from "../versioned_model/manual_renderer";
  10. import {InfoHoverCard} from "../info_hover_card";
  11. import corr_csImage from './assets/corr_cs.svg';
  12. import corr_asImage from './assets/corr_as.svg';
  13. import corr_corrImage from './assets/corr_corr.svg';
  14. import {Actionblock, Resultblock} from "./blocks";
  15. export const demo_Corr_description =
  16. <>
  17. <Title order={4}>
  18. Correspondence Model
  19. </Title>
  20. <Text>
  21. The different parts we have seen in the previous demos, are now in combined in different tabs in one column.
  22. 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
  23. different models.
  24. </Text>
  25. <Text>
  26. The following figure shows the connection of the different models combined in the "Concrete Syntax" (CS)
  27. column.
  28. The two abstraction levels of Deltas L1 and L0 are combined as "CS Delta(s)" and the History is omitted in the
  29. figure.
  30. </Text>
  31. <Image src={corr_csImage}/>
  32. <Text>
  33. Analogously, the third column combines the different models shown in the first demo "Primitive Delta" into
  34. a single view, representing the "Abstract Syntax model" (AS).
  35. The difference to the Concrete Syntax in the first column is, that there is no additional "user-friendly"
  36. editor for editing the state. Instead, the state graph can be manipulated directly as already introduced in the first
  37. demo "Primitive Deltas". This way of manipulation is also illustrated in the following picture.
  38. </Text>
  39. <Image src={corr_asImage}/>
  40. <Text>
  41. Between the CS and AS the "Correspondence model" (Corr) encapsulates and connects the Deltas of the CS and
  42. AS models as visualized in the following picture.
  43. </Text>
  44. <Image src={corr_corrImage}/>
  45. <Text>
  46. The creation of Deltas of the Correspondence model and AS Deltas is triggered by the "Parsing" process.
  47. Parsing can either be automatically started after each user interaction or interactively at specific points
  48. in time, simulated by pressing the "Parse &gt;&gt;" button in the upper right corner of the first column.
  49. </Text>
  50. <Text>
  51. In turn, changes to the AS model are taken into account in the rendering process. Since the CS can contain
  52. information the AS does not contain, such as layout information, some user interaction
  53. may be required to add this missing information. This process is not automatically triggered by default.
  54. </Text>
  55. <Text>
  56. Common to all these three models (CS, Corr, AS) is the central foundation in Deltas encoding any change of
  57. the state graph. On this generic basis all other functionality is built on: conflict detection, versioning,
  58. undo/redo, etc. That is also the reason why these features can be presented in a homogeneous way for each of
  59. the models.
  60. </Text>
  61. <Text>
  62. This demo focuses on the parsing (CS &rarr; AS) and rendering (AS &rarr; CS).
  63. </Text>
  64. <Actionblock>
  65. 1. Create a Rountangle!
  66. </Actionblock>
  67. <Resultblock>
  68. Below the rountangle editor, the new State graph of the CS is shown.
  69. </Resultblock>
  70. <Resultblock>
  71. Automatic parsing recognizes this rountangle as a state in the AS with ID = 2 and connects both via the
  72. Correspondence model by introducing a "connection node" with ID = 1.
  73. </Resultblock>
  74. <Resultblock>
  75. As visualized in the above picture, the Correspondence model contains the complete CS and AS model plus some
  76. more information relevant to maintain the relations between elements contained in the AS and the CS.
  77. </Resultblock>
  78. <Actionblock>
  79. 2. Draw a second Rountangle and move and resize it such that the new rountangle completely surrounds the
  80. first one!
  81. </Actionblock>
  82. <Resultblock>
  83. The parser recognizes the (visual) containment relation between the two rountangles and translates this to a
  84. "has-parent" relation between the two (abstract) states. Again, you can find this relation also in the correspondence
  85. model.
  86. </Resultblock>
  87. <Actionblock>
  88. 3. Create a new State in the AS by a right click in the canvas!
  89. </Actionblock>
  90. <Actionblock>
  91. 4. Press the "&lt;&lt; Render"-button at the top!
  92. </Actionblock>
  93. <Resultblock>
  94. The rendering process detects missing information while it tries to create a CS model for the new state.
  95. </Resultblock>
  96. <Resultblock>
  97. A new dialog appears where one can position and resize the new rectangle.
  98. </Resultblock>
  99. <Resultblock>
  100. The system does not allow any position/size whose parsing would result in a different AS (e.g., additional or missing "hasParent" relation).
  101. </Resultblock>
  102. <Actionblock>
  103. 5. Position the new state according to the given constraints!
  104. </Actionblock>
  105. <Resultblock>
  106. Your CS model is updated and the rountangles are visualized accordingly.
  107. </Resultblock>
  108. {/* TODO: remove z-index!
  109. TODO: deleted nodes/Rountangles are still considered in the "Missing information"-dialog
  110. TODO: everywhere: Arrows with directions!
  111. */}
  112. </>;
  113. export function getDemoCorr() {
  114. const deltaRegistry = new DeltaRegistry();
  115. const generateUUID = mockUuid();
  116. const versionRegistry = new VersionRegistry();
  117. const as = newOnion({readonly: false, deltaRegistry, versionRegistry});
  118. const cs = newOnion({readonly: false, deltaRegistry, versionRegistry});
  119. const corr = newCorrespondence({deltaRegistry, generateUUID, versionRegistry});
  120. // returns functional react component
  121. return function () {
  122. const onionAs = as.useOnion(reducer => ({
  123. onUserEdit: (deltas, description) => {
  124. const newVersion = onionAs.reducer.createAndGotoNewVersion(deltas, description);
  125. if (autoRender) {
  126. onionCorr.reducer.renderExistingVersion(newVersion, setManualRendererState);
  127. }
  128. },
  129. }));
  130. const onionCs = cs.useOnion(reducer => ({
  131. onUserEdit: (deltas, description) => {
  132. const newVersion = reducer.createAndGotoNewVersion(deltas, description);
  133. if (autoParse) {
  134. onionCorr.reducer.parseExistingVersion(newVersion);
  135. }
  136. },
  137. }));
  138. const onionCorr = corr.useCorrespondence(onionCs, onionAs);
  139. const [autoParse, setAutoParse] = React.useState<boolean>(true);
  140. const [autoRender, setAutoRender] = React.useState<boolean>(false);
  141. const [manualRendererState, setManualRendererState] = React.useState<null | ManualRendererProps>(null);
  142. const csTabs = ["editor", "state", "merge", "deltaL1", "deltaL0"];
  143. const corrTabs = ["state", "merge", "deltaL1", "deltaL0"];
  144. const asTabs = ["state", "merge", "deltaL1", "deltaL0"];
  145. return (<div style={{minWidth: 1300}}>
  146. <OnionContext.Provider value={{generateUUID, deltaRegistry}}>
  147. <ModalManualRenderer manualRendererState={manualRendererState}/>
  148. <SimpleGrid cols={3}>
  149. <div>
  150. <Group position="apart">
  151. <Title order={4}>Concrete Syntax</Title>
  152. {onionCorr.components.getCaptionWithParseButton(
  153. autoParse, setAutoParse)}
  154. </Group>
  155. <Space h="sm"/>
  156. <Stack>
  157. {onionCs.components.makeTabs("editor", csTabs)}
  158. {onionCs.components.makeTabs("merge", csTabs)}
  159. <Center>
  160. {onionCs.components.undoRedoButtons}
  161. <Space w="sm"/>
  162. <InfoHoverCard>
  163. {undoButtonHelpText}
  164. </InfoHoverCard>
  165. </Center>
  166. </Stack>
  167. </div>
  168. <div>
  169. <Group position="center">
  170. <Title order={4}>Correspondence</Title>
  171. </Group>
  172. <Space h="sm"/>
  173. <Stack>
  174. {onionCorr.components.makeTabs("state", corrTabs)}
  175. {onionCorr.components.makeTabs("merge", corrTabs)}
  176. <Center>
  177. {onionCorr.components.undoRedoButtons}
  178. <Space w="sm"/>
  179. <InfoHoverCard>
  180. {undoButtonHelpText}
  181. <Space h="sm"/>
  182. {undoButtonHelpTextCorr}
  183. </InfoHoverCard>
  184. </Center>
  185. </Stack>
  186. </div>
  187. <div>
  188. <Group position="apart">
  189. {onionCorr.components.getCaptionWithRenderButton(
  190. autoRender, setAutoRender, setManualRendererState)}
  191. <Title order={4}>Abstract Syntax</Title>
  192. </Group>
  193. <Space h="sm"/>
  194. <Stack>
  195. {onionAs.components.makeTabs("state", asTabs)}
  196. {onionAs.components.makeTabs("merge", asTabs)}
  197. <Center>
  198. {onionAs.components.undoRedoButtons}
  199. <Space w="sm"/>
  200. <InfoHoverCard>
  201. {undoButtonHelpText}
  202. </InfoHoverCard>
  203. </Center>
  204. </Stack>
  205. </div>
  206. </SimpleGrid>
  207. </OnionContext.Provider>
  208. </div>);
  209. }
  210. }