@jax-data-science/sci-image-visualizer 0.8.2 → 0.9.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/README.md +201 -460
- package/esm2022/index.mjs +28 -15
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
- package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
- package/esm2022/lib/contracts/color.mjs +60 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
- package/esm2022/lib/contracts/display-types.mjs +11 -1
- package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/intensity.mjs +48 -5
- package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
- package/esm2022/lib/contracts/plot-type.mjs +134 -17
- package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
- package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
- package/esm2022/lib/contracts/sam.contract.mjs +1 -1
- package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
- package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +2 -1
- package/esm2022/lib/geometry/contour.mjs +63 -0
- package/esm2022/lib/geometry/raster.mjs +98 -0
- package/esm2022/lib/geometry/ring.mjs +201 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
- package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
- package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
- package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
- package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
- package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
- package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +361 -4184
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
- package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
- package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
- package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
- package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
- package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
- package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
- package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
- package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
- package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
- package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
- package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
- package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
- package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
- package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
- package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
- package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
- package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
- package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
- package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
- package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
- package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
- package/esm2022/lib/implementations/region-centroids.mjs +47 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
- package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
- package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
- package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
- package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
- package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
- package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
- package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
- package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
- package/esm2022/lib/models/bezier.mjs +1 -11
- package/esm2022/lib/models/class-preset.mjs +41 -3
- package/esm2022/lib/models/geometry.mjs +27 -164
- package/esm2022/lib/models/polygon-edit.mjs +254 -0
- package/esm2022/lib/models/polygon-factory.mjs +118 -0
- package/esm2022/lib/models/region-clone.mjs +68 -0
- package/esm2022/lib/models/region-geojson.mjs +373 -0
- package/esm2022/lib/models/region.mjs +34 -33
- package/esm2022/lib/models/shape.mjs +18 -16
- package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
- package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
- package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
- package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
- package/esm2022/lib/plot.utilities.mjs +296 -473
- package/esm2022/lib/processing/image-crop.mjs +1 -1
- package/esm2022/lib/processing/processing-image.mjs +28 -15
- package/esm2022/lib/provide-visualization.mjs +40 -14
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
- package/esm2022/lib/region-editor/file-stem.mjs +13 -0
- package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
- package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
- package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
- package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
- package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
- package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
- package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
- package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
- package/esm2022/lib/region-ops.service.mjs +28 -70
- package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
- package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
- package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
- package/esm2022/lib/render-orchestrator.mjs +14 -11
- package/esm2022/lib/render-session.mjs +207 -0
- package/esm2022/lib/routing-visualizer.service.mjs +459 -411
- package/esm2022/lib/spatial/density-raster.mjs +14 -0
- package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
- package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
- package/esm2022/lib/spatial/gene-search.mjs +1 -1
- package/esm2022/lib/spatial/glyphs.mjs +97 -0
- package/esm2022/lib/spatial/lod.mjs +187 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
- package/esm2022/lib/spatial/spatial-density.mjs +25 -16
- package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
- package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
- package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
- package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
- package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
- package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
- package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
- package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
- package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
- package/esm2022/lib/spatial/stats.mjs +71 -0
- package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
- package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
- package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
- package/esm2022/lib/store/class-color.util.mjs +46 -3
- package/esm2022/lib/store/region-history.mjs +146 -0
- package/esm2022/lib/store/region-scope-cache.mjs +140 -0
- package/esm2022/lib/store/region-selection.mjs +82 -0
- package/esm2022/lib/store/region-store.service.mjs +279 -675
- package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
- package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
- package/esm2022/lib/toast-outlets.mjs +5 -4
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
- package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
- package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
- package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
- package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
- package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
- package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
- package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
- package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
- package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
- package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
- package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
- package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
- package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
- package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
- package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
- package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
- package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
- package/esm2022/lib/util/mark-for-check.mjs +17 -0
- package/esm2022/lib/util/supersede.mjs +56 -0
- package/esm2022/lib/visualization.module.mjs +39 -141
- package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
- package/esm2022/lib/visualizer/region-actions.mjs +149 -0
- package/esm2022/lib/visualizer/region-load.mjs +60 -0
- package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
- package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
- package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
- package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
- package/esm2022/lib/visualizer.component.mjs +480 -1902
- package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
- package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
- package/esm2022/lib/workers/spatial-math.mjs +190 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34430
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/fesm2022/mask.worker.js +36 -917
- package/fesm2022/onnx-sam.worker.js +52 -16
- package/fesm2022/spatial-math.worker.js +471 -0
- package/fesm2022/tsne.worker.js +32 -15
- package/index.d.ts +13 -10
- package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
- package/lib/contracts/capabilities.contract.d.ts +4 -2
- package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
- package/lib/contracts/color.d.ts +27 -0
- package/lib/contracts/colormap-lut.d.ts +19 -4
- package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
- package/lib/contracts/display-types.d.ts +21 -0
- package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
- package/lib/contracts/intensity.d.ts +13 -2
- package/lib/contracts/plot-type.d.ts +3 -1
- package/lib/contracts/ports/image-state.port.d.ts +6 -2
- package/lib/contracts/ports/preferences.port.d.ts +4 -0
- package/lib/contracts/ports/region-io.port.d.ts +1 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
- package/lib/contracts/ports/tile-access.port.d.ts +1 -0
- package/lib/contracts/region-editor-api.contract.d.ts +1 -1
- package/lib/contracts/region-overlay.contract.d.ts +5 -0
- package/lib/contracts/sam.contract.d.ts +7 -0
- package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
- package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
- package/lib/contracts/visualizer.contract.d.ts +221 -54
- package/lib/contracts/viz-config.d.ts +1 -0
- package/lib/geometry/contour.d.ts +24 -0
- package/lib/geometry/raster.d.ts +42 -0
- package/lib/geometry/ring.d.ts +67 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
- package/lib/implementations/base-store-visualizer.d.ts +61 -15
- package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
- package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
- package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
- package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
- package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
- package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
- package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
- package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
- package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
- package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -878
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
- package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
- package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
- package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
- package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
- package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
- package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
- package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
- package/lib/implementations/osd/display-pipeline.d.ts +38 -9
- package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
- package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
- package/lib/implementations/osd/osd-coords.d.ts +6 -4
- package/lib/implementations/osd/osd-export.d.ts +36 -0
- package/lib/implementations/osd/osd-lib.d.ts +7 -0
- package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
- package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
- package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
- package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
- package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
- package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
- package/lib/implementations/osd/osd-viewport.d.ts +77 -0
- package/lib/implementations/osd/osd-zoom.d.ts +6 -0
- package/lib/implementations/osd/simple-source.d.ts +161 -0
- package/lib/implementations/osd/slice-cache.d.ts +12 -3
- package/lib/implementations/osd/tile-client.d.ts +11 -14
- package/lib/implementations/osd/tile-recolor.d.ts +141 -0
- package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
- package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
- package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
- package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
- package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
- package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
- package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
- package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
- package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
- package/lib/implementations/plotly/plotly.service.d.ts +136 -401
- package/lib/implementations/region-centroids.d.ts +14 -0
- package/lib/implementations/simple-slice-access.service.d.ts +7 -4
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
- package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
- package/lib/implementations/tile-server/index.d.ts +5 -0
- package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
- package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
- package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
- package/lib/implementations/tile-server/transport.d.ts +62 -0
- package/lib/intensity/intensity-profile.d.ts +66 -0
- package/lib/intensity/intensity-profile.service.d.ts +108 -0
- package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
- package/lib/models/bezier.d.ts +0 -5
- package/lib/models/class-preset.d.ts +18 -0
- package/lib/models/geometry.d.ts +14 -48
- package/lib/models/polygon-edit.d.ts +72 -0
- package/lib/models/polygon-factory.d.ts +40 -0
- package/lib/models/region-clone.d.ts +20 -0
- package/lib/models/region-geojson.d.ts +17 -0
- package/lib/models/region.d.ts +40 -4
- package/lib/models/shape.d.ts +8 -0
- package/lib/plot-mode/contribution-host.d.ts +125 -0
- package/lib/plot-mode/plot-type-menu.d.ts +60 -0
- package/lib/plot-mode/tool-params-model.d.ts +49 -0
- package/lib/plot.utilities.d.ts +19 -30
- package/lib/processing/processing-image.d.ts +5 -2
- package/lib/provide-visualization.d.ts +19 -2
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
- package/lib/region-editor/file-stem.d.ts +7 -0
- package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
- package/lib/region-editor/mask-export.service.d.ts +54 -0
- package/lib/region-editor/mask-raster.d.ts +2 -8
- package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
- package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
- package/lib/region-editor/region-editor.component.d.ts +166 -199
- package/lib/region-editor/region-metrics.d.ts +26 -0
- package/lib/region-editor/region-persistence.service.d.ts +69 -0
- package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
- package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
- package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
- package/lib/region-ops.service.d.ts +1 -7
- package/lib/region-overlay/region-geometry.d.ts +157 -0
- package/lib/region-overlay/region-hit-test.d.ts +38 -0
- package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
- package/lib/render-orchestrator.d.ts +6 -2
- package/lib/render-session.d.ts +75 -0
- package/lib/routing-visualizer.service.d.ts +110 -58
- package/lib/spatial/density-raster.d.ts +6 -0
- package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
- package/lib/spatial/embedding-compute.d.ts +21 -2
- package/lib/spatial/glyphs.d.ts +16 -0
- package/lib/spatial/lod.d.ts +94 -0
- package/lib/spatial/spatial-controls.facade.d.ts +64 -0
- package/lib/spatial/spatial-density.d.ts +15 -5
- package/lib/spatial/spatial-encoding.d.ts +11 -44
- package/lib/spatial/spatial-expression.d.ts +40 -22
- package/lib/spatial/spatial-framing.d.ts +1 -0
- package/lib/spatial/spatial-heatmap.d.ts +2 -0
- package/lib/spatial/spatial-hover.d.ts +4 -16
- package/lib/spatial/spatial-panel-model.d.ts +135 -0
- package/lib/spatial/spatial-selection.d.ts +21 -26
- package/lib/spatial/spatial-tile-merge.d.ts +41 -0
- package/lib/spatial/spatial-tiles.d.ts +9 -256
- package/lib/spatial/stats.d.ts +38 -0
- package/lib/spatial/transcript-grouping.d.ts +119 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
- package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
- package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
- package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
- package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
- package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
- package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
- package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
- package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
- package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
- package/lib/store/class-color.util.d.ts +35 -1
- package/lib/store/region-history.d.ts +66 -0
- package/lib/store/region-scope-cache.d.ts +63 -0
- package/lib/store/region-selection.d.ts +36 -0
- package/lib/store/region-store.service.d.ts +104 -112
- package/lib/store/visualizer-store.service.d.ts +22 -33
- package/lib/toast-outlets.d.ts +4 -3
- package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
- package/lib/toolbar/canvas-tools.d.ts +20 -0
- package/lib/toolbar/crop/slide-crop.d.ts +10 -4
- package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
- package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
- package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
- package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
- package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
- package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
- package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
- package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
- package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
- package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
- package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
- package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
- package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
- package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
- package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
- package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
- package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
- package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
- package/lib/toolbar/toolbar.component.d.ts +47 -83
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
- package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
- package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
- package/lib/toolbar/wand/wand.service.d.ts +22 -116
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
- package/lib/util/mark-for-check.d.ts +11 -0
- package/lib/util/supersede.d.ts +53 -0
- package/lib/visualization.module.d.ts +18 -39
- package/lib/visualizer/floating-drag.directive.d.ts +30 -0
- package/lib/visualizer/region-actions.d.ts +54 -0
- package/lib/visualizer/region-load.d.ts +27 -0
- package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
- package/lib/visualizer/tool-modes.d.ts +49 -0
- package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
- package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
- package/lib/visualizer.component.d.ts +201 -447
- package/lib/workers/spatial-math-ops.d.ts +65 -0
- package/lib/workers/spatial-math-worker.d.ts +7 -0
- package/lib/workers/spatial-math.d.ts +74 -0
- package/package.json +12 -3
- package/src/lib/styles/_viz-icons-rules.scss +73 -0
- package/src/lib/styles/viz-icons.scss +14 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
- package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
- package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
- package/src/lib/assets/cell-detection.svg +0 -37
- package/src/lib/assets/click.svg +0 -1
- package/src/lib/assets/colormap-luts.json +0 -1
- package/src/lib/assets/edit-selection-white.svg +0 -47
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
- package/src/lib/assets/picture-segmentation.svg +0 -43
- package/src/lib/assets/test/download-379.svg +0 -1
- package/src/lib/assets/test/download-98.svg +0 -1
- package/src/lib/assets/test/json-1.svg +0 -1
- package/src/lib/assets/test/load-53.svg +0 -1
- package/src/lib/assets/test/mask-44.svg +0 -1
- package/src/lib/assets/test/mask-download-44.svg +0 -15
- package/src/lib/assets/test/mask-save-44.svg +0 -11
- package/src/lib/assets/test/overlay-1.svg +0 -1
- package/src/lib/assets/test/overlay-4.svg +0 -1
- package/src/lib/assets/test/region-26.svg +0 -1
- package/src/lib/assets/test/save-56.svg +0 -1
- package/src/lib/assets/test/upload-43.svg +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withRegionPatch } from '../models/region-clone';
|
|
1
2
|
export function normalizeLabel(s) {
|
|
2
3
|
return (s ?? '').trim().toLowerCase();
|
|
3
4
|
}
|
|
@@ -10,14 +11,24 @@ export function hashString(s) {
|
|
|
10
11
|
// Fold to non-negative without the Math.abs(INT_MIN) overflow pitfall.
|
|
11
12
|
return h < 0 ? ~h : h;
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The key two class names are compared by under the set's match mode: the name
|
|
16
|
+
* itself for `exact`, trimmed and lower-cased for `normalized`.
|
|
17
|
+
*/
|
|
18
|
+
export function presetKey(set, label) {
|
|
19
|
+
return set?.matchMode === 'normalized' ? normalizeLabel(label) : label;
|
|
20
|
+
}
|
|
21
|
+
/** `#RRGGBB` (upper-case) for an HSL colour: hue in degrees, saturation and lightness in %. */
|
|
22
|
+
export function hslToHex(hDeg, sPct, lPct) {
|
|
14
23
|
const s = sPct / 100;
|
|
15
24
|
const l = lPct / 100;
|
|
16
25
|
const k = (n) => (n + hDeg / 30) % 12;
|
|
17
26
|
const a = s * Math.min(l, 1 - l);
|
|
18
27
|
const channel = (n) => {
|
|
19
28
|
const v = l - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
|
|
20
|
-
return Math.round(255 * v)
|
|
29
|
+
return Math.round(255 * v)
|
|
30
|
+
.toString(16)
|
|
31
|
+
.padStart(2, '0');
|
|
21
32
|
};
|
|
22
33
|
return `#${channel(0)}${channel(8)}${channel(4)}`.toUpperCase();
|
|
23
34
|
}
|
|
@@ -49,4 +60,36 @@ export function colorForLabel(label, set) {
|
|
|
49
60
|
const preset = findPreset(label, set);
|
|
50
61
|
return preset ? preset.color : fallbackColorFor(label, set.fallbackPalette);
|
|
51
62
|
}
|
|
52
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Resolve each labelled region's colour from the preset set (jit-ui#70). The
|
|
65
|
+
* presets are the source of truth: a matching preset gives the class colour,
|
|
66
|
+
* an unknown class its deterministic fallback, **overriding any colour already
|
|
67
|
+
* on the region** (e.g. embedded in imported GeoJSON). Unlabelled regions and
|
|
68
|
+
* ones the user recoloured (`colorOverridden`) are left untouched. Unknown
|
|
69
|
+
* classes are reported through `onPromote` when `autoPromote` is on.
|
|
70
|
+
*
|
|
71
|
+
* Returns a new array; regions whose colour is already right are the same
|
|
72
|
+
* instances.
|
|
73
|
+
*/
|
|
74
|
+
export function applyPresetColors(regions, set, opts = {}) {
|
|
75
|
+
const known = new Set(set.classes.map((c) => presetKey(set, c.name)));
|
|
76
|
+
return regions.map((region) => {
|
|
77
|
+
if (!region.label || region.colorOverridden)
|
|
78
|
+
return region;
|
|
79
|
+
const color = colorForLabel(region.label, set);
|
|
80
|
+
if (set.autoPromote && !known.has(presetKey(set, region.label))) {
|
|
81
|
+
known.add(presetKey(set, region.label));
|
|
82
|
+
// In normalized mode, trim the promoted name so leading/trailing
|
|
83
|
+
// whitespace doesn't create invisible duplicates or odd display names.
|
|
84
|
+
const name = set.matchMode === 'normalized' ? region.label.trim() : region.label;
|
|
85
|
+
opts.onPromote?.({ name, color, source: 'auto' });
|
|
86
|
+
}
|
|
87
|
+
if (region.color === color)
|
|
88
|
+
return region;
|
|
89
|
+
if (!opts.inPlace?.(region))
|
|
90
|
+
return withRegionPatch(region, { color });
|
|
91
|
+
region.color = color;
|
|
92
|
+
return region;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3MtY29sb3IudXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvY2xhc3MtY29sb3IudXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFjQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFekQsTUFBTSxVQUFVLGNBQWMsQ0FBQyxDQUFTO0lBQ3RDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDeEMsQ0FBQztBQUVELG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsVUFBVSxDQUFDLENBQVM7SUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNsQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFDRCx1RUFBdUU7SUFDdkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQWlDLEVBQUUsS0FBYTtJQUN4RSxPQUFPLEdBQUcsRUFBRSxTQUFTLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUN6RSxDQUFDO0FBRUQsK0ZBQStGO0FBQy9GLE1BQU0sVUFBVSxRQUFRLENBQUMsSUFBWSxFQUFFLElBQVksRUFBRSxJ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QUFPLE1BQU0sQ0FBQztRQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU8sZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdkUsTUFBTSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDckIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEZXRlcm1pbmlzdGljIGNvbG91ciBlbmdpbmUgZm9yIHByZXNldCBhbm5vdGF0aW9uIGNsYXNzZXMgKGppdC11aSM3MCkuXG4gKlxuICogUmVzb2x1dGlvbiBvcmRlciBmb3IgYSByZWdpb24gYGxhYmVsYDpcbiAqICAgMS4gYSBtYXRjaGluZyBwcmVzZXQgKGV4YWN0IGJ5IGRlZmF1bHQsIG9yIG5vcm1hbGl6ZWQgaWYgdGhlIHNldCdzIG1hdGNoTW9kZSBzYXlzIHNvKVxuICogICAgICAtPiB0aGUgcHJlc2V0J3MgY29sb3VyO1xuICogICAyLiBvdGhlcndpc2UgYSBkZXRlcm1pbmlzdGljIGZhbGxiYWNrIGNvbG91ciBkZXJpdmVkIGZyb20gYSBzdGFibGUgaGFzaCBvZiB0aGUgbmFtZSxcbiAqICAgICAgc28gdGhlIHNhbWUgdW5rbm93biBjbGFzcyBhbHdheXMgZ2V0cyB0aGUgc2FtZSBjb2xvdXIgd2l0aCBubyBzdG9yZWQgc3RhdGUuXG4gKlxuICogVGhlc2UgZnVuY3Rpb25zIGFyZSBwdXJlIChubyBtdXRhdGlvbik7IG9wdC1pbiBwcm9tb3Rpb24gb2YgdW5rbm93biBjbGFzc2VzIGludG8gdGhlXG4gKiBzZXQgaXMgcmVwb3J0ZWQgdG8gdGhlIGNhbGxlciAoc2VlIHtAbGluayBhcHBseVByZXNldENvbG9yc30pLCB3aGljaCBvd25zIHBlcnNpc3RlbmNlLlxuICovXG5pbXBvcnQgeyBDbGFzc1ByZXNldCwgUHJlc2V0U2V0IH0gZnJvbSAnLi4vbW9kZWxzL2NsYXNzLXByZXNldCc7XG5pbXBvcnQgeyBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IHdpdGhSZWdpb25QYXRjaCB9IGZyb20gJy4uL21vZGVscy9yZWdpb24tY2xvbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplTGFiZWwoczogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIChzID8/ICcnKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbn1cblxuLyoqIFN0YWJsZSwgbm9uLW5lZ2F0aXZlIDMyLWJpdCBzdHJpbmcgaGFzaCAoaWRlbnRpY2FsIGFjcm9zcyBydW5zIGFuZCBtYWNoaW5lcykuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaFN0cmluZyhzOiBzdHJpbmcpOiBudW1iZXIge1xuICBsZXQgaCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcy5sZW5ndGg7IGkrKykge1xuICAgIGggPSAoTWF0aC5pbXVsKDMxLCBoKSArIHMuY2hhckNvZGVBdChpKSkgfCAwO1xuICB9XG4gIC8vIEZvbGQgdG8gbm9uLW5lZ2F0aXZlIHdpdGhvdXQgdGhlIE1hdGguYWJzKElOVF9NSU4pIG92ZXJmbG93IHBpdGZhbGwuXG4gIHJldHVybiBoIDwgMCA/IH5oIDogaDtcbn1cblxuLyoqXG4gKiBUaGUga2V5IHR3byBjbGFzcyBuYW1lcyBhcmUgY29tcGFyZWQgYnkgdW5kZXIgdGhlIHNldCdzIG1hdGNoIG1vZGU6IHRoZSBuYW1lXG4gKiBpdHNlbGYgZm9yIGBleGFjdGAsIHRyaW1tZWQgYW5kIGxvd2VyLWNhc2VkIGZvciBgbm9ybWFsaXplZGAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVzZXRLZXkoc2V0OiBQaWNrPFByZXNldFNldCwgJ21hdGNoTW9kZSc+LCBsYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNldD8ubWF0Y2hNb2RlID09PSAnbm9ybWFsaXplZCcgPyBub3JtYWxpemVMYWJlbChsYWJlbCkgOiBsYWJlbDtcbn1cblxuLyoqIGAjUlJHR0JCYCAodXBwZXItY2FzZSkgZm9yIGFuIEhTTCBjb2xvdXI6IGh1ZSBpbiBkZWdyZWVzLCBzYXR1cmF0aW9uIGFuZCBsaWdodG5lc3MgaW4gJS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoc2xUb0hleChoRGVnOiBudW1iZXIsIHNQY3Q6IG51bWJlciwgbFBjdDogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgcyA9IHNQY3QgLyAxMDA7XG4gIGNvbnN0IGwgPSBsUGN0IC8gMTAwO1xuICBjb25zdCBrID0gKG46IG51bWJlcikgPT4gKG4gKyBoRGVnIC8gMzApICUgMTI7XG4gIGNvbnN0IGEgPSBzICogTWF0aC5taW4obCwgMSAtIGwpO1xuICBjb25zdCBjaGFubmVsID0gKG46IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IHYgPSBsIC0gYSAqIE1hdGgubWF4KC0xLCBNYXRoLm1pbihrKG4pIC0gMywgOSAtIGsobiksIDEpKTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCgyNTUgKiB2KVxuICAgICAgLnRvU3RyaW5nKDE2KVxuICAgICAgLnBhZFN0YXJ0KDIsICcwJyk7XG4gIH07XG4gIHJldHVybiBgIyR7Y2hhbm5lbCgwKX0ke2NoYW5uZWwoOCl9JHtjaGFubmVsKDQpfWAudG9VcHBlckNhc2UoKTtcbn1cblxuLyoqIEZpbmQgdGhlIHByZXNldCBtYXRjaGluZyBgbGFiZWxgIHVuZGVyIHRoZSBzZXQncyBtYXRjaCBtb2RlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRQcmVzZXQobGFiZWw6IHN0cmluZywgc2V0OiBQcmVzZXRTZXQpOiBDbGFzc1ByZXNldCB8IHVuZGVmaW5lZCB7XG4gIGlmICghbGFiZWwgfHwgIXNldD8uY2xhc3NlcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKHNldC5tYXRjaE1vZGUgPT09ICdub3JtYWxpemVkJykge1xuICAgIGNvbnN0IG4gPSBub3JtYWxpemVMYWJlbChsYWJlbCk7XG4gICAgcmV0dXJuIHNldC5jbGFzc2VzLmZpbmQoKGMpID0+IG5vcm1hbGl6ZUxhYmVsKGMubmFtZSkgPT09IG4pO1xuICB9XG4gIHJldHVybiBzZXQuY2xhc3Nlcy5maW5kKChjKSA9PiBjLm5hbWUgPT09IGxhYmVsKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmlzdGljIGZhbGxiYWNrIGNvbG91ciBmb3IgYW4gdW5rbm93biBjbGFzcyBuYW1lOiBpbmRleCBpbnRvIHRoZSBwYWxldHRlIGJ5IGFcbiAqIHN0YWJsZSBoYXNoIG9mIHRoZSAobm9ybWFsaXplZCkgbmFtZTsgaWYgdGhlIHBhbGV0dGUgaXMgZW1wdHksIGdlbmVyYXRlIGEgZ29sZGVuLWFuZ2xlXG4gKiBIU0wgaHVlLiBTYW1lIG5hbWUgLT4gc2FtZSBjb2xvdXIsIGV2ZXJ5IHJ1bi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhbGxiYWNrQ29sb3JGb3IobGFiZWw6IHN0cmluZywgcGFsZXR0ZTogc3RyaW5nW10pOiBzdHJpbmcge1xuICBjb25zdCBrZXkgPSBub3JtYWxpemVMYWJlbChsYWJlbCk7XG4gIGlmIChwYWxldHRlICYmIHBhbGV0dGUubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBwYWxldHRlW2hhc2hTdHJpbmcoa2V5KSAlIHBhbGV0dGUubGVuZ3RoXTtcbiAgfVxuICBjb25zdCBodWUgPSAoaGFzaFN0cmluZyhrZXkpICogMTM3LjUwOCkgJSAzNjA7XG4gIHJldHVybiBoc2xUb0hleChodWUsIDY1LCA1MCk7XG59XG5cbi8qKiBSZXNvbHZlIGEgY29sb3VyIGZvciBgbGFiZWxgOiBhIG1hdGNoaW5nIHByZXNldCdzIGNvbG91ciwgZWxzZSB0aGUgZGV0ZXJtaW5pc3RpYyBmYWxsYmFjay4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvckZvckxhYmVsKGxhYmVsOiBzdHJpbmcsIHNldDogUHJlc2V0U2V0KTogc3RyaW5nIHtcbiAgY29uc3QgcHJlc2V0ID0gZmluZFByZXNldChsYWJlbCwgc2V0KTtcbiAgcmV0dXJuIHByZXNldCA/IHByZXNldC5jb2xvciA6IGZhbGxiYWNrQ29sb3JGb3IobGFiZWwsIHNldC5mYWxsYmFja1BhbGV0dGUpO1xufVxuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIGFwcGx5UHJlc2V0Q29sb3JzfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbHlQcmVzZXRDb2xvcnNPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRydWUgZm9yIGEgcmVnaW9uIHRoZSBjYWxsZXIgb3ducyBvdXRyaWdodCAoZnJlc2gsIG5vdCB5ZXQgc3RvcmVkLCBzbyBpbiBub1xuICAgKiB1bmRvIHNuYXBzaG90KTogaXRzIGNvbG91ciBpcyBzZXQgaW4gcGxhY2UuIEV2ZXJ5IG90aGVyIHJlZ2lvbiB3aG9zZVxuICAgKiBjb2xvdXIgY2hhbmdlcyBpcyBjb3BpZWQuIERlZmF1bHQ6IG5ldmVyIGluIHBsYWNlLlxuICAgKi9cbiAgaW5QbGFjZT86IChyOiBSZWdpb24pID0+IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDYWxsZWQgb25jZSBwZXIgdW5rbm93biBjbGFzcyB3aGVuIGBzZXQuYXV0b1Byb21vdGVgIGlzIG9uLCB3aXRoIHRoZVxuICAgKiBwcmVzZXQgdG8gYWRkIChuYW1lIHRyaW1tZWQgaW4gYG5vcm1hbGl6ZWRgIG1hdGNoIG1vZGUsIGBzb3VyY2U6ICdhdXRvJ2ApLlxuICAgKi9cbiAgb25Qcm9tb3RlPzogKHByZXNldDogQ2xhc3NQcmVzZXQpID0+IHZvaWQ7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBlYWNoIGxhYmVsbGVkIHJlZ2lvbidzIGNvbG91ciBmcm9tIHRoZSBwcmVzZXQgc2V0IChqaXQtdWkjNzApLiBUaGVcbiAqIHByZXNldHMgYXJlIHRoZSBzb3VyY2Ugb2YgdHJ1dGg6IGEgbWF0Y2hpbmcgcHJlc2V0IGdpdmVzIHRoZSBjbGFzcyBjb2xvdXIsXG4gKiBhbiB1bmtub3duIGNsYXNzIGl0cyBkZXRlcm1pbmlzdGljIGZhbGxiYWNrLCAqKm92ZXJyaWRpbmcgYW55IGNvbG91ciBhbHJlYWR5XG4gKiBvbiB0aGUgcmVnaW9uKiogKGUuZy4gZW1iZWRkZWQgaW4gaW1wb3J0ZWQgR2VvSlNPTikuIFVubGFiZWxsZWQgcmVnaW9ucyBhbmRcbiAqIG9uZXMgdGhlIHVzZXIgcmVjb2xvdXJlZCAoYGNvbG9yT3ZlcnJpZGRlbmApIGFyZSBsZWZ0IHVudG91Y2hlZC4gVW5rbm93blxuICogY2xhc3NlcyBhcmUgcmVwb3J0ZWQgdGhyb3VnaCBgb25Qcm9tb3RlYCB3aGVuIGBhdXRvUHJvbW90ZWAgaXMgb24uXG4gKlxuICogUmV0dXJucyBhIG5ldyBhcnJheTsgcmVnaW9ucyB3aG9zZSBjb2xvdXIgaXMgYWxyZWFkeSByaWdodCBhcmUgdGhlIHNhbWVcbiAqIGluc3RhbmNlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UHJlc2V0Q29sb3JzKFxuICByZWdpb25zOiBSZWdpb25bXSxcbiAgc2V0OiBQcmVzZXRTZXQsXG4gIG9wdHM6IEFwcGx5UHJlc2V0Q29sb3JzT3B0aW9ucyA9IHt9LFxuKTogUmVnaW9uW10ge1xuICBjb25zdCBrbm93biA9IG5ldyBTZXQoc2V0LmNsYXNzZXMubWFwKChjKSA9PiBwcmVzZXRLZXkoc2V0LCBjLm5hbWUpKSk7XG4gIHJldHVybiByZWdpb25zLm1hcCgocmVnaW9uKSA9PiB7XG4gICAgaWYgKCFyZWdpb24ubGFiZWwgfHwgcmVnaW9uLmNvbG9yT3ZlcnJpZGRlbikgcmV0dXJuIHJlZ2lvbjtcbiAgICBjb25zdCBjb2xvciA9IGNvbG9yRm9yTGFiZWwocmVnaW9uLmxhYmVsLCBzZXQpO1xuICAgIGlmIChzZXQuYXV0b1Byb21vdGUgJiYgIWtub3duLmhhcyhwcmVzZXRLZXkoc2V0LCByZWdpb24ubGFiZWwpKSkge1xuICAgICAga25vd24uYWRkKHByZXNldEtleShzZXQsIHJlZ2lvbi5sYWJlbCkpO1xuICAgICAgLy8gSW4gbm9ybWFsaXplZCBtb2RlLCB0cmltIHRoZSBwcm9tb3RlZCBuYW1lIHNvIGxlYWRpbmcvdHJhaWxpbmdcbiAgICAgIC8vIHdoaXRlc3BhY2UgZG9lc24ndCBjcmVhdGUgaW52aXNpYmxlIGR1cGxpY2F0ZXMgb3Igb2RkIGRpc3BsYXkgbmFtZXMuXG4gICAgICBjb25zdCBuYW1lID0gc2V0Lm1hdGNoTW9kZSA9PT0gJ25vcm1hbGl6ZWQnID8gcmVnaW9uLmxhYmVsLnRyaW0oKSA6IHJlZ2lvbi5sYWJlbDtcbiAgICAgIG9wdHMub25Qcm9tb3RlPy4oeyBuYW1lLCBjb2xvciwgc291cmNlOiAnYXV0bycgfSk7XG4gICAgfVxuICAgIGlmIChyZWdpb24uY29sb3IgPT09IGNvbG9yKSByZXR1cm4gcmVnaW9uO1xuICAgIGlmICghb3B0cy5pblBsYWNlPy4ocmVnaW9uKSkgcmV0dXJuIHdpdGhSZWdpb25QYXRjaChyZWdpb24sIHsgY29sb3IgfSk7XG4gICAgcmVnaW9uLmNvbG9yID0gY29sb3I7XG4gICAgcmV0dXJuIHJlZ2lvbjtcbiAgfSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* Bounded undo/redo history of immutable snapshots (review RT-13, RegionStore
|
|
4
|
+
* split "RegionHistory").
|
|
5
|
+
*
|
|
6
|
+
* Holds snapshots by reference. That is only sound because the store never
|
|
7
|
+
* changes a snapshot after recording it — `RegionStore` is copy-on-write: each
|
|
8
|
+
* edit replaces the edited region (and the array) rather than mutating them —
|
|
9
|
+
* so a snapshot costs one array of pointers, not a deep clone of every vertex.
|
|
10
|
+
*
|
|
11
|
+
* Recording: call {@link record} with the state just BEFORE a change. Commits
|
|
12
|
+
* coalesce into one step:
|
|
13
|
+
* - between {@link beginGesture} and {@link endGesture} every commit folds into
|
|
14
|
+
* the step its first commit opened, however long the pauses, and a gesture
|
|
15
|
+
* never merges with a commit before or after it (RT-12);
|
|
16
|
+
* - outside a gesture, each commit within `coalesceMs` of the previous one
|
|
17
|
+
* folds into the same step.
|
|
18
|
+
* A fresh step drops the redo future. Up to `limit` steps are kept each way.
|
|
19
|
+
*/
|
|
20
|
+
export class RegionHistory {
|
|
21
|
+
constructor(limit = 10, coalesceMs = 250) {
|
|
22
|
+
this.limit = limit;
|
|
23
|
+
this.coalesceMs = coalesceMs;
|
|
24
|
+
this.undoStack = [];
|
|
25
|
+
this.redoStack = [];
|
|
26
|
+
/** True while a coalescing burst is open (further commits fold into it). */
|
|
27
|
+
this.burstOpen = false;
|
|
28
|
+
/** Open gestures (nested begin/end); while > 0 the burst stays open with no timer. */
|
|
29
|
+
this.gestureDepth = 0;
|
|
30
|
+
this.burstTimer = null;
|
|
31
|
+
/** True while a snapshot is being restored, so the restore records nothing. */
|
|
32
|
+
this.restoring = false;
|
|
33
|
+
this.canUndoSubject = new BehaviorSubject(false);
|
|
34
|
+
this.canRedoSubject = new BehaviorSubject(false);
|
|
35
|
+
/** Whether an undo step is available (drives the toolbar's Undo button). */
|
|
36
|
+
this.canUndo$ = this.canUndoSubject.asObservable();
|
|
37
|
+
/** Whether a redo step is available. */
|
|
38
|
+
this.canRedo$ = this.canRedoSubject.asObservable();
|
|
39
|
+
}
|
|
40
|
+
canUndo() {
|
|
41
|
+
return this.undoStack.length > 0;
|
|
42
|
+
}
|
|
43
|
+
canRedo() {
|
|
44
|
+
return this.redoStack.length > 0;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Record `before` — the state just before a change — unless the change
|
|
48
|
+
* folds into the step already open, or a restore is in progress.
|
|
49
|
+
*/
|
|
50
|
+
record(before) {
|
|
51
|
+
if (this.restoring)
|
|
52
|
+
return;
|
|
53
|
+
const startsBurst = !this.burstOpen;
|
|
54
|
+
if (this.gestureDepth > 0)
|
|
55
|
+
this.burstOpen = true; // closed by endGesture()
|
|
56
|
+
else
|
|
57
|
+
this.armBurst();
|
|
58
|
+
if (!startsBurst)
|
|
59
|
+
return;
|
|
60
|
+
this.push(this.undoStack, before);
|
|
61
|
+
this.redoStack = [];
|
|
62
|
+
this.emit();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Step back: returns the state to restore (and keeps `current` for redo), or
|
|
66
|
+
* undefined when there is nothing to undo. Restore it inside {@link restore}.
|
|
67
|
+
*/
|
|
68
|
+
undo(current) {
|
|
69
|
+
const snapshot = this.undoStack.pop();
|
|
70
|
+
if (snapshot === undefined)
|
|
71
|
+
return undefined;
|
|
72
|
+
this.push(this.redoStack, current);
|
|
73
|
+
this.closeBurst();
|
|
74
|
+
this.emit();
|
|
75
|
+
return snapshot;
|
|
76
|
+
}
|
|
77
|
+
/** Step forward again: the mirror of {@link undo}. */
|
|
78
|
+
redo(current) {
|
|
79
|
+
const snapshot = this.redoStack.pop();
|
|
80
|
+
if (snapshot === undefined)
|
|
81
|
+
return undefined;
|
|
82
|
+
this.push(this.undoStack, current);
|
|
83
|
+
this.closeBurst();
|
|
84
|
+
this.emit();
|
|
85
|
+
return snapshot;
|
|
86
|
+
}
|
|
87
|
+
/** Run `fn` (applying an undo/redo snapshot) without recording anything it triggers. */
|
|
88
|
+
restore(fn) {
|
|
89
|
+
this.restoring = true;
|
|
90
|
+
try {
|
|
91
|
+
fn();
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
this.restoring = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** Forget every step (an image load/switch: history never crosses images). */
|
|
98
|
+
reset() {
|
|
99
|
+
this.undoStack = [];
|
|
100
|
+
this.redoStack = [];
|
|
101
|
+
this.closeBurst();
|
|
102
|
+
this.emit();
|
|
103
|
+
}
|
|
104
|
+
/** Start one user gesture: every commit until the matching {@link endGesture} is one step. Nests. */
|
|
105
|
+
beginGesture() {
|
|
106
|
+
if (this.gestureDepth++ === 0)
|
|
107
|
+
this.closeBurst();
|
|
108
|
+
}
|
|
109
|
+
/** End the gesture opened by {@link beginGesture}; the next commit starts a new step. */
|
|
110
|
+
endGesture() {
|
|
111
|
+
if (this.gestureDepth === 0)
|
|
112
|
+
return;
|
|
113
|
+
if (--this.gestureDepth === 0)
|
|
114
|
+
this.closeBurst();
|
|
115
|
+
}
|
|
116
|
+
push(stack, state) {
|
|
117
|
+
stack.push(state);
|
|
118
|
+
if (stack.length > this.limit)
|
|
119
|
+
stack.shift();
|
|
120
|
+
}
|
|
121
|
+
/** (Re)arm the idle timer that closes the current coalescing burst. */
|
|
122
|
+
armBurst() {
|
|
123
|
+
this.burstOpen = true;
|
|
124
|
+
if (this.burstTimer)
|
|
125
|
+
clearTimeout(this.burstTimer);
|
|
126
|
+
this.burstTimer = setTimeout(() => {
|
|
127
|
+
this.burstOpen = false;
|
|
128
|
+
this.burstTimer = null;
|
|
129
|
+
}, this.coalesceMs);
|
|
130
|
+
}
|
|
131
|
+
closeBurst() {
|
|
132
|
+
this.burstOpen = false;
|
|
133
|
+
if (this.burstTimer) {
|
|
134
|
+
clearTimeout(this.burstTimer);
|
|
135
|
+
this.burstTimer = null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
emit() {
|
|
139
|
+
const canUndo = this.canUndo(), canRedo = this.canRedo();
|
|
140
|
+
if (this.canUndoSubject.value !== canUndo)
|
|
141
|
+
this.canUndoSubject.next(canUndo);
|
|
142
|
+
if (this.canRedoSubject.value !== canRedo)
|
|
143
|
+
this.canRedoSubject.next(canRedo);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWhpc3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3N0b3JlL3JlZ2lvbi1oaXN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFFbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFheEIsWUFDbUIsUUFBUSxFQUFFLEVBQ1YsYUFBYSxHQUFHO1FBRGhCLFVBQUssR0FBTCxLQUFLLENBQUs7UUFDVixlQUFVLEdBQVYsVUFBVSxDQUFNO1FBZDNCLGNBQVMsR0FBUSxFQUFFLENBQUM7UUFDcEIsY0FBUyxHQUFRLEVBQUUsQ0FBQztRQUM1Qiw0RUFBNEU7UUFDcEUsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUMxQixzRkFBc0Y7UUFDOUUsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFDakIsZUFBVSxHQUF5QyxJQUFJLENBQUM7UUFDaEUsK0VBQStFO1FBQ3ZFLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDVCxtQkFBYyxHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3JELG1CQUFjLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7UUFPdEUsNEVBQTRFO1FBQ25FLGFBQVEsR0FBd0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM1RSx3Q0FBd0M7UUFDL0IsYUFBUSxHQUF3QixJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBTHpFLENBQUM7SUFPSixPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lB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QVU7WUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztZQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFTyxVQUFVO1FBQ2hCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDOUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDekIsQ0FBQztJQUNILENBQUM7SUFFTyxJQUFJO1FBQ1YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUM1QixPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzNCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssT0FBTztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdFLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssT0FBTztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9FLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG4vKipcbiAqIEJvdW5kZWQgdW5kby9yZWRvIGhpc3Rvcnkgb2YgaW1tdXRhYmxlIHNuYXBzaG90cyAocmV2aWV3IFJULTEzLCBSZWdpb25TdG9yZVxuICogc3BsaXQgXCJSZWdpb25IaXN0b3J5XCIpLlxuICpcbiAqIEhvbGRzIHNuYXBzaG90cyBieSByZWZlcmVuY2UuIFRoYXQgaXMgb25seSBzb3VuZCBiZWNhdXNlIHRoZSBzdG9yZSBuZXZlclxuICogY2hhbmdlcyBhIHNuYXBzaG90IGFmdGVyIHJlY29yZGluZyBpdCDigJQgYFJlZ2lvblN0b3JlYCBpcyBjb3B5LW9uLXdyaXRlOiBlYWNoXG4gKiBlZGl0IHJlcGxhY2VzIHRoZSBlZGl0ZWQgcmVnaW9uIChhbmQgdGhlIGFycmF5KSByYXRoZXIgdGhhbiBtdXRhdGluZyB0aGVtIOKAlFxuICogc28gYSBzbmFwc2hvdCBjb3N0cyBvbmUgYXJyYXkgb2YgcG9pbnRlcnMsIG5vdCBhIGRlZXAgY2xvbmUgb2YgZXZlcnkgdmVydGV4LlxuICpcbiAqIFJlY29yZGluZzogY2FsbCB7QGxpbmsgcmVjb3JkfSB3aXRoIHRoZSBzdGF0ZSBqdXN0IEJFRk9SRSBhIGNoYW5nZS4gQ29tbWl0c1xuICogY29hbGVzY2UgaW50byBvbmUgc3RlcDpcbiAqICAtIGJldHdlZW4ge0BsaW5rIGJlZ2luR2VzdHVyZX0gYW5kIHtAbGluayBlbmRHZXN0dXJlfSBldmVyeSBjb21taXQgZm9sZHMgaW50b1xuICogICAgdGhlIHN0ZXAgaXRzIGZpcnN0IGNvbW1pdCBvcGVuZWQsIGhvd2V2ZXIgbG9uZyB0aGUgcGF1c2VzLCBhbmQgYSBnZXN0dXJlXG4gKiAgICBuZXZlciBtZXJnZXMgd2l0aCBhIGNvbW1pdCBiZWZvcmUgb3IgYWZ0ZXIgaXQgKFJULTEyKTtcbiAqICAtIG91dHNpZGUgYSBnZXN0dXJlLCBlYWNoIGNvbW1pdCB3aXRoaW4gYGNvYWxlc2NlTXNgIG9mIHRoZSBwcmV2aW91cyBvbmVcbiAqICAgIGZvbGRzIGludG8gdGhlIHNhbWUgc3RlcC5cbiAqIEEgZnJlc2ggc3RlcCBkcm9wcyB0aGUgcmVkbyBmdXR1cmUuIFVwIHRvIGBsaW1pdGAgc3RlcHMgYXJlIGtlcHQgZWFjaCB3YXkuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25IaXN0b3J5PFQ+IHtcbiAgcHJpdmF0ZSB1bmRvU3RhY2s6IFRbXSA9IFtdO1xuICBwcml2YXRlIHJlZG9TdGFjazogVFtdID0gW107XG4gIC8qKiBUcnVlIHdoaWxlIGEgY29hbGVzY2luZyBidXJzdCBpcyBvcGVuIChmdXJ0aGVyIGNvbW1pdHMgZm9sZCBpbnRvIGl0KS4gKi9cbiAgcHJpdmF0ZSBidXJzdE9wZW4gPSBmYWxzZTtcbiAgLyoqIE9wZW4gZ2VzdHVyZXMgKG5lc3RlZCBiZWdpbi9lbmQpOyB3aGlsZSA+IDAgdGhlIGJ1cnN0IHN0YXlzIG9wZW4gd2l0aCBubyB0aW1lci4gKi9cbiAgcHJpdmF0ZSBnZXN0dXJlRGVwdGggPSAwO1xuICBwcml2YXRlIGJ1cnN0VGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUcnVlIHdoaWxlIGEgc25hcHNob3QgaXMgYmVpbmcgcmVzdG9yZWQsIHNvIHRoZSByZXN0b3JlIHJlY29yZHMgbm90aGluZy4gKi9cbiAgcHJpdmF0ZSByZXN0b3JpbmcgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSBjYW5VbmRvU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNhblJlZG9TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsaW1pdCA9IDEwLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29hbGVzY2VNcyA9IDI1MCxcbiAgKSB7fVxuXG4gIC8qKiBXaGV0aGVyIGFuIHVuZG8gc3RlcCBpcyBhdmFpbGFibGUgKGRyaXZlcyB0aGUgdG9vbGJhcidzIFVuZG8gYnV0dG9uKS4gKi9cbiAgcmVhZG9ubHkgY2FuVW5kbyQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLmNhblVuZG9TdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAvKiogV2hldGhlciBhIHJlZG8gc3RlcCBpcyBhdmFpbGFibGUuICovXG4gIHJlYWRvbmx5IGNhblJlZG8kOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5jYW5SZWRvU3ViamVjdC5hc09ic2VydmFibGUoKTtcblxuICBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnVuZG9TdGFjay5sZW5ndGggPiAwO1xuICB9XG5cbiAgY2FuUmVkbygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWRvU3RhY2subGVuZ3RoID4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvcmQgYGJlZm9yZWAg4oCUIHRoZSBzdGF0ZSBqdXN0IGJlZm9yZSBhIGNoYW5nZSDigJQgdW5sZXNzIHRoZSBjaGFuZ2VcbiAgICogZm9sZHMgaW50byB0aGUgc3RlcCBhbHJlYWR5IG9wZW4sIG9yIGEgcmVzdG9yZSBpcyBpbiBwcm9ncmVzcy5cbiAgICovXG4gIHJlY29yZChiZWZvcmU6IFQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5yZXN0b3JpbmcpIHJldHVybjtcbiAgICBjb25zdCBzdGFydHNCdXJzdCA9ICF0aGlzLmJ1cnN0T3BlbjtcbiAgICBpZiAodGhpcy5nZXN0dXJlRGVwdGggPiAwKVxuICAgICAgdGhpcy5idXJzdE9wZW4gPSB0cnVlOyAvLyBjbG9zZWQgYnkgZW5kR2VzdHVyZSgpXG4gICAgZWxzZSB0aGlzLmFybUJ1cnN0KCk7XG4gICAgaWYgKCFzdGFydHNCdXJzdCkgcmV0dXJuO1xuICAgIHRoaXMucHVzaCh0aGlzLnVuZG9TdGFjaywgYmVmb3JlKTtcbiAgICB0aGlzLnJlZG9TdGFjayA9IFtdO1xuICAgIHRoaXMuZW1pdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0ZXAgYmFjazogcmV0dXJucyB0aGUgc3RhdGUgdG8gcmVzdG9yZSAoYW5kIGtlZXBzIGBjdXJyZW50YCBmb3IgcmVkbyksIG9yXG4gICAqIHVuZGVmaW5lZCB3aGVuIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5kby4gUmVzdG9yZSBpdCBpbnNpZGUge0BsaW5rIHJlc3RvcmV9LlxuICAgKi9cbiAgdW5kbyhjdXJyZW50OiBUKTogVCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLnVuZG9TdGFjay5wb3AoKTtcbiAgICBpZiAoc25hcHNob3QgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB0aGlzLnB1c2godGhpcy5yZWRvU3RhY2ssIGN1cnJlbnQpO1xuICAgIHRoaXMuY2xvc2VCdXJzdCgpO1xuICAgIHRoaXMuZW1pdCgpO1xuICAgIHJldHVybiBzbmFwc2hvdDtcbiAgfVxuXG4gIC8qKiBTdGVwIGZvcndhcmQgYWdhaW46IHRoZSBtaXJyb3Igb2Yge0BsaW5rIHVuZG99LiAqL1xuICByZWRvKGN1cnJlbnQ6IFQpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBzbmFwc2hvdCA9IHRoaXMucmVkb1N0YWNrLnBvcCgpO1xuICAgIGlmIChzbmFwc2hvdCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHRoaXMucHVzaCh0aGlzLnVuZG9TdGFjaywgY3VycmVudCk7XG4gICAgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gICAgcmV0dXJuIHNuYXBzaG90O1xuICB9XG5cbiAgLyoqIFJ1biBgZm5gIChhcHBseWluZyBhbiB1bmRvL3JlZG8gc25hcHNob3QpIHdpdGhvdXQgcmVjb3JkaW5nIGFueXRoaW5nIGl0IHRyaWdnZXJzLiAqL1xuICByZXN0b3JlKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5yZXN0b3JpbmcgPSB0cnVlO1xuICAgIHRyeSB7XG4gICAgICBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLnJlc3RvcmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBGb3JnZXQgZXZlcnkgc3RlcCAoYW4gaW1hZ2UgbG9hZC9zd2l0Y2g6IGhpc3RvcnkgbmV2ZXIgY3Jvc3NlcyBpbWFnZXMpLiAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLnVuZG9TdGFjayA9IFtdO1xuICAgIHRoaXMucmVkb1N0YWNrID0gW107XG4gICAgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gICAgdGhpcy5lbWl0KCk7XG4gIH1cblxuICAvKiogU3RhcnQgb25lIHVzZXIgZ2VzdHVyZTogZXZlcnkgY29tbWl0IHVudGlsIHRoZSBtYXRjaGluZyB7QGxpbmsgZW5kR2VzdHVyZX0gaXMgb25lIHN0ZXAuIE5lc3RzLiAqL1xuICBiZWdpbkdlc3R1cmUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZ2VzdHVyZURlcHRoKysgPT09IDApIHRoaXMuY2xvc2VCdXJzdCgpO1xuICB9XG5cbiAgLyoqIEVuZCB0aGUgZ2VzdHVyZSBvcGVuZWQgYnkge0BsaW5rIGJlZ2luR2VzdHVyZX07IHRoZSBuZXh0IGNvbW1pdCBzdGFydHMgYSBuZXcgc3RlcC4gKi9cbiAgZW5kR2VzdHVyZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5nZXN0dXJlRGVwdGggPT09IDApIHJldHVybjtcbiAgICBpZiAoLS10aGlzLmdlc3R1cmVEZXB0aCA9PT0gMCkgdGhpcy5jbG9zZUJ1cnN0KCk7XG4gIH1cblxuICBwcml2YXRlIHB1c2goc3RhY2s6IFRbXSwgc3RhdGU6IFQpOiB2b2lkIHtcbiAgICBzdGFjay5wdXNoKHN0YXRlKTtcbiAgICBpZiAoc3RhY2subGVuZ3RoID4gdGhpcy5saW1pdCkgc3RhY2suc2hpZnQoKTtcbiAgfVxuXG4gIC8qKiAoUmUpYXJtIHRoZSBpZGxlIHRpbWVyIHRoYXQgY2xvc2VzIHRoZSBjdXJyZW50IGNvYWxlc2NpbmcgYnVyc3QuICovXG4gIHByaXZhdGUgYXJtQnVyc3QoKTogdm9pZCB7XG4gICAgdGhpcy5idXJzdE9wZW4gPSB0cnVlO1xuICAgIGlmICh0aGlzLmJ1cnN0VGltZXIpIGNsZWFyVGltZW91dCh0aGlzLmJ1cnN0VGltZXIpO1xuICAgIHRoaXMuYnVyc3RUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5idXJzdE9wZW4gPSBmYWxzZTtcbiAgICAgIHRoaXMuYnVyc3RUaW1lciA9IG51bGw7XG4gICAgfSwgdGhpcy5jb2FsZXNjZU1zKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VCdXJzdCgpOiB2b2lkIHtcbiAgICB0aGlzLmJ1cnN0T3BlbiA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmJ1cnN0VGltZXIpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmJ1cnN0VGltZXIpO1xuICAgICAgdGhpcy5idXJzdFRpbWVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGVtaXQoKTogdm9pZCB7XG4gICAgY29uc3QgY2FuVW5kbyA9IHRoaXMuY2FuVW5kbygpLFxuICAgICAgY2FuUmVkbyA9IHRoaXMuY2FuUmVkbygpO1xuICAgIGlmICh0aGlzLmNhblVuZG9TdWJqZWN0LnZhbHVlICE9PSBjYW5VbmRvKSB0aGlzLmNhblVuZG9TdWJqZWN0Lm5leHQoY2FuVW5kbyk7XG4gICAgaWYgKHRoaXMuY2FuUmVkb1N1YmplY3QudmFsdWUgIT09IGNhblJlZG8pIHRoaXMuY2FuUmVkb1N1YmplY3QubmV4dChjYW5SZWRvKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { withRegionZ } from '../models/region-clone';
|
|
2
|
+
/**
|
|
3
|
+
* Where the region store's *live* set comes from and goes back to: a per-image
|
|
4
|
+
* cache (keyed by the image's first URL, else its file name) and, while a
|
|
5
|
+
* z-stack is loaded, a per-slice map for the current image (jit-ui#93).
|
|
6
|
+
*
|
|
7
|
+
* The owner holds the live array; every method that can change scope takes
|
|
8
|
+
* the current live array (to capture its edits) and returns the incoming
|
|
9
|
+
* live set, or null when nothing changes. It never changes a region: slice
|
|
10
|
+
* tags are applied to copies ({@link withRegionZ}).
|
|
11
|
+
*/
|
|
12
|
+
export class RegionScopeCache {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.byImage = new Map();
|
|
15
|
+
this.bySlice = new Map();
|
|
16
|
+
this.stack = false;
|
|
17
|
+
this.sliceZ = 0;
|
|
18
|
+
this.layout = 'combined';
|
|
19
|
+
/** Slices loaded with regions: a per-slice-file save re-writes them even when
|
|
20
|
+
* now empty, so clearing a slice and saving removes its geojson. */
|
|
21
|
+
this.initialNonEmpty = new Set();
|
|
22
|
+
}
|
|
23
|
+
/** The cache key for an image: its first URL, else its file name. */
|
|
24
|
+
static imageKey(imageInfo) {
|
|
25
|
+
if (!imageInfo)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (imageInfo.urls && imageInfo.urls.length > 0 && imageInfo.urls[0]) {
|
|
28
|
+
return imageInfo.urls[0];
|
|
29
|
+
}
|
|
30
|
+
return imageInfo.fileName || undefined;
|
|
31
|
+
}
|
|
32
|
+
/** True while a z-stack is loaded and regions are held per slice. */
|
|
33
|
+
get stackMode() {
|
|
34
|
+
return this.stack;
|
|
35
|
+
}
|
|
36
|
+
/** The current display slice (zero-based; 0 outside stack mode unless set). */
|
|
37
|
+
get displaySlice() {
|
|
38
|
+
return this.sliceZ;
|
|
39
|
+
}
|
|
40
|
+
/** How the current stack persists; meaningless outside stack mode. */
|
|
41
|
+
get saveLayout() {
|
|
42
|
+
return this.layout;
|
|
43
|
+
}
|
|
44
|
+
/** Record `live` as the current image's regions. */
|
|
45
|
+
sync(live) {
|
|
46
|
+
if (this.imageKey)
|
|
47
|
+
this.byImage.set(this.imageKey, live.slice());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Make `key` the active image: ends stack mode, caches `live` under the
|
|
51
|
+
* outgoing image, and returns the incoming image's regions (or []). Null when
|
|
52
|
+
* `key` already is the active image (repeated replots keep their regions).
|
|
53
|
+
*/
|
|
54
|
+
switchImage(key, live) {
|
|
55
|
+
if (this.imageKey === key)
|
|
56
|
+
return null;
|
|
57
|
+
// The loader re-enters stack mode afterwards if the new image is a z-stack.
|
|
58
|
+
this.exitStack();
|
|
59
|
+
if (this.imageKey)
|
|
60
|
+
this.byImage.set(this.imageKey, live.slice());
|
|
61
|
+
this.imageKey = key;
|
|
62
|
+
const cached = key ? this.byImage.get(key) : undefined;
|
|
63
|
+
return cached ? cached.slice() : [];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Enter per-slice mode with `slices` (already admitted by the store, each
|
|
67
|
+
* region tagged with its slice) and return `initialZ`'s slice as the live set.
|
|
68
|
+
*/
|
|
69
|
+
enterStack(slices, initialZ, layout) {
|
|
70
|
+
this.stack = true;
|
|
71
|
+
this.layout = layout;
|
|
72
|
+
this.sliceZ = initialZ || 0;
|
|
73
|
+
this.bySlice = new Map();
|
|
74
|
+
this.initialNonEmpty = new Set();
|
|
75
|
+
for (const [z, regs] of slices) {
|
|
76
|
+
this.bySlice.set(z, regs);
|
|
77
|
+
if (regs.length)
|
|
78
|
+
this.initialNonEmpty.add(z);
|
|
79
|
+
}
|
|
80
|
+
return (this.bySlice.get(this.sliceZ) ?? []).slice();
|
|
81
|
+
}
|
|
82
|
+
/** Leave stack mode; a no-op outside it. */
|
|
83
|
+
exitStack() {
|
|
84
|
+
if (!this.stack)
|
|
85
|
+
return;
|
|
86
|
+
this.stack = false;
|
|
87
|
+
this.sliceZ = 0;
|
|
88
|
+
this.bySlice = new Map();
|
|
89
|
+
this.initialNonEmpty = new Set();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Show slice `z`: capture `live` into the current slice and return slice
|
|
93
|
+
* `z`'s regions. Null when nothing swaps — the same slice, or outside stack
|
|
94
|
+
* mode (where the index is only recorded).
|
|
95
|
+
*/
|
|
96
|
+
showSlice(z, live) {
|
|
97
|
+
const next = z || 0;
|
|
98
|
+
if (!this.stack) {
|
|
99
|
+
this.sliceZ = next;
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (this.sliceZ === next)
|
|
103
|
+
return null;
|
|
104
|
+
this.bySlice.set(this.sliceZ, live.slice());
|
|
105
|
+
this.sliceZ = next;
|
|
106
|
+
return (this.bySlice.get(next) ?? []).slice();
|
|
107
|
+
}
|
|
108
|
+
/** Every slice's regions (current one from `live`), each tagged with its z,
|
|
109
|
+
* in slice order; `live` itself outside stack mode. */
|
|
110
|
+
sliceRegions(live) {
|
|
111
|
+
if (!this.stack)
|
|
112
|
+
return live.slice();
|
|
113
|
+
this.bySlice.set(this.sliceZ, live.slice());
|
|
114
|
+
const out = [];
|
|
115
|
+
const zs = Array.from(this.bySlice.keys()).sort((a, b) => a - b);
|
|
116
|
+
for (const z of zs) {
|
|
117
|
+
for (const r of this.bySlice.get(z))
|
|
118
|
+
out.push(withRegionZ(r, z));
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
/** Slices to write on a per-slice-file save: every slice with regions plus
|
|
123
|
+
* every slice loaded non-empty (re-written empty when cleared). Empty
|
|
124
|
+
* outside stack mode. */
|
|
125
|
+
stackSaveSlices(live) {
|
|
126
|
+
const out = new Map();
|
|
127
|
+
if (!this.stack)
|
|
128
|
+
return out;
|
|
129
|
+
this.bySlice.set(this.sliceZ, live.slice());
|
|
130
|
+
const zs = new Set(this.initialNonEmpty);
|
|
131
|
+
for (const [z, regs] of this.bySlice)
|
|
132
|
+
if (regs.length)
|
|
133
|
+
zs.add(z);
|
|
134
|
+
for (const z of Array.from(zs).sort((a, b) => a - b)) {
|
|
135
|
+
out.set(z, (this.bySlice.get(z) ?? []).map((r) => withRegionZ(r, z)));
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXNjb3BlLWNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zdG9yZS9yZWdpb24tc2NvcGUtY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBT3JEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFBN0I7UUFDVSxZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFHdEMsWUFBTyxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO1FBQ3RDLFVBQUssR0FBRyxLQUFLLENBQUM7UUFDZCxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsV0FBTSxHQUFvQixVQUFVLENBQUM7UUFDN0M7NkVBQ3FFO1FBQzdELG9CQUFlLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQXVIOUMsQ0FBQztJQXJIQyxxRUFBcUU7SUFDckUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFpQztRQUMvQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQ2pDLElBQUksU0FBUyxDQUFDLElBQUksSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JFLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUMsUUFBUSxJQUFJLFNBQVMsQ0FBQztJQUN6QyxDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRUQsK0VBQStFO0lBQy9FLElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsc0VBQXNF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QztRQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sRUFBRSxHQUFHLElBQUksR0FBRyxDQUFTLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNqRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU87WUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNO2dCQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakUsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3JELEdBQUcsQ0FBQyxHQUFHLENBQ0wsQ0FBQyxFQUNELENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQzFELENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvbiB9IGZyb20gJy4uL21vZGVscy9yZWdpb24nO1xuaW1wb3J0IHsgd2l0aFJlZ2lvblogfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uLWNsb25lJztcblxuLyoqIEhvdyBhIHN0YWNrJ3MgcmVnaW9ucyByb3VuZC10cmlwIHRvIGRpc2sgKGppdC11aSM5Myk6IGBjb21iaW5lZGAgd3JpdGVzIG9uZVxuICogIHotaW5kZXhlZCBnZW9qc29uIChzaW5nbGUtZmlsZSB6LXN0YWNrLCBRdVBhdGggc2NoZW1hKTsgYHBlci1zbGljZS1maWxlYFxuICogIHdyaXRlcyBvbmUgZ2VvanNvbiBwZXIgc2xpY2UtZmlsZSAoYSBmb2xkZXIgb2YgbnVtYmVyZWQgaW1hZ2VzKS4gKi9cbmV4cG9ydCB0eXBlIFN0YWNrU2F2ZUxheW91dCA9ICdjb21iaW5lZCcgfCAncGVyLXNsaWNlLWZpbGUnO1xuXG4vKipcbiAqIFdoZXJlIHRoZSByZWdpb24gc3RvcmUncyAqbGl2ZSogc2V0IGNvbWVzIGZyb20gYW5kIGdvZXMgYmFjayB0bzogYSBwZXItaW1hZ2VcbiAqIGNhY2hlIChrZXllZCBieSB0aGUgaW1hZ2UncyBmaXJzdCBVUkwsIGVsc2UgaXRzIGZpbGUgbmFtZSkgYW5kLCB3aGlsZSBhXG4gKiB6LXN0YWNrIGlzIGxvYWRlZCwgYSBwZXItc2xpY2UgbWFwIGZvciB0aGUgY3VycmVudCBpbWFnZSAoaml0LXVpIzkzKS5cbiAqXG4gKiBUaGUgb3duZXIgaG9sZHMgdGhlIGxpdmUgYXJyYXk7IGV2ZXJ5IG1ldGhvZCB0aGF0IGNhbiBjaGFuZ2Ugc2NvcGUgdGFrZXNcbiAqIHRoZSBjdXJyZW50IGxpdmUgYXJyYXkgKHRvIGNhcHR1cmUgaXRzIGVkaXRzKSBhbmQgcmV0dXJucyB0aGUgaW5jb21pbmdcbiAqIGxpdmUgc2V0LCBvciBudWxsIHdoZW4gbm90aGluZyBjaGFuZ2VzLiBJdCBuZXZlciBjaGFuZ2VzIGEgcmVnaW9uOiBzbGljZVxuICogdGFncyBhcmUgYXBwbGllZCB0byBjb3BpZXMgKHtAbGluayB3aXRoUmVnaW9uWn0pLlxuICovXG5leHBvcnQgY2xhc3MgUmVnaW9uU2NvcGVDYWNoZSB7XG4gIHByaXZhdGUgYnlJbWFnZSA9IG5ldyBNYXA8c3RyaW5nLCBSZWdpb25bXT4oKTtcbiAgcHJpdmF0ZSBpbWFnZUtleTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgYnlTbGljZSA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgcHJpdmF0ZSBzdGFjayA9IGZhbHNlO1xuICBwcml2YXRlIHNsaWNlWiA9IDA7XG4gIHByaXZhdGUgbGF5b3V0OiBTdGFja1NhdmVMYXlvdXQgPSAnY29tYmluZWQnO1xuICAvKiogU2xpY2VzIGxvYWRlZCB3aXRoIHJlZ2lvbnM6IGEgcGVyLXNsaWNlLWZpbGUgc2F2ZSByZS13cml0ZXMgdGhlbSBldmVuIHdoZW5cbiAgICogIG5vdyBlbXB0eSwgc28gY2xlYXJpbmcgYSBzbGljZSBhbmQgc2F2aW5nIHJlbW92ZXMgaXRzIGdlb2pzb24uICovXG4gIHByaXZhdGUgaW5pdGlhbE5vbkVtcHR5ID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgLyoqIFRoZSBjYWNoZSBrZXkgZm9yIGFuIGltYWdlOiBpdHMgZmlyc3QgVVJMLCBlbHNlIGl0cyBmaWxlIG5hbWUuICovXG4gIHN0YXRpYyBpbWFnZUtleShpbWFnZUluZm86IElJbWFnZUluZm8gfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghaW1hZ2VJbmZvKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChpbWFnZUluZm8udXJscyAmJiBpbWFnZUluZm8udXJscy5sZW5ndGggPiAwICYmIGltYWdlSW5mby51cmxzWzBdKSB7XG4gICAgICByZXR1cm4gaW1hZ2VJbmZvLnVybHNbMF07XG4gICAgfVxuICAgIHJldHVybiBpbWFnZUluZm8uZmlsZU5hbWUgfHwgdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIFRydWUgd2hpbGUgYSB6LXN0YWNrIGlzIGxvYWRlZCBhbmQgcmVnaW9ucyBhcmUgaGVsZCBwZXIgc2xpY2UuICovXG4gIGdldCBzdGFja01vZGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc3RhY2s7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnQgZGlzcGxheSBzbGljZSAoemVyby1iYXNlZDsgMCBvdXRzaWRlIHN0YWNrIG1vZGUgdW5sZXNzIHNldCkuICovXG4gIGdldCBkaXNwbGF5U2xpY2UoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zbGljZVo7XG4gIH1cblxuICAvKiogSG93IHRoZSBjdXJyZW50IHN0YWNrIHBlcnNpc3RzOyBtZWFuaW5nbGVzcyBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIGdldCBzYXZlTGF5b3V0KCk6IFN0YWNrU2F2ZUxheW91dCB7XG4gICAgcmV0dXJuIHRoaXMubGF5b3V0O1xuICB9XG5cbiAgLyoqIFJlY29yZCBgbGl2ZWAgYXMgdGhlIGN1cnJlbnQgaW1hZ2UncyByZWdpb25zLiAqL1xuICBzeW5jKGxpdmU6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW1hZ2VLZXkpIHRoaXMuYnlJbWFnZS5zZXQodGhpcy5pbWFnZUtleSwgbGl2ZS5zbGljZSgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIGBrZXlgIHRoZSBhY3RpdmUgaW1hZ2U6IGVuZHMgc3RhY2sgbW9kZSwgY2FjaGVzIGBsaXZlYCB1bmRlciB0aGVcbiAgICogb3V0Z29pbmcgaW1hZ2UsIGFuZCByZXR1cm5zIHRoZSBpbmNvbWluZyBpbWFnZSdzIHJlZ2lvbnMgKG9yIFtdKS4gTnVsbCB3aGVuXG4gICAqIGBrZXlgIGFscmVhZHkgaXMgdGhlIGFjdGl2ZSBpbWFnZSAocmVwZWF0ZWQgcmVwbG90cyBrZWVwIHRoZWlyIHJlZ2lvbnMpLlxuICAgKi9cbiAgc3dpdGNoSW1hZ2Uoa2V5OiBzdHJpbmcgfCB1bmRlZmluZWQsIGxpdmU6IFJlZ2lvbltdKTogUmVnaW9uW10gfCBudWxsIHtcbiAgICBpZiAodGhpcy5pbWFnZUtleSA9PT0ga2V5KSByZXR1cm4gbnVsbDtcbiAgICAvLyBUaGUgbG9hZGVyIHJlLWVudGVycyBzdGFjayBtb2RlIGFmdGVyd2FyZHMgaWYgdGhlIG5ldyBpbWFnZSBpcyBhIHotc3RhY2suXG4gICAgdGhpcy5leGl0U3RhY2soKTtcbiAgICBpZiAodGhpcy5pbWFnZUtleSkgdGhpcy5ieUltYWdlLnNldCh0aGlzLmltYWdlS2V5LCBsaXZlLnNsaWNlKCkpO1xuICAgIHRoaXMuaW1hZ2VLZXkgPSBrZXk7XG4gICAgY29uc3QgY2FjaGVkID0ga2V5ID8gdGhpcy5ieUltYWdlLmdldChrZXkpIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiBjYWNoZWQgPyBjYWNoZWQuc2xpY2UoKSA6IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEVudGVyIHBlci1zbGljZSBtb2RlIHdpdGggYHNsaWNlc2AgKGFscmVhZHkgYWRtaXR0ZWQgYnkgdGhlIHN0b3JlLCBlYWNoXG4gICAqIHJlZ2lvbiB0YWdnZWQgd2l0aCBpdHMgc2xpY2UpIGFuZCByZXR1cm4gYGluaXRpYWxaYCdzIHNsaWNlIGFzIHRoZSBsaXZlIHNldC5cbiAgICovXG4gIGVudGVyU3RhY2soc2xpY2VzOiBNYXA8bnVtYmVyLCBSZWdpb25bXT4sIGluaXRpYWxaOiBudW1iZXIsIGxheW91dDogU3RhY2tTYXZlTGF5b3V0KTogUmVnaW9uW10ge1xuICAgIHRoaXMuc3RhY2sgPSB0cnVlO1xuICAgIHRoaXMubGF5b3V0ID0gbGF5b3V0O1xuICAgIHRoaXMuc2xpY2VaID0gaW5pdGlhbFogfHwgMDtcbiAgICB0aGlzLmJ5U2xpY2UgPSBuZXcgTWFwPG51bWJlciwgUmVnaW9uW10+KCk7XG4gICAgdGhpcy5pbml0aWFsTm9uRW1wdHkgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IFt6LCByZWdzXSBvZiBzbGljZXMpIHtcbiAgICAgIHRoaXMuYnlTbGljZS5zZXQoeiwgcmVncyk7XG4gICAgICBpZiAocmVncy5sZW5ndGgpIHRoaXMuaW5pdGlhbE5vbkVtcHR5LmFkZCh6KTtcbiAgICB9XG4gICAgcmV0dXJuICh0aGlzLmJ5U2xpY2UuZ2V0KHRoaXMuc2xpY2VaKSA/PyBbXSkuc2xpY2UoKTtcbiAgfVxuXG4gIC8qKiBMZWF2ZSBzdGFjayBtb2RlOyBhIG5vLW9wIG91dHNpZGUgaXQuICovXG4gIGV4aXRTdGFjaygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc3RhY2spIHJldHVybjtcbiAgICB0aGlzLnN0YWNrID0gZmFsc2U7XG4gICAgdGhpcy5zbGljZVogPSAwO1xuICAgIHRoaXMuYnlTbGljZSA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgICB0aGlzLmluaXRpYWxOb25FbXB0eSA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3cgc2xpY2UgYHpgOiBjYXB0dXJlIGBsaXZlYCBpbnRvIHRoZSBjdXJyZW50IHNsaWNlIGFuZCByZXR1cm4gc2xpY2VcbiAgICogYHpgJ3MgcmVnaW9ucy4gTnVsbCB3aGVuIG5vdGhpbmcgc3dhcHMg4oCUIHRoZSBzYW1lIHNsaWNlLCBvciBvdXRzaWRlIHN0YWNrXG4gICAqIG1vZGUgKHdoZXJlIHRoZSBpbmRleCBpcyBvbmx5IHJlY29yZGVkKS5cbiAgICovXG4gIHNob3dTbGljZSh6OiBudW1iZXIsIGxpdmU6IFJlZ2lvbltdKTogUmVnaW9uW10gfCBudWxsIHtcbiAgICBjb25zdCBuZXh0ID0geiB8fCAwO1xuICAgIGlmICghdGhpcy5zdGFjaykge1xuICAgICAgdGhpcy5zbGljZVogPSBuZXh0O1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICh0aGlzLnNsaWNlWiA9PT0gbmV4dCkgcmV0dXJuIG51bGw7XG4gICAgdGhpcy5ieVNsaWNlLnNldCh0aGlzLnNsaWNlWiwgbGl2ZS5zbGljZSgpKTtcbiAgICB0aGlzLnNsaWNlWiA9IG5leHQ7XG4gICAgcmV0dXJuICh0aGlzLmJ5U2xpY2UuZ2V0KG5leHQpID8/IFtdKS5zbGljZSgpO1xuICB9XG5cbiAgLyoqIEV2ZXJ5IHNsaWNlJ3MgcmVnaW9ucyAoY3VycmVudCBvbmUgZnJvbSBgbGl2ZWApLCBlYWNoIHRhZ2dlZCB3aXRoIGl0cyB6LFxuICAgKiAgaW4gc2xpY2Ugb3JkZXI7IGBsaXZlYCBpdHNlbGYgb3V0c2lkZSBzdGFjayBtb2RlLiAqL1xuICBzbGljZVJlZ2lvbnMobGl2ZTogUmVnaW9uW10pOiBSZWdpb25bXSB7XG4gICAgaWYgKCF0aGlzLnN0YWNrKSByZXR1cm4gbGl2ZS5zbGljZSgpO1xuICAgIHRoaXMuYnlTbGljZS5zZXQodGhpcy5zbGljZVosIGxpdmUuc2xpY2UoKSk7XG4gICAgY29uc3Qgb3V0OiBSZWdpb25bXSA9IFtdO1xuICAgIGNvbnN0IHpzID0gQXJyYXkuZnJvbSh0aGlzLmJ5U2xpY2Uua2V5cygpKS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gICAgZm9yIChjb25zdCB6IG9mIHpzKSB7XG4gICAgICBmb3IgKGNvbnN0IHIgb2YgdGhpcy5ieVNsaWNlLmdldCh6KSBhcyBSZWdpb25bXSkgb3V0LnB1c2god2l0aFJlZ2lvbloociwgeikpO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqIFNsaWNlcyB0byB3cml0ZSBvbiBhIHBlci1zbGljZS1maWxlIHNhdmU6IGV2ZXJ5IHNsaWNlIHdpdGggcmVnaW9ucyBwbHVzXG4gICAqICBldmVyeSBzbGljZSBsb2FkZWQgbm9uLWVtcHR5IChyZS13cml0dGVuIGVtcHR5IHdoZW4gY2xlYXJlZCkuIEVtcHR5XG4gICAqICBvdXRzaWRlIHN0YWNrIG1vZGUuICovXG4gIHN0YWNrU2F2ZVNsaWNlcyhsaXZlOiBSZWdpb25bXSk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IE1hcDxudW1iZXIsIFJlZ2lvbltdPigpO1xuICAgIGlmICghdGhpcy5zdGFjaykgcmV0dXJuIG91dDtcbiAgICB0aGlzLmJ5U2xpY2Uuc2V0KHRoaXMuc2xpY2VaLCBsaXZlLnNsaWNlKCkpO1xuICAgIGNvbnN0IHpzID0gbmV3IFNldDxudW1iZXI+KHRoaXMuaW5pdGlhbE5vbkVtcHR5KTtcbiAgICBmb3IgKGNvbnN0IFt6LCByZWdzXSBvZiB0aGlzLmJ5U2xpY2UpIGlmIChyZWdzLmxlbmd0aCkgenMuYWRkKHopO1xuICAgIGZvciAoY29uc3QgeiBvZiBBcnJheS5mcm9tKHpzKS5zb3J0KChhLCBiKSA9PiBhIC0gYikpIHtcbiAgICAgIG91dC5zZXQoXG4gICAgICAgIHosXG4gICAgICAgICh0aGlzLmJ5U2xpY2UuZ2V0KHopID8/IFtdKS5tYXAoKHIpID0+IHdpdGhSZWdpb25aKHIsIHopKSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BehaviorSubject } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* Region selection, held by region *id* (stable across edits, reorders and
|
|
4
|
+
* delete/add cycles) and projected to array indices for the IRegionStore
|
|
5
|
+
* boundary. Changing the ids ({@link replace}, {@link retain}) is silent; the
|
|
6
|
+
* owner calls {@link sync} once the region array it projects onto is final,
|
|
7
|
+
* which prunes ids that no longer exist and emits {@link indices$} only when
|
|
8
|
+
* the index set changed.
|
|
9
|
+
*/
|
|
10
|
+
export class RegionSelection {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.selected = [];
|
|
13
|
+
this.indicesSubject = new BehaviorSubject([]);
|
|
14
|
+
/** The selected regions' current array indices (emits on change only). */
|
|
15
|
+
this.indices$ = this.indicesSubject.asObservable();
|
|
16
|
+
}
|
|
17
|
+
/** The selected indices as last projected by {@link sync}. */
|
|
18
|
+
get indices() {
|
|
19
|
+
return this.indicesSubject.value;
|
|
20
|
+
}
|
|
21
|
+
/** The selected ids, in selection order. */
|
|
22
|
+
get ids() {
|
|
23
|
+
return this.selected;
|
|
24
|
+
}
|
|
25
|
+
/** Replace the selected ids (no emit until {@link sync}). */
|
|
26
|
+
replace(ids) {
|
|
27
|
+
this.selected = ids.slice();
|
|
28
|
+
}
|
|
29
|
+
/** Keep only the ids `keep` accepts (no emit until {@link sync}). */
|
|
30
|
+
retain(keep) {
|
|
31
|
+
this.selected = this.selected.filter(keep);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Select by array index into `regions`: invalid and duplicate indices are
|
|
35
|
+
* dropped, the given order is kept. Projects and emits.
|
|
36
|
+
*/
|
|
37
|
+
selectIndices(indices, regions) {
|
|
38
|
+
const ids = [];
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
for (const i of indices || []) {
|
|
41
|
+
if (!Number.isFinite(i) || i < 0 || i >= regions.length)
|
|
42
|
+
continue;
|
|
43
|
+
const id = regions[i].id;
|
|
44
|
+
if (!seen.has(id)) {
|
|
45
|
+
seen.add(id);
|
|
46
|
+
ids.push(id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.selected = ids;
|
|
50
|
+
this.sync(regions);
|
|
51
|
+
}
|
|
52
|
+
/** Project the selected ids onto `regions`, pruning ids it no longer holds,
|
|
53
|
+
* and emit if the index set changed. */
|
|
54
|
+
sync(regions) {
|
|
55
|
+
const indexOf = new Map();
|
|
56
|
+
regions.forEach((r, i) => {
|
|
57
|
+
if (!indexOf.has(r.id))
|
|
58
|
+
indexOf.set(r.id, i);
|
|
59
|
+
});
|
|
60
|
+
const indices = [];
|
|
61
|
+
const live = [];
|
|
62
|
+
for (const id of this.selected) {
|
|
63
|
+
const idx = indexOf.get(id);
|
|
64
|
+
if (idx !== undefined) {
|
|
65
|
+
indices.push(idx);
|
|
66
|
+
live.push(id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
this.selected = live;
|
|
70
|
+
if (!sameIndices(this.indicesSubject.value, indices))
|
|
71
|
+
this.indicesSubject.next(indices);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function sameIndices(a, b) {
|
|
75
|
+
if (a.length !== b.length)
|
|
76
|
+
return false;
|
|
77
|
+
for (let i = 0; i < a.length; i++)
|
|
78
|
+
if (a[i] !== b[i])
|
|
79
|
+
return false;
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXNlbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3RvcmUvcmVnaW9uLXNlbGVjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBT25EOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUE1QjtRQUNVLGFBQVEsR0FBYSxFQUFFLENBQUM7UUFDZixtQkFBYyxHQUFHLElBQUksZUFBZSxDQUFXLEVBQUUsQ0FBQyxDQUFDO1FBRXBFLDBFQUEwRTtRQUNqRSxhQUFRLEdBQXlCLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLENBQUM7SUE0RC9FLENBQUM7SUExREMsOERBQThEO0lBQzlELElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUM7SUFDbkMsQ0FBQztJQUVELDRDQUE0QztJQUM1QyxJQUFJLEdBQUc7UUFDTCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELDZEQUE2RDtJQUM3RCxPQUFPLENBQUMsR0FBYTtRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLE1BQU0sQ0FBQyxJQUE2QjtRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhLENBQUMsT0FBaUIsRUFBRSxPQUF5QjtRQUN4RCxNQUFNLEdBQUcsR0FBYSxFQUFFLENBQUM7UUFDekIsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUMvQixLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU8sSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTTtnQkFBRSxTQUFTO1lBQ2xFLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDbEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDYixHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRDs2Q0FDeUM7SUFDekMsSUFBSSxDQUFDLE9BQXlCO1FBQzVCLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQzFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsTUFBTSxJQUFJLEdBQWEsRUFBRSxDQUFDO1FBQzFCLEtBQUssTUFBTSxFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQy9CLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDNUIsSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDaEIsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQztZQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFGLENBQUM7Q0FDRjtBQUVELFNBQVMsV0FBVyxDQUFDLENBQVcsRUFBRSxDQUFXO0lBQzNDLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsTUFBTTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtRQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztJQUNuRSxPQUFPLElBQUksQ0FBQztBQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuLyoqIFRoZSBwYXJ0IG9mIGEgcmVnaW9uIHRoZSBzZWxlY3Rpb24gcmVhZHM6IGl0cyBzdGFibGUgaWQuICovXG5pbnRlcmZhY2UgSGFzSWQge1xuICBpZDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlZ2lvbiBzZWxlY3Rpb24sIGhlbGQgYnkgcmVnaW9uICppZCogKHN0YWJsZSBhY3Jvc3MgZWRpdHMsIHJlb3JkZXJzIGFuZFxuICogZGVsZXRlL2FkZCBjeWNsZXMpIGFuZCBwcm9qZWN0ZWQgdG8gYXJyYXkgaW5kaWNlcyBmb3IgdGhlIElSZWdpb25TdG9yZVxuICogYm91bmRhcnkuIENoYW5naW5nIHRoZSBpZHMgKHtAbGluayByZXBsYWNlfSwge0BsaW5rIHJldGFpbn0pIGlzIHNpbGVudDsgdGhlXG4gKiBvd25lciBjYWxscyB7QGxpbmsgc3luY30gb25jZSB0aGUgcmVnaW9uIGFycmF5IGl0IHByb2plY3RzIG9udG8gaXMgZmluYWwsXG4gKiB3aGljaCBwcnVuZXMgaWRzIHRoYXQgbm8gbG9uZ2VyIGV4aXN0IGFuZCBlbWl0cyB7QGxpbmsgaW5kaWNlcyR9IG9ubHkgd2hlblxuICogdGhlIGluZGV4IHNldCBjaGFuZ2VkLlxuICovXG5leHBvcnQgY2xhc3MgUmVnaW9uU2VsZWN0aW9uIHtcbiAgcHJpdmF0ZSBzZWxlY3RlZDogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRpY2VzU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyW10+KFtdKTtcblxuICAvKiogVGhlIHNlbGVjdGVkIHJlZ2lvbnMnIGN1cnJlbnQgYXJyYXkgaW5kaWNlcyAoZW1pdHMgb24gY2hhbmdlIG9ubHkpLiAqL1xuICByZWFkb25seSBpbmRpY2VzJDogT2JzZXJ2YWJsZTxudW1iZXJbXT4gPSB0aGlzLmluZGljZXNTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8qKiBUaGUgc2VsZWN0ZWQgaW5kaWNlcyBhcyBsYXN0IHByb2plY3RlZCBieSB7QGxpbmsgc3luY30uICovXG4gIGdldCBpbmRpY2VzKCk6IG51bWJlcltdIHtcbiAgICByZXR1cm4gdGhpcy5pbmRpY2VzU3ViamVjdC52YWx1ZTtcbiAgfVxuXG4gIC8qKiBUaGUgc2VsZWN0ZWQgaWRzLCBpbiBzZWxlY3Rpb24gb3JkZXIuICovXG4gIGdldCBpZHMoKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNlbGVjdGVkIGlkcyAobm8gZW1pdCB1bnRpbCB7QGxpbmsgc3luY30pLiAqL1xuICByZXBsYWNlKGlkczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkID0gaWRzLnNsaWNlKCk7XG4gIH1cblxuICAvKiogS2VlcCBvbmx5IHRoZSBpZHMgYGtlZXBgIGFjY2VwdHMgKG5vIGVtaXQgdW50aWwge0BsaW5rIHN5bmN9KS4gKi9cbiAgcmV0YWluKGtlZXA6IChpZDogbnVtYmVyKSA9PiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZCA9IHRoaXMuc2VsZWN0ZWQuZmlsdGVyKGtlZXApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdCBieSBhcnJheSBpbmRleCBpbnRvIGByZWdpb25zYDogaW52YWxpZCBhbmQgZHVwbGljYXRlIGluZGljZXMgYXJlXG4gICAqIGRyb3BwZWQsIHRoZSBnaXZlbiBvcmRlciBpcyBrZXB0LiBQcm9qZWN0cyBhbmQgZW1pdHMuXG4gICAqL1xuICBzZWxlY3RJbmRpY2VzKGluZGljZXM6IG51bWJlcltdLCByZWdpb25zOiByZWFkb25seSBIYXNJZFtdKTogdm9pZCB7XG4gICAgY29uc3QgaWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IGkgb2YgaW5kaWNlcyB8fCBbXSkge1xuICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoaSkgfHwgaSA8IDAgfHwgaSA+PSByZWdpb25zLmxlbmd0aCkgY29udGludWU7XG4gICAgICBjb25zdCBpZCA9IHJlZ2lvbnNbaV0uaWQ7XG4gICAgICBpZiAoIXNlZW4uaGFzKGlkKSkge1xuICAgICAgICBzZWVuLmFkZChpZCk7XG4gICAgICAgIGlkcy5wdXNoKGlkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZCA9IGlkcztcbiAgICB0aGlzLnN5bmMocmVnaW9ucyk7XG4gIH1cblxuICAvKiogUHJvamVjdCB0aGUgc2VsZWN0ZWQgaWRzIG9udG8gYHJlZ2lvbnNgLCBwcnVuaW5nIGlkcyBpdCBubyBsb25nZXIgaG9sZHMsXG4gICAqICBhbmQgZW1pdCBpZiB0aGUgaW5kZXggc2V0IGNoYW5nZWQuICovXG4gIHN5bmMocmVnaW9uczogcmVhZG9ubHkgSGFzSWRbXSk6IHZvaWQge1xuICAgIGNvbnN0IGluZGV4T2YgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuICAgIHJlZ2lvbnMuZm9yRWFjaCgociwgaSkgPT4ge1xuICAgICAgaWYgKCFpbmRleE9mLmhhcyhyLmlkKSkgaW5kZXhPZi5zZXQoci5pZCwgaSk7XG4gICAgfSk7XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICBjb25zdCBsaXZlOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgaWQgb2YgdGhpcy5zZWxlY3RlZCkge1xuICAgICAgY29uc3QgaWR4ID0gaW5kZXhPZi5nZXQoaWQpO1xuICAgICAgaWYgKGlkeCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGljZXMucHVzaChpZHgpO1xuICAgICAgICBsaXZlLnB1c2goaWQpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnNlbGVjdGVkID0gbGl2ZTtcbiAgICBpZiAoIXNhbWVJbmRpY2VzKHRoaXMuaW5kaWNlc1N1YmplY3QudmFsdWUsIGluZGljZXMpKSB0aGlzLmluZGljZXNTdWJqZWN0Lm5leHQoaW5kaWNlcyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2FtZUluZGljZXMoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogYm9vbGVhbiB7XG4gIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSBpZiAoYVtpXSAhPT0gYltpXSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==
|