@peter.prib/renderengine 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -2
  3. package/REFERENCE.md +2198 -0
  4. package/dist/renderengine-workspace.umd.js +46905 -0
  5. package/dist/renderengine.umd.js +42223 -0
  6. package/examples/archimate.html +66 -0
  7. package/examples/diagram-editor.html +51 -0
  8. package/package.json +65 -4
  9. package/src/BaseRenderer.js +57 -0
  10. package/src/CanvasRenderer.js +194 -0
  11. package/src/Mat4.js +111 -0
  12. package/src/OrbitCamera.js +57 -0
  13. package/src/RendererFactory.js +50 -0
  14. package/src/SVGRenderer.js +439 -0
  15. package/src/archimate.js +723 -0
  16. package/src/archimateArchiFormat.js +1693 -0
  17. package/src/archimateArchiTypes.js +72 -0
  18. package/src/archimateArchive.js +140 -0
  19. package/src/archimateCSV.js +127 -0
  20. package/src/archimateDrawio.js +182 -0
  21. package/src/archimateExchangeFormat.js +546 -0
  22. package/src/archimateRelationshipTable.js +93 -0
  23. package/src/archimateSpecializations.js +161 -0
  24. package/src/chartCatalog.js +589 -0
  25. package/src/charting/ArchimateDiagramEditor.js +1624 -0
  26. package/src/charting/ArchimateSpecializationSelector.js +134 -0
  27. package/src/charting/Axis.js +68 -0
  28. package/src/charting/CameraSeeder.js +30 -0
  29. package/src/charting/CatalogDialog.js +92 -0
  30. package/src/charting/Chart.js +37 -0
  31. package/src/charting/Chart3D.js +99 -0
  32. package/src/charting/ChartBox.js +80 -0
  33. package/src/charting/ChartData.js +27 -0
  34. package/src/charting/ChartRegistry.js +76 -0
  35. package/src/charting/CheckboxTreeSelector.js +304 -0
  36. package/src/charting/ColorField.js +107 -0
  37. package/src/charting/ColorPalette.js +88 -0
  38. package/src/charting/CommandHistory.js +176 -0
  39. package/src/charting/DataFilter.js +52 -0
  40. package/src/charting/Diagram.js +36 -0
  41. package/src/charting/Diagram3D.js +29 -0
  42. package/src/charting/DiagramClipboard.js +31 -0
  43. package/src/charting/DiagramEditor.js +3330 -0
  44. package/src/charting/DiagramEditorCommand.js +110 -0
  45. package/src/charting/DiagramEditorCommands.js +237 -0
  46. package/src/charting/DiagramEditorEdgeCommands.js +142 -0
  47. package/src/charting/DiagramEditorState.js +98 -0
  48. package/src/charting/DiagramRegistry.js +86 -0
  49. package/src/charting/DiagramTypeRegistry.js +326 -0
  50. package/src/charting/DiagramViewPropertiesDialog.js +46 -0
  51. package/src/charting/Edge.js +113 -0
  52. package/src/charting/ErrorBars.js +37 -0
  53. package/src/charting/FilterSystem.js +285 -0
  54. package/src/charting/FindReplaceDialog.js +139 -0
  55. package/src/charting/FormDialog.js +385 -0
  56. package/src/charting/Gauge.js +58 -0
  57. package/src/charting/Hierarchy.js +175 -0
  58. package/src/charting/HintPanel.js +86 -0
  59. package/src/charting/ImageSelector.js +148 -0
  60. package/src/charting/InteractionManager.js +725 -0
  61. package/src/charting/Legend.js +58 -0
  62. package/src/charting/MenuBar.js +62 -0
  63. package/src/charting/ModelFileFormat.js +115 -0
  64. package/src/charting/OrbitControls.js +77 -0
  65. package/src/charting/Palette.js +119 -0
  66. package/src/charting/PopupMenu.js +117 -0
  67. package/src/charting/PropertiesPanel.js +155 -0
  68. package/src/charting/PropertyListEditor.js +96 -0
  69. package/src/charting/PropertyLog.js +92 -0
  70. package/src/charting/SettingsCascade.js +93 -0
  71. package/src/charting/SettingsDialog.js +53 -0
  72. package/src/charting/SettingsManager.js +179 -0
  73. package/src/charting/SettingsViewPropertiesDialog.js +58 -0
  74. package/src/charting/ShapePaths.js +27 -0
  75. package/src/charting/Statistics.js +134 -0
  76. package/src/charting/TemplateCatalog.js +59 -0
  77. package/src/charting/TemplateLibrary.js +103 -0
  78. package/src/charting/TextStyle.js +168 -0
  79. package/src/charting/ViewFit.js +55 -0
  80. package/src/charting/ViewMenu.js +70 -0
  81. package/src/charting/ViewPropertiesDialog.js +77 -0
  82. package/src/charting/ViewTabStrip.js +81 -0
  83. package/src/charting/archimate/ArchiFileFormat.js +32 -0
  84. package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
  85. package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
  86. package/src/charting/archimate/ArchimateEdge.js +137 -0
  87. package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
  88. package/src/charting/archimate/ArchimatePalette.js +102 -0
  89. package/src/charting/archimate/CsvImportDialog.js +105 -0
  90. package/src/charting/archimate/CustomViewpoints.js +74 -0
  91. package/src/charting/archimate/DerivedEdge.js +29 -0
  92. package/src/charting/archimate/DrawioFileFormat.js +24 -0
  93. package/src/charting/archimate/ElementFilterRule.js +21 -0
  94. package/src/charting/archimate/ExchangeFileFormat.js +28 -0
  95. package/src/charting/archimate/ViewGroupTemplate.js +137 -0
  96. package/src/charting/archimate/ViewLineEdge.js +84 -0
  97. package/src/charting/archimate/ViewpointRule.js +45 -0
  98. package/src/charting/archimate/archimateFileFormats.js +12 -0
  99. package/src/charting/archimate/archimateNames.js +5 -0
  100. package/src/charting/archimate/csvMapping.js +122 -0
  101. package/src/charting/archimate/elementMenuItems.js +32 -0
  102. package/src/charting/archimate/elementProperties.js +146 -0
  103. package/src/charting/archimate/elementTypeChoices.js +7 -0
  104. package/src/charting/archimate/elementTypeGroups.js +19 -0
  105. package/src/charting/archimate/index.js +17 -0
  106. package/src/charting/archimate/specializationCatalogDialog.js +64 -0
  107. package/src/charting/archimate/typeGlyph.js +29 -0
  108. package/src/charting/arrangement/Arrangement.js +112 -0
  109. package/src/charting/arrangement/ArrangementCommand.js +29 -0
  110. package/src/charting/arrangement/BackgroundCommand.js +41 -0
  111. package/src/charting/arrangement/BackgroundGroup.js +18 -0
  112. package/src/charting/arrangement/GroupCommand.js +46 -0
  113. package/src/charting/arrangement/ItemGroup.js +62 -0
  114. package/src/charting/arrangement/LockCommand.js +32 -0
  115. package/src/charting/arrangement/UngroupCommand.js +27 -0
  116. package/src/charting/arrangement/alignment.js +88 -0
  117. package/src/charting/arrangement/arrangeMenuItems.js +25 -0
  118. package/src/charting/arrangement/index.js +11 -0
  119. package/src/charting/arrangement/layouts.js +233 -0
  120. package/src/charting/canvas/ArchiHint.js +78 -0
  121. package/src/charting/canvas/CanvasBoxKind.js +39 -0
  122. package/src/charting/canvas/CanvasPalette.js +49 -0
  123. package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
  124. package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
  125. package/src/charting/canvas/EditHintCommand.js +28 -0
  126. package/src/charting/canvas/canvasBoxKinds.js +27 -0
  127. package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
  128. package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
  129. package/src/charting/canvas/diagramBoxKinds.js +12 -0
  130. package/src/charting/canvas/hintMenuItems.js +49 -0
  131. package/src/charting/charts/ArcGauge.js +55 -0
  132. package/src/charting/charts/AreaChart.js +71 -0
  133. package/src/charting/charts/BarChart.js +80 -0
  134. package/src/charting/charts/BarChart3D.js +56 -0
  135. package/src/charting/charts/BarChart3DOrbit.js +53 -0
  136. package/src/charting/charts/BarChartBase.js +70 -0
  137. package/src/charting/charts/BarGauge.js +42 -0
  138. package/src/charting/charts/BoxPlotChart.js +41 -0
  139. package/src/charting/charts/BubbleChart.js +99 -0
  140. package/src/charting/charts/BubbleChart3D.js +78 -0
  141. package/src/charting/charts/BulletGauge.js +87 -0
  142. package/src/charting/charts/CalendarHeatmapChart.js +204 -0
  143. package/src/charting/charts/CandlestickChart.js +54 -0
  144. package/src/charting/charts/ChordDiagram.js +130 -0
  145. package/src/charting/charts/DensityChart.js +73 -0
  146. package/src/charting/charts/DialGauge.js +65 -0
  147. package/src/charting/charts/DonutChart.js +15 -0
  148. package/src/charting/charts/FunnelChart.js +47 -0
  149. package/src/charting/charts/GanttChart.js +201 -0
  150. package/src/charting/charts/GaugeChart.js +175 -0
  151. package/src/charting/charts/GeoMapChart.js +146 -0
  152. package/src/charting/charts/GroupedBarChart.js +88 -0
  153. package/src/charting/charts/GroupedDistributionChart.js +70 -0
  154. package/src/charting/charts/HeatmapChart.js +80 -0
  155. package/src/charting/charts/HierarchyChart.js +39 -0
  156. package/src/charting/charts/HistogramChart.js +45 -0
  157. package/src/charting/charts/KpiTile.js +72 -0
  158. package/src/charting/charts/LagPlotChart.js +41 -0
  159. package/src/charting/charts/LineChart.js +124 -0
  160. package/src/charting/charts/MultiRingGauge.js +54 -0
  161. package/src/charting/charts/OutlineChart.js +95 -0
  162. package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
  163. package/src/charting/charts/PieChart.js +56 -0
  164. package/src/charting/charts/PipeChart.js +88 -0
  165. package/src/charting/charts/PopulationPyramidChart.js +106 -0
  166. package/src/charting/charts/QQPlotChart.js +64 -0
  167. package/src/charting/charts/RadarChart.js +76 -0
  168. package/src/charting/charts/RadialBarChart.js +96 -0
  169. package/src/charting/charts/RingGauge.js +23 -0
  170. package/src/charting/charts/SankeyDiagram.js +174 -0
  171. package/src/charting/charts/ScatterChart.js +104 -0
  172. package/src/charting/charts/StackedAreaChart.js +15 -0
  173. package/src/charting/charts/StackedBarChart.js +33 -0
  174. package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
  175. package/src/charting/charts/StreamGraphChart.js +131 -0
  176. package/src/charting/charts/SunburstChart.js +57 -0
  177. package/src/charting/charts/ThermometerGauge.js +43 -0
  178. package/src/charting/charts/TreemapChart.js +54 -0
  179. package/src/charting/charts/ViolinChart.js +37 -0
  180. package/src/charting/charts/WaterfallChart.js +66 -0
  181. package/src/charting/charts/WordCloudChart.js +104 -0
  182. package/src/charting/diagramModel/AddViewCommand.js +33 -0
  183. package/src/charting/diagramModel/DiagramModel.js +39 -0
  184. package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
  185. package/src/charting/diagramModel/DiagramView.js +50 -0
  186. package/src/charting/diagramModel/ModelHistory.js +43 -0
  187. package/src/charting/diagramModel/ModelReport.js +153 -0
  188. package/src/charting/diagramModel/ModelSearch.js +223 -0
  189. package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
  190. package/src/charting/diagramModel/RenameViewCommand.js +21 -0
  191. package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
  192. package/src/charting/diagramModel/ViewSetChecker.js +34 -0
  193. package/src/charting/diagramModel/ViewSetModel.js +243 -0
  194. package/src/charting/diagramModel/index.js +6 -0
  195. package/src/charting/diagramModel/nameTransforms.js +29 -0
  196. package/src/charting/diagrams/ArchimateCommands.js +141 -0
  197. package/src/charting/diagrams/ArchimateDiagram.js +263 -0
  198. package/src/charting/diagrams/ArchimateModel.js +1155 -0
  199. package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
  200. package/src/charting/diagrams/ArchimateModelReport.js +128 -0
  201. package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
  202. package/src/charting/diagrams/ArchimateValidator.js +357 -0
  203. package/src/charting/diagrams/CanvasView.js +112 -0
  204. package/src/charting/diagrams/ContextMenu.js +37 -0
  205. package/src/charting/diagrams/DataModelDiagram.js +86 -0
  206. package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
  207. package/src/charting/diagrams/DerivedRelationships.js +102 -0
  208. package/src/charting/diagrams/EbnfDiagram.js +39 -0
  209. package/src/charting/diagrams/EdgeGeometry.js +553 -0
  210. package/src/charting/diagrams/EditViewItemCommand.js +128 -0
  211. package/src/charting/diagrams/ElementInstance.js +157 -0
  212. package/src/charting/diagrams/GraphDiagram.js +1340 -0
  213. package/src/charting/diagrams/GraphDiagram3D.js +152 -0
  214. package/src/charting/diagrams/GraphMetrics.js +81 -0
  215. package/src/charting/diagrams/GridOverlay.js +137 -0
  216. package/src/charting/diagrams/ImportRowsCommand.js +62 -0
  217. package/src/charting/diagrams/LabelHelper.js +108 -0
  218. package/src/charting/diagrams/MergeElementsCommand.js +101 -0
  219. package/src/charting/diagrams/NestInstanceCommand.js +34 -0
  220. package/src/charting/diagrams/NodeGeometry.js +158 -0
  221. package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
  222. package/src/charting/diagrams/RadialLayout.js +101 -0
  223. package/src/charting/diagrams/RelationshipInstance.js +93 -0
  224. package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
  225. package/src/charting/diagrams/RemoveLineCommand.js +27 -0
  226. package/src/charting/diagrams/ShowElementCommand.js +43 -0
  227. package/src/charting/diagrams/SvgCoordinate.js +17 -0
  228. package/src/charting/diagrams/SvgZoom.js +127 -0
  229. package/src/charting/diagrams/Tooltip.js +62 -0
  230. package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
  231. package/src/charting/diagrams/ViewObjectInstance.js +56 -0
  232. package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
  233. package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
  234. package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
  235. package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
  236. package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
  237. package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
  238. package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
  239. package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
  240. package/src/charting/diagrams/commands/GraphCommand.js +65 -0
  241. package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
  242. package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
  243. package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
  244. package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
  245. package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
  246. package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
  247. package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
  248. package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
  249. package/src/charting/diagrams/commands/index.js +17 -0
  250. package/src/charting/diagrams/duplicates.js +49 -0
  251. package/src/charting/diagrams/nesting.js +30 -0
  252. package/src/charting/diagrams/roadmap.js +77 -0
  253. package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
  254. package/src/charting/edgeMarkers/CircleMarker.js +13 -0
  255. package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
  256. package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
  257. package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
  258. package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
  259. package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
  260. package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
  261. package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
  262. package/src/charting/edgeMarkers/index.js +27 -0
  263. package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
  264. package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
  265. package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
  266. package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
  267. package/src/charting/edgeStyle/index.js +4 -0
  268. package/src/charting/emphasis/EmphasisRule.js +42 -0
  269. package/src/charting/emphasis/HighlightRule.js +24 -0
  270. package/src/charting/gauges/ArcTrack.js +51 -0
  271. package/src/charting/gauges/GaugeAnimation.js +51 -0
  272. package/src/charting/gauges/GaugeBands.js +48 -0
  273. package/src/charting/gauges/GaugeScale.js +87 -0
  274. package/src/charting/gauges/GaugeTrack.js +44 -0
  275. package/src/charting/gauges/GaugeValue.js +61 -0
  276. package/src/charting/gauges/HorizontalTrack.js +14 -0
  277. package/src/charting/gauges/LinearTrack.js +29 -0
  278. package/src/charting/gauges/Sparkline.js +42 -0
  279. package/src/charting/gauges/VerticalTrack.js +17 -0
  280. package/src/charting/glyphs/ArrowGlyph.js +21 -0
  281. package/src/charting/glyphs/BatteryGlyph.js +18 -0
  282. package/src/charting/glyphs/ChevronGlyph.js +18 -0
  283. package/src/charting/glyphs/CircleGlyph.js +15 -0
  284. package/src/charting/glyphs/CloudGlyph.js +19 -0
  285. package/src/charting/glyphs/ComponentGlyph.js +18 -0
  286. package/src/charting/glyphs/ConstraintGlyph.js +24 -0
  287. package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
  288. package/src/charting/glyphs/CubeGlyph.js +19 -0
  289. package/src/charting/glyphs/CylinderGlyph.js +19 -0
  290. package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
  291. package/src/charting/glyphs/DeviceGlyph.js +17 -0
  292. package/src/charting/glyphs/DiamondGlyph.js +17 -0
  293. package/src/charting/glyphs/DocumentGlyph.js +17 -0
  294. package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
  295. package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
  296. package/src/charting/glyphs/EllipseGlyph.js +18 -0
  297. package/src/charting/glyphs/FactoryGlyph.js +20 -0
  298. package/src/charting/glyphs/FlagGlyph.js +16 -0
  299. package/src/charting/glyphs/GapCircleGlyph.js +17 -0
  300. package/src/charting/glyphs/GearGlyph.js +37 -0
  301. package/src/charting/glyphs/Glyph.js +98 -0
  302. package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
  303. package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
  304. package/src/charting/glyphs/HexagonGlyph.js +28 -0
  305. package/src/charting/glyphs/IconGlyph.js +22 -0
  306. package/src/charting/glyphs/ImageGlyph.js +16 -0
  307. package/src/charting/glyphs/JunctionGlyph.js +17 -0
  308. package/src/charting/glyphs/LollipopGlyph.js +22 -0
  309. package/src/charting/glyphs/MagnifierGlyph.js +17 -0
  310. package/src/charting/glyphs/NoteGlyph.js +33 -0
  311. package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
  312. package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
  313. package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
  314. package/src/charting/glyphs/PersonGlyph.js +23 -0
  315. package/src/charting/glyphs/PillGlyph.js +23 -0
  316. package/src/charting/glyphs/PinGlyph.js +18 -0
  317. package/src/charting/glyphs/PrincipleGlyph.js +23 -0
  318. package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
  319. package/src/charting/glyphs/RectGlyph.js +15 -0
  320. package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
  321. package/src/charting/glyphs/StackGlyph.js +14 -0
  322. package/src/charting/glyphs/StepsGlyph.js +20 -0
  323. package/src/charting/glyphs/StickFigureGlyph.js +32 -0
  324. package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
  325. package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
  326. package/src/charting/glyphs/TargetGlyph.js +23 -0
  327. package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
  328. package/src/charting/glyphs/WheelGlyph.js +28 -0
  329. package/src/charting/glyphs/drawGlyph.js +28 -0
  330. package/src/charting/glyphs/glyphSvg.js +55 -0
  331. package/src/charting/glyphs/index.js +109 -0
  332. package/src/charting/modelTree/AnalysisPanel.js +159 -0
  333. package/src/charting/modelTree/DiagramTabs.js +217 -0
  334. package/src/charting/modelTree/ModelTree.js +164 -0
  335. package/src/charting/modelTree/ModelTreePanel.js +914 -0
  336. package/src/charting/modelTree/TreeBuilder.js +238 -0
  337. package/src/charting/modelTree/TreeModeRegistry.js +51 -0
  338. package/src/charting/modelTree/TreeViewMode.js +110 -0
  339. package/src/charting/modelTree/buildFilterTrees.js +138 -0
  340. package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
  341. package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
  342. package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
  343. package/src/charting/modelTree/treeLayers.js +11 -0
  344. package/src/charting/report/reportHtml.js +82 -0
  345. package/src/charting/report/reportViewer.js +118 -0
  346. package/src/charting/shapes/CircleShape.js +19 -0
  347. package/src/charting/shapes/PathShape.js +17 -0
  348. package/src/charting/shapes/RectShape.js +20 -0
  349. package/src/charting/shapes/Shape.js +20 -0
  350. package/src/charting/shapes/ShapeFactory.js +23 -0
  351. package/src/charting/storage/LocalJsonStore.js +43 -0
  352. package/src/charting/templates/ActorTemplate.js +36 -0
  353. package/src/charting/templates/BoxTemplate.js +27 -0
  354. package/src/charting/templates/CircleTemplate.js +18 -0
  355. package/src/charting/templates/ClassTemplate.js +20 -0
  356. package/src/charting/templates/CloudTemplate.js +43 -0
  357. package/src/charting/templates/ComponentTemplate.js +19 -0
  358. package/src/charting/templates/CylinderTemplate.js +30 -0
  359. package/src/charting/templates/DataStoreTemplate.js +16 -0
  360. package/src/charting/templates/DiamondTemplate.js +10 -0
  361. package/src/charting/templates/DocumentTemplate.js +32 -0
  362. package/src/charting/templates/EllipseTemplate.js +15 -0
  363. package/src/charting/templates/FinalStateTemplate.js +12 -0
  364. package/src/charting/templates/GlyphTemplate.js +47 -0
  365. package/src/charting/templates/HexagonTemplate.js +17 -0
  366. package/src/charting/templates/LifelineTemplate.js +20 -0
  367. package/src/charting/templates/ManualInputTemplate.js +12 -0
  368. package/src/charting/templates/NoteTemplate.js +23 -0
  369. package/src/charting/templates/OctagonTemplate.js +7 -0
  370. package/src/charting/templates/PackageTemplate.js +25 -0
  371. package/src/charting/templates/ParallelogramTemplate.js +11 -0
  372. package/src/charting/templates/PentagonTemplate.js +5 -0
  373. package/src/charting/templates/PolygonTemplate.js +18 -0
  374. package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
  375. package/src/charting/templates/RectangleTemplate.js +28 -0
  376. package/src/charting/templates/RegularPolygonTemplate.js +21 -0
  377. package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
  378. package/src/charting/templates/StadiumTemplate.js +8 -0
  379. package/src/charting/templates/StarTemplate.js +17 -0
  380. package/src/charting/templates/SwimlaneTemplate.js +18 -0
  381. package/src/charting/templates/Template.js +208 -0
  382. package/src/charting/templates/TrapezoidTemplate.js +11 -0
  383. package/src/charting/templates/TriangleTemplate.js +12 -0
  384. package/src/charting/templates/index.js +31 -0
  385. package/src/charting/templates/outline.js +59 -0
  386. package/src/charting/templates/svg.js +19 -0
  387. package/src/charting/textToShapes.js +61 -0
  388. package/src/charting/toolbar/ToolbarButton.js +38 -0
  389. package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
  390. package/src/charting/toolbar/ToolbarItem.js +19 -0
  391. package/src/charting/toolbar/ToolbarMenu.js +36 -0
  392. package/src/charting/toolbar/ToolbarSelect.js +38 -0
  393. package/src/charting/toolbar/ToolbarSeparator.js +7 -0
  394. package/src/charting/toolbar/ToolbarText.js +22 -0
  395. package/src/charting/toolbar/index.js +8 -0
  396. package/src/charting/toolbar/pickFile.js +14 -0
  397. package/src/charting/viewDecorations.js +85 -0
  398. package/src/charting/zOrder.js +57 -0
  399. package/src/csvTable.js +61 -0
  400. package/src/datamodel.js +122 -0
  401. package/src/datawindow/BoundedWindow.js +36 -0
  402. package/src/datawindow/FlatDataWindow.js +34 -0
  403. package/src/datawindow/GraphDataWindow.js +40 -0
  404. package/src/datawindow/GroupedSampleDataWindow.js +16 -0
  405. package/src/datawindow/SeriesDataWindow.js +42 -0
  406. package/src/datawindow/index.js +31 -0
  407. package/src/diagramCatalog.js +30 -0
  408. package/src/ebnfDiagram.js +57 -0
  409. package/src/ebnfParser.js +129 -0
  410. package/src/exportImage.js +233 -0
  411. package/src/index.js +2636 -0
  412. package/src/itIcons.js +84 -0
  413. package/src/kernelExpr.js +243 -0
  414. package/src/propertiesDialog.js +463 -0
  415. package/src/railroadDiagram.js +571 -0
  416. package/src/treeModeCatalog.js +16 -0
  417. package/src/workspace/ContextBus.js +79 -0
  418. package/src/workspace/EditorShell.js +67 -0
  419. package/src/workspace/Part.js +163 -0
  420. package/src/workspace/PartFactory.js +49 -0
  421. package/src/workspace/PartRegistry.js +86 -0
  422. package/src/workspace/Workspace.js +321 -0
  423. package/src/workspace/archimateServices.js +33 -0
  424. package/src/workspace/dom.js +120 -0
  425. package/src/workspace/index.js +75 -0
  426. package/src/workspace/layout/GridNode.js +280 -0
  427. package/src/workspace/layout/LayoutNode.js +89 -0
  428. package/src/workspace/layout/PartNode.js +77 -0
  429. package/src/workspace/layout/SplitNode.js +114 -0
  430. package/src/workspace/layout/TabsNode.js +191 -0
  431. package/src/workspace/layout/index.js +24 -0
  432. package/src/workspace/parts/AdapterPart.js +33 -0
  433. package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
  434. package/src/workspace/parts/ArchimateEditorPart.js +79 -0
  435. package/src/workspace/parts/ChartPart.js +115 -0
  436. package/src/workspace/parts/ContentPart.js +34 -0
  437. package/src/workspace/parts/DetailPart.js +46 -0
  438. package/src/workspace/parts/DiagramEditorPart.js +135 -0
  439. package/src/workspace/parts/EditorPart.js +388 -0
  440. package/src/workspace/parts/HtmlPart.js +25 -0
  441. package/src/workspace/parts/ListPart.js +57 -0
  442. package/src/workspace/parts/ModelFile.js +187 -0
  443. package/src/workspace/parts/ModelsPart.js +135 -0
  444. package/src/workspace/styles.js +258 -0
  445. package/src/workspace/themes.js +96 -0
  446. package/src/workspace/workArea.js +413 -0
  447. package/src/workspace/workAreaModel.js +197 -0
  448. package/src/workspace.js +16 -0
  449. package/src/zip/ZipArchive.js +160 -0
  450. package/src/zip/crc32.js +25 -0
  451. package/src/zip/inflate.js +159 -0
@@ -0,0 +1,146 @@
1
+ import { ArchimateNotation } from '../../archimate.js';
2
+ import { ArchimateSpecializationRegistry } from '../../archimateSpecializations.js';
3
+ import { PropertyListEditor } from '../PropertyListEditor.js';
4
+ import { EditViewItemCommand } from '../diagrams/EditViewItemCommand.js';
5
+ import { FormDialog } from '../FormDialog.js';
6
+ import { typeTitle } from './archimateNames.js';
7
+
8
+ /**
9
+ * What a model element is, as dialog fields and an edit: its own name, type,
10
+ * specialization (those registered for its type, and its own), icon (its
11
+ * type's choices), documentation and typed properties, the same on every
12
+ * view. One definition for the canvas editor's shape dialog (its Element
13
+ * section) and the model tree's Properties….
14
+ *
15
+ * Field keys are `element.<key>`, so they sit beside other fields in one form.
16
+ */
17
+
18
+ /**
19
+ * The fields for an element.
20
+ * @param {Object} element - A model element
21
+ * @param {Object} [options]
22
+ * @param {string} [options.version] - Whose types and icons to offer
23
+ * @param {Document} [options.document]
24
+ * @returns {Array<Object>} FormDialog fields (headings included)
25
+ */
26
+ export function elementPropertyFields(element, { version = '4', document: doc = globalThis.document } = {}) {
27
+ return [
28
+ { key: 'element.name', label: 'Name', type: 'text', value: element.name ?? '' },
29
+ ...elementKindFields(element, { version }),
30
+ {
31
+ key: 'element.icon', label: 'Icon', type: 'select', value: element.icon ?? '',
32
+ choices: [['', '(the type default)'], ...[...new Set([...ArchimateNotation.iconChoices(element.type, version), element.icon].filter(Boolean))].map(i => [i, i])],
33
+ },
34
+ { key: 'element.documentation', label: 'Documentation', type: 'textarea', rows: 4, value: element.documentation ?? '' },
35
+ { type: 'heading', label: 'Properties' },
36
+ PropertyListEditor.field(element.properties, { key: 'element.properties', document: doc }),
37
+ ];
38
+ }
39
+
40
+ /** An element's type and specialization (those registered for its type, and its own), as fields. */
41
+ export function elementKindFields(element, { version = '4' } = {}) {
42
+ const types = [...new Set([...ArchimateNotation.elementTypeNames(version), element.type].filter(Boolean))];
43
+ return [
44
+ { key: 'element.type', label: 'Type', type: 'select', value: element.type, choices: types.map(t => [t, typeTitle(t)]) },
45
+ {
46
+ key: 'element.specialization', label: 'Specialization', type: 'select', value: element.specialization ?? '',
47
+ choices: [['', '(none)'], ...[...new Set([...ArchimateSpecializationRegistry.forBaseType(element.type).map(s => s.name), element.specialization].filter(Boolean))].map(n => [n, n])],
48
+ },
49
+ ];
50
+ }
51
+
52
+ /**
53
+ * The fields for several elements edited together (see FormDialog.many):
54
+ * their type, their specialization when they share a type (each type has its
55
+ * own), and one property to give them all (set where they have it, added where
56
+ * they don't).
57
+ */
58
+ export function manyElementsFields(elements, { version = '4' } = {}) {
59
+ const oneType = new Set(elements.map(e => e.type)).size === 1;
60
+ return [
61
+ { type: 'heading', label: `Elements (${elements.length}, on every view)` },
62
+ ...FormDialog.many(elements.map(e => elementKindFields(e, { version }).filter(f => oneType || f.key === 'element.type'))),
63
+ { key: 'element.property.name', label: 'Set property', type: 'text', value: '', placeholder: 'name (empty: none)' },
64
+ { key: 'element.property.value', label: 'To', type: 'text', value: '' },
65
+ ...(() => {
66
+ const names = [...new Set(elements.flatMap(e => (e.properties ?? []).map(p => p.name ?? p.key)).filter(Boolean))].sort();
67
+ return names.length ? [{ key: 'element.property.remove', label: 'Remove property', type: 'select', value: '', choices: [['', '(none)'], ...names.map(n => [n, n])] }] : [];
68
+ })(),
69
+ ];
70
+ }
71
+
72
+ /**
73
+ * `manyElementsFields`' values as each element's edit (fields left on Keep are
74
+ * undefined): EditViewItemCommands, only for the elements that change.
75
+ * `instanceOf(element)` is the occurrence edited with it, if any.
76
+ */
77
+ export function manyElementsEditCommands(elements, values, { instanceOf = () => null } = {}) {
78
+ const name = String(values['element.property.name'] ?? '').trim();
79
+ const kind = Object.fromEntries(['element.type', 'element.specialization'].filter(k => values[k] !== undefined).map(k => [k, values[k]]));
80
+ return elements.map(element => {
81
+ const own = element.properties ?? [];
82
+ const property = { name, type: own.find(p => p.name === name)?.type ?? 'string', value: String(values['element.property.value'] ?? '') };
83
+ const remove = String(values['element.property.remove'] ?? '');
84
+ let list = !name ? own : own.some(p => p.name === name) ? own.map(p => (p.name === name ? property : p)) : [...own, property];
85
+ if (remove) list = list.filter(p => (p.name ?? p.key) !== remove);
86
+ const properties = list === own ? {} : { 'element.properties': list };
87
+ return elementEditCommand(element, { ...kind, ...properties }, { instance: instanceOf(element) });
88
+ }).filter(Boolean);
89
+ }
90
+
91
+ /**
92
+ * The changed `<prefix>.<key>` values as an edit of a concept (an element or
93
+ * relationship): one EditViewItemCommand, or null when nothing changed. An
94
+ * empty text or list is unset. `instance` is the occurrence edited with it
95
+ * (none from the model tree).
96
+ */
97
+ export function conceptEditCommand(concept, values, { prefix, instance = null, adjust = () => {} }) {
98
+ const unset = (v) => v === undefined || v === null || v === '' || (Array.isArray(v) && !v.length);
99
+ const changes = {};
100
+ for (const [field, value] of Object.entries(values)) {
101
+ if (!field.startsWith(`${prefix}.`)) continue;
102
+ const key = field.slice(prefix.length + 1);
103
+ const before = concept[key];
104
+ if ((unset(before) && unset(value)) || JSON.stringify(before) === JSON.stringify(value)) continue;
105
+ changes[key] = unset(value) ? undefined : value;
106
+ }
107
+ if (!Object.keys(changes).length) return null;
108
+ adjust(changes);
109
+ return new EditViewItemCommand({ concept, instance }, { concept: changes, appearance: {} }, `Edit ${concept.name || concept.label || concept.id}`);
110
+ }
111
+
112
+ /** An element's edit (elementPropertyFields' values): a new type drops a stored layer, which then follows the type. */
113
+ export function elementEditCommand(element, values, { instance = null } = {}) {
114
+ return conceptEditCommand(element, values, {
115
+ prefix: 'element', instance,
116
+ adjust: (changes) => { if ('type' in changes && element.layer) changes.layer = undefined; },
117
+ });
118
+ }
119
+
120
+ /**
121
+ * Edit a model element in its own dialog (from the model tree): its
122
+ * properties, saved as one undo step on `history`.
123
+ * @param {Object} element
124
+ * @param {Object} options
125
+ * @param {CommandHistory} options.history - Where the edit goes (the current view's)
126
+ * @param {() => void} [options.onSaved] - After a change (redraw, refresh the tree)
127
+ * @param {string} [options.version]
128
+ * @param {Document} [options.document]
129
+ */
130
+ export function editElementProperties(element, { history, onSaved = () => {}, version = '4', document: doc = globalThis.document }) {
131
+ return new FormDialog({
132
+ title: `Properties: ${element.name || element.id}`,
133
+ description: 'The element itself: these show on every view it is on.',
134
+ fields: elementPropertyFields(element, { version, document: doc }),
135
+ submitLabel: 'Save',
136
+ idPrefix: 'element-props-',
137
+ document: doc,
138
+ onApply: (values) => {
139
+ const cmd = elementEditCommand(element, values);
140
+ if (!cmd) return;
141
+ if (history) history.execute(cmd);
142
+ else cmd.execute();
143
+ onSaved(cmd);
144
+ },
145
+ }).open();
146
+ }
@@ -0,0 +1,7 @@
1
+ import { elementTypeGroups } from './elementTypeGroups.js';
2
+ import { typeTitle } from './archimateNames.js';
3
+
4
+ /** Every element type of a version as checklist choices, grouped by layer as the palette groups them. */
5
+ export function elementTypeChoices(version = '4') {
6
+ return elementTypeGroups(version).flatMap(group => group.types.map(type => [type.name, typeTitle(type.name), group.label]));
7
+ }
@@ -0,0 +1,19 @@
1
+ import { ArchimateNotation } from '../../archimate.js';
2
+ import { typeTitle } from './archimateNames.js';
3
+
4
+ /**
5
+ * The element types of a version, grouped as people look for them: each layer
6
+ * that has types (the notation's order), then ArchiMate 4's common behaviour
7
+ * types (no layer of their own). The palette's groups, and the type lists of
8
+ * the specialization and viewpoint dialogs.
9
+ * @returns {Array<{key: string, label: string, types: ArchimateElementType[]}>}
10
+ */
11
+ export function elementTypeGroups(version = '4') {
12
+ const groups = ArchimateNotation.layers()
13
+ .map(layer => ({ key: layer.name, label: typeTitle(layer.name), types: ArchimateNotation.typesInLayer(layer.name, version) }))
14
+ .filter(g => g.types.length);
15
+ const grouped = new Set(groups.flatMap(g => g.types.map(t => t.name)));
16
+ const common = ArchimateNotation.elementTypeNames(version).filter(n => !grouped.has(n)).map(n => ArchimateNotation.elementType(n, version));
17
+ if (common.length) groups.push({ key: 'common', label: 'Common behaviour', types: common });
18
+ return groups;
19
+ }
@@ -0,0 +1,17 @@
1
+ export { ArchimateElementTemplate } from './ArchimateElementTemplate.js';
2
+ export { ArchimateEdge } from './ArchimateEdge.js';
3
+ export { ViewLineEdge } from './ViewLineEdge.js';
4
+ export { ArchimateCanvasEditor, ARCHIMATE_TYPE_MIME, KIND_PREFERENCE, typeTitle } from './ArchimateCanvasEditor.js';
5
+ export { ArchimatePalette } from './ArchimatePalette.js';
6
+ export { ArchiFileFormat } from './ArchiFileFormat.js';
7
+ export { ExchangeFileFormat } from './ExchangeFileFormat.js';
8
+ export { ArchimateCsvFileFormat } from './ArchimateCsvFileFormat.js';
9
+ export { ARCHIMATE_FILE_FORMATS } from './archimateFileFormats.js';
10
+ export { DrawioFileFormat } from './DrawioFileFormat.js';
11
+ export { ViewpointRule } from './ViewpointRule.js';
12
+ export { ElementFilterRule } from './ElementFilterRule.js';
13
+ export { DerivedEdge } from './DerivedEdge.js';
14
+ export { ViewGroupTemplate, GROUP_FILL } from './ViewGroupTemplate.js';
15
+ export { CustomViewpoints, CUSTOM_VIEWPOINTS_STORE } from './CustomViewpoints.js';
16
+ export { specializationCatalogDialog } from './specializationCatalogDialog.js';
17
+ export { elementTypeChoices } from './elementTypeChoices.js';
@@ -0,0 +1,64 @@
1
+ import { CatalogDialog } from '../CatalogDialog.js';
2
+ import { ArchimateSpecializationRegistry, SPECIALIZATIONS_STORE } from '../../archimateSpecializations.js';
3
+ import { elementTypeChoices } from './elementTypeChoices.js';
4
+
5
+ /**
6
+ * Edit the specialization catalog (ArchimateSpecializationRegistry): name,
7
+ * the element types it applies to, its icon, colour and description. Every
8
+ * change is saved to `store` (this browser's catalog), which both editors
9
+ * load.
10
+ * @param {Object} [options]
11
+ * @param {string} [options.version] - Whose element types to offer
12
+ * @param {LocalJsonStore} [options.store]
13
+ * @param {() => void} [options.onChange] - After a change (redraw)
14
+ * @param {Document} [options.document]
15
+ * @returns {CatalogDialog}
16
+ */
17
+ export function specializationCatalogDialog({ version = '4', store = SPECIALIZATIONS_STORE, onChange = () => {}, document: doc = globalThis.document } = {}) {
18
+ const R = ArchimateSpecializationRegistry;
19
+ const keep = () => store.save(R.serialize());
20
+ return new CatalogDialog({
21
+ title: 'Specializations',
22
+ description: 'Kinds of element of your own (a Firewall is a Node): their icon and colour show on every element given one.',
23
+ noun: 'specialization',
24
+ items: () => R.list().sort((a, b) => a.name.localeCompare(b.name)),
25
+ label: (spec) => `${spec.icon ? `${spec.icon} ` : ''}${spec.name}`,
26
+ fields: (spec) => [
27
+ { key: 'name', label: 'Name', type: 'text', value: spec?.name ?? '' },
28
+ { key: 'icon', label: 'Icon', type: 'text', value: spec?.icon ?? '', hint: 'An emoji or a short text, drawn in the corner' },
29
+ { key: 'color', label: 'Colour', type: 'color', value: spec?.color ?? '' },
30
+ { key: 'description', label: 'Description', type: 'textarea', rows: 2, value: spec?.description ?? '' },
31
+ { key: 'baseTypes', label: 'For types', type: 'checklist', value: spec?.baseTypes ?? [], choices: elementTypeChoices(version), hint: 'None chosen: every type' },
32
+ ],
33
+ validate: (spec, { name }) => {
34
+ const wanted = String(name ?? '').trim();
35
+ if (!wanted) return 'A specialization needs a name.';
36
+ const other = R.resolve(wanted);
37
+ if (other && other.id !== spec?.id) return `There is already a specialization called "${wanted}".`;
38
+ return null;
39
+ },
40
+ save: (spec, { name, icon, color, description, baseTypes }) => {
41
+ R.register({
42
+ id: spec?.id ?? uniqueId(name.trim(), (id) => !!R.get(id)),
43
+ name: name.trim(),
44
+ baseTypes,
45
+ icon: icon?.trim() || undefined,
46
+ iconUrl: spec?.iconUrl,
47
+ color: color && color !== 'none' ? color : undefined,
48
+ description: description?.trim() || undefined,
49
+ });
50
+ keep();
51
+ },
52
+ remove: (spec) => { R.unregister(spec.id); keep(); },
53
+ onChange,
54
+ document: doc,
55
+ });
56
+ }
57
+
58
+ /** An id made from a name, not yet `taken`. */
59
+ export function uniqueId(name, taken) {
60
+ const base = name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'item';
61
+ let id = base;
62
+ for (let n = 2; taken(id); n++) id = `${base}-${n}`;
63
+ return id;
64
+ }
@@ -0,0 +1,29 @@
1
+ import { ArchimateDiagram } from '../diagrams/ArchimateDiagram.js';
2
+ import { ArchimateNotation } from '../../archimate.js';
3
+ import { Glyph } from '../glyphs/Glyph.js';
4
+ import { glyphFor } from '../glyphs/index.js';
5
+ import { glyphToSvg } from '../glyphs/glyphSvg.js';
6
+ import { svgEl } from '../templates/svg.js';
7
+
8
+ /**
9
+ * A small picture of an element type: its notation glyph in its layer
10
+ * colour, as an <svg> (a type of the other ArchiMate version as that version draws it). One drawing for every place a type is shown small:
11
+ * the palette's tiles and the model tree's elements and type folders.
12
+ * @param {string} typeName - An element type ('business-actor', ...)
13
+ * @param {Object} [options]
14
+ * @param {number} [options.size] - Its height in pixels (it is 1.4 times as wide)
15
+ * @param {string} [options.version] - ArchiMate version
16
+ * @param {Document} [options.document]
17
+ * @returns {SVGElement}
18
+ */
19
+ export function typeGlyph(typeName, { size = 22, version = '4', document: doc = globalThis.document } = {}) {
20
+ // A type of the other version (3.2's business-process under 4) is drawn as that version draws it.
21
+ const own = ArchimateNotation.elementType(typeName, version) ? version : (ArchimateNotation.elementType(typeName, '3.2') ? '3.2' : version);
22
+ const type = ArchimateNotation.elementType(typeName, own);
23
+ const node = ArchimateDiagram.buildNode({ id: typeName, name: '', type: typeName }, { archimateVersion: own });
24
+ const glyph = glyphFor(type?.notationShape ?? 'rect');
25
+ const ctx = Glyph.context({ R: size / 2, size: { w: size * 1.3, h: size }, color: node.color, cornerStyle: node.cornerStyle, strokeColor: '#333', strokeWidth: 1 });
26
+ const svg = svgEl('svg', { width: size * 1.4, height: size + 4, viewBox: `${-size * 0.7} ${-size / 2 - 2} ${size * 1.4} ${size + 4}` }, doc);
27
+ svg.appendChild(glyphToSvg(glyph.parts(ctx), doc));
28
+ return svg;
29
+ }
@@ -0,0 +1,112 @@
1
+ import { ItemGroup } from './ItemGroup.js';
2
+ import './BackgroundGroup.js'; // registers its kind, so fromJSON makes it
3
+
4
+ /**
5
+ * Arrangement — how the items on one view hold together: which are grouped
6
+ * (an ItemGroup moves as one) and which are locked (fixed in place: not moved,
7
+ * resized or rotated). An item or a whole group can be locked; a locked group
8
+ * locks every member. Items are known by id only, so the same arrangement
9
+ * serves a template diagram's templates and an ArchiMate view's instances.
10
+ *
11
+ * A group may be pinned to the back (a BackgroundGroup, what a canvas takes
12
+ * from its template): its members stack behind every other item.
13
+ *
14
+ * Change it through the commands (GroupCommand, UngroupCommand, LockCommand,
15
+ * BackgroundCommand), so each change is one undo step on the view's history.
16
+ */
17
+ export class Arrangement {
18
+ /**
19
+ * @param {Object} [spec]
20
+ * @param {Array<ItemGroup|Object>} [spec.groups]
21
+ * @param {Iterable<string>} [spec.locked] - Ids of locked items and groups
22
+ */
23
+ constructor({ groups = [], locked = [] } = {}) {
24
+ /** @type {Map<string, ItemGroup>} */
25
+ this.groups = new Map(groups.map(g => {
26
+ const group = g instanceof ItemGroup ? g : ItemGroup.fromJSON(g);
27
+ return [group.id, group];
28
+ }));
29
+ /** @type {Set<string>} ids of locked items and groups */
30
+ this.locked = new Set(locked);
31
+ }
32
+
33
+ /** The group an item belongs to, or null. */
34
+ groupOf(itemId) {
35
+ for (const group of this.groups.values()) if (group.has(itemId)) return group;
36
+ return null;
37
+ }
38
+
39
+ /** The ids that move when `itemId` moves: its group's members, or itself. */
40
+ movingWith(itemId) {
41
+ const group = this.groupOf(itemId);
42
+ return group ? new Set(group.memberIds) : new Set([itemId]);
43
+ }
44
+
45
+ /** Everything that moves when these items move, groups included. */
46
+ movers(itemIds) {
47
+ const all = new Set();
48
+ for (const id of itemIds) for (const m of this.movingWith(id)) all.add(m);
49
+ return all;
50
+ }
51
+
52
+ /** Whether an item is fixed in place: locked itself, or in a locked group. */
53
+ isLocked(itemId) {
54
+ if (this.locked.has(itemId)) return true;
55
+ const group = this.groupOf(itemId);
56
+ return !!group && this.locked.has(group.id);
57
+ }
58
+
59
+ /** Whether these items (with their groups) may move: none of them is locked. */
60
+ canMove(itemIds) {
61
+ return [...this.movers(itemIds)].every(id => !this.isLocked(id));
62
+ }
63
+
64
+ /** Whether an item stays behind every item not pinned (it is in a BackgroundGroup). */
65
+ isPinnedToBack(itemId) {
66
+ return !!this.groupOf(itemId)?.pinnedToBack;
67
+ }
68
+
69
+ /** What locking `itemId` locks: its group if it has one, else the item. */
70
+ lockTargetOf(itemId) {
71
+ return this.groupOf(itemId)?.id ?? itemId;
72
+ }
73
+
74
+ /**
75
+ * The arrangement of some of the items only (what a part of a view takes
76
+ * with it): groups keep the members among them (a group left with none
77
+ * goes), and their locks.
78
+ * @param {Iterable<string>} itemIds
79
+ * @returns {Arrangement}
80
+ */
81
+ only(itemIds) {
82
+ const keep = new Set(itemIds);
83
+ const groups = [...this.groups.values()]
84
+ .map(g => g.withMembers([...g.memberIds].filter(id => keep.has(id))))
85
+ .filter(g => g.memberIds.size > 0);
86
+ const groupIds = new Set(groups.map(g => g.id));
87
+ return new Arrangement({ groups, locked: [...this.locked].filter(id => keep.has(id) || groupIds.has(id)) });
88
+ }
89
+
90
+ /** A copy with item ids mapped (for a copied view whose items have new ids). */
91
+ copy(mapId = (id) => id) {
92
+ return new Arrangement({
93
+ groups: [...this.groups.values()].map(g => g.withMembers([...g.memberIds].map(mapId))),
94
+ locked: [...this.locked].map(id => (this.groups.has(id) ? id : mapId(id))),
95
+ });
96
+ }
97
+
98
+ toJSON() {
99
+ return { groups: [...this.groups.values()].map(g => g.toJSON()), locked: [...this.locked] };
100
+ }
101
+
102
+ static fromJSON(data) {
103
+ return new Arrangement(data ?? {});
104
+ }
105
+
106
+ /** Replace this arrangement's state with a snapshot (toJSON). Used by undo. @protected */
107
+ restore(snapshot) {
108
+ const again = Arrangement.fromJSON(snapshot);
109
+ this.groups = again.groups;
110
+ this.locked = again.locked;
111
+ }
112
+ }
@@ -0,0 +1,29 @@
1
+ import { Command } from '../CommandHistory.js';
2
+
3
+ /**
4
+ * ArrangementCommand — one undoable change to an Arrangement. Undo puts back
5
+ * the arrangement exactly as it was (a snapshot taken when first applied);
6
+ * redo applies the change again. Subclasses implement apply().
7
+ */
8
+ export class ArrangementCommand extends Command {
9
+ constructor(arrangement, label) {
10
+ super(label);
11
+ if (new.target === ArrangementCommand) throw new TypeError('ArrangementCommand is abstract — subclass it');
12
+ this.arrangement = arrangement;
13
+ this._before = null;
14
+ }
15
+
16
+ execute() {
17
+ this._before ??= this.arrangement.toJSON();
18
+ this.apply();
19
+ }
20
+
21
+ undo() {
22
+ this.arrangement.restore(this._before);
23
+ }
24
+
25
+ /** Change the arrangement. @abstract */
26
+ apply() {
27
+ throw new Error(`${this.constructor.name} must implement apply()`);
28
+ }
29
+ }
@@ -0,0 +1,41 @@
1
+ import { ArrangementCommand } from './ArrangementCommand.js';
2
+ import { BackgroundGroup } from './BackgroundGroup.js';
3
+
4
+ let nextBackground = 1;
5
+
6
+ /**
7
+ * BackgroundCommand — make items the view's background: one BackgroundGroup
8
+ * (their old groups dissolved into it), locked. Their stacking is the view's
9
+ * to settle (DiagramEditorState#arrangeAsBackground puts them behind).
10
+ */
11
+ export class BackgroundCommand extends ArrangementCommand {
12
+ /**
13
+ * @param {Arrangement} arrangement
14
+ * @param {Iterable<string>} itemIds
15
+ * @param {Object} [options]
16
+ * @param {string} [options.id] - The group's id (default: generated)
17
+ * @param {string} [options.name]
18
+ * @param {boolean} [options.locked] - Lock it (default true)
19
+ */
20
+ constructor(arrangement, itemIds, { id = `background-${Date.now().toString(36)}-${nextBackground++}`, name = 'Background', locked = true } = {}) {
21
+ super(arrangement, 'Make background');
22
+ this.itemIds = [...itemIds];
23
+ this.groupId = id;
24
+ this.name = name;
25
+ this.lockedValue = locked;
26
+ }
27
+
28
+ apply() {
29
+ const arrangement = this.arrangement;
30
+ const members = arrangement.movers(this.itemIds);
31
+ for (const id of this.itemIds) {
32
+ const old = arrangement.groupOf(id);
33
+ if (!old) continue;
34
+ arrangement.locked.delete(old.id);
35
+ arrangement.groups.delete(old.id);
36
+ }
37
+ for (const id of members) arrangement.locked.delete(id);
38
+ arrangement.groups.set(this.groupId, new BackgroundGroup({ id: this.groupId, name: this.name, memberIds: members }));
39
+ if (this.lockedValue) arrangement.locked.add(this.groupId);
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ import { ItemGroup } from './ItemGroup.js';
2
+
3
+ /**
4
+ * BackgroundGroup — a group pinned behind everything else on its view: what a
5
+ * canvas takes from its template. Its members always stack below every other
6
+ * item, whatever is sent to the back; it is made locked (BackgroundCommand),
7
+ * so it is neither moved nor changed until unlocked. Unlocked, it moves as
8
+ * one like any group; ungrouped, its items are ordinary items again.
9
+ */
10
+ export class BackgroundGroup extends ItemGroup {
11
+ static kind = 'background';
12
+
13
+ get pinnedToBack() {
14
+ return true;
15
+ }
16
+ }
17
+
18
+ ItemGroup.register(BackgroundGroup);
@@ -0,0 +1,46 @@
1
+ import { ArrangementCommand } from './ArrangementCommand.js';
2
+ import { ItemGroup } from './ItemGroup.js';
3
+
4
+ let nextGroup = 1;
5
+
6
+ /**
7
+ * GroupCommand — group items so they move as one. Groups do not nest: an item
8
+ * already in a group brings its whole group into the new one, and the old
9
+ * group goes. A locked group's lock passes to the new group, and so does a
10
+ * background group's kind (the new group is pinned to the back too).
11
+ */
12
+ export class GroupCommand extends ArrangementCommand {
13
+ /**
14
+ * @param {Arrangement} arrangement
15
+ * @param {Iterable<string>} itemIds - At least two items (with their groups)
16
+ * @param {Object} [options]
17
+ * @param {string} [options.id] - The new group's id (default: generated)
18
+ * @param {string} [options.name]
19
+ */
20
+ constructor(arrangement, itemIds, { id = `group-${Date.now().toString(36)}-${nextGroup++}`, name = '' } = {}) {
21
+ super(arrangement, 'Group');
22
+ this.itemIds = [...itemIds];
23
+ this.groupId = id;
24
+ this.name = name;
25
+ }
26
+
27
+ apply() {
28
+ const arrangement = this.arrangement;
29
+ const members = arrangement.movers(this.itemIds);
30
+ let locked = false;
31
+ let kindOf = null;
32
+ for (const id of this.itemIds) {
33
+ const old = arrangement.groupOf(id);
34
+ if (!old) continue;
35
+ locked ||= arrangement.locked.has(old.id);
36
+ if (old.pinnedToBack) kindOf = old;
37
+ arrangement.locked.delete(old.id);
38
+ arrangement.groups.delete(old.id);
39
+ }
40
+ const group = kindOf
41
+ ? new kindOf.constructor({ id: this.groupId, name: this.name || kindOf.name, memberIds: members })
42
+ : new ItemGroup({ id: this.groupId, name: this.name, memberIds: members });
43
+ arrangement.groups.set(this.groupId, group);
44
+ if (locked) arrangement.locked.add(this.groupId);
45
+ }
46
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ItemGroup — items on a view grouped logically: they move as one. It draws
3
+ * nothing of its own (not a container); a dashed outline shows it while one of
4
+ * its members is selected.
5
+ *
6
+ * A kind of group is a subclass (BackgroundGroup: pinned behind everything);
7
+ * each names its `kind`, which its JSON carries, and registers itself so
8
+ * `ItemGroup.fromJSON` makes the right class.
9
+ */
10
+ export class ItemGroup {
11
+ /** The kind of group, as its JSON names it. */
12
+ static kind = 'group';
13
+
14
+ /** Group classes by kind (see register). */
15
+ static TYPES = new Map();
16
+
17
+ /** Make `GroupClass` the class for its `kind` when read from JSON. */
18
+ static register(GroupClass) {
19
+ ItemGroup.TYPES.set(GroupClass.kind, GroupClass);
20
+ }
21
+
22
+ /**
23
+ * @param {Object} spec
24
+ * @param {string} spec.id
25
+ * @param {Iterable<string>} spec.memberIds - Ids of the items in the group
26
+ * @param {string} [spec.name]
27
+ */
28
+ constructor({ id, memberIds, name = '' }) {
29
+ if (!id) throw new TypeError('ItemGroup needs an id');
30
+ this.id = id;
31
+ this.name = name;
32
+ /** @type {Set<string>} */
33
+ this.memberIds = new Set(memberIds);
34
+ }
35
+
36
+ /** Whether its members stay behind every other item (a BackgroundGroup's do). */
37
+ get pinnedToBack() {
38
+ return false;
39
+ }
40
+
41
+ has(itemId) {
42
+ return this.memberIds.has(itemId);
43
+ }
44
+
45
+ /** The same kind of group, with other members (a copied view's, say). */
46
+ withMembers(memberIds) {
47
+ return new this.constructor({ id: this.id, name: this.name, memberIds });
48
+ }
49
+
50
+ toJSON() {
51
+ const kind = this.constructor.kind;
52
+ return { id: this.id, ...(kind !== ItemGroup.kind && { kind }), ...(this.name && { name: this.name }), memberIds: [...this.memberIds] };
53
+ }
54
+
55
+ /** The group its JSON describes, of the class registered for its `kind`. */
56
+ static fromJSON(data) {
57
+ const GroupClass = ItemGroup.TYPES.get(data.kind) ?? ItemGroup;
58
+ return new GroupClass(data);
59
+ }
60
+ }
61
+
62
+ ItemGroup.register(ItemGroup);
@@ -0,0 +1,32 @@
1
+ import { ArrangementCommand } from './ArrangementCommand.js';
2
+
3
+ /**
4
+ * LockCommand — fix items in place, or free them. An item in a group locks or
5
+ * frees its whole group. Freeing also frees any member locked on its own, so
6
+ * after "Unlock" the group moves.
7
+ */
8
+ export class LockCommand extends ArrangementCommand {
9
+ /**
10
+ * @param {Arrangement} arrangement
11
+ * @param {Iterable<string>} itemIds
12
+ * @param {boolean} locked - true to fix in place, false to free
13
+ */
14
+ constructor(arrangement, itemIds, locked) {
15
+ super(arrangement, locked ? 'Lock' : 'Unlock');
16
+ this.itemIds = [...itemIds];
17
+ this.lockedValue = !!locked;
18
+ }
19
+
20
+ apply() {
21
+ const arrangement = this.arrangement;
22
+ for (const id of this.itemIds) {
23
+ const target = arrangement.lockTargetOf(id);
24
+ if (this.lockedValue) {
25
+ arrangement.locked.add(target);
26
+ } else {
27
+ arrangement.locked.delete(target);
28
+ for (const member of arrangement.movingWith(id)) arrangement.locked.delete(member);
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,27 @@
1
+ import { ArrangementCommand } from './ArrangementCommand.js';
2
+
3
+ /**
4
+ * UngroupCommand — dissolve the group an item is in: its members move on
5
+ * their own again. A locked group's lock passes to each member, so nothing
6
+ * that was fixed comes loose.
7
+ */
8
+ export class UngroupCommand extends ArrangementCommand {
9
+ /**
10
+ * @param {Arrangement} arrangement
11
+ * @param {string} itemId - A member of the group (or the group's id)
12
+ */
13
+ constructor(arrangement, itemId) {
14
+ super(arrangement, 'Ungroup');
15
+ this.itemId = itemId;
16
+ }
17
+
18
+ apply() {
19
+ const arrangement = this.arrangement;
20
+ const group = arrangement.groups.get(this.itemId) ?? arrangement.groupOf(this.itemId);
21
+ if (!group) return;
22
+ if (arrangement.locked.delete(group.id)) {
23
+ for (const id of group.memberIds) arrangement.locked.add(id);
24
+ }
25
+ arrangement.groups.delete(group.id);
26
+ }
27
+ }