@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.
- package/LICENSE +21 -0
- package/README.md +203 -2
- package/REFERENCE.md +2198 -0
- package/dist/renderengine-workspace.umd.js +46905 -0
- package/dist/renderengine.umd.js +42223 -0
- package/examples/archimate.html +66 -0
- package/examples/diagram-editor.html +51 -0
- package/package.json +65 -4
- package/src/BaseRenderer.js +57 -0
- package/src/CanvasRenderer.js +194 -0
- package/src/Mat4.js +111 -0
- package/src/OrbitCamera.js +57 -0
- package/src/RendererFactory.js +50 -0
- package/src/SVGRenderer.js +439 -0
- package/src/archimate.js +723 -0
- package/src/archimateArchiFormat.js +1693 -0
- package/src/archimateArchiTypes.js +72 -0
- package/src/archimateArchive.js +140 -0
- package/src/archimateCSV.js +127 -0
- package/src/archimateDrawio.js +182 -0
- package/src/archimateExchangeFormat.js +546 -0
- package/src/archimateRelationshipTable.js +93 -0
- package/src/archimateSpecializations.js +161 -0
- package/src/chartCatalog.js +589 -0
- package/src/charting/ArchimateDiagramEditor.js +1624 -0
- package/src/charting/ArchimateSpecializationSelector.js +134 -0
- package/src/charting/Axis.js +68 -0
- package/src/charting/CameraSeeder.js +30 -0
- package/src/charting/CatalogDialog.js +92 -0
- package/src/charting/Chart.js +37 -0
- package/src/charting/Chart3D.js +99 -0
- package/src/charting/ChartBox.js +80 -0
- package/src/charting/ChartData.js +27 -0
- package/src/charting/ChartRegistry.js +76 -0
- package/src/charting/CheckboxTreeSelector.js +304 -0
- package/src/charting/ColorField.js +107 -0
- package/src/charting/ColorPalette.js +88 -0
- package/src/charting/CommandHistory.js +176 -0
- package/src/charting/DataFilter.js +52 -0
- package/src/charting/Diagram.js +36 -0
- package/src/charting/Diagram3D.js +29 -0
- package/src/charting/DiagramClipboard.js +31 -0
- package/src/charting/DiagramEditor.js +3330 -0
- package/src/charting/DiagramEditorCommand.js +110 -0
- package/src/charting/DiagramEditorCommands.js +237 -0
- package/src/charting/DiagramEditorEdgeCommands.js +142 -0
- package/src/charting/DiagramEditorState.js +98 -0
- package/src/charting/DiagramRegistry.js +86 -0
- package/src/charting/DiagramTypeRegistry.js +326 -0
- package/src/charting/DiagramViewPropertiesDialog.js +46 -0
- package/src/charting/Edge.js +113 -0
- package/src/charting/ErrorBars.js +37 -0
- package/src/charting/FilterSystem.js +285 -0
- package/src/charting/FindReplaceDialog.js +139 -0
- package/src/charting/FormDialog.js +385 -0
- package/src/charting/Gauge.js +58 -0
- package/src/charting/Hierarchy.js +175 -0
- package/src/charting/HintPanel.js +86 -0
- package/src/charting/ImageSelector.js +148 -0
- package/src/charting/InteractionManager.js +725 -0
- package/src/charting/Legend.js +58 -0
- package/src/charting/MenuBar.js +62 -0
- package/src/charting/ModelFileFormat.js +115 -0
- package/src/charting/OrbitControls.js +77 -0
- package/src/charting/Palette.js +119 -0
- package/src/charting/PopupMenu.js +117 -0
- package/src/charting/PropertiesPanel.js +155 -0
- package/src/charting/PropertyListEditor.js +96 -0
- package/src/charting/PropertyLog.js +92 -0
- package/src/charting/SettingsCascade.js +93 -0
- package/src/charting/SettingsDialog.js +53 -0
- package/src/charting/SettingsManager.js +179 -0
- package/src/charting/SettingsViewPropertiesDialog.js +58 -0
- package/src/charting/ShapePaths.js +27 -0
- package/src/charting/Statistics.js +134 -0
- package/src/charting/TemplateCatalog.js +59 -0
- package/src/charting/TemplateLibrary.js +103 -0
- package/src/charting/TextStyle.js +168 -0
- package/src/charting/ViewFit.js +55 -0
- package/src/charting/ViewMenu.js +70 -0
- package/src/charting/ViewPropertiesDialog.js +77 -0
- package/src/charting/ViewTabStrip.js +81 -0
- package/src/charting/archimate/ArchiFileFormat.js +32 -0
- package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
- package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
- package/src/charting/archimate/ArchimateEdge.js +137 -0
- package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
- package/src/charting/archimate/ArchimatePalette.js +102 -0
- package/src/charting/archimate/CsvImportDialog.js +105 -0
- package/src/charting/archimate/CustomViewpoints.js +74 -0
- package/src/charting/archimate/DerivedEdge.js +29 -0
- package/src/charting/archimate/DrawioFileFormat.js +24 -0
- package/src/charting/archimate/ElementFilterRule.js +21 -0
- package/src/charting/archimate/ExchangeFileFormat.js +28 -0
- package/src/charting/archimate/ViewGroupTemplate.js +137 -0
- package/src/charting/archimate/ViewLineEdge.js +84 -0
- package/src/charting/archimate/ViewpointRule.js +45 -0
- package/src/charting/archimate/archimateFileFormats.js +12 -0
- package/src/charting/archimate/archimateNames.js +5 -0
- package/src/charting/archimate/csvMapping.js +122 -0
- package/src/charting/archimate/elementMenuItems.js +32 -0
- package/src/charting/archimate/elementProperties.js +146 -0
- package/src/charting/archimate/elementTypeChoices.js +7 -0
- package/src/charting/archimate/elementTypeGroups.js +19 -0
- package/src/charting/archimate/index.js +17 -0
- package/src/charting/archimate/specializationCatalogDialog.js +64 -0
- package/src/charting/archimate/typeGlyph.js +29 -0
- package/src/charting/arrangement/Arrangement.js +112 -0
- package/src/charting/arrangement/ArrangementCommand.js +29 -0
- package/src/charting/arrangement/BackgroundCommand.js +41 -0
- package/src/charting/arrangement/BackgroundGroup.js +18 -0
- package/src/charting/arrangement/GroupCommand.js +46 -0
- package/src/charting/arrangement/ItemGroup.js +62 -0
- package/src/charting/arrangement/LockCommand.js +32 -0
- package/src/charting/arrangement/UngroupCommand.js +27 -0
- package/src/charting/arrangement/alignment.js +88 -0
- package/src/charting/arrangement/arrangeMenuItems.js +25 -0
- package/src/charting/arrangement/index.js +11 -0
- package/src/charting/arrangement/layouts.js +233 -0
- package/src/charting/canvas/ArchiHint.js +78 -0
- package/src/charting/canvas/CanvasBoxKind.js +39 -0
- package/src/charting/canvas/CanvasPalette.js +49 -0
- package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
- package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
- package/src/charting/canvas/EditHintCommand.js +28 -0
- package/src/charting/canvas/canvasBoxKinds.js +27 -0
- package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
- package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
- package/src/charting/canvas/diagramBoxKinds.js +12 -0
- package/src/charting/canvas/hintMenuItems.js +49 -0
- package/src/charting/charts/ArcGauge.js +55 -0
- package/src/charting/charts/AreaChart.js +71 -0
- package/src/charting/charts/BarChart.js +80 -0
- package/src/charting/charts/BarChart3D.js +56 -0
- package/src/charting/charts/BarChart3DOrbit.js +53 -0
- package/src/charting/charts/BarChartBase.js +70 -0
- package/src/charting/charts/BarGauge.js +42 -0
- package/src/charting/charts/BoxPlotChart.js +41 -0
- package/src/charting/charts/BubbleChart.js +99 -0
- package/src/charting/charts/BubbleChart3D.js +78 -0
- package/src/charting/charts/BulletGauge.js +87 -0
- package/src/charting/charts/CalendarHeatmapChart.js +204 -0
- package/src/charting/charts/CandlestickChart.js +54 -0
- package/src/charting/charts/ChordDiagram.js +130 -0
- package/src/charting/charts/DensityChart.js +73 -0
- package/src/charting/charts/DialGauge.js +65 -0
- package/src/charting/charts/DonutChart.js +15 -0
- package/src/charting/charts/FunnelChart.js +47 -0
- package/src/charting/charts/GanttChart.js +201 -0
- package/src/charting/charts/GaugeChart.js +175 -0
- package/src/charting/charts/GeoMapChart.js +146 -0
- package/src/charting/charts/GroupedBarChart.js +88 -0
- package/src/charting/charts/GroupedDistributionChart.js +70 -0
- package/src/charting/charts/HeatmapChart.js +80 -0
- package/src/charting/charts/HierarchyChart.js +39 -0
- package/src/charting/charts/HistogramChart.js +45 -0
- package/src/charting/charts/KpiTile.js +72 -0
- package/src/charting/charts/LagPlotChart.js +41 -0
- package/src/charting/charts/LineChart.js +124 -0
- package/src/charting/charts/MultiRingGauge.js +54 -0
- package/src/charting/charts/OutlineChart.js +95 -0
- package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
- package/src/charting/charts/PieChart.js +56 -0
- package/src/charting/charts/PipeChart.js +88 -0
- package/src/charting/charts/PopulationPyramidChart.js +106 -0
- package/src/charting/charts/QQPlotChart.js +64 -0
- package/src/charting/charts/RadarChart.js +76 -0
- package/src/charting/charts/RadialBarChart.js +96 -0
- package/src/charting/charts/RingGauge.js +23 -0
- package/src/charting/charts/SankeyDiagram.js +174 -0
- package/src/charting/charts/ScatterChart.js +104 -0
- package/src/charting/charts/StackedAreaChart.js +15 -0
- package/src/charting/charts/StackedBarChart.js +33 -0
- package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
- package/src/charting/charts/StreamGraphChart.js +131 -0
- package/src/charting/charts/SunburstChart.js +57 -0
- package/src/charting/charts/ThermometerGauge.js +43 -0
- package/src/charting/charts/TreemapChart.js +54 -0
- package/src/charting/charts/ViolinChart.js +37 -0
- package/src/charting/charts/WaterfallChart.js +66 -0
- package/src/charting/charts/WordCloudChart.js +104 -0
- package/src/charting/diagramModel/AddViewCommand.js +33 -0
- package/src/charting/diagramModel/DiagramModel.js +39 -0
- package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
- package/src/charting/diagramModel/DiagramView.js +50 -0
- package/src/charting/diagramModel/ModelHistory.js +43 -0
- package/src/charting/diagramModel/ModelReport.js +153 -0
- package/src/charting/diagramModel/ModelSearch.js +223 -0
- package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
- package/src/charting/diagramModel/RenameViewCommand.js +21 -0
- package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
- package/src/charting/diagramModel/ViewSetChecker.js +34 -0
- package/src/charting/diagramModel/ViewSetModel.js +243 -0
- package/src/charting/diagramModel/index.js +6 -0
- package/src/charting/diagramModel/nameTransforms.js +29 -0
- package/src/charting/diagrams/ArchimateCommands.js +141 -0
- package/src/charting/diagrams/ArchimateDiagram.js +263 -0
- package/src/charting/diagrams/ArchimateModel.js +1155 -0
- package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
- package/src/charting/diagrams/ArchimateModelReport.js +128 -0
- package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
- package/src/charting/diagrams/ArchimateValidator.js +357 -0
- package/src/charting/diagrams/CanvasView.js +112 -0
- package/src/charting/diagrams/ContextMenu.js +37 -0
- package/src/charting/diagrams/DataModelDiagram.js +86 -0
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
- package/src/charting/diagrams/DerivedRelationships.js +102 -0
- package/src/charting/diagrams/EbnfDiagram.js +39 -0
- package/src/charting/diagrams/EdgeGeometry.js +553 -0
- package/src/charting/diagrams/EditViewItemCommand.js +128 -0
- package/src/charting/diagrams/ElementInstance.js +157 -0
- package/src/charting/diagrams/GraphDiagram.js +1340 -0
- package/src/charting/diagrams/GraphDiagram3D.js +152 -0
- package/src/charting/diagrams/GraphMetrics.js +81 -0
- package/src/charting/diagrams/GridOverlay.js +137 -0
- package/src/charting/diagrams/ImportRowsCommand.js +62 -0
- package/src/charting/diagrams/LabelHelper.js +108 -0
- package/src/charting/diagrams/MergeElementsCommand.js +101 -0
- package/src/charting/diagrams/NestInstanceCommand.js +34 -0
- package/src/charting/diagrams/NodeGeometry.js +158 -0
- package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
- package/src/charting/diagrams/RadialLayout.js +101 -0
- package/src/charting/diagrams/RelationshipInstance.js +93 -0
- package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
- package/src/charting/diagrams/RemoveLineCommand.js +27 -0
- package/src/charting/diagrams/ShowElementCommand.js +43 -0
- package/src/charting/diagrams/SvgCoordinate.js +17 -0
- package/src/charting/diagrams/SvgZoom.js +127 -0
- package/src/charting/diagrams/Tooltip.js +62 -0
- package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
- package/src/charting/diagrams/ViewObjectInstance.js +56 -0
- package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
- package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
- package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
- package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
- package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
- package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
- package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
- package/src/charting/diagrams/commands/GraphCommand.js +65 -0
- package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
- package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
- package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
- package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
- package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
- package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
- package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
- package/src/charting/diagrams/commands/index.js +17 -0
- package/src/charting/diagrams/duplicates.js +49 -0
- package/src/charting/diagrams/nesting.js +30 -0
- package/src/charting/diagrams/roadmap.js +77 -0
- package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
- package/src/charting/edgeMarkers/CircleMarker.js +13 -0
- package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
- package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
- package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
- package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
- package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
- package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
- package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
- package/src/charting/edgeMarkers/index.js +27 -0
- package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
- package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
- package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
- package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
- package/src/charting/edgeStyle/index.js +4 -0
- package/src/charting/emphasis/EmphasisRule.js +42 -0
- package/src/charting/emphasis/HighlightRule.js +24 -0
- package/src/charting/gauges/ArcTrack.js +51 -0
- package/src/charting/gauges/GaugeAnimation.js +51 -0
- package/src/charting/gauges/GaugeBands.js +48 -0
- package/src/charting/gauges/GaugeScale.js +87 -0
- package/src/charting/gauges/GaugeTrack.js +44 -0
- package/src/charting/gauges/GaugeValue.js +61 -0
- package/src/charting/gauges/HorizontalTrack.js +14 -0
- package/src/charting/gauges/LinearTrack.js +29 -0
- package/src/charting/gauges/Sparkline.js +42 -0
- package/src/charting/gauges/VerticalTrack.js +17 -0
- package/src/charting/glyphs/ArrowGlyph.js +21 -0
- package/src/charting/glyphs/BatteryGlyph.js +18 -0
- package/src/charting/glyphs/ChevronGlyph.js +18 -0
- package/src/charting/glyphs/CircleGlyph.js +15 -0
- package/src/charting/glyphs/CloudGlyph.js +19 -0
- package/src/charting/glyphs/ComponentGlyph.js +18 -0
- package/src/charting/glyphs/ConstraintGlyph.js +24 -0
- package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
- package/src/charting/glyphs/CubeGlyph.js +19 -0
- package/src/charting/glyphs/CylinderGlyph.js +19 -0
- package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
- package/src/charting/glyphs/DeviceGlyph.js +17 -0
- package/src/charting/glyphs/DiamondGlyph.js +17 -0
- package/src/charting/glyphs/DocumentGlyph.js +17 -0
- package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
- package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
- package/src/charting/glyphs/EllipseGlyph.js +18 -0
- package/src/charting/glyphs/FactoryGlyph.js +20 -0
- package/src/charting/glyphs/FlagGlyph.js +16 -0
- package/src/charting/glyphs/GapCircleGlyph.js +17 -0
- package/src/charting/glyphs/GearGlyph.js +37 -0
- package/src/charting/glyphs/Glyph.js +98 -0
- package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
- package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
- package/src/charting/glyphs/HexagonGlyph.js +28 -0
- package/src/charting/glyphs/IconGlyph.js +22 -0
- package/src/charting/glyphs/ImageGlyph.js +16 -0
- package/src/charting/glyphs/JunctionGlyph.js +17 -0
- package/src/charting/glyphs/LollipopGlyph.js +22 -0
- package/src/charting/glyphs/MagnifierGlyph.js +17 -0
- package/src/charting/glyphs/NoteGlyph.js +33 -0
- package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
- package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
- package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
- package/src/charting/glyphs/PersonGlyph.js +23 -0
- package/src/charting/glyphs/PillGlyph.js +23 -0
- package/src/charting/glyphs/PinGlyph.js +18 -0
- package/src/charting/glyphs/PrincipleGlyph.js +23 -0
- package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
- package/src/charting/glyphs/RectGlyph.js +15 -0
- package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
- package/src/charting/glyphs/StackGlyph.js +14 -0
- package/src/charting/glyphs/StepsGlyph.js +20 -0
- package/src/charting/glyphs/StickFigureGlyph.js +32 -0
- package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
- package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
- package/src/charting/glyphs/TargetGlyph.js +23 -0
- package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
- package/src/charting/glyphs/WheelGlyph.js +28 -0
- package/src/charting/glyphs/drawGlyph.js +28 -0
- package/src/charting/glyphs/glyphSvg.js +55 -0
- package/src/charting/glyphs/index.js +109 -0
- package/src/charting/modelTree/AnalysisPanel.js +159 -0
- package/src/charting/modelTree/DiagramTabs.js +217 -0
- package/src/charting/modelTree/ModelTree.js +164 -0
- package/src/charting/modelTree/ModelTreePanel.js +914 -0
- package/src/charting/modelTree/TreeBuilder.js +238 -0
- package/src/charting/modelTree/TreeModeRegistry.js +51 -0
- package/src/charting/modelTree/TreeViewMode.js +110 -0
- package/src/charting/modelTree/buildFilterTrees.js +138 -0
- package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
- package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
- package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
- package/src/charting/modelTree/treeLayers.js +11 -0
- package/src/charting/report/reportHtml.js +82 -0
- package/src/charting/report/reportViewer.js +118 -0
- package/src/charting/shapes/CircleShape.js +19 -0
- package/src/charting/shapes/PathShape.js +17 -0
- package/src/charting/shapes/RectShape.js +20 -0
- package/src/charting/shapes/Shape.js +20 -0
- package/src/charting/shapes/ShapeFactory.js +23 -0
- package/src/charting/storage/LocalJsonStore.js +43 -0
- package/src/charting/templates/ActorTemplate.js +36 -0
- package/src/charting/templates/BoxTemplate.js +27 -0
- package/src/charting/templates/CircleTemplate.js +18 -0
- package/src/charting/templates/ClassTemplate.js +20 -0
- package/src/charting/templates/CloudTemplate.js +43 -0
- package/src/charting/templates/ComponentTemplate.js +19 -0
- package/src/charting/templates/CylinderTemplate.js +30 -0
- package/src/charting/templates/DataStoreTemplate.js +16 -0
- package/src/charting/templates/DiamondTemplate.js +10 -0
- package/src/charting/templates/DocumentTemplate.js +32 -0
- package/src/charting/templates/EllipseTemplate.js +15 -0
- package/src/charting/templates/FinalStateTemplate.js +12 -0
- package/src/charting/templates/GlyphTemplate.js +47 -0
- package/src/charting/templates/HexagonTemplate.js +17 -0
- package/src/charting/templates/LifelineTemplate.js +20 -0
- package/src/charting/templates/ManualInputTemplate.js +12 -0
- package/src/charting/templates/NoteTemplate.js +23 -0
- package/src/charting/templates/OctagonTemplate.js +7 -0
- package/src/charting/templates/PackageTemplate.js +25 -0
- package/src/charting/templates/ParallelogramTemplate.js +11 -0
- package/src/charting/templates/PentagonTemplate.js +5 -0
- package/src/charting/templates/PolygonTemplate.js +18 -0
- package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
- package/src/charting/templates/RectangleTemplate.js +28 -0
- package/src/charting/templates/RegularPolygonTemplate.js +21 -0
- package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
- package/src/charting/templates/StadiumTemplate.js +8 -0
- package/src/charting/templates/StarTemplate.js +17 -0
- package/src/charting/templates/SwimlaneTemplate.js +18 -0
- package/src/charting/templates/Template.js +208 -0
- package/src/charting/templates/TrapezoidTemplate.js +11 -0
- package/src/charting/templates/TriangleTemplate.js +12 -0
- package/src/charting/templates/index.js +31 -0
- package/src/charting/templates/outline.js +59 -0
- package/src/charting/templates/svg.js +19 -0
- package/src/charting/textToShapes.js +61 -0
- package/src/charting/toolbar/ToolbarButton.js +38 -0
- package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
- package/src/charting/toolbar/ToolbarItem.js +19 -0
- package/src/charting/toolbar/ToolbarMenu.js +36 -0
- package/src/charting/toolbar/ToolbarSelect.js +38 -0
- package/src/charting/toolbar/ToolbarSeparator.js +7 -0
- package/src/charting/toolbar/ToolbarText.js +22 -0
- package/src/charting/toolbar/index.js +8 -0
- package/src/charting/toolbar/pickFile.js +14 -0
- package/src/charting/viewDecorations.js +85 -0
- package/src/charting/zOrder.js +57 -0
- package/src/csvTable.js +61 -0
- package/src/datamodel.js +122 -0
- package/src/datawindow/BoundedWindow.js +36 -0
- package/src/datawindow/FlatDataWindow.js +34 -0
- package/src/datawindow/GraphDataWindow.js +40 -0
- package/src/datawindow/GroupedSampleDataWindow.js +16 -0
- package/src/datawindow/SeriesDataWindow.js +42 -0
- package/src/datawindow/index.js +31 -0
- package/src/diagramCatalog.js +30 -0
- package/src/ebnfDiagram.js +57 -0
- package/src/ebnfParser.js +129 -0
- package/src/exportImage.js +233 -0
- package/src/index.js +2636 -0
- package/src/itIcons.js +84 -0
- package/src/kernelExpr.js +243 -0
- package/src/propertiesDialog.js +463 -0
- package/src/railroadDiagram.js +571 -0
- package/src/treeModeCatalog.js +16 -0
- package/src/workspace/ContextBus.js +79 -0
- package/src/workspace/EditorShell.js +67 -0
- package/src/workspace/Part.js +163 -0
- package/src/workspace/PartFactory.js +49 -0
- package/src/workspace/PartRegistry.js +86 -0
- package/src/workspace/Workspace.js +321 -0
- package/src/workspace/archimateServices.js +33 -0
- package/src/workspace/dom.js +120 -0
- package/src/workspace/index.js +75 -0
- package/src/workspace/layout/GridNode.js +280 -0
- package/src/workspace/layout/LayoutNode.js +89 -0
- package/src/workspace/layout/PartNode.js +77 -0
- package/src/workspace/layout/SplitNode.js +114 -0
- package/src/workspace/layout/TabsNode.js +191 -0
- package/src/workspace/layout/index.js +24 -0
- package/src/workspace/parts/AdapterPart.js +33 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
- package/src/workspace/parts/ArchimateEditorPart.js +79 -0
- package/src/workspace/parts/ChartPart.js +115 -0
- package/src/workspace/parts/ContentPart.js +34 -0
- package/src/workspace/parts/DetailPart.js +46 -0
- package/src/workspace/parts/DiagramEditorPart.js +135 -0
- package/src/workspace/parts/EditorPart.js +388 -0
- package/src/workspace/parts/HtmlPart.js +25 -0
- package/src/workspace/parts/ListPart.js +57 -0
- package/src/workspace/parts/ModelFile.js +187 -0
- package/src/workspace/parts/ModelsPart.js +135 -0
- package/src/workspace/styles.js +258 -0
- package/src/workspace/themes.js +96 -0
- package/src/workspace/workArea.js +413 -0
- package/src/workspace/workAreaModel.js +197 -0
- package/src/workspace.js +16 -0
- package/src/zip/ZipArchive.js +160 -0
- package/src/zip/crc32.js +25 -0
- package/src/zip/inflate.js +159 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Diagram3D } from '../Diagram3D.js';
|
|
2
|
+
import { OrbitCamera } from '../../OrbitCamera.js';
|
|
3
|
+
import { GraphMetrics } from './GraphMetrics.js';
|
|
4
|
+
import { LabelHelper } from './LabelHelper.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* GraphDiagram3D — interactive 3D node/edge graph viewed through the orbit camera.
|
|
8
|
+
*/
|
|
9
|
+
export class GraphDiagram3D extends Diagram3D {
|
|
10
|
+
static diagramType = 'graph3d';
|
|
11
|
+
|
|
12
|
+
constructor(renderer, nodes, edges, options = {}, camera = null, engine = null) {
|
|
13
|
+
super(renderer, { nodes, edges }, options);
|
|
14
|
+
this.camera = camera;
|
|
15
|
+
this.engine = engine;
|
|
16
|
+
this._graph3DPos = null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
render() {
|
|
20
|
+
if (!this.renderer || !this.renderer.supportsSceneGraph) {
|
|
21
|
+
console.warn('3D graph diagram is only supported in SVG renderer.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
super.render();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_render() {
|
|
28
|
+
const { nodes, edges } = this.data;
|
|
29
|
+
const options = this.options;
|
|
30
|
+
const renderer = this.renderer;
|
|
31
|
+
|
|
32
|
+
if (!renderer || !renderer.supportsSceneGraph) {
|
|
33
|
+
console.warn('3D graph diagram is only supported in SVG renderer.');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
onNodeClick, nodeRadius = 8,
|
|
39
|
+
colors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452'],
|
|
40
|
+
edgeColor: defaultEdgeColor = '#bdc3c7',
|
|
41
|
+
initialTheta = -0.6, initialPhi = 0.35, initialDistance = 2.2,
|
|
42
|
+
sizeBy, minRadius = nodeRadius, maxRadius = nodeRadius * 2.5, sizeScale = 'linear',
|
|
43
|
+
minEdgeWidth = 1.2, maxEdgeWidth = minEdgeWidth * 4, edgeWidthScale = 'linear',
|
|
44
|
+
} = options;
|
|
45
|
+
|
|
46
|
+
const degreeMap = sizeBy === 'degree' ? GraphMetrics.computeNodeDegrees(nodes, edges) : null;
|
|
47
|
+
const sizeDomain = GraphMetrics.computeSizeDomain(nodes, { sizeBy, degreeMap });
|
|
48
|
+
const sizeOptions = { minRadius, maxRadius, sizeScale, sizeBy, degreeMap };
|
|
49
|
+
const edgeWidthDomain = GraphMetrics.computeEdgeWidthDomain(edges);
|
|
50
|
+
const edgeWidthOptions = { minEdgeWidth, maxEdgeWidth, widthScale: edgeWidthScale };
|
|
51
|
+
|
|
52
|
+
this.seedCamera({ theta: initialTheta, phi: initialPhi, distance: initialDistance });
|
|
53
|
+
|
|
54
|
+
// Layout: simulate once per distinct node set, not on every camera-only redraw.
|
|
55
|
+
if (!this._graph3DPos || !nodes.every(n => this._graph3DPos.has(n.id))) {
|
|
56
|
+
this._graph3DPos = GraphDiagram3D.layoutForce3D(nodes, edges);
|
|
57
|
+
}
|
|
58
|
+
const pos = this._graph3DPos;
|
|
59
|
+
|
|
60
|
+
const W = renderer.width, H = renderer.height;
|
|
61
|
+
const cx = W / 2, cy = H / 2;
|
|
62
|
+
const pixelRadius = Math.min(W, H) / 2 - 20;
|
|
63
|
+
const camera = new OrbitCamera(this.camera);
|
|
64
|
+
const toScreen = (p) => {
|
|
65
|
+
const proj = camera.project(p, 1);
|
|
66
|
+
return { x: cx + proj.sx * pixelRadius, y: cy - proj.sy * pixelRadius, depth: proj.depth, scale: proj.scale };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const groups = new Map();
|
|
70
|
+
nodes.forEach(n => { if (n.group && !groups.has(n.group)) groups.set(n.group, colors[groups.size % colors.length]); });
|
|
71
|
+
|
|
72
|
+
const nodeItems = nodes.map(n => {
|
|
73
|
+
const p = pos.get(n.id);
|
|
74
|
+
const screen = toScreen(p);
|
|
75
|
+
const color = n.color || (n.group ? groups.get(n.group) : (options.nodeColor || '#4f8ef7'));
|
|
76
|
+
return { kind: 'node', node: n, screen, color, depth: screen.depth };
|
|
77
|
+
});
|
|
78
|
+
const edgeItems = edges.map(e => {
|
|
79
|
+
const a = pos.get(e.source), b = pos.get(e.target);
|
|
80
|
+
if (!a || !b) return null;
|
|
81
|
+
const sa = toScreen(a), sb = toScreen(b);
|
|
82
|
+
return { kind: 'edge', edge: e, sa, sb, depth: (sa.depth + sb.depth) / 2 };
|
|
83
|
+
}).filter(Boolean);
|
|
84
|
+
|
|
85
|
+
const scene = [...edgeItems, ...nodeItems].sort((a, b) => b.depth - a.depth);
|
|
86
|
+
const nodeEls = [];
|
|
87
|
+
for (const item of scene) {
|
|
88
|
+
if (item.kind === 'edge') {
|
|
89
|
+
const edgeWidth = GraphMetrics.effectiveEdgeWidth(item.edge, 1.2, edgeWidthDomain, edgeWidthOptions);
|
|
90
|
+
renderer.path(`M${item.sa.x},${item.sa.y} L${item.sb.x},${item.sb.y}`, 'none',
|
|
91
|
+
{ color: item.edge.color || defaultEdgeColor, width: edgeWidth });
|
|
92
|
+
} else {
|
|
93
|
+
const { node, screen, color } = item;
|
|
94
|
+
const baseR = GraphMetrics.effectiveNodeRadius(node, nodeRadius, sizeDomain, sizeOptions);
|
|
95
|
+
const r = Math.max(2, baseR * screen.scale);
|
|
96
|
+
const label3D = LabelHelper.resolveNodeLabel(node) || node.id;
|
|
97
|
+
const g = renderer.group({ transform: `translate(${screen.x},${screen.y})`, nodeId: node.id, tooltip: label3D });
|
|
98
|
+
g.appendChild(renderer.circle(0, 0, r, color, { color: '#fff', width: 1.5 }));
|
|
99
|
+
g.appendChild(renderer.text(label3D, 0, r + 9, { fill: '#333', textAnchor: 'middle', fontSize: '9px', 'pointer-events': 'none' }));
|
|
100
|
+
if (onNodeClick) g.addEventListener('click', () => onNodeClick(node));
|
|
101
|
+
nodeEls.push(g);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
this._graph3D = { nodes, edges, pos, nodeEls };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static layoutForce3D(nodes, edges, { iterations = 150 } = {}) {
|
|
108
|
+
const fixed = new Set(nodes.filter(n => n.x != null || n.y != null || n.z != null).map(n => n.id));
|
|
109
|
+
const pos = new Map(nodes.map(n => [n.id, {
|
|
110
|
+
x: n.x ?? (Math.random() * 2 - 1),
|
|
111
|
+
y: n.y ?? (Math.random() * 2 - 1),
|
|
112
|
+
z: n.z ?? (Math.random() * 2 - 1),
|
|
113
|
+
vx: 0, vy: 0, vz: 0,
|
|
114
|
+
}]));
|
|
115
|
+
const K = 1 / Math.cbrt(Math.max(nodes.length, 1));
|
|
116
|
+
let temp = 0.2;
|
|
117
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
118
|
+
nodes.forEach(n => { if (!fixed.has(n.id)) { const p = pos.get(n.id); p.vx = 0; p.vy = 0; p.vz = 0; } });
|
|
119
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
120
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
121
|
+
const a = pos.get(nodes[i].id), b = pos.get(nodes[j].id);
|
|
122
|
+
const dx = b.x - a.x, dy = b.y - a.y, dz = b.z - a.z;
|
|
123
|
+
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz) || 0.01;
|
|
124
|
+
const f = (K * K) / dist;
|
|
125
|
+
const ux = dx / dist, uy = dy / dist, uz = dz / dist;
|
|
126
|
+
a.vx -= ux * f; a.vy -= uy * f; a.vz -= uz * f;
|
|
127
|
+
b.vx += ux * f; b.vy += uy * f; b.vz += uz * f;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
edges.forEach(e => {
|
|
131
|
+
const a = pos.get(e.source), b = pos.get(e.target);
|
|
132
|
+
if (!a || !b) return;
|
|
133
|
+
const dx = b.x - a.x, dy = b.y - a.y, dz = b.z - a.z;
|
|
134
|
+
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz) || 0.01;
|
|
135
|
+
const f = (dist * dist) / (K * 1.5);
|
|
136
|
+
const ux = dx / dist, uy = dy / dist, uz = dz / dist;
|
|
137
|
+
a.vx += ux * f; a.vy += uy * f; a.vz += uz * f;
|
|
138
|
+
b.vx -= ux * f; b.vy -= uy * f; b.vz -= uz * f;
|
|
139
|
+
});
|
|
140
|
+
nodes.forEach(n => {
|
|
141
|
+
if (fixed.has(n.id)) return;
|
|
142
|
+
const p = pos.get(n.id);
|
|
143
|
+
p.vx += -p.x * 0.02; p.vy += -p.y * 0.02; p.vz += -p.z * 0.02; // pull toward origin — no pixel container to center within, in 3D
|
|
144
|
+
const mag = Math.sqrt(p.vx * p.vx + p.vy * p.vy + p.vz * p.vz) || 1;
|
|
145
|
+
const dt = Math.min(mag, temp) / mag;
|
|
146
|
+
p.x += p.vx * dt; p.y += p.vy * dt; p.z += p.vz * dt;
|
|
147
|
+
});
|
|
148
|
+
temp *= 0.97;
|
|
149
|
+
}
|
|
150
|
+
return pos;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphMetrics — pure, stateless helpers for graph-diagram sizing and scaling.
|
|
3
|
+
*
|
|
4
|
+
* These functions used to live on RenderEngine; they are collected here so
|
|
5
|
+
* GraphDiagram, GraphDiagram3D, and any future diagram can use them without
|
|
6
|
+
* going through the engine façade.
|
|
7
|
+
*/
|
|
8
|
+
export class GraphMetrics {
|
|
9
|
+
/** Pure — no DOM/renderer access. Map<nodeId, connectionCount> — how many
|
|
10
|
+
* edge ENDPOINTS touch each node (a self-loop, where source===target,
|
|
11
|
+
* counts twice — it really does attach to that node twice). Nodes with
|
|
12
|
+
* no edges at all still get an entry (0), so a domain computed over this
|
|
13
|
+
* always includes them rather than treating "no data" as "not sized". */
|
|
14
|
+
static computeNodeDegrees(nodes, edges) {
|
|
15
|
+
const degrees = new Map(nodes.map(n => [n.id, 0]));
|
|
16
|
+
for (const e of edges) {
|
|
17
|
+
if (degrees.has(e.source)) degrees.set(e.source, degrees.get(e.source) + 1);
|
|
18
|
+
if (degrees.has(e.target)) degrees.set(e.target, degrees.get(e.target) + 1);
|
|
19
|
+
}
|
|
20
|
+
return degrees;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Pure. What a node's own size VALUE is, before it's mapped to a radius —
|
|
24
|
+
* `node.size` (the default), or that node's connection count when
|
|
25
|
+
* `sizeBy: 'degree'` is in play (`degreeMap` from computeNodeDegrees). */
|
|
26
|
+
static nodeSizeValue(node, sizeBy, degreeMap) {
|
|
27
|
+
return sizeBy === 'degree' ? (degreeMap?.get(node?.id) ?? 0) : node?.size;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Pure — no DOM/renderer access. {min,max} of every node's size VALUE
|
|
31
|
+
* (see nodeSizeValue) across all nodes, or null if none carry a finite
|
|
32
|
+
* one (keeps effectiveNodeRadius's fixed-R behavior when the feature
|
|
33
|
+
* isn't in use at all). `{sizeBy, degreeMap}` switches the value source
|
|
34
|
+
* from `node.size` to connection count — same {min,max} shape either way. */
|
|
35
|
+
static computeSizeDomain(nodes, { sizeBy, degreeMap } = {}) {
|
|
36
|
+
const values = nodes.map(n => GraphMetrics.nodeSizeValue(n, sizeBy, degreeMap)).filter(Number.isFinite);
|
|
37
|
+
if (!values.length) return null;
|
|
38
|
+
return { min: Math.min(...values), max: Math.max(...values) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Pure. Maps a node's size value (see nodeSizeValue) into
|
|
42
|
+
* [minRadius,maxRadius] given a precomputed domain; falls back to R
|
|
43
|
+
* unchanged when this node isn't part of the sizing (no domain, or its
|
|
44
|
+
* value not finite). `node.radius` — set by dragging that node's own
|
|
45
|
+
* resize handle — is a hard per-node override and wins over all of that
|
|
46
|
+
* (sizeBy/domain/plain R alike), the same way an explicit `node.x`/
|
|
47
|
+
* `node.y` already overrides computed layout. */
|
|
48
|
+
static effectiveNodeRadius(node, R, sizeDomain, sizeOptions = {}) {
|
|
49
|
+
if (Number.isFinite(node?.radius)) return node.radius;
|
|
50
|
+
const { minRadius = R, maxRadius = R * 2.5, sizeScale = 'linear', sizeBy, degreeMap } = sizeOptions;
|
|
51
|
+
const value = GraphMetrics.nodeSizeValue(node, sizeBy, degreeMap);
|
|
52
|
+
if (!sizeDomain || !Number.isFinite(value)) return R;
|
|
53
|
+
const { min, max } = sizeDomain;
|
|
54
|
+
if (max === min) return maxRadius;
|
|
55
|
+
let t = (value - min) / (max - min);
|
|
56
|
+
if (sizeScale === 'sqrt') t = Math.sqrt(t);
|
|
57
|
+
return minRadius + t * (maxRadius - minRadius);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Pure. {min,max} of edge.weight across all edges, or null if none carry
|
|
61
|
+
* a finite one — the edge-thickness counterpart of computeSizeDomain. */
|
|
62
|
+
static computeEdgeWidthDomain(edges) {
|
|
63
|
+
const values = edges.map(e => e.weight).filter(Number.isFinite);
|
|
64
|
+
if (!values.length) return null;
|
|
65
|
+
return { min: Math.min(...values), max: Math.max(...values) };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Pure. Maps edge.weight into [minEdgeWidth,maxEdgeWidth] given a
|
|
69
|
+
* precomputed domain; falls back to `defaultWidth` when this edge isn't
|
|
70
|
+
* part of the sizing (no domain, or edge.weight not finite) — the
|
|
71
|
+
* edge-thickness counterpart of effectiveNodeRadius. */
|
|
72
|
+
static effectiveEdgeWidth(edge, defaultWidth, widthDomain, widthOptions = {}) {
|
|
73
|
+
if (!widthDomain || !Number.isFinite(edge?.weight)) return defaultWidth;
|
|
74
|
+
const { minEdgeWidth = defaultWidth, maxEdgeWidth = defaultWidth * 4, widthScale = 'linear' } = widthOptions;
|
|
75
|
+
const { min, max } = widthDomain;
|
|
76
|
+
if (max === min) return maxEdgeWidth;
|
|
77
|
+
let t = (edge.weight - min) / (max - min);
|
|
78
|
+
if (widthScale === 'sqrt') t = Math.sqrt(t);
|
|
79
|
+
return minEdgeWidth + t * (maxEdgeWidth - minEdgeWidth);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GridOverlay — renders a dynamically scaled grid that responds to pan/zoom.
|
|
3
|
+
* Creates a separate SVG layer that redraw whenever the viewBox changes.
|
|
4
|
+
*/
|
|
5
|
+
export class GridOverlay {
|
|
6
|
+
constructor(svgContainer, { gridSize = 20, color = '#e5e5e5', width = 0.5 } = {}) {
|
|
7
|
+
this.svgContainer = svgContainer;
|
|
8
|
+
this.gridSize = gridSize;
|
|
9
|
+
this.color = color;
|
|
10
|
+
this.width = width;
|
|
11
|
+
|
|
12
|
+
// Create overlay SVG
|
|
13
|
+
this.overlayElement = this._createOverlay();
|
|
14
|
+
// Prepend so it renders behind other SVGs
|
|
15
|
+
this.svgContainer.insertBefore(this.overlayElement, this.svgContainer.firstChild);
|
|
16
|
+
|
|
17
|
+
// Find the main SVG and listen for viewBox changes
|
|
18
|
+
this.mainSvg = null;
|
|
19
|
+
this._observeViewBoxChanges();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Create the grid overlay SVG element.
|
|
24
|
+
*/
|
|
25
|
+
_createOverlay() {
|
|
26
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
27
|
+
svg.setAttribute('class', 'grid-overlay');
|
|
28
|
+
svg.style.cssText = `
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
width: 100%;
|
|
33
|
+
height: 100%;
|
|
34
|
+
pointer-events: none;
|
|
35
|
+
z-index: 0;
|
|
36
|
+
`;
|
|
37
|
+
return svg;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Find main SVG and observe its viewBox changes.
|
|
42
|
+
*/
|
|
43
|
+
_observeViewBoxChanges() {
|
|
44
|
+
// Find the main SVG element
|
|
45
|
+
const svgs = this.svgContainer.querySelectorAll('svg');
|
|
46
|
+
for (const svg of svgs) {
|
|
47
|
+
if (svg !== this.overlayElement && svg.viewBox?.baseVal) {
|
|
48
|
+
this.mainSvg = svg;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!this.mainSvg) return;
|
|
54
|
+
|
|
55
|
+
// The overlay is positioned (absolute, z-index 0), and CSS paints positioned boxes over
|
|
56
|
+
// unpositioned ones whatever their order: lift the drawing above it, so the grid stays behind.
|
|
57
|
+
GridOverlay.stackAbove(this.mainSvg);
|
|
58
|
+
|
|
59
|
+
// Watch for viewBox attribute changes
|
|
60
|
+
const observer = new MutationObserver(() => {
|
|
61
|
+
this._updateGrid();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
observer.observe(this.mainSvg, { attributes: true, attributeFilter: ['viewBox'] });
|
|
65
|
+
|
|
66
|
+
// Initial draw
|
|
67
|
+
this._updateGrid();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Update grid based on current viewBox.
|
|
72
|
+
*/
|
|
73
|
+
_updateGrid() {
|
|
74
|
+
if (!this.mainSvg) return;
|
|
75
|
+
|
|
76
|
+
const viewBox = this.mainSvg.viewBox.baseVal;
|
|
77
|
+
const W = viewBox.width;
|
|
78
|
+
const H = viewBox.height;
|
|
79
|
+
const x0 = viewBox.x;
|
|
80
|
+
const y0 = viewBox.y;
|
|
81
|
+
|
|
82
|
+
// Clear existing grid
|
|
83
|
+
this.overlayElement.innerHTML = '';
|
|
84
|
+
|
|
85
|
+
// Sync overlay viewBox with main SVG
|
|
86
|
+
this.overlayElement.setAttribute('viewBox', `${x0} ${y0} ${W} ${H}`);
|
|
87
|
+
|
|
88
|
+
// Generate grid path aligned to grid
|
|
89
|
+
const lines = [];
|
|
90
|
+
const { gridSize } = this;
|
|
91
|
+
|
|
92
|
+
// Vertical lines
|
|
93
|
+
const firstX = Math.floor(x0 / gridSize) * gridSize;
|
|
94
|
+
for (let x = firstX; x < x0 + W; x += gridSize) {
|
|
95
|
+
lines.push(`M${x},${y0} L${x},${y0 + H}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Horizontal lines
|
|
99
|
+
const firstY = Math.floor(y0 / gridSize) * gridSize;
|
|
100
|
+
for (let y = firstY; y < y0 + H; y += gridSize) {
|
|
101
|
+
lines.push(`M${x0},${y} L${x0 + W},${y}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Create path element
|
|
105
|
+
if (lines.length > 0) {
|
|
106
|
+
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
107
|
+
path.setAttribute('d', lines.join(' '));
|
|
108
|
+
path.setAttribute('stroke', this.color);
|
|
109
|
+
path.setAttribute('stroke-width', this.width);
|
|
110
|
+
path.setAttribute('fill', 'none');
|
|
111
|
+
this.overlayElement.appendChild(path);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Make `drawing` paint above the overlay (z-index 0): positioned, one level up. A drawing already given a stacking order keeps it. */
|
|
116
|
+
static stackAbove(drawing) {
|
|
117
|
+
if (!drawing.style.position || drawing.style.position === 'static') drawing.style.position = 'relative';
|
|
118
|
+
if (!drawing.style.zIndex) drawing.style.zIndex = '1';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update grid size and redraw.
|
|
123
|
+
*/
|
|
124
|
+
setGridSize(gridSize) {
|
|
125
|
+
this.gridSize = gridSize;
|
|
126
|
+
this._updateGrid();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Remove the grid overlay.
|
|
131
|
+
*/
|
|
132
|
+
destroy() {
|
|
133
|
+
if (this.overlayElement && this.overlayElement.parentNode) {
|
|
134
|
+
this.overlayElement.parentNode.removeChild(this.overlayElement);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from '../CommandHistory.js';
|
|
2
|
+
import { ElementInstance } from './ElementInstance.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ImportRowsCommand — a planned import (csvMapping.js's planCsvImport) carried
|
|
6
|
+
* out as one undo step: the new elements and relationships added, the
|
|
7
|
+
* elements it updates given their new documentation and properties, and,
|
|
8
|
+
* with `view`, a box for each new element on it in a grid from `at`.
|
|
9
|
+
* Undo takes it all back.
|
|
10
|
+
*/
|
|
11
|
+
export class ImportRowsCommand extends Command {
|
|
12
|
+
/**
|
|
13
|
+
* @param {ArchimateModel} model
|
|
14
|
+
* @param {{creates, updates, relationships}} plan
|
|
15
|
+
* @param {{view?: ArchimateView, at?: {x, y}, columns?: number}} [options]
|
|
16
|
+
*/
|
|
17
|
+
constructor(model, plan, { view = null, at = { x: 60, y: 60 }, columns = 6 } = {}) {
|
|
18
|
+
super(`Import ${plan.creates.length} new, ${plan.updates.length} updated`);
|
|
19
|
+
this.model = model;
|
|
20
|
+
this.plan = plan;
|
|
21
|
+
this.view = view;
|
|
22
|
+
this.at = at;
|
|
23
|
+
this.columns = columns;
|
|
24
|
+
this._before = null;
|
|
25
|
+
this._instances = [];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
execute() {
|
|
29
|
+
const { model, plan, view } = this;
|
|
30
|
+
this._before = {
|
|
31
|
+
updates: plan.updates.map(({ element }) => [element, { documentation: element.documentation, properties: element.properties }]),
|
|
32
|
+
elementIds: Array.isArray(view?.elementIds) ? [...view.elementIds] : null,
|
|
33
|
+
};
|
|
34
|
+
for (const element of plan.creates) model.addElement(structured(element));
|
|
35
|
+
for (const { element, changes } of plan.updates) Object.assign(element, structured(changes));
|
|
36
|
+
for (const rel of plan.relationships) if (!model.getRelationship(rel.id)) model.addRelationship({ ...rel });
|
|
37
|
+
if (view) {
|
|
38
|
+
this._instances = plan.creates.map((e, i) => {
|
|
39
|
+
const inst = new ElementInstance(e.id, this.at.x + (i % this.columns) * 160 + 60, this.at.y + Math.floor(i / this.columns) * 90 + 28);
|
|
40
|
+
view.addElementInstance(inst);
|
|
41
|
+
return inst;
|
|
42
|
+
});
|
|
43
|
+
if (Array.isArray(view.elementIds)) view.elementIds = [...new Set([...view.elementIds, ...plan.creates.map(e => e.id)])];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
undo() {
|
|
48
|
+
const { model, plan, view } = this;
|
|
49
|
+
for (const inst of this._instances) view.removeElementInstance(inst.id);
|
|
50
|
+
this._instances = [];
|
|
51
|
+
if (view && this._before.elementIds) view.elementIds = this._before.elementIds;
|
|
52
|
+
for (const rel of plan.relationships) model.removeRelationship(rel.id);
|
|
53
|
+
for (const [element, before] of this._before.updates) {
|
|
54
|
+
for (const k of ['documentation', 'properties']) {
|
|
55
|
+
if (before[k] === undefined) delete element[k]; else element[k] = before[k];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const element of plan.creates) model.removeElement(element.id);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const structured = (v) => JSON.parse(JSON.stringify(v));
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LabelHelper — pure, stateless helpers for resolving node labels, word-
|
|
3
|
+
* wrapping them, and surfacing caller-supplied "extra data" lines.
|
|
4
|
+
*
|
|
5
|
+
* These used to live on RenderEngine; they are collected here so diagram
|
|
6
|
+
* classes and property dialogs can use them without going through the engine
|
|
7
|
+
* façade.
|
|
8
|
+
*/
|
|
9
|
+
export class LabelHelper {
|
|
10
|
+
/** Pure. The text that actually renders for a node's label — resolved
|
|
11
|
+
* BEFORE wrapping. `node.label`:
|
|
12
|
+
* - a function `(node) => string` — called directly.
|
|
13
|
+
* - a string with `${field}` (Archi-style) or `{field}` placeholders — each
|
|
14
|
+
* is replaced with that field's own value straight off the node.
|
|
15
|
+
* - falsy/unset — falls back to `node.name`, then `''`.
|
|
16
|
+
* Table nodes' header text and graphDiagram3D's node caption both read
|
|
17
|
+
* this too, not just the 2D `shape:'rect'` box. */
|
|
18
|
+
static resolveNodeLabel(node) {
|
|
19
|
+
if (typeof node?.label === 'function') return String(node.label(node) ?? '');
|
|
20
|
+
const raw = node?.label || node?.name || '';
|
|
21
|
+
if (typeof raw !== 'string') return String(raw);
|
|
22
|
+
if (!raw.includes('{') && !raw.includes('$')) return raw;
|
|
23
|
+
let result = raw;
|
|
24
|
+
result = result.replace(/\$\{(\w+)\}/g, (_match, field) => {
|
|
25
|
+
const value = node[field];
|
|
26
|
+
return value == null ? '' : String(value);
|
|
27
|
+
});
|
|
28
|
+
result = result.replace(/\{(\w+)\}/g, (_match, field) => {
|
|
29
|
+
const value = node[field];
|
|
30
|
+
return value == null ? '' : String(value);
|
|
31
|
+
});
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Pure. Word-wraps `text` to fit within `maxWidth` px at `fontSize` px,
|
|
36
|
+
* returning as many `lineHeight`-px lines as fit within `maxHeight` — a
|
|
37
|
+
* single word wider than `maxWidth` is hard-broken rather than left
|
|
38
|
+
* overflowing. The last line gets an ellipsis appended if more text existed
|
|
39
|
+
* than fit. Widths come from `measure(text)` (px) when given, e.g. the
|
|
40
|
+
* renderer's measureText; otherwise from an average character width. */
|
|
41
|
+
static wrapLabelLines(text, maxWidth, fontSize, maxHeight, lineHeight, measure = null) {
|
|
42
|
+
const AVG_CHAR_WIDTH_RATIO = 0.55; // rough sans-serif average
|
|
43
|
+
const width = measure ?? ((s) => s.length * fontSize * AVG_CHAR_WIDTH_RATIO);
|
|
44
|
+
const fits = (s) => width(s) <= maxWidth;
|
|
45
|
+
/** The longest prefix of a word that fits (at least one character). */
|
|
46
|
+
const fittingPrefix = (word) => {
|
|
47
|
+
let n = 1;
|
|
48
|
+
while (n < word.length && fits(word.slice(0, n + 1))) n++;
|
|
49
|
+
return n;
|
|
50
|
+
};
|
|
51
|
+
const maxLines = Math.max(1, Math.floor(maxHeight / lineHeight));
|
|
52
|
+
const words = String(text ?? '').split(/\s+/).filter(Boolean);
|
|
53
|
+
|
|
54
|
+
const lines = [];
|
|
55
|
+
let current = '';
|
|
56
|
+
let truncated = false;
|
|
57
|
+
for (let i = 0; i < words.length; i++) {
|
|
58
|
+
if (lines.length >= maxLines) { truncated = true; break; }
|
|
59
|
+
const word = words[i];
|
|
60
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
61
|
+
if (fits(candidate)) {
|
|
62
|
+
current = candidate;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (current) lines.push(current);
|
|
66
|
+
if (lines.length >= maxLines) { truncated = true; current = ''; break; }
|
|
67
|
+
if (!fits(word)) {
|
|
68
|
+
let rest = word;
|
|
69
|
+
while (!fits(rest) && lines.length < maxLines) {
|
|
70
|
+
const n = fittingPrefix(rest);
|
|
71
|
+
lines.push(rest.slice(0, n));
|
|
72
|
+
rest = rest.slice(n);
|
|
73
|
+
}
|
|
74
|
+
current = lines.length >= maxLines ? '' : rest;
|
|
75
|
+
if (lines.length >= maxLines && rest) truncated = true;
|
|
76
|
+
} else {
|
|
77
|
+
current = word;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (current) {
|
|
81
|
+
if (lines.length < maxLines) lines.push(current);
|
|
82
|
+
else truncated = true;
|
|
83
|
+
}
|
|
84
|
+
if (!truncated && lines.length === 0 && String(text ?? '').trim() === '') return [];
|
|
85
|
+
|
|
86
|
+
if (truncated && lines.length) {
|
|
87
|
+
const last = lines[lines.length - 1];
|
|
88
|
+
lines[lines.length - 1] = last.length > 1 ? `${last.slice(0, -1)}…` : `${last}…`;
|
|
89
|
+
}
|
|
90
|
+
return lines;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Pure. "key: value" lines for any of an object's own fields not in
|
|
94
|
+
* knownKeys and not undefined — surfaces caller-supplied extra data
|
|
95
|
+
* (e.g. `{owner:'Alice', headcount:12}`) in the hover tooltip without
|
|
96
|
+
* the caller having to build a bespoke tooltip string themselves. */
|
|
97
|
+
/** Whether a value is data a person reads and edits as text: a string, number or boolean, or a list of them (not an object). */
|
|
98
|
+
static isDataValue(value) {
|
|
99
|
+
const plain = (v) => ['string', 'number', 'boolean'].includes(typeof v);
|
|
100
|
+
return plain(value) || (Array.isArray(value) && value.every(plain));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static nodeExtraDataLines(node, knownKeys) {
|
|
104
|
+
return Object.entries(node)
|
|
105
|
+
.filter(([k, v]) => !knownKeys.has(k) && LabelHelper.isDataValue(v))
|
|
106
|
+
.map(([k, v]) => `${k}: ${Array.isArray(v) ? v.join(', ') : v}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Command } from '../CommandHistory.js';
|
|
2
|
+
import { structuredCopy } from './ElementInstance.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MergeElementsCommand — elements that are one thing twice made into one
|
|
6
|
+
* (Archi's merge): the one kept takes the others' relationships, their boxes
|
|
7
|
+
* on every view, the documentation it lacks and the properties it lacks; the
|
|
8
|
+
* others go. A relationship left joining the kept element to itself, or the
|
|
9
|
+
* same as another (kind and ends), goes too, its lines drawn as the other.
|
|
10
|
+
* Undo puts everything back as it was.
|
|
11
|
+
*/
|
|
12
|
+
export class MergeElementsCommand extends Command {
|
|
13
|
+
/**
|
|
14
|
+
* @param {ArchimateModel} model
|
|
15
|
+
* @param {string} keepId - The element kept
|
|
16
|
+
* @param {Array<string>} otherIds - The elements merged into it
|
|
17
|
+
*/
|
|
18
|
+
constructor(model, keepId, otherIds, label = `Merge ${otherIds.length + 1} elements into "${model.getElement(keepId)?.name || keepId}"`) {
|
|
19
|
+
super(label);
|
|
20
|
+
this.model = model;
|
|
21
|
+
this.keepId = keepId;
|
|
22
|
+
this.otherIds = otherIds.filter(id => id !== keepId && model.getElement(id));
|
|
23
|
+
this._before = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
execute() {
|
|
27
|
+
const { model, keepId } = this;
|
|
28
|
+
const keep = model.getElement(keepId);
|
|
29
|
+
if (!keep || !this.otherIds.length) return;
|
|
30
|
+
this._before = this._snapshot();
|
|
31
|
+
const merged = new Set(this.otherIds);
|
|
32
|
+
const into = (id) => (merged.has(id) ? keepId : id);
|
|
33
|
+
for (const other of this.otherIds.map(id => model.getElement(id))) {
|
|
34
|
+
if (other.documentation && !(keep.documentation ?? '').includes(other.documentation)) {
|
|
35
|
+
keep.documentation = keep.documentation ? `${keep.documentation}\n\n${other.documentation}` : other.documentation;
|
|
36
|
+
}
|
|
37
|
+
const own = new Set((keep.properties ?? []).map(p => p.name ?? p.key));
|
|
38
|
+
const added = (other.properties ?? []).filter(p => !own.has(p.name ?? p.key));
|
|
39
|
+
if (added.length) keep.properties = [...(keep.properties ?? []), ...added.map(p => ({ ...p }))];
|
|
40
|
+
if (!keep.specialization && other.specialization) keep.specialization = other.specialization;
|
|
41
|
+
}
|
|
42
|
+
// Relationships end at the kept element; one left joining it to itself, or doubling another, goes.
|
|
43
|
+
const seen = new Map();
|
|
44
|
+
const replaced = new Map(); // removed relationship id -> the one its lines now draw
|
|
45
|
+
for (const rel of model.relationships()) {
|
|
46
|
+
const touched = merged.has(rel.source) || merged.has(rel.target);
|
|
47
|
+
rel.source = into(rel.source);
|
|
48
|
+
rel.target = into(rel.target);
|
|
49
|
+
if (touched && rel.source === keepId && rel.target === keepId) { replaced.set(rel.id, null); continue; }
|
|
50
|
+
const key = `${rel.kind} ${rel.source} ${rel.target} ${rel.name ?? ''}`;
|
|
51
|
+
if (touched && seen.has(key)) replaced.set(rel.id, seen.get(key));
|
|
52
|
+
else if (!seen.has(key)) seen.set(key, rel.id);
|
|
53
|
+
}
|
|
54
|
+
for (const id of replaced.keys()) model.removeRelationship(id);
|
|
55
|
+
for (const view of model.views()) {
|
|
56
|
+
if (Array.isArray(view.elementIds)) view.elementIds = [...new Set(view.elementIds.map(into))];
|
|
57
|
+
for (const inst of view.elementInstances?.values() ?? []) if (merged.has(inst.elementId)) inst.elementId = keepId;
|
|
58
|
+
for (const inst of [...(view.relationshipInstances?.values() ?? [])]) {
|
|
59
|
+
if (!replaced.has(inst.relationshipId)) continue;
|
|
60
|
+
const now = replaced.get(inst.relationshipId);
|
|
61
|
+
if (now) inst.relationshipId = now;
|
|
62
|
+
else view.relationshipInstances.delete(inst.id);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const id of this.otherIds) model.removeElement(id);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
undo() {
|
|
69
|
+
if (!this._before) return;
|
|
70
|
+
const { model } = this;
|
|
71
|
+
const b = this._before;
|
|
72
|
+
model._elements = new Map(b.elements.map(([id, el]) => [id, el]));
|
|
73
|
+
const keep = model._elements.get(this.keepId);
|
|
74
|
+
Object.keys(keep).forEach(k => delete keep[k]); // what the merge added too
|
|
75
|
+
Object.assign(keep, structuredCopy(b.keep));
|
|
76
|
+
model._elementFolder = new Map(b.folders);
|
|
77
|
+
model._relationships = new Map(b.relationships.map(([id, rel, ends]) => [id, Object.assign(rel, ends)]));
|
|
78
|
+
for (const v of b.views) {
|
|
79
|
+
v.view.elementIds = v.elementIds;
|
|
80
|
+
for (const [inst, elementId] of v.instances) inst.elementId = elementId;
|
|
81
|
+
v.view.relationshipInstances = new Map(v.lines.map(([inst, relationshipId]) => { inst.relationshipId = relationshipId; return [inst.id, inst]; }));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Everything the merge changes, to put back. @private */
|
|
86
|
+
_snapshot() {
|
|
87
|
+
const { model } = this;
|
|
88
|
+
return {
|
|
89
|
+
elements: [...model._elements],
|
|
90
|
+
keep: structuredCopy(model.getElement(this.keepId)),
|
|
91
|
+
folders: [...model._elementFolder],
|
|
92
|
+
relationships: [...model._relationships].map(([id, rel]) => [id, rel, { source: rel.source, target: rel.target }]),
|
|
93
|
+
views: model.views().map(view => ({
|
|
94
|
+
view,
|
|
95
|
+
elementIds: Array.isArray(view.elementIds) ? [...view.elementIds] : view.elementIds,
|
|
96
|
+
instances: [...(view.elementInstances?.values() ?? [])].map(inst => [inst, inst.elementId]),
|
|
97
|
+
lines: [...(view.relationshipInstances?.values() ?? [])].map(inst => [inst, inst.relationshipId]),
|
|
98
|
+
})),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Command } from '../CommandHistory.js';
|
|
2
|
+
import { structuredCopy } from './ElementInstance.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NestInstanceCommand — draw a box inside another on its view, or take it out
|
|
6
|
+
* (Archi's nesting): the instance's `archi.parent` becomes the parent's
|
|
7
|
+
* visual id, so it moves with the parent and an Archi file nests it there. A
|
|
8
|
+
* box nested under one drawn above it is raised just above its parent, so it
|
|
9
|
+
* stays in sight. Undo restores both.
|
|
10
|
+
*/
|
|
11
|
+
export class NestInstanceCommand extends Command {
|
|
12
|
+
/**
|
|
13
|
+
* @param {ElementInstance} instance - The box
|
|
14
|
+
* @param {ElementInstance|null} parent - The box it goes in; null takes it out
|
|
15
|
+
*/
|
|
16
|
+
constructor(instance, parent, label = parent ? 'Nest' : 'Take out') {
|
|
17
|
+
super(label);
|
|
18
|
+
this.instance = instance;
|
|
19
|
+
this.parent = parent;
|
|
20
|
+
this._before = { archi: instance.archi ? structuredCopy(instance.archi) : null, zIndex: instance.zIndex };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
execute() {
|
|
24
|
+
const { instance, parent } = this;
|
|
25
|
+
const { parent: _was, ...rest } = instance.archi ?? {};
|
|
26
|
+
instance.archi = parent ? { ...rest, parent: parent.visualId } : (Object.keys(rest).length ? rest : null);
|
|
27
|
+
if (parent && (instance.zIndex ?? 0) <= (parent.zIndex ?? 0)) instance.zIndex = (parent.zIndex ?? 0) + 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
undo() {
|
|
31
|
+
this.instance.archi = this._before.archi ? structuredCopy(this._before.archi) : null;
|
|
32
|
+
this.instance.zIndex = this._before.zIndex;
|
|
33
|
+
}
|
|
34
|
+
}
|