@jax-data-science/sci-image-visualizer 0.8.3 → 0.10.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 +34 -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/image.contract.mjs +1 -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/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/sam.contract.mjs +1 -1
- package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
- 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/loft.mjs +128 -0
- package/esm2022/lib/geometry/polylabel.mjs +156 -0
- package/esm2022/lib/geometry/raster.mjs +98 -0
- package/esm2022/lib/geometry/reconstruct.mjs +315 -0
- package/esm2022/lib/geometry/reslice-image.mjs +57 -0
- package/esm2022/lib/geometry/ring.mjs +201 -0
- package/esm2022/lib/geometry/section.mjs +215 -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 +12 -9
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
- package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -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 +270 -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 +347 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -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 +194 -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 +164 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
- 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 +134 -0
- package/esm2022/lib/models/region-clone.mjs +68 -0
- package/esm2022/lib/models/region-geojson.mjs +411 -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/class-tree/class-tree.component.mjs +156 -0
- package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -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 +896 -660
- package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
- package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -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/region-source-layer.mjs +378 -0
- package/esm2022/lib/region-overlay/region-style.mjs +97 -0
- package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
- package/esm2022/lib/region-source/http-region-source.mjs +104 -0
- package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
- package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
- package/esm2022/lib/region-source/region-source.mjs +67 -0
- package/esm2022/lib/region-source/region-tiles.mjs +708 -0
- package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
- package/esm2022/lib/render-orchestrator.mjs +14 -11
- package/esm2022/lib/render-session.mjs +207 -0
- package/esm2022/lib/routing-visualizer.service.mjs +858 -414
- package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
- 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 +53 -5
- package/esm2022/lib/store/class-signatures.mjs +63 -0
- package/esm2022/lib/store/region-history.mjs +146 -0
- package/esm2022/lib/store/region-scope-cache.mjs +144 -0
- package/esm2022/lib/store/region-selection.mjs +82 -0
- package/esm2022/lib/store/region-source-scope.mjs +171 -0
- package/esm2022/lib/store/region-store.service.mjs +986 -670
- package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
- package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
- 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 +120 -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 +121 -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 +84 -119
- 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 +123 -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/volume-sections.mjs +175 -0
- package/esm2022/lib/visualizer.component.mjs +602 -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-BKQhpbHv.mjs +47169 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.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 -34467
- 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/region-source.worker.js +1067 -0
- package/fesm2022/spatial-math.worker.js +471 -0
- package/fesm2022/tsne.worker.js +32 -15
- package/index.d.ts +19 -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/image.contract.d.ts +4 -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 +85 -1
- package/lib/contracts/region-overlay.contract.d.ts +5 -0
- package/lib/contracts/region-store.contract.d.ts +22 -0
- package/lib/contracts/sam.contract.d.ts +7 -0
- package/lib/contracts/section-view.contract.d.ts +44 -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 +231 -54
- package/lib/contracts/viz-config.d.ts +9 -0
- package/lib/geometry/contour.d.ts +24 -0
- package/lib/geometry/loft.d.ts +22 -0
- package/lib/geometry/polylabel.d.ts +23 -0
- package/lib/geometry/raster.d.ts +42 -0
- package/lib/geometry/reconstruct.d.ts +54 -0
- package/lib/geometry/reslice-image.d.ts +33 -0
- package/lib/geometry/ring.d.ts +67 -0
- package/lib/geometry/section.d.ts +52 -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 +4 -3
- package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
- package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
- package/lib/implementations/napari-js/napari-scene.d.ts +126 -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 +91 -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 +169 -883
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
- package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -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 +38 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
- 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 +83 -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 +25 -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 +45 -0
- package/lib/models/region-clone.d.ts +20 -0
- package/lib/models/region-geojson.d.ts +57 -0
- package/lib/models/region.d.ts +59 -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/class-tree/class-tree.component.d.ts +78 -0
- package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -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 +283 -200
- package/lib/region-editor/region-metrics.d.ts +34 -0
- package/lib/region-editor/region-persistence.service.d.ts +77 -0
- package/lib/region-editor/region-table/region-table.component.d.ts +89 -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 +158 -0
- package/lib/region-overlay/region-hit-test.d.ts +38 -0
- package/lib/region-overlay/region-source-layer.d.ts +96 -0
- package/lib/region-overlay/region-style.d.ts +52 -0
- package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
- package/lib/region-source/http-region-source.d.ts +45 -0
- package/lib/region-source/region-source-ops.d.ts +89 -0
- package/lib/region-source/region-source-worker.d.ts +7 -0
- package/lib/region-source/region-source.d.ts +82 -0
- package/lib/region-source/region-tiles.d.ts +289 -0
- package/lib/region-source/worker-region-source.d.ts +65 -0
- package/lib/render-orchestrator.d.ts +6 -2
- package/lib/render-session.d.ts +75 -0
- package/lib/routing-visualizer.service.d.ts +248 -59
- package/lib/section-pane/section-pane.component.d.ts +47 -0
- 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 +39 -2
- package/lib/store/class-signatures.d.ts +11 -0
- package/lib/store/region-history.d.ts +66 -0
- package/lib/store/region-scope-cache.d.ts +65 -0
- package/lib/store/region-selection.d.ts +36 -0
- package/lib/store/region-source-scope.d.ts +68 -0
- package/lib/store/region-store.service.d.ts +312 -116
- package/lib/store/visualizer-store.service.d.ts +32 -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 +62 -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 +51 -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 +55 -84
- 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 +46 -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/volume-sections.d.ts +64 -0
- package/lib/visualizer.component.d.ts +232 -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/assets/slice.svg +23 -0
- 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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Directive, EventEmitter, HostListener, Input, NgZone, Output } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Drag handle of a floating, `position: fixed` panel (the intensity inset header,
|
|
5
|
+
* the toolbar dock handle). On mousedown it asks {@link origin} where the panel is —
|
|
6
|
+
* the host may detach a docked panel right there — then emits the new position on
|
|
7
|
+
* every move until mouseup.
|
|
8
|
+
*
|
|
9
|
+
* The move/up listeners exist only while a drag is in progress and run outside the
|
|
10
|
+
* Angular zone, re-entering it per emitted position: a permanent window mousemove
|
|
11
|
+
* listener made every pointer move anywhere in the host app run change detection.
|
|
12
|
+
*/
|
|
13
|
+
export class FloatingDragDirective {
|
|
14
|
+
constructor(zone) {
|
|
15
|
+
this.zone = zone;
|
|
16
|
+
/** The panel's new position, per pointer move. */
|
|
17
|
+
this.vizFloatingDragMove = new EventEmitter();
|
|
18
|
+
this.end = null;
|
|
19
|
+
}
|
|
20
|
+
onMouseDown(e) {
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
this.end?.();
|
|
23
|
+
const from = this.origin();
|
|
24
|
+
const start = { mx: e.clientX, my: e.clientY, x: from.x, y: from.y };
|
|
25
|
+
const move = (ev) => this.zone.run(() => this.vizFloatingDragMove.emit({
|
|
26
|
+
x: start.x + (ev.clientX - start.mx),
|
|
27
|
+
y: start.y + (ev.clientY - start.my),
|
|
28
|
+
}));
|
|
29
|
+
const up = () => this.end?.();
|
|
30
|
+
this.zone.runOutsideAngular(() => {
|
|
31
|
+
window.addEventListener('mousemove', move);
|
|
32
|
+
window.addEventListener('mouseup', up);
|
|
33
|
+
});
|
|
34
|
+
this.end = () => {
|
|
35
|
+
window.removeEventListener('mousemove', move);
|
|
36
|
+
window.removeEventListener('mouseup', up);
|
|
37
|
+
this.end = null;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
ngOnDestroy() {
|
|
41
|
+
this.end?.();
|
|
42
|
+
}
|
|
43
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: FloatingDragDirective, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
44
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.9", type: FloatingDragDirective, isStandalone: true, selector: "[vizFloatingDrag]", inputs: { origin: ["vizFloatingDrag", "origin"] }, outputs: { vizFloatingDragMove: "vizFloatingDragMove" }, host: { listeners: { "mousedown": "onMouseDown($event)" } }, ngImport: i0 }); }
|
|
45
|
+
}
|
|
46
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: FloatingDragDirective, decorators: [{
|
|
47
|
+
type: Directive,
|
|
48
|
+
args: [{ selector: '[vizFloatingDrag]', standalone: true }]
|
|
49
|
+
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { origin: [{
|
|
50
|
+
type: Input,
|
|
51
|
+
args: ['vizFloatingDrag']
|
|
52
|
+
}], vizFloatingDragMove: [{
|
|
53
|
+
type: Output
|
|
54
|
+
}], onMouseDown: [{
|
|
55
|
+
type: HostListener,
|
|
56
|
+
args: ['mousedown', ['$event']]
|
|
57
|
+
}] } });
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctZHJhZy5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvZmxvYXRpbmctZHJhZy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDOztBQVF4Rzs7Ozs7Ozs7O0dBU0c7QUFFSCxNQUFNLE9BQU8scUJBQXFCO0lBUWhDLFlBQTZCLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFRO1FBTHpDLGtEQUFrRDtRQUMvQix3QkFBbUIsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO1FBRWpFLFFBQUcsR0FBd0IsSUFBSSxDQUFDO0lBRUksQ0FBQztJQUc3QyxXQUFXLENBQUMsQ0FBYTtRQUN2QixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0IsTUFBTSxLQUFLLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBYyxFQUFFLEVBQUUsQ0FDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQ2pCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUM7WUFDNUIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDcEMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7U0FDckMsQ0FBQyxDQUNILENBQUM7UUFDSixNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtZQUMvQixNQUFNLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzNDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsRUFBRTtZQUNkLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ2YsQ0FBQzs4R0FyQ1UscUJBQXFCO2tHQUFyQixxQkFBcUI7OzJGQUFyQixxQkFBcUI7a0JBRGpDLFNBQVM7bUJBQUMsRUFBRSxRQUFRLEVBQUUsbUJBQW1CLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRTsyRUFHbEMsTUFBTTtzQkFBL0IsS0FBSzt1QkFBQyxpQkFBaUI7Z0JBRUwsbUJBQW1CO3NCQUFyQyxNQUFNO2dCQU9QLFdBQVc7c0JBRFYsWUFBWTt1QkFBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKiogQSBzY3JlZW4gcG9zaXRpb24sIGluIENTUyBwaXhlbHMuICovXG5leHBvcnQgaW50ZXJmYWNlIEZsb2F0aW5nUG9zIHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG59XG5cbi8qKlxuICogRHJhZyBoYW5kbGUgb2YgYSBmbG9hdGluZywgYHBvc2l0aW9uOiBmaXhlZGAgcGFuZWwgKHRoZSBpbnRlbnNpdHkgaW5zZXQgaGVhZGVyLFxuICogdGhlIHRvb2xiYXIgZG9jayBoYW5kbGUpLiBPbiBtb3VzZWRvd24gaXQgYXNrcyB7QGxpbmsgb3JpZ2lufSB3aGVyZSB0aGUgcGFuZWwgaXMg4oCUXG4gKiB0aGUgaG9zdCBtYXkgZGV0YWNoIGEgZG9ja2VkIHBhbmVsIHJpZ2h0IHRoZXJlIOKAlCB0aGVuIGVtaXRzIHRoZSBuZXcgcG9zaXRpb24gb25cbiAqIGV2ZXJ5IG1vdmUgdW50aWwgbW91c2V1cC5cbiAqXG4gKiBUaGUgbW92ZS91cCBsaXN0ZW5lcnMgZXhpc3Qgb25seSB3aGlsZSBhIGRyYWcgaXMgaW4gcHJvZ3Jlc3MgYW5kIHJ1biBvdXRzaWRlIHRoZVxuICogQW5ndWxhciB6b25lLCByZS1lbnRlcmluZyBpdCBwZXIgZW1pdHRlZCBwb3NpdGlvbjogYSBwZXJtYW5lbnQgd2luZG93IG1vdXNlbW92ZVxuICogbGlzdGVuZXIgbWFkZSBldmVyeSBwb2ludGVyIG1vdmUgYW55d2hlcmUgaW4gdGhlIGhvc3QgYXBwIHJ1biBjaGFuZ2UgZGV0ZWN0aW9uLlxuICovXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICdbdml6RmxvYXRpbmdEcmFnXScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBGbG9hdGluZ0RyYWdEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAvKiogQ2FsbGVkIG9uIG1vdXNlZG93bjogdGhlIHBhbmVsJ3MgcG9zaXRpb24gdGhlIGRyYWcgc3RhcnRzIGZyb20uICovXG4gIEBJbnB1dCgndml6RmxvYXRpbmdEcmFnJykgb3JpZ2luITogKCkgPT4gRmxvYXRpbmdQb3M7XG4gIC8qKiBUaGUgcGFuZWwncyBuZXcgcG9zaXRpb24sIHBlciBwb2ludGVyIG1vdmUuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSB2aXpGbG9hdGluZ0RyYWdNb3ZlID0gbmV3IEV2ZW50RW1pdHRlcjxGbG9hdGluZ1Bvcz4oKTtcblxuICBwcml2YXRlIGVuZDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSB6b25lOiBOZ1pvbmUpIHt9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2Vkb3duJywgWyckZXZlbnQnXSlcbiAgb25Nb3VzZURvd24oZTogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmVuZD8uKCk7XG4gICAgY29uc3QgZnJvbSA9IHRoaXMub3JpZ2luKCk7XG4gICAgY29uc3Qgc3RhcnQgPSB7IG14OiBlLmNsaWVudFgsIG15OiBlLmNsaWVudFksIHg6IGZyb20ueCwgeTogZnJvbS55IH07XG4gICAgY29uc3QgbW92ZSA9IChldjogTW91c2VFdmVudCkgPT5cbiAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT5cbiAgICAgICAgdGhpcy52aXpGbG9hdGluZ0RyYWdNb3ZlLmVtaXQoe1xuICAgICAgICAgIHg6IHN0YXJ0LnggKyAoZXYuY2xpZW50WCAtIHN0YXJ0Lm14KSxcbiAgICAgICAgICB5OiBzdGFydC55ICsgKGV2LmNsaWVudFkgLSBzdGFydC5teSksXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICBjb25zdCB1cCA9ICgpID0+IHRoaXMuZW5kPy4oKTtcbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdmUpO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB1cCk7XG4gICAgfSk7XG4gICAgdGhpcy5lbmQgPSAoKSA9PiB7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW92ZSk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHVwKTtcbiAgICAgIHRoaXMuZW5kID0gbnVsbDtcbiAgICB9O1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5lbmQ/LigpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { takeUntil } from 'rxjs/operators';
|
|
2
|
+
import { MultiPolygon, Polygon, Rectangle } from '../models/region';
|
|
3
|
+
import { opEligible, regionsAt } from './visualizer-context-menu';
|
|
4
|
+
/**
|
|
5
|
+
* Region set-operations on the current selection (jit-ui#85) — select all, merge,
|
|
6
|
+
* ungroup, inverse, simplify — plus the store mirrors the toolbar and the context
|
|
7
|
+
* menu read synchronously: the selection and the undo/redo availability.
|
|
8
|
+
*
|
|
9
|
+
* Every operation commits through `setRegions`, so it is undo-tracked and the
|
|
10
|
+
* backend on screen re-renders; profile lines and unselected regions are kept.
|
|
11
|
+
*/
|
|
12
|
+
export class RegionActions {
|
|
13
|
+
constructor(target, ops,
|
|
14
|
+
/** `[width, height]` of the image, when known — the frame inverse and merge rasterize in. */
|
|
15
|
+
imageSize, notify) {
|
|
16
|
+
this.target = target;
|
|
17
|
+
this.ops = ops;
|
|
18
|
+
this.imageSize = imageSize;
|
|
19
|
+
this.notify = notify;
|
|
20
|
+
/** Current selection (array indices), mirrored from the store. */
|
|
21
|
+
this.selectedIndices = [];
|
|
22
|
+
/** Whether a region action is available to undo / redo; drive the toolbar buttons. */
|
|
23
|
+
this.canUndo = false;
|
|
24
|
+
this.canRedo = false;
|
|
25
|
+
/** Custom-threshold Simplify dialog. */
|
|
26
|
+
this.displaySimplifyDialog = false;
|
|
27
|
+
this.simplifyThreshold = 3;
|
|
28
|
+
}
|
|
29
|
+
/** Mirror the store's selection and undo/redo depth until `until$` emits.
|
|
30
|
+
* `changed` runs after an undo/redo flip (the toolbar binds those). */
|
|
31
|
+
bind(until$, changed) {
|
|
32
|
+
this.target
|
|
33
|
+
.getCanUndo$()
|
|
34
|
+
.pipe(takeUntil(until$))
|
|
35
|
+
.subscribe((v) => {
|
|
36
|
+
this.canUndo = v;
|
|
37
|
+
changed();
|
|
38
|
+
});
|
|
39
|
+
this.target
|
|
40
|
+
.getCanRedo$()
|
|
41
|
+
.pipe(takeUntil(until$))
|
|
42
|
+
.subscribe((v) => {
|
|
43
|
+
this.canRedo = v;
|
|
44
|
+
changed();
|
|
45
|
+
});
|
|
46
|
+
this.target
|
|
47
|
+
.getSelectedShapeIndices$()
|
|
48
|
+
.pipe(takeUntil(until$))
|
|
49
|
+
.subscribe((indices) => {
|
|
50
|
+
this.selectedIndices = indices || [];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** The currently-selected regions (live store instances). */
|
|
54
|
+
get selected() {
|
|
55
|
+
return regionsAt(this.target.getRegions(), this.selectedIndices);
|
|
56
|
+
}
|
|
57
|
+
/** Select every region on the image (excludes intensity-profile lines). */
|
|
58
|
+
selectAll() {
|
|
59
|
+
const indices = [];
|
|
60
|
+
this.target.getRegions().forEach((r, i) => {
|
|
61
|
+
if (r.kind !== 'profile')
|
|
62
|
+
indices.push(i);
|
|
63
|
+
});
|
|
64
|
+
this.target.setSelectedShapeIndices(indices);
|
|
65
|
+
}
|
|
66
|
+
/** Merge the selected regions into a single (possibly multi-part) region. */
|
|
67
|
+
merge() {
|
|
68
|
+
const sel = opEligible(this.selected);
|
|
69
|
+
if (sel.length < 2)
|
|
70
|
+
return;
|
|
71
|
+
const { w, h } = this.frame(sel);
|
|
72
|
+
const merged = this.ops.merge(sel, w, h);
|
|
73
|
+
if (merged)
|
|
74
|
+
this.replace(sel, [merged]);
|
|
75
|
+
}
|
|
76
|
+
/** Split each selected multi-part region into one region per part. */
|
|
77
|
+
ungroup() {
|
|
78
|
+
const sel = this.selected.filter((r) => this.ops.canUngroup(r));
|
|
79
|
+
if (sel.length === 0)
|
|
80
|
+
return;
|
|
81
|
+
this.replace(sel, sel.flatMap((r) => this.ops.ungroup(r)));
|
|
82
|
+
}
|
|
83
|
+
/** Replace the selection with its inverse inside the image rectangle. */
|
|
84
|
+
inverse() {
|
|
85
|
+
const sel = opEligible(this.selected);
|
|
86
|
+
if (sel.length === 0)
|
|
87
|
+
return;
|
|
88
|
+
const { w, h } = this.frame(sel);
|
|
89
|
+
const inv = this.ops.inverse(sel, w, h);
|
|
90
|
+
if (!inv) {
|
|
91
|
+
this.notify({
|
|
92
|
+
severity: 'warn',
|
|
93
|
+
summary: 'Inverse',
|
|
94
|
+
detail: 'Nothing to invert — select one or more closed regions first.',
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.replace(sel, [inv]);
|
|
99
|
+
}
|
|
100
|
+
/** Douglas–Peucker simplify each selected region by `thresholdPx`, closing the dialog. */
|
|
101
|
+
simplify(thresholdPx) {
|
|
102
|
+
const sel = opEligible(this.selected);
|
|
103
|
+
if (sel.length === 0)
|
|
104
|
+
return;
|
|
105
|
+
this.replace(sel, sel.map((r) => this.ops.simplify(r, thresholdPx)));
|
|
106
|
+
this.displaySimplifyDialog = false;
|
|
107
|
+
}
|
|
108
|
+
openSimplifyDialog() {
|
|
109
|
+
this.displaySimplifyDialog = true;
|
|
110
|
+
}
|
|
111
|
+
/** Commit a set-op: drop `remove`, append `add`, and select the results. */
|
|
112
|
+
replace(remove, add) {
|
|
113
|
+
if (add.length === 0)
|
|
114
|
+
return;
|
|
115
|
+
const removeSet = new Set(remove);
|
|
116
|
+
const kept = this.target.getRegions().filter((r) => !removeSet.has(r));
|
|
117
|
+
this.target.setRegions([...kept, ...add]); // mints ids on `add`, records undo
|
|
118
|
+
const stored = this.target.getRegions();
|
|
119
|
+
this.target.setSelectedShapeIndices(add.map((r) => stored.indexOf(r)).filter((i) => i >= 0));
|
|
120
|
+
}
|
|
121
|
+
/** Image pixel dimensions for the raster ops; falls back to the selection's extent
|
|
122
|
+
* when the image size isn't known (keeps clamping sane). */
|
|
123
|
+
frame(regions) {
|
|
124
|
+
let [w, h] = this.imageSize() ?? [0, 0];
|
|
125
|
+
if (!(w > 0) || !(h > 0)) {
|
|
126
|
+
let maxX = 0, maxY = 0;
|
|
127
|
+
const scan = (xs, ys) => {
|
|
128
|
+
for (const x of xs)
|
|
129
|
+
maxX = Math.max(maxX, x);
|
|
130
|
+
for (const y of ys)
|
|
131
|
+
maxY = Math.max(maxY, y);
|
|
132
|
+
};
|
|
133
|
+
for (const r of regions) {
|
|
134
|
+
const b = r.bounds;
|
|
135
|
+
if (b instanceof Rectangle)
|
|
136
|
+
scan([b.x + b.width], [b.y + b.height]);
|
|
137
|
+
else if (b instanceof Polygon)
|
|
138
|
+
scan(b.xpoints, b.ypoints);
|
|
139
|
+
else if (b instanceof MultiPolygon)
|
|
140
|
+
for (const p of b.polygons)
|
|
141
|
+
scan(p.xpoints, p.ypoints);
|
|
142
|
+
}
|
|
143
|
+
w = Math.max(w, Math.ceil(maxX) + 2);
|
|
144
|
+
h = Math.max(h, Math.ceil(maxY) + 2);
|
|
145
|
+
}
|
|
146
|
+
return { w, h };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWFjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvcmVnaW9uLWFjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSTNDLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBVSxNQUFNLGtCQUFrQixDQUFDO0FBRTVFLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFhbEU7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBVXhCLFlBQ21CLE1BQTJCLEVBQzNCLEdBQXFCO0lBQ3RDLDZGQUE2RjtJQUM1RSxTQUFxQyxFQUNyQyxNQUFrQztRQUpsQyxXQUFNLEdBQU4sTUFBTSxDQUFxQjtRQUMzQixRQUFHLEdBQUgsR0FBRyxDQUFrQjtRQUVyQixjQUFTLEdBQVQsU0FBUyxDQUE0QjtRQUNyQyxXQUFNLEdBQU4sTUFBTSxDQUE0QjtRQWRyRCxrRUFBa0U7UUFDbEUsb0JBQWUsR0FBYSxFQUFFLENBQUM7UUFDL0Isc0ZBQXNGO1FBQ3RGLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQix3Q0FBd0M7UUFDeEMsMEJBQXFCLEdBQUcsS0FBSyxDQUFDO1FBQzlCLHNCQUFpQixHQUFHLENBQUMsQ0FBQztJQVFuQixDQUFDO0lBRUo7NEVBQ3dFO0lBQ3hFLElBQUksQ0FBQyxNQUEyQixFQUFFLE9BQW1CO1FBQ25ELElBQUksQ0FBQyxNQUFNO2FBQ1IsV0FBVyxFQUFFO2FBQ2IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUN2QixTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNmLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQyxDQUFDLENBQUM7UUFDTCxJQUFJLENBQUMsTUFBTTthQUNSLFdBQVcsRUFBRTthQUNiLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDdkIsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDZixJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztZQUNqQixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQyxDQUFDO1FBQ0wsSUFBSSxDQUFDLE1BQU07YUFDUix3QkFBd0IsRUFBRTthQUMxQixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQ3ZCLFNBQVMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3JCLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCw2REFBNkQ7SUFDN0QsSUFBSSxRQUFRO1FBQ1YsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSxTQUFTO1FBQ1AsTUFBTSxPQUFPLEdBQWEsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hDLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTO2dCQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRCw2RUFBNkU7SUFDN0UsS0FBSztRQUNILE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUM7WUFBRSxPQUFPO1FBQzNCLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLElBQUksTUFBTTtZQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsc0VBQXNFO0lBQ3RFLE9BQU87UUFDTCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoRSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDN0IsSUFBSSxDQUFDLE9BQU8sQ0FDVixHQUFHLEVBQ0gsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDeEMsQ0FBQztJQUNKLENBQUM7SUFFRCx5RUFBeUU7SUFDekUsT0FBTztRQUNMLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLENBQUM7WUFBRSxPQUFPO1FBQzdCLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNULElBQUksQ0FBQyxNQUFNLENBQUM7Z0JBQ1YsUUFBUSxFQUFFLE1BQU07Z0JBQ2hCLE9BQU8sRUFBRSxTQUFTO2dCQUNsQixNQUFNLEVBQUUsOERBQThEO2FBQ3ZFLENBQUMsQ0FBQztZQUNILE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRCwwRkFBMEY7SUFDMUYsUUFBUSxDQUFDLFdBQW1CO1FBQzFCLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLENBQUM7WUFBRSxPQUFPO1FBQzdCLElBQUksQ0FBQyxPQUFPLENBQ1YsR0FBRyxFQUNILEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUNsRCxDQUFDO1FBQ0YsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEtBQUssQ0FBQztJQUNyQyxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7SUFDcEMsQ0FBQztJQUVELDRFQUE0RTtJQUNwRSxPQUFPLENBQUMsTUFBZ0IsRUFBRSxHQUFhO1FBQzdDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDO1lBQUUsT0FBTztRQUM3QixNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQ0FBbUM7UUFDOUUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9GLENBQUM7SUFFRDtpRUFDNkQ7SUFDckQsS0FBSyxDQUFDLE9BQWlCO1FBQzdCLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUNWLElBQUksR0FBRyxDQUFDLENBQUM7WUFDWCxNQUFNLElBQUksR0FBRyxDQUFDLEVBQVksRUFBRSxFQUFZLEVBQUUsRUFBRTtnQkFDMUMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFO29CQUFFLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDN0MsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFO29CQUFFLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvQyxDQUFDLENBQUM7WUFDRixLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO2dCQUNuQixJQUFJLENBQUMsWUFBWSxTQUFTO29CQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztxQkFDL0QsSUFBSSxDQUFDLFlBQVksT0FBTztvQkFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7cUJBQ3JELElBQUksQ0FBQyxZQUFZLFlBQVk7b0JBQUUsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUTt3QkFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDN0YsQ0FBQztZQUNELENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFDRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ2xCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1lc3NhZ2UgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5cbmltcG9ydCB7IElSZWdpb25TdG9yZSB9IGZyb20gJy4uL2NvbnRyYWN0cy92aXN1YWxpemVyLmNvbnRyYWN0JztcbmltcG9ydCB7IE11bHRpUG9seWdvbiwgUG9seWdvbiwgUmVjdGFuZ2xlLCBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IFJlZ2lvbk9wc1NlcnZpY2UgfSBmcm9tICcuLi9yZWdpb24tb3BzLnNlcnZpY2UnO1xuaW1wb3J0IHsgb3BFbGlnaWJsZSwgcmVnaW9uc0F0IH0gZnJvbSAnLi92aXN1YWxpemVyLWNvbnRleHQtbWVudSc7XG5cbi8qKiBUaGUgcmVnaW9uLXN0b3JlIG1lbWJlcnMgdGhlIHNldC1vcGVyYXRpb25zIHJlYWQgYW5kIHdyaXRlIHRocm91Z2guICovXG5leHBvcnQgdHlwZSBSZWdpb25BY3Rpb25zVGFyZ2V0ID0gUGljazxcbiAgSVJlZ2lvblN0b3JlLFxuICB8ICdnZXRSZWdpb25zJ1xuICB8ICdzZXRSZWdpb25zJ1xuICB8ICdzZXRTZWxlY3RlZFNoYXBlSW5kaWNlcydcbiAgfCAnZ2V0U2VsZWN0ZWRTaGFwZUluZGljZXMkJ1xuICB8ICdnZXRDYW5VbmRvJCdcbiAgfCAnZ2V0Q2FuUmVkbyQnXG4+O1xuXG4vKipcbiAqIFJlZ2lvbiBzZXQtb3BlcmF0aW9ucyBvbiB0aGUgY3VycmVudCBzZWxlY3Rpb24gKGppdC11aSM4NSkg4oCUIHNlbGVjdCBhbGwsIG1lcmdlLFxuICogdW5ncm91cCwgaW52ZXJzZSwgc2ltcGxpZnkg4oCUIHBsdXMgdGhlIHN0b3JlIG1pcnJvcnMgdGhlIHRvb2xiYXIgYW5kIHRoZSBjb250ZXh0XG4gKiBtZW51IHJlYWQgc3luY2hyb25vdXNseTogdGhlIHNlbGVjdGlvbiBhbmQgdGhlIHVuZG8vcmVkbyBhdmFpbGFiaWxpdHkuXG4gKlxuICogRXZlcnkgb3BlcmF0aW9uIGNvbW1pdHMgdGhyb3VnaCBgc2V0UmVnaW9uc2AsIHNvIGl0IGlzIHVuZG8tdHJhY2tlZCBhbmQgdGhlXG4gKiBiYWNrZW5kIG9uIHNjcmVlbiByZS1yZW5kZXJzOyBwcm9maWxlIGxpbmVzIGFuZCB1bnNlbGVjdGVkIHJlZ2lvbnMgYXJlIGtlcHQuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25BY3Rpb25zIHtcbiAgLyoqIEN1cnJlbnQgc2VsZWN0aW9uIChhcnJheSBpbmRpY2VzKSwgbWlycm9yZWQgZnJvbSB0aGUgc3RvcmUuICovXG4gIHNlbGVjdGVkSW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgLyoqIFdoZXRoZXIgYSByZWdpb24gYWN0aW9uIGlzIGF2YWlsYWJsZSB0byB1bmRvIC8gcmVkbzsgZHJpdmUgdGhlIHRvb2xiYXIgYnV0dG9ucy4gKi9cbiAgY2FuVW5kbyA9IGZhbHNlO1xuICBjYW5SZWRvID0gZmFsc2U7XG4gIC8qKiBDdXN0b20tdGhyZXNob2xkIFNpbXBsaWZ5IGRpYWxvZy4gKi9cbiAgZGlzcGxheVNpbXBsaWZ5RGlhbG9nID0gZmFsc2U7XG4gIHNpbXBsaWZ5VGhyZXNob2xkID0gMztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhcmdldDogUmVnaW9uQWN0aW9uc1RhcmdldCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wczogUmVnaW9uT3BzU2VydmljZSxcbiAgICAvKiogYFt3aWR0aCwgaGVpZ2h0XWAgb2YgdGhlIGltYWdlLCB3aGVuIGtub3duIOKAlCB0aGUgZnJhbWUgaW52ZXJzZSBhbmQgbWVyZ2UgcmFzdGVyaXplIGluLiAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaW1hZ2VTaXplOiAoKSA9PiBudW1iZXJbXSB8IHVuZGVmaW5lZCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeTogKG1lc3NhZ2U6IE1lc3NhZ2UpID0+IHZvaWQsXG4gICkge31cblxuICAvKiogTWlycm9yIHRoZSBzdG9yZSdzIHNlbGVjdGlvbiBhbmQgdW5kby9yZWRvIGRlcHRoIHVudGlsIGB1bnRpbCRgIGVtaXRzLlxuICAgKiAgYGNoYW5nZWRgIHJ1bnMgYWZ0ZXIgYW4gdW5kby9yZWRvIGZsaXAgKHRoZSB0b29sYmFyIGJpbmRzIHRob3NlKS4gKi9cbiAgYmluZCh1bnRpbCQ6IE9ic2VydmFibGU8dW5rbm93bj4sIGNoYW5nZWQ6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldENhblVuZG8kKClcbiAgICAgIC5waXBlKHRha2VVbnRpbCh1bnRpbCQpKVxuICAgICAgLnN1YnNjcmliZSgodikgPT4ge1xuICAgICAgICB0aGlzLmNhblVuZG8gPSB2O1xuICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICB9KTtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldENhblJlZG8kKClcbiAgICAgIC5waXBlKHRha2VVbnRpbCh1bnRpbCQpKVxuICAgICAgLnN1YnNjcmliZSgodikgPT4ge1xuICAgICAgICB0aGlzLmNhblJlZG8gPSB2O1xuICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICB9KTtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpXG4gICAgICAucGlwZSh0YWtlVW50aWwodW50aWwkKSlcbiAgICAgIC5zdWJzY3JpYmUoKGluZGljZXMpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEluZGljZXMgPSBpbmRpY2VzIHx8IFtdO1xuICAgICAgfSk7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnRseS1zZWxlY3RlZCByZWdpb25zIChsaXZlIHN0b3JlIGluc3RhbmNlcykuICovXG4gIGdldCBzZWxlY3RlZCgpOiBSZWdpb25bXSB7XG4gICAgcmV0dXJuIHJlZ2lvbnNBdCh0aGlzLnRhcmdldC5nZXRSZWdpb25zKCksIHRoaXMuc2VsZWN0ZWRJbmRpY2VzKTtcbiAgfVxuXG4gIC8qKiBTZWxlY3QgZXZlcnkgcmVnaW9uIG9uIHRoZSBpbWFnZSAoZXhjbHVkZXMgaW50ZW5zaXR5LXByb2ZpbGUgbGluZXMpLiAqL1xuICBzZWxlY3RBbGwoKTogdm9pZCB7XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICB0aGlzLnRhcmdldC5nZXRSZWdpb25zKCkuZm9yRWFjaCgociwgaSkgPT4ge1xuICAgICAgaWYgKHIua2luZCAhPT0gJ3Byb2ZpbGUnKSBpbmRpY2VzLnB1c2goaSk7XG4gICAgfSk7XG4gICAgdGhpcy50YXJnZXQuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlcyk7XG4gIH1cblxuICAvKiogTWVyZ2UgdGhlIHNlbGVjdGVkIHJlZ2lvbnMgaW50byBhIHNpbmdsZSAocG9zc2libHkgbXVsdGktcGFydCkgcmVnaW9uLiAqL1xuICBtZXJnZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzZWwgPSBvcEVsaWdpYmxlKHRoaXMuc2VsZWN0ZWQpO1xuICAgIGlmIChzZWwubGVuZ3RoIDwgMikgcmV0dXJuO1xuICAgIGNvbnN0IHsgdywgaCB9ID0gdGhpcy5mcmFtZShzZWwpO1xuICAgIGNvbnN0IG1lcmdlZCA9IHRoaXMub3BzLm1lcmdlKHNlbCwgdywgaCk7XG4gICAgaWYgKG1lcmdlZCkgdGhpcy5yZXBsYWNlKHNlbCwgW21lcmdlZF0pO1xuICB9XG5cbiAgLyoqIFNwbGl0IGVhY2ggc2VsZWN0ZWQgbXVsdGktcGFydCByZWdpb24gaW50byBvbmUgcmVnaW9uIHBlciBwYXJ0LiAqL1xuICB1bmdyb3VwKCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IHRoaXMuc2VsZWN0ZWQuZmlsdGVyKChyKSA9PiB0aGlzLm9wcy5jYW5Vbmdyb3VwKHIpKTtcbiAgICBpZiAoc2VsLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIHRoaXMucmVwbGFjZShcbiAgICAgIHNlbCxcbiAgICAgIHNlbC5mbGF0TWFwKChyKSA9PiB0aGlzLm9wcy51bmdyb3VwKHIpKSxcbiAgICApO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNlbGVjdGlvbiB3aXRoIGl0cyBpbnZlcnNlIGluc2lkZSB0aGUgaW1hZ2UgcmVjdGFuZ2xlLiAqL1xuICBpbnZlcnNlKCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IG9wRWxpZ2libGUodGhpcy5zZWxlY3RlZCk7XG4gICAgaWYgKHNlbC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICBjb25zdCB7IHcsIGggfSA9IHRoaXMuZnJhbWUoc2VsKTtcbiAgICBjb25zdCBpbnYgPSB0aGlzLm9wcy5pbnZlcnNlKHNlbCwgdywgaCk7XG4gICAgaWYgKCFpbnYpIHtcbiAgICAgIHRoaXMubm90aWZ5KHtcbiAgICAgICAgc2V2ZXJpdHk6ICd3YXJuJyxcbiAgICAgICAgc3VtbWFyeTogJ0ludmVyc2UnLFxuICAgICAgICBkZXRhaWw6ICdOb3RoaW5nIHRvIGludmVydCDigJQgc2VsZWN0IG9uZSBvciBtb3JlIGNsb3NlZCByZWdpb25zIGZpcnN0LicsXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yZXBsYWNlKHNlbCwgW2ludl0pO1xuICB9XG5cbiAgLyoqIERvdWdsYXPigJNQZXVja2VyIHNpbXBsaWZ5IGVhY2ggc2VsZWN0ZWQgcmVnaW9uIGJ5IGB0aHJlc2hvbGRQeGAsIGNsb3NpbmcgdGhlIGRpYWxvZy4gKi9cbiAgc2ltcGxpZnkodGhyZXNob2xkUHg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IG9wRWxpZ2libGUodGhpcy5zZWxlY3RlZCk7XG4gICAgaWYgKHNlbC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnJlcGxhY2UoXG4gICAgICBzZWwsXG4gICAgICBzZWwubWFwKChyKSA9PiB0aGlzLm9wcy5zaW1wbGlmeShyLCB0aHJlc2hvbGRQeCkpLFxuICAgICk7XG4gICAgdGhpcy5kaXNwbGF5U2ltcGxpZnlEaWFsb2cgPSBmYWxzZTtcbiAgfVxuXG4gIG9wZW5TaW1wbGlmeURpYWxvZygpOiB2b2lkIHtcbiAgICB0aGlzLmRpc3BsYXlTaW1wbGlmeURpYWxvZyA9IHRydWU7XG4gIH1cblxuICAvKiogQ29tbWl0IGEgc2V0LW9wOiBkcm9wIGByZW1vdmVgLCBhcHBlbmQgYGFkZGAsIGFuZCBzZWxlY3QgdGhlIHJlc3VsdHMuICovXG4gIHByaXZhdGUgcmVwbGFjZShyZW1vdmU6IFJlZ2lvbltdLCBhZGQ6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgaWYgKGFkZC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICBjb25zdCByZW1vdmVTZXQgPSBuZXcgU2V0KHJlbW92ZSk7XG4gICAgY29uc3Qga2VwdCA9IHRoaXMudGFyZ2V0LmdldFJlZ2lvbnMoKS5maWx0ZXIoKHIpID0+ICFyZW1vdmVTZXQuaGFzKHIpKTtcbiAgICB0aGlzLnRhcmdldC5zZXRSZWdpb25zKFsuLi5rZXB0LCAuLi5hZGRdKTsgLy8gbWludHMgaWRzIG9uIGBhZGRgLCByZWNvcmRzIHVuZG9cbiAgICBjb25zdCBzdG9yZWQgPSB0aGlzLnRhcmdldC5nZXRSZWdpb25zKCk7XG4gICAgdGhpcy50YXJnZXQuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoYWRkLm1hcCgocikgPT4gc3RvcmVkLmluZGV4T2YocikpLmZpbHRlcigoaSkgPT4gaSA+PSAwKSk7XG4gIH1cblxuICAvKiogSW1hZ2UgcGl4ZWwgZGltZW5zaW9ucyBmb3IgdGhlIHJhc3RlciBvcHM7IGZhbGxzIGJhY2sgdG8gdGhlIHNlbGVjdGlvbidzIGV4dGVudFxuICAgKiAgd2hlbiB0aGUgaW1hZ2Ugc2l6ZSBpc24ndCBrbm93biAoa2VlcHMgY2xhbXBpbmcgc2FuZSkuICovXG4gIHByaXZhdGUgZnJhbWUocmVnaW9uczogUmVnaW9uW10pOiB7IHc6IG51bWJlcjsgaDogbnVtYmVyIH0ge1xuICAgIGxldCBbdywgaF0gPSB0aGlzLmltYWdlU2l6ZSgpID8/IFswLCAwXTtcbiAgICBpZiAoISh3ID4gMCkgfHwgIShoID4gMCkpIHtcbiAgICAgIGxldCBtYXhYID0gMCxcbiAgICAgICAgbWF4WSA9IDA7XG4gICAgICBjb25zdCBzY2FuID0gKHhzOiBudW1iZXJbXSwgeXM6IG51bWJlcltdKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgeCBvZiB4cykgbWF4WCA9IE1hdGgubWF4KG1heFgsIHgpO1xuICAgICAgICBmb3IgKGNvbnN0IHkgb2YgeXMpIG1heFkgPSBNYXRoLm1heChtYXhZLCB5KTtcbiAgICAgIH07XG4gICAgICBmb3IgKGNvbnN0IHIgb2YgcmVnaW9ucykge1xuICAgICAgICBjb25zdCBiID0gci5ib3VuZHM7XG4gICAgICAgIGlmIChiIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSBzY2FuKFtiLnggKyBiLndpZHRoXSwgW2IueSArIGIuaGVpZ2h0XSk7XG4gICAgICAgIGVsc2UgaWYgKGIgaW5zdGFuY2VvZiBQb2x5Z29uKSBzY2FuKGIueHBvaW50cywgYi55cG9pbnRzKTtcbiAgICAgICAgZWxzZSBpZiAoYiBpbnN0YW5jZW9mIE11bHRpUG9seWdvbikgZm9yIChjb25zdCBwIG9mIGIucG9seWdvbnMpIHNjYW4ocC54cG9pbnRzLCBwLnlwb2ludHMpO1xuICAgICAgfVxuICAgICAgdyA9IE1hdGgubWF4KHcsIE1hdGguY2VpbChtYXhYKSArIDIpO1xuICAgICAgaCA9IE1hdGgubWF4KGgsIE1hdGguY2VpbChtYXhZKSArIDIpO1xuICAgIH1cbiAgICByZXR1cm4geyB3LCBoIH07XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { openHttpRegionSource } from '../region-source/http-region-source';
|
|
2
|
+
import { REGION_SOURCE_MIN_CHARS } from '../region-source/region-source';
|
|
3
|
+
import { openGeoJsonRegionSource } from '../region-source/worker-region-source';
|
|
4
|
+
/** Per target, the latest {@link applyImageRois}: a stack source that opens after a later load is dropped. */
|
|
5
|
+
const loads = new WeakMap();
|
|
6
|
+
/**
|
|
7
|
+
* Apply an image's saved ROIs once its render has landed, choosing the region
|
|
8
|
+
* layout from the image's shape:
|
|
9
|
+
*
|
|
10
|
+
* - **Folder stack** (`isStack && tiled === false`, see loadSeriesAsStack): a stack
|
|
11
|
+
* of self-contained per-slice files. Each slice-file may carry its own sibling
|
|
12
|
+
* `<stem>.geojson` (`roiJsonStrs[z]`), but a fresh folder with none yet leaves
|
|
13
|
+
* `roiJsonStrs` undefined — so this keys off `tiled === false`, NOT `roiJsonStrs`,
|
|
14
|
+
* and an unannotated folder stack still enters the per-slice-file layout (saving
|
|
15
|
+
* back one geojson per slice-file) rather than the combined one (jit-ui#93).
|
|
16
|
+
* - **Single-file z-stack**: one sibling geojson holding every slice's regions,
|
|
17
|
+
* indexed by QuPath's `geometry.plane.z`. Per-slice (combined) mode is entered when
|
|
18
|
+
* the geojson actually carries slice indices, or when there is nothing yet to
|
|
19
|
+
* author against. A legacy geojson whose regions are all on the default plane
|
|
20
|
+
* stays global (shown on every slice), so existing single-plane annotations are
|
|
21
|
+
* not confined to slice 0.
|
|
22
|
+
* - **Single plane** (or that legacy global stack): one region set for the image.
|
|
23
|
+
* Loading saved ROIs is not a user edit, so the undo history starts fresh and the
|
|
24
|
+
* first undo cannot wipe them (jit-ui#85).
|
|
25
|
+
*
|
|
26
|
+
* Large ROI files (`minSourceChars` and up) and a server-side source (`regionSourceUrl`)
|
|
27
|
+
* become tiled region sources instead of regions; a z-indexed one serves each slice its own
|
|
28
|
+
* plane. On a single-file stack the source is opened first, to tell which: one on the default
|
|
29
|
+
* plane only stays global, as its regions would. A folder stack's sources open lazily, the first
|
|
30
|
+
* time their slice is shown.
|
|
31
|
+
*
|
|
32
|
+
* `z` is the slice shown now; entering stack mode makes it live and resets undo. `http`, the
|
|
33
|
+
* host's `HttpClient`, carries a server-side source's requests, so the host's interceptors (its
|
|
34
|
+
* auth) apply to them as to the image tiles.
|
|
35
|
+
*/
|
|
36
|
+
export function applyImageRois(info, target, z, minSourceChars = REGION_SOURCE_MIN_CHARS, http) {
|
|
37
|
+
const attach = target.attachRegionSource?.bind(target);
|
|
38
|
+
const load = (loads.get(target) ?? 0) + 1;
|
|
39
|
+
loads.set(target, load);
|
|
40
|
+
const asSource = (json) => !!attach && !!json && json.length >= minSourceChars;
|
|
41
|
+
if (info.isStack && info.tiled === false) {
|
|
42
|
+
const perSlice = info.roiJsonStrs;
|
|
43
|
+
const sliceCount = info.urls?.length ?? perSlice?.length ?? 0;
|
|
44
|
+
const slices = new Map();
|
|
45
|
+
const sourced = [];
|
|
46
|
+
for (let s = 0; s < sliceCount; s++) {
|
|
47
|
+
const json = perSlice?.[s] ?? null;
|
|
48
|
+
if (asSource(json))
|
|
49
|
+
sourced.push(s);
|
|
50
|
+
slices.set(s, json && !asSource(json) ? target.importRegions(json) : []);
|
|
51
|
+
}
|
|
52
|
+
target.enterStackMode(slices, z, 'per-slice-file');
|
|
53
|
+
for (const s of sourced)
|
|
54
|
+
attach?.(() => openGeoJsonRegionSource(perSlice?.[s]), { slice: s });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const roiJson = info.roiJsonStr;
|
|
58
|
+
if (attach && (info.regionSourceUrl || asSource(roiJson))) {
|
|
59
|
+
const url = info.regionSourceUrl;
|
|
60
|
+
const open = url
|
|
61
|
+
? () => openHttpRegionSource(url, { http })
|
|
62
|
+
: () => openGeoJsonRegionSource(roiJson);
|
|
63
|
+
// As loading a file of regions replaces the regions, a source starts the image afresh.
|
|
64
|
+
target.setRegions([]);
|
|
65
|
+
target.resetUndoHistory();
|
|
66
|
+
if (!info.isStack) {
|
|
67
|
+
attach(open, { slice: 0 });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// A stack: per slice when the source is z-indexed, else global (as its regions would be).
|
|
71
|
+
// The store learns the slice the image opened on (a host may open a stack on any slice), so
|
|
72
|
+
// the source, laid out on the store's slice once it opens, shows that one; a scrub meanwhile
|
|
73
|
+
// records its own, which then wins.
|
|
74
|
+
if (!target.isStackMode?.())
|
|
75
|
+
target.setDisplaySlice?.(z);
|
|
76
|
+
let first = open();
|
|
77
|
+
const reuse = () => {
|
|
78
|
+
const opening = first;
|
|
79
|
+
first = null;
|
|
80
|
+
return opening ?? open();
|
|
81
|
+
};
|
|
82
|
+
const lay = (zIndexed) => {
|
|
83
|
+
if (loads.get(target) !== load) {
|
|
84
|
+
void first?.then((source) => source.dispose(), () => undefined);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (zIndexed) {
|
|
88
|
+
target.enterStackMode(new Map(), target.getDisplaySlice?.() ?? z, 'combined');
|
|
89
|
+
attach(reuse, 'planes');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
attach(reuse, { slice: 0 });
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
// One that cannot be opened is attached as a single plane (its slice reports the failure).
|
|
96
|
+
first.then((source) => lay(source.info.planes.some((p) => p !== 0)), () => lay(false));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (info.isStack) {
|
|
100
|
+
const regions = roiJson ? target.importRegions(roiJson) : [];
|
|
101
|
+
if (!roiJson || regions.some((r) => (r.z ?? 0) !== 0)) {
|
|
102
|
+
target.enterStackMode(bySlice(regions), z, 'combined');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (roiJson)
|
|
107
|
+
target.setRegions(target.importRegions(roiJson));
|
|
108
|
+
target.resetUndoHistory();
|
|
109
|
+
}
|
|
110
|
+
/** Bucket regions by their zero-based {@link Region.z} (unset = slice 0). */
|
|
111
|
+
function bySlice(regions) {
|
|
112
|
+
const slices = new Map();
|
|
113
|
+
for (const r of regions) {
|
|
114
|
+
const z = r.z ?? 0;
|
|
115
|
+
const bucket = slices.get(z);
|
|
116
|
+
if (bucket)
|
|
117
|
+
bucket.push(r);
|
|
118
|
+
else
|
|
119
|
+
slices.set(z, [r]);
|
|
120
|
+
}
|
|
121
|
+
return slices;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvcmVnaW9uLWxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDM0UsT0FBTyxFQUFFLHVCQUF1QixFQUFnQixNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZGLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBaUJoRiw4R0FBOEc7QUFDOUcsTUFBTSxLQUFLLEdBQUcsSUFBSSxPQUFPLEVBQTRCLENBQUM7QUFFdEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FDNUIsSUFBZ0IsRUFDaEIsTUFBd0IsRUFDeEIsQ0FBUyxFQUNULGNBQWMsR0FBRyx1QkFBdUIsRUFDeEMsSUFBaUI7SUFFakIsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2RCxNQUFNLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3hCLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBK0IsRUFBa0IsRUFBRSxDQUNuRSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxjQUFjLENBQUM7SUFFdEQsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDekMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNsQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sSUFBSSxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUM5RCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztRQUMzQyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7UUFDN0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxHQUFHLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztZQUNuQyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFDRCxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNuRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU87WUFBRSxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQVcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDeEcsT0FBTztJQUNULENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ2hDLElBQUksTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDakMsTUFBTSxJQUFJLEdBQXVCLEdBQUc7WUFDbEMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDO1lBQzNDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxPQUFpQixDQUFDLENBQUM7UUFDckQsdUZBQXVGO1FBQ3ZGLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEIsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNsQixNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDM0IsT0FBTztRQUNULENBQUM7UUFDRCwwRkFBMEY7UUFDMUYsNEZBQTRGO1FBQzVGLDZGQUE2RjtRQUM3RixvQ0FBb0M7UUFDcEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRTtZQUFFLE1BQU0sQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6RCxJQUFJLEtBQUssR0FBaUMsSUFBSSxFQUFFLENBQUM7UUFDakQsTUFBTSxLQUFLLEdBQXVCLEdBQUcsRUFBRTtZQUNyQyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDdEIsS0FBSyxHQUFHLElBQUksQ0FBQztZQUNiLE9BQU8sT0FBTyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQzNCLENBQUMsQ0FBQztRQUNGLE1BQU0sR0FBRyxHQUFHLENBQUMsUUFBaUIsRUFBRSxFQUFFO1lBQ2hDLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDL0IsS0FBSyxLQUFLLEVBQUUsSUFBSSxDQUNkLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQzVCLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FDaEIsQ0FBQztnQkFDRixPQUFPO1lBQ1QsQ0FBQztZQUNELElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEdBQUcsRUFBRSxFQUFFLE1BQU0sQ0FBQyxlQUFlLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDOUUsTUFBTSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztZQUMxQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzlCLENBQUM7UUFDSCxDQUFDLENBQUM7UUFDRiwyRkFBMkY7UUFDM0YsS0FBSyxDQUFDLElBQUksQ0FDUixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQ3hELEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FDakIsQ0FBQztRQUNGLE9BQU87SUFDVCxDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakIsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDN0QsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN0RCxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDdkQsT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxPQUFPO1FBQUUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDOUQsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDNUIsQ0FBQztBQUVELDZFQUE2RTtBQUM3RSxTQUFTLE9BQU8sQ0FBQyxPQUFpQjtJQUNoQyxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztJQUMzQyxLQUFLLE1BQU0sQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25CLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsSUFBSSxNQUFNO1lBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQzs7WUFDdEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgSUltYWdlSW5mbyB9IGZyb20gJy4uL2NvbnRyYWN0cy9pbWFnZS5jb250cmFjdCc7XG5pbXBvcnQgeyBJUmVnaW9uU3RvcmUgfSBmcm9tICcuLi9jb250cmFjdHMvdmlzdWFsaXplci5jb250cmFjdCc7XG5pbXBvcnQgeyBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IG9wZW5IdHRwUmVnaW9uU291cmNlIH0gZnJvbSAnLi4vcmVnaW9uLXNvdXJjZS9odHRwLXJlZ2lvbi1zb3VyY2UnO1xuaW1wb3J0IHsgUkVHSU9OX1NPVVJDRV9NSU5fQ0hBUlMsIFJlZ2lvblNvdXJjZSB9IGZyb20gJy4uL3JlZ2lvbi1zb3VyY2UvcmVnaW9uLXNvdXJjZSc7XG5pbXBvcnQgeyBvcGVuR2VvSnNvblJlZ2lvblNvdXJjZSB9IGZyb20gJy4uL3JlZ2lvbi1zb3VyY2Uvd29ya2VyLXJlZ2lvbi1zb3VyY2UnO1xuaW1wb3J0IHR5cGUgeyBSZWdpb25Tb3VyY2VPcGVuZXIsIFJlZ2lvblNvdXJjZVNsaWNlcyB9IGZyb20gJy4uL3N0b3JlL3JlZ2lvbi1zb3VyY2Utc2NvcGUnO1xuXG4vKiogVGhlIHJlZ2lvbi1zdG9yZSBtZW1iZXJzIHtAbGluayBhcHBseUltYWdlUm9pc30gd3JpdGVzIHRocm91Z2guIEEgdGFyZ2V0IHdpdGhvdXRcbiAqICBgYXR0YWNoUmVnaW9uU291cmNlYCBsb2FkcyBldmVyeSBST0kgZmlsZSBhcyByZWdpb25zLiAqL1xuZXhwb3J0IHR5cGUgUmVnaW9uTG9hZFRhcmdldCA9IFBpY2s8XG4gIElSZWdpb25TdG9yZSxcbiAgJ2ltcG9ydFJlZ2lvbnMnIHwgJ2VudGVyU3RhY2tNb2RlJyB8ICdzZXRSZWdpb25zJyB8ICdyZXNldFVuZG9IaXN0b3J5J1xuPiAmIHtcbiAgYXR0YWNoUmVnaW9uU291cmNlPyhzb3VyY2U6IFJlZ2lvblNvdXJjZSB8IFJlZ2lvblNvdXJjZU9wZW5lciwgc2xpY2VzPzogUmVnaW9uU291cmNlU2xpY2VzKTogdm9pZDtcbiAgLyoqIFRoZSBzbGljZSBzaG93biBub3cgKHdoYXQgYSBzdGFjaydzIHNvdXJjZSwgbGFpZCBvdXQgb25jZSBpdCBvcGVucywgbWFrZXMgbGl2ZSkuICovXG4gIGdldERpc3BsYXlTbGljZT8oKTogbnVtYmVyO1xuICAvKiogUmVjb3JkIHRoZSBzbGljZSBzaG93biAob3V0c2lkZSBzdGFjayBtb2RlIGl0IG9ubHkgcmVjb3JkcyBpdCk6IHNlZSB7QGxpbmsgYXBwbHlJbWFnZVJvaXN9LiAqL1xuICBzZXREaXNwbGF5U2xpY2U/KHo6IG51bWJlcik6IHZvaWQ7XG4gIGlzU3RhY2tNb2RlPygpOiBib29sZWFuO1xufTtcblxuLyoqIFBlciB0YXJnZXQsIHRoZSBsYXRlc3Qge0BsaW5rIGFwcGx5SW1hZ2VSb2lzfTogYSBzdGFjayBzb3VyY2UgdGhhdCBvcGVucyBhZnRlciBhIGxhdGVyIGxvYWQgaXMgZHJvcHBlZC4gKi9cbmNvbnN0IGxvYWRzID0gbmV3IFdlYWtNYXA8UmVnaW9uTG9hZFRhcmdldCwgbnVtYmVyPigpO1xuXG4vKipcbiAqIEFwcGx5IGFuIGltYWdlJ3Mgc2F2ZWQgUk9JcyBvbmNlIGl0cyByZW5kZXIgaGFzIGxhbmRlZCwgY2hvb3NpbmcgdGhlIHJlZ2lvblxuICogbGF5b3V0IGZyb20gdGhlIGltYWdlJ3Mgc2hhcGU6XG4gKlxuICogIC0gKipGb2xkZXIgc3RhY2sqKiAoYGlzU3RhY2sgJiYgdGlsZWQgPT09IGZhbHNlYCwgc2VlIGxvYWRTZXJpZXNBc1N0YWNrKTogYSBzdGFja1xuICogICAgb2Ygc2VsZi1jb250YWluZWQgcGVyLXNsaWNlIGZpbGVzLiBFYWNoIHNsaWNlLWZpbGUgbWF5IGNhcnJ5IGl0cyBvd24gc2libGluZ1xuICogICAgYDxzdGVtPi5nZW9qc29uYCAoYHJvaUpzb25TdHJzW3pdYCksIGJ1dCBhIGZyZXNoIGZvbGRlciB3aXRoIG5vbmUgeWV0IGxlYXZlc1xuICogICAgYHJvaUpzb25TdHJzYCB1bmRlZmluZWQg4oCUIHNvIHRoaXMga2V5cyBvZmYgYHRpbGVkID09PSBmYWxzZWAsIE5PVCBgcm9pSnNvblN0cnNgLFxuICogICAgYW5kIGFuIHVuYW5ub3RhdGVkIGZvbGRlciBzdGFjayBzdGlsbCBlbnRlcnMgdGhlIHBlci1zbGljZS1maWxlIGxheW91dCAoc2F2aW5nXG4gKiAgICBiYWNrIG9uZSBnZW9qc29uIHBlciBzbGljZS1maWxlKSByYXRoZXIgdGhhbiB0aGUgY29tYmluZWQgb25lIChqaXQtdWkjOTMpLlxuICogIC0gKipTaW5nbGUtZmlsZSB6LXN0YWNrKio6IG9uZSBzaWJsaW5nIGdlb2pzb24gaG9sZGluZyBldmVyeSBzbGljZSdzIHJlZ2lvbnMsXG4gKiAgICBpbmRleGVkIGJ5IFF1UGF0aCdzIGBnZW9tZXRyeS5wbGFuZS56YC4gUGVyLXNsaWNlIChjb21iaW5lZCkgbW9kZSBpcyBlbnRlcmVkIHdoZW5cbiAqICAgIHRoZSBnZW9qc29uIGFjdHVhbGx5IGNhcnJpZXMgc2xpY2UgaW5kaWNlcywgb3Igd2hlbiB0aGVyZSBpcyBub3RoaW5nIHlldCB0b1xuICogICAgYXV0aG9yIGFnYWluc3QuIEEgbGVnYWN5IGdlb2pzb24gd2hvc2UgcmVnaW9ucyBhcmUgYWxsIG9uIHRoZSBkZWZhdWx0IHBsYW5lXG4gKiAgICBzdGF5cyBnbG9iYWwgKHNob3duIG9uIGV2ZXJ5IHNsaWNlKSwgc28gZXhpc3Rpbmcgc2luZ2xlLXBsYW5lIGFubm90YXRpb25zIGFyZVxuICogICAgbm90IGNvbmZpbmVkIHRvIHNsaWNlIDAuXG4gKiAgLSAqKlNpbmdsZSBwbGFuZSoqIChvciB0aGF0IGxlZ2FjeSBnbG9iYWwgc3RhY2spOiBvbmUgcmVnaW9uIHNldCBmb3IgdGhlIGltYWdlLlxuICogICAgTG9hZGluZyBzYXZlZCBST0lzIGlzIG5vdCBhIHVzZXIgZWRpdCwgc28gdGhlIHVuZG8gaGlzdG9yeSBzdGFydHMgZnJlc2ggYW5kIHRoZVxuICogICAgZmlyc3QgdW5kbyBjYW5ub3Qgd2lwZSB0aGVtIChqaXQtdWkjODUpLlxuICpcbiAqIExhcmdlIFJPSSBmaWxlcyAoYG1pblNvdXJjZUNoYXJzYCBhbmQgdXApIGFuZCBhIHNlcnZlci1zaWRlIHNvdXJjZSAoYHJlZ2lvblNvdXJjZVVybGApXG4gKiBiZWNvbWUgdGlsZWQgcmVnaW9uIHNvdXJjZXMgaW5zdGVhZCBvZiByZWdpb25zOyBhIHotaW5kZXhlZCBvbmUgc2VydmVzIGVhY2ggc2xpY2UgaXRzIG93blxuICogcGxhbmUuIE9uIGEgc2luZ2xlLWZpbGUgc3RhY2sgdGhlIHNvdXJjZSBpcyBvcGVuZWQgZmlyc3QsIHRvIHRlbGwgd2hpY2g6IG9uZSBvbiB0aGUgZGVmYXVsdFxuICogcGxhbmUgb25seSBzdGF5cyBnbG9iYWwsIGFzIGl0cyByZWdpb25zIHdvdWxkLiBBIGZvbGRlciBzdGFjaydzIHNvdXJjZXMgb3BlbiBsYXppbHksIHRoZSBmaXJzdFxuICogdGltZSB0aGVpciBzbGljZSBpcyBzaG93bi5cbiAqXG4gKiBgemAgaXMgdGhlIHNsaWNlIHNob3duIG5vdzsgZW50ZXJpbmcgc3RhY2sgbW9kZSBtYWtlcyBpdCBsaXZlIGFuZCByZXNldHMgdW5kby4gYGh0dHBgLCB0aGVcbiAqIGhvc3QncyBgSHR0cENsaWVudGAsIGNhcnJpZXMgYSBzZXJ2ZXItc2lkZSBzb3VyY2UncyByZXF1ZXN0cywgc28gdGhlIGhvc3QncyBpbnRlcmNlcHRvcnMgKGl0c1xuICogYXV0aCkgYXBwbHkgdG8gdGhlbSBhcyB0byB0aGUgaW1hZ2UgdGlsZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseUltYWdlUm9pcyhcbiAgaW5mbzogSUltYWdlSW5mbyxcbiAgdGFyZ2V0OiBSZWdpb25Mb2FkVGFyZ2V0LFxuICB6OiBudW1iZXIsXG4gIG1pblNvdXJjZUNoYXJzID0gUkVHSU9OX1NPVVJDRV9NSU5fQ0hBUlMsXG4gIGh0dHA/OiBIdHRwQ2xpZW50LFxuKTogdm9pZCB7XG4gIGNvbnN0IGF0dGFjaCA9IHRhcmdldC5hdHRhY2hSZWdpb25Tb3VyY2U/LmJpbmQodGFyZ2V0KTtcbiAgY29uc3QgbG9hZCA9IChsb2Fkcy5nZXQodGFyZ2V0KSA/PyAwKSArIDE7XG4gIGxvYWRzLnNldCh0YXJnZXQsIGxvYWQpO1xuICBjb25zdCBhc1NvdXJjZSA9IChqc29uOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKToganNvbiBpcyBzdHJpbmcgPT5cbiAgICAhIWF0dGFjaCAmJiAhIWpzb24gJiYganNvbi5sZW5ndGggPj0gbWluU291cmNlQ2hhcnM7XG5cbiAgaWYgKGluZm8uaXNTdGFjayAmJiBpbmZvLnRpbGVkID09PSBmYWxzZSkge1xuICAgIGNvbnN0IHBlclNsaWNlID0gaW5mby5yb2lKc29uU3RycztcbiAgICBjb25zdCBzbGljZUNvdW50ID0gaW5mby51cmxzPy5sZW5ndGggPz8gcGVyU2xpY2U/Lmxlbmd0aCA/PyAwO1xuICAgIGNvbnN0IHNsaWNlcyA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgICBjb25zdCBzb3VyY2VkOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IHMgPSAwOyBzIDwgc2xpY2VDb3VudDsgcysrKSB7XG4gICAgICBjb25zdCBqc29uID0gcGVyU2xpY2U/LltzXSA/PyBudWxsO1xuICAgICAgaWYgKGFzU291cmNlKGpzb24pKSBzb3VyY2VkLnB1c2gocyk7XG4gICAgICBzbGljZXMuc2V0KHMsIGpzb24gJiYgIWFzU291cmNlKGpzb24pID8gdGFyZ2V0LmltcG9ydFJlZ2lvbnMoanNvbikgOiBbXSk7XG4gICAgfVxuICAgIHRhcmdldC5lbnRlclN0YWNrTW9kZShzbGljZXMsIHosICdwZXItc2xpY2UtZmlsZScpO1xuICAgIGZvciAoY29uc3QgcyBvZiBzb3VyY2VkKSBhdHRhY2g/LigoKSA9PiBvcGVuR2VvSnNvblJlZ2lvblNvdXJjZShwZXJTbGljZT8uW3NdIGFzIHN0cmluZyksIHsgc2xpY2U6IHMgfSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgcm9pSnNvbiA9IGluZm8ucm9pSnNvblN0cjtcbiAgaWYgKGF0dGFjaCAmJiAoaW5mby5yZWdpb25Tb3VyY2VVcmwgfHwgYXNTb3VyY2Uocm9pSnNvbikpKSB7XG4gICAgY29uc3QgdXJsID0gaW5mby5yZWdpb25Tb3VyY2VVcmw7XG4gICAgY29uc3Qgb3BlbjogUmVnaW9uU291cmNlT3BlbmVyID0gdXJsXG4gICAgICA/ICgpID0+IG9wZW5IdHRwUmVnaW9uU291cmNlKHVybCwgeyBodHRwIH0pXG4gICAgICA6ICgpID0+IG9wZW5HZW9Kc29uUmVnaW9uU291cmNlKHJvaUpzb24gYXMgc3RyaW5nKTtcbiAgICAvLyBBcyBsb2FkaW5nIGEgZmlsZSBvZiByZWdpb25zIHJlcGxhY2VzIHRoZSByZWdpb25zLCBhIHNvdXJjZSBzdGFydHMgdGhlIGltYWdlIGFmcmVzaC5cbiAgICB0YXJnZXQuc2V0UmVnaW9ucyhbXSk7XG4gICAgdGFyZ2V0LnJlc2V0VW5kb0hpc3RvcnkoKTtcbiAgICBpZiAoIWluZm8uaXNTdGFjaykge1xuICAgICAgYXR0YWNoKG9wZW4sIHsgc2xpY2U6IDAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIEEgc3RhY2s6IHBlciBzbGljZSB3aGVuIHRoZSBzb3VyY2UgaXMgei1pbmRleGVkLCBlbHNlIGdsb2JhbCAoYXMgaXRzIHJlZ2lvbnMgd291bGQgYmUpLlxuICAgIC8vIFRoZSBzdG9yZSBsZWFybnMgdGhlIHNsaWNlIHRoZSBpbWFnZSBvcGVuZWQgb24gKGEgaG9zdCBtYXkgb3BlbiBhIHN0YWNrIG9uIGFueSBzbGljZSksIHNvXG4gICAgLy8gdGhlIHNvdXJjZSwgbGFpZCBvdXQgb24gdGhlIHN0b3JlJ3Mgc2xpY2Ugb25jZSBpdCBvcGVucywgc2hvd3MgdGhhdCBvbmU7IGEgc2NydWIgbWVhbndoaWxlXG4gICAgLy8gcmVjb3JkcyBpdHMgb3duLCB3aGljaCB0aGVuIHdpbnMuXG4gICAgaWYgKCF0YXJnZXQuaXNTdGFja01vZGU/LigpKSB0YXJnZXQuc2V0RGlzcGxheVNsaWNlPy4oeik7XG4gICAgbGV0IGZpcnN0OiBQcm9taXNlPFJlZ2lvblNvdXJjZT4gfCBudWxsID0gb3BlbigpO1xuICAgIGNvbnN0IHJldXNlOiBSZWdpb25Tb3VyY2VPcGVuZXIgPSAoKSA9PiB7XG4gICAgICBjb25zdCBvcGVuaW5nID0gZmlyc3Q7XG4gICAgICBmaXJzdCA9IG51bGw7XG4gICAgICByZXR1cm4gb3BlbmluZyA/PyBvcGVuKCk7XG4gICAgfTtcbiAgICBjb25zdCBsYXkgPSAoekluZGV4ZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgIGlmIChsb2Fkcy5nZXQodGFyZ2V0KSAhPT0gbG9hZCkge1xuICAgICAgICB2b2lkIGZpcnN0Py50aGVuKFxuICAgICAgICAgIChzb3VyY2UpID0+IHNvdXJjZS5kaXNwb3NlKCksXG4gICAgICAgICAgKCkgPT4gdW5kZWZpbmVkLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoekluZGV4ZWQpIHtcbiAgICAgICAgdGFyZ2V0LmVudGVyU3RhY2tNb2RlKG5ldyBNYXAoKSwgdGFyZ2V0LmdldERpc3BsYXlTbGljZT8uKCkgPz8geiwgJ2NvbWJpbmVkJyk7XG4gICAgICAgIGF0dGFjaChyZXVzZSwgJ3BsYW5lcycpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXR0YWNoKHJldXNlLCB7IHNsaWNlOiAwIH0pO1xuICAgICAgfVxuICAgIH07XG4gICAgLy8gT25lIHRoYXQgY2Fubm90IGJlIG9wZW5lZCBpcyBhdHRhY2hlZCBhcyBhIHNpbmdsZSBwbGFuZSAoaXRzIHNsaWNlIHJlcG9ydHMgdGhlIGZhaWx1cmUpLlxuICAgIGZpcnN0LnRoZW4oXG4gICAgICAoc291cmNlKSA9PiBsYXkoc291cmNlLmluZm8ucGxhbmVzLnNvbWUoKHApID0+IHAgIT09IDApKSxcbiAgICAgICgpID0+IGxheShmYWxzZSksXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGluZm8uaXNTdGFjaykge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSByb2lKc29uID8gdGFyZ2V0LmltcG9ydFJlZ2lvbnMocm9pSnNvbikgOiBbXTtcbiAgICBpZiAoIXJvaUpzb24gfHwgcmVnaW9ucy5zb21lKChyKSA9PiAoci56ID8/IDApICE9PSAwKSkge1xuICAgICAgdGFyZ2V0LmVudGVyU3RhY2tNb2RlKGJ5U2xpY2UocmVnaW9ucyksIHosICdjb21iaW5lZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuICBpZiAocm9pSnNvbikgdGFyZ2V0LnNldFJlZ2lvbnModGFyZ2V0LmltcG9ydFJlZ2lvbnMocm9pSnNvbikpO1xuICB0YXJnZXQucmVzZXRVbmRvSGlzdG9yeSgpO1xufVxuXG4vKiogQnVja2V0IHJlZ2lvbnMgYnkgdGhlaXIgemVyby1iYXNlZCB7QGxpbmsgUmVnaW9uLnp9ICh1bnNldCA9IHNsaWNlIDApLiAqL1xuZnVuY3Rpb24gYnlTbGljZShyZWdpb25zOiBSZWdpb25bXSk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gIGNvbnN0IHNsaWNlcyA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgZm9yIChjb25zdCByIG9mIHJlZ2lvbnMpIHtcbiAgICBjb25zdCB6ID0gci56ID8/IDA7XG4gICAgY29uc3QgYnVja2V0ID0gc2xpY2VzLmdldCh6KTtcbiAgICBpZiAoYnVja2V0KSBidWNrZXQucHVzaChyKTtcbiAgICBlbHNlIHNsaWNlcy5zZXQoeiwgW3JdKTtcbiAgfVxuICByZXR1cm4gc2xpY2VzO1xufVxuIl19
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { takeUntil } from 'rxjs/operators';
|
|
2
|
+
import { PlotType, isSpatialOmics3d } from '../contracts/plot-type';
|
|
3
|
+
import { buildVolumeStackImage } from '../spatial/spatial-volume-image';
|
|
4
|
+
/**
|
|
5
|
+
* Binds the viewer to the spatial-omics dataset on `SPATIAL_DATA_PORT`: the gates it
|
|
6
|
+
* puts on the plot-type selector ({@link gates}), the mode an image-less dataset opens
|
|
7
|
+
* on, and publishing a dataset's registered volume AS the image.
|
|
8
|
+
*
|
|
9
|
+
* No-op when the host provides no port — the spatial types then stay hidden.
|
|
10
|
+
*/
|
|
11
|
+
export class SpatialDatasetBinder {
|
|
12
|
+
constructor(port, host) {
|
|
13
|
+
this.port = port;
|
|
14
|
+
this.host = host;
|
|
15
|
+
/** The dataset on offer, for drawing one that brings no image. */
|
|
16
|
+
this.dataset = null;
|
|
17
|
+
/** A dataset is published — gates the spatial plot types; the toolbar binds it too. */
|
|
18
|
+
this.hasDataset = false;
|
|
19
|
+
/** Its observations carry a z, gating the 3D spatial mode. */
|
|
20
|
+
this.has3d = false;
|
|
21
|
+
/** It brings pixels of its own (see {@link SpatialGates.hasPixels}). */
|
|
22
|
+
this.hasPixels = false;
|
|
23
|
+
/** Dataset identity + capability shape the last emission was handled at, so a
|
|
24
|
+
* switch between two datasets of the same shape is not mistaken for a repeat. */
|
|
25
|
+
this.key = null;
|
|
26
|
+
/** Dataset + geometry the published volume image was built from, so a re-emitted
|
|
27
|
+
* dataset doesn't re-fetch megabytes or reset the user's scrub. */
|
|
28
|
+
this.volumeImageKey = null;
|
|
29
|
+
/** Blob URLs backing that image — ours to revoke. */
|
|
30
|
+
this.volumeImageUrls = [];
|
|
31
|
+
}
|
|
32
|
+
/** Follow the port's dataset until `until$` emits. */
|
|
33
|
+
bind(until$) {
|
|
34
|
+
this.port
|
|
35
|
+
?.getDataset$()
|
|
36
|
+
.pipe(takeUntil(until$))
|
|
37
|
+
.subscribe((dataset) => this.onDataset(dataset ?? null));
|
|
38
|
+
}
|
|
39
|
+
/** Revoke the published volume image's blob URLs (teardown). */
|
|
40
|
+
dispose() {
|
|
41
|
+
this.revokeVolumeImageUrls();
|
|
42
|
+
}
|
|
43
|
+
onDataset(dataset) {
|
|
44
|
+
this.dataset = dataset;
|
|
45
|
+
// Only a dataset whose observations carry a z can be drawn as a cloud, so the 3D
|
|
46
|
+
// mode is gated on the coordinates, not merely on a dataset being present.
|
|
47
|
+
const has3d = !!dataset?.observations.z;
|
|
48
|
+
const hasVolume = !!dataset?.volume;
|
|
49
|
+
// The port publishes its current value on subscribe, so the initial `null` would
|
|
50
|
+
// otherwise recompute the selector for no change. Keyed by dataset IDENTITY as well
|
|
51
|
+
// as capability shape: two 3D datasets that both carry a volume have the same
|
|
52
|
+
// shape, and comparing only that skipped the switch — leaving the previous
|
|
53
|
+
// dataset's volume image on screen underneath the new one's observations.
|
|
54
|
+
const key = dataset
|
|
55
|
+
? `${dataset.id}|${has3d}|${hasVolume}|${dataset.volume ? `${dataset.volume.width}x${dataset.volume.height}x${dataset.volume.depth}` : ''}`
|
|
56
|
+
: null;
|
|
57
|
+
if (key === this.key)
|
|
58
|
+
return;
|
|
59
|
+
this.key = key;
|
|
60
|
+
this.hasDataset = !!dataset;
|
|
61
|
+
this.has3d = has3d;
|
|
62
|
+
// Whether the dataset brings pixels: it registers onto a tissue image (which may
|
|
63
|
+
// still be on its way — the pixel modes must not flicker out while it arrives), or
|
|
64
|
+
// its volume is published AS a grayscale z-stack image. Either way the pixel modes
|
|
65
|
+
// stay on offer — Volume and Isosurface are exactly how a 3D omics dataset is read.
|
|
66
|
+
this.hasPixels = !!dataset?.imageRef || hasVolume;
|
|
67
|
+
this.host.gatesChanged();
|
|
68
|
+
if (dataset && !dataset.imageRef && hasVolume) {
|
|
69
|
+
// No section to draw observations over (a cloud registered into a common frame,
|
|
70
|
+
// the Allen CCF), but a registered VOLUME: make that the image and open on it,
|
|
71
|
+
// slice bar and all. Ordered after the gates so the type is on offer first.
|
|
72
|
+
void this.showVolumeAsImage(dataset);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Anything else means a published volume image is no longer what is on screen.
|
|
76
|
+
// Forget it, or coming BACK to the volume dataset would short-circuit on a
|
|
77
|
+
// matching key and leave the other dataset's slide up.
|
|
78
|
+
this.dropVolumeImage();
|
|
79
|
+
if (dataset && !dataset.imageRef) {
|
|
80
|
+
// No reference image and no volume: the observations are all there is, so open
|
|
81
|
+
// on whichever spatial mode their coordinates support — leaving the type alone
|
|
82
|
+
// strands the host on the previous slide. A one-plane assay has no z and
|
|
83
|
+
// cannot be a cloud.
|
|
84
|
+
const target = has3d ? PlotType.SPATIAL_OMICS_3D : PlotType.SPATIAL_OMICS;
|
|
85
|
+
if (this.host.selectedId() !== target)
|
|
86
|
+
this.host.selectPlotType(target);
|
|
87
|
+
// Same mode, another image-less dataset, nothing loaded: re-plot so its
|
|
88
|
+
// placeholder image info (and with it the regions' key) is this dataset's.
|
|
89
|
+
else if (!this.host.hasImage())
|
|
90
|
+
this.host.replot();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Clearing the dataset while a spatial mode is active leaves a type that is no
|
|
94
|
+
// longer offered — the host falls back, as turning test mode off does.
|
|
95
|
+
this.host.settled();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Publish a dataset's reference volume AS the image, and open the 2D Image view on it:
|
|
99
|
+
* the slice bar scrubs z, and the contrast window, colormaps and region tools all work
|
|
100
|
+
* because the volume genuinely is the image now. The 3D cloud stays one pick away.
|
|
101
|
+
*
|
|
102
|
+
* Keyed by dataset + geometry: the dataset stream re-emits on things like a
|
|
103
|
+
* colour-column change, and rebuilding then would re-fetch the voxels and throw the
|
|
104
|
+
* user back to the middle slice.
|
|
105
|
+
*/
|
|
106
|
+
async showVolumeAsImage(dataset) {
|
|
107
|
+
const meta = dataset.volume;
|
|
108
|
+
if (!meta || !this.port?.getVolume)
|
|
109
|
+
return;
|
|
110
|
+
const key = `${dataset.id}:${meta.width}x${meta.height}x${meta.depth}`;
|
|
111
|
+
if (key === this.volumeImageKey)
|
|
112
|
+
return;
|
|
113
|
+
// Claim the key BEFORE awaiting: the stream can emit again while the voxels are in
|
|
114
|
+
// flight, and two builds of the same volume would race to publish.
|
|
115
|
+
this.volumeImageKey = key;
|
|
116
|
+
this.host.setImageLoading(true);
|
|
117
|
+
try {
|
|
118
|
+
const built = await buildVolumeStackImage(dataset, await this.port.getVolume());
|
|
119
|
+
// A different dataset was selected while this one encoded: drop what we built.
|
|
120
|
+
if (this.volumeImageKey !== key) {
|
|
121
|
+
built?.urls.forEach((u) => URL.revokeObjectURL(u));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!built) {
|
|
125
|
+
this.volumeImageKey = null;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Pick the mode first so the image lands in the view that will show it.
|
|
129
|
+
if (this.host.selectedId() !== PlotType.IMAGE)
|
|
130
|
+
this.host.selectPlotType(PlotType.IMAGE);
|
|
131
|
+
this.revokeVolumeImageUrls();
|
|
132
|
+
this.volumeImageUrls = built.urls;
|
|
133
|
+
this.host.publishImage(built.info);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
// No volume served after all: the cloud is still renderable, so fall back to it.
|
|
137
|
+
console.warn('[visualizer] reference volume unavailable — falling back to the 3D cloud', err);
|
|
138
|
+
this.volumeImageKey = null;
|
|
139
|
+
if (this.has3d && !isSpatialOmics3d(this.host.basePlotType())) {
|
|
140
|
+
this.host.selectPlotType(PlotType.SPATIAL_OMICS_3D);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
// Only the build still on screen (or one that failed and released its key) may
|
|
145
|
+
// drop the overlay: a newer volume build that superseded this one is still encoding.
|
|
146
|
+
if (this.volumeImageKey === key || this.volumeImageKey === null)
|
|
147
|
+
this.host.setImageLoading(false);
|
|
148
|
+
this.host.detectChanges();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** Forget the published volume image so re-selecting the dataset rebuilds it. The
|
|
152
|
+
* URLs deliberately stay alive: the host may still be displaying that image, and
|
|
153
|
+
* revoking under it would break every later tile read. They are freed when the next
|
|
154
|
+
* volume replaces them, or on {@link dispose}. */
|
|
155
|
+
dropVolumeImage() {
|
|
156
|
+
this.volumeImageKey = null;
|
|
157
|
+
}
|
|
158
|
+
revokeVolumeImageUrls() {
|
|
159
|
+
this.volumeImageUrls.forEach((u) => URL.revokeObjectURL(u));
|
|
160
|
+
this.volumeImageUrls = [];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1kYXRhc2V0LWJpbmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmlzdWFsaXplci9zcGF0aWFsLWRhdGFzZXQtYmluZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUczQyxPQUFPLEVBQUUsUUFBUSxFQUFjLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFJaEYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFzQnhFOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFrQi9CLFlBQ21CLElBQWlDLEVBQ2pDLElBQXVCO1FBRHZCLFNBQUksR0FBSixJQUFJLENBQTZCO1FBQ2pDLFNBQUksR0FBSixJQUFJLENBQW1CO1FBbkIxQyxrRUFBa0U7UUFDbEUsWUFBTyxHQUEwQixJQUFJLENBQUM7UUFDdEMsdUZBQXVGO1FBQ3ZGLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbkIsOERBQThEO1FBQzlELFVBQUssR0FBRyxLQUFLLENBQUM7UUFDZCx3RUFBd0U7UUFDeEUsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQjswRkFDa0Y7UUFDMUUsUUFBRyxHQUFrQixJQUFJLENBQUM7UUFDbEM7NEVBQ29FO1FBQzVELG1CQUFjLEdBQWtCLElBQUksQ0FBQztRQUM3QyxxREFBcUQ7UUFDN0Msb0JBQWUsR0FBYSxFQUFFLENBQUM7SUFLcEMsQ0FBQztJQUVKLHNEQUFzRDtJQUN0RCxJQUFJLENBQUMsTUFBMkI7UUFDOUIsSUFBSSxDQUFDLElBQUk7WUFDUCxFQUFFLFdBQVcsRUFBRTthQUNkLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDdkIsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sSUFBSSxJ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aW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFBsb3RUeXBlLCBQbG90VHlwZUlkLCBpc1NwYXRpYWxPbWljczNkIH0gZnJvbSAnLi4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQgeyBTcGF0aWFsRGF0YVBvcnQgfSBmcm9tICcuLi9jb250cmFjdHMvcG9ydHMvc3BhdGlhbC1kYXRhLnBvcnQnO1xuaW1wb3J0IHsgU3BhdGlhbERhdGFzZXQgfSBmcm9tICcuLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7IFNwYXRpYWxHYXRlcyB9IGZyb20gJy4uL3Bsb3QtbW9kZS9wbG90LXR5cGUtbWVudSc7XG5pbXBvcnQgeyBidWlsZFZvbHVtZVN0YWNrSW1hZ2UgfSBmcm9tICcuLi9zcGF0aWFsL3NwYXRpYWwtdm9sdW1lLWltYWdlJztcblxuLyoqIFdoYXQgYSBkYXRhc2V0IHN3aXRjaCBhc2tzIG9mIHRoZSB2aWV3ZXIuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXRpYWxCaW5kZXJIb3N0IHtcbiAgLyoqIFRoZSBwbG90LXR5cGUgZ2F0ZXMgY2hhbmdlZDogcmVjb21wdXRlIHRoZSBzZWxlY3Rvci4gKi9cbiAgZ2F0ZXNDaGFuZ2VkKCk6IHZvaWQ7XG4gIC8qKiBUaGUgc2VsZWN0b3IncyBjdXJyZW50IGlkLCBhbmQgdGhlIGJ1aWx0LWluIHR5cGUgcmVuZGVyZWQgZm9yIGl0LiAqL1xuICBzZWxlY3RlZElkKCk6IFBsb3RUeXBlSWQ7XG4gIGJhc2VQbG90VHlwZSgpOiBQbG90VHlwZTtcbiAgLyoqIFdoZXRoZXIgYW4gaW1hZ2UgaXMgbG9hZGVkLiAqL1xuICBoYXNJbWFnZSgpOiBib29sZWFuO1xuICBzZWxlY3RQbG90VHlwZSh0eXBlOiBQbG90VHlwZSk6IHZvaWQ7XG4gIC8qKiBSZS1wbG90IHRoZSBjdXJyZW50IG1vZGUuICovXG4gIHJlcGxvdCgpOiB2b2lkO1xuICAvKiogUHVibGlzaCBhbiBpbWFnZSBhcyB0aGUgaG9zdCdzIGN1cnJlbnQgb25lLiAqL1xuICBwdWJsaXNoSW1hZ2UoaW5mbzogSUltYWdlSW5mbyk6IHZvaWQ7XG4gIHNldEltYWdlTG9hZGluZyhsb2FkaW5nOiBib29sZWFuKTogdm9pZDtcbiAgLyoqIFRoZSBzd2l0Y2ggaXMgaGFuZGxlZDogcmVjb25jaWxlIHRoZSBzZWxlY3Rpb24gd2l0aCB0aGUgbmV3IGdhdGVzIGFuZCByZS1yZW5kZXIuICovXG4gIHNldHRsZWQoKTogdm9pZDtcbiAgZGV0ZWN0Q2hhbmdlcygpOiB2b2lkO1xufVxuXG4vKipcbiAqIEJpbmRzIHRoZSB2aWV3ZXIgdG8gdGhlIHNwYXRpYWwtb21pY3MgZGF0YXNldCBvbiBgU1BBVElBTF9EQVRBX1BPUlRgOiB0aGUgZ2F0ZXMgaXRcbiAqIHB1dHMgb24gdGhlIHBsb3QtdHlwZSBzZWxlY3RvciAoe0BsaW5rIGdhdGVzfSksIHRoZSBtb2RlIGFuIGltYWdlLWxlc3MgZGF0YXNldCBvcGVuc1xuICogb24sIGFuZCBwdWJsaXNoaW5nIGEgZGF0YXNldCdzIHJlZ2lzdGVyZWQgdm9sdW1lIEFTIHRoZSBpbWFnZS5cbiAqXG4gKiBOby1vcCB3aGVuIHRoZSBob3N0IHByb3ZpZGVzIG5vIHBvcnQg4oCUIHRoZSBzcGF0aWFsIHR5cGVzIHRoZW4gc3RheSBoaWRkZW4uXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGF0aWFsRGF0YXNldEJpbmRlciBpbXBsZW1lbnRzIFNwYXRpYWxHYXRlcyB7XG4gIC8qKiBUaGUgZGF0YXNldCBvbiBvZmZlciwgZm9yIGRyYXdpbmcgb25lIHRoYXQgYnJpbmdzIG5vIGltYWdlLiAqL1xuICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwgPSBudWxsO1xuICAvKiogQSBkYXRhc2V0IGlzIHB1Ymxpc2hlZCDigJQgZ2F0ZXMgdGhlIHNwYXRpYWwgcGxvdCB0eXBlczsgdGhlIHRvb2xiYXIgYmluZHMgaXQgdG9vLiAqL1xuICBoYXNEYXRhc2V0ID0gZmFsc2U7XG4gIC8qKiBJdHMgb2JzZXJ2YXRpb25zIGNhcnJ5IGEgeiwgZ2F0aW5nIHRoZSAzRCBzcGF0aWFsIG1vZGUuICovXG4gIGhhczNkID0gZmFsc2U7XG4gIC8qKiBJdCBicmluZ3MgcGl4ZWxzIG9mIGl0cyBvd24gKHNlZSB7QGxpbmsgU3BhdGlhbEdhdGVzLmhhc1BpeGVsc30pLiAqL1xuICBoYXNQaXhlbHMgPSBmYWxzZTtcbiAgLyoqIERhdGFzZXQgaWRlbnRpdHkgKyBjYXBhYmlsaXR5IHNoYXBlIHRoZSBsYXN0IGVtaXNzaW9uIHdhcyBoYW5kbGVkIGF0LCBzbyBhXG4gICAqICBzd2l0Y2ggYmV0d2VlbiB0d28gZGF0YXNldHMgb2YgdGhlIHNhbWUgc2hhcGUgaXMgbm90IG1pc3Rha2VuIGZvciBhIHJlcGVhdC4gKi9cbiAgcHJpdmF0ZSBrZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogRGF0YXNldCArIGdlb21ldHJ5IHRoZSBwdWJsaXNoZWQgdm9sdW1lIGltYWdlIHdhcyBidWlsdCBmcm9tLCBzbyBhIHJlLWVtaXR0ZWRcbiAgICogIGRhdGFzZXQgZG9lc24ndCByZS1mZXRjaCBtZWdhYnl0ZXMgb3IgcmVzZXQgdGhlIHVzZXIncyBzY3J1Yi4gKi9cbiAgcHJpdmF0ZSB2b2x1bWVJbWFnZUtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBCbG9iIFVSTHMgYmFja2luZyB0aGF0IGltYWdlIOKAlCBvdXJzIHRvIHJldm9rZS4gKi9cbiAgcHJpdmF0ZSB2b2x1bWVJbWFnZVVybHM6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb3J0OiBTcGF0aWFsRGF0YVBvcnQgfCB1bmRlZmluZWQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBTcGF0aWFsQmluZGVySG9zdCxcbiAgKSB7fVxuXG4gIC8qKiBGb2xsb3cgdGhlIHBvcnQncyBkYXRhc2V0IHVudGlsIGB1bnRpbCRgIGVtaXRzLiAqL1xuICBiaW5kKHVudGlsJDogT2JzZXJ2YWJsZTx1bmtub3duPik6IHZvaWQge1xuICAgIHRoaXMucG9ydFxuICAgICAgPy5nZXREYXRhc2V0JCgpXG4gICAgICAucGlwZSh0YWtlVW50aWwodW50aWwkKSlcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGFzZXQpID0+IHRoaXMub25EYXRhc2V0KGRhdGFzZXQgPz8gbnVsbCkpO1xuICB9XG5cbiAgLyoqIFJldm9rZSB0aGUgcHVibGlzaGVkIHZvbHVtZSBpbWFnZSdzIGJsb2IgVVJMcyAodGVhcmRvd24pLiAqL1xuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMucmV2b2tlVm9sdW1lSW1hZ2VVcmxzKCk7XG4gIH1cblxuICBwcml2YXRlIG9uRGF0YXNldChkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGFzZXQgPSBkYXRhc2V0O1xuICAgIC8vIE9ubHkgYSBkYXRhc2V0IHdob3NlIG9ic2VydmF0aW9ucyBjYXJyeSBhIHogY2FuIGJlIGRyYXduIGFzIGEgY2xvdWQsIHNvIHRoZSAzRFxuICAgIC8vIG1vZGUgaXMgZ2F0ZWQgb24gdGhlIGNvb3JkaW5hdGVzLCBub3QgbWVyZWx5IG9uIGEgZGF0YXNldCBiZWluZyBwcmVzZW50LlxuICAgIGNvbnN0IGhhczNkID0gISFkYXRhc2V0Py5vYnNlcnZhdGlvbnMuejtcbiAgICBjb25zdCBoYXNWb2x1bWUgPSAhIWRhdGFzZXQ/LnZvbHVtZTtcbiAgICAvLyBUaGUgcG9ydCBwdWJsaXNoZXMgaXRzIGN1cnJlbnQgdmFsdWUgb24gc3Vic2NyaWJlLCBzbyB0aGUgaW5pdGlhbCBgbnVsbGAgd291bGRcbiAgICAvLyBvdGhlcndpc2UgcmVjb21wdXRlIHRoZSBzZWxlY3RvciBmb3Igbm8gY2hhbmdlLiBLZXllZCBieSBkYXRhc2V0IElERU5USVRZIGFzIHdlbGxcbiAgICAvLyBhcyBjYXBhYmlsaXR5IHNoYXBlOiB0d28gM0QgZGF0YXNldHMgdGhhdCBib3RoIGNhcnJ5IGEgdm9sdW1lIGhhdmUgdGhlIHNhbWVcbiAgICAvLyBzaGFwZSwgYW5kIGNvbXBhcmluZyBvbmx5IHRoYXQgc2tpcHBlZCB0aGUgc3dpdGNoIOKAlCBsZWF2aW5nIHRoZSBwcmV2aW91c1xuICAgIC8vIGRhdGFzZXQncyB2b2x1bWUgaW1hZ2Ugb24gc2NyZWVuIHVuZGVybmVhdGggdGhlIG5ldyBvbmUncyBvYnNlcnZhdGlvbnMuXG4gICAgY29uc3Qga2V5ID0gZGF0YXNldFxuICAgICAgPyBgJHtkYXRhc2V0LmlkfXwke2hhczNkfXwke2hhc1ZvbHVtZX18JHtcbiAgICAgICAgICBkYXRhc2V0LnZvbHVtZSA/IGAke2RhdGFzZXQudm9sdW1lLndpZHRofXgke2RhdGFzZXQudm9sdW1lLmhlaWdodH14JHtkYXRhc2V0LnZvbHVtZS5kZXB0aH1gIDogJydcbiAgICAgICAgfWBcbiAgICAgIDogbnVsbDtcbiAgICBpZiAoa2V5ID09PSB0aGlzLmtleSkgcmV0dXJuO1xuICAgIHRoaXMua2V5ID0ga2V5O1xuICAgIHRoaXMuaGFzRGF0YXNldCA9ICEhZGF0YXNldDtcbiAgICB0aGlzLmhhczNkID0gaGFzM2Q7XG4gICAgLy8gV2hldGhlciB0aGUgZGF0YXNldCBicmluZ3MgcGl4ZWxzOiBpdCByZWdpc3RlcnMgb250byBhIHRpc3N1ZSBpbWFnZSAod2hpY2ggbWF5XG4gICAgLy8gc3RpbGwgYmUgb24gaXRzIHdheSDigJQgdGhlIHBpeGVsIG1vZGVzIG11c3Qgbm90IGZsaWNrZXIgb3V0IHdoaWxlIGl0IGFycml2ZXMpLCBvclxuICAgIC8vIGl0cyB2b2x1bWUgaXMgcHVibGlzaGVkIEFTIGEgZ3JheXNjYWxlIHotc3RhY2sgaW1hZ2UuIEVpdGhlciB3YXkgdGhlIHBpeGVsIG1vZGVzXG4gICAgLy8gc3RheSBvbiBvZmZlciDigJQgVm9sdW1lIGFuZCBJc29zdXJmYWNlIGFyZSBleGFjdGx5IGhvdyBhIDNEIG9taWNzIGRhdGFzZXQgaXMgcmVhZC5cbiAgICB0aGlzLmhhc1BpeGVscyA9ICEhZGF0YXNldD8uaW1hZ2VSZWYgfHwgaGFzVm9sdW1lO1xuICAgIHRoaXMuaG9zdC5nYXRlc0NoYW5nZWQoKTtcbiAgICBpZiAoZGF0YXNldCAmJiAhZGF0YXNldC5pbWFnZVJlZiAmJiBoYXNWb2x1bWUpIHtcbiAgICAgIC8vIE5vIHNlY3Rpb24gdG8gZHJhdyBvYnNlcnZhdGlvbnMgb3ZlciAoYSBjbG91ZCByZWdpc3RlcmVkIGludG8gYSBjb21tb24gZnJhbWUsXG4gICAgICAvLyB0aGUgQWxsZW4gQ0NGKSwgYnV0IGEgcmVnaXN0ZXJlZCBWT0xVTUU6IG1ha2UgdGhhdCB0aGUgaW1hZ2UgYW5kIG9wZW4gb24gaXQsXG4gICAgICAvLyBzbGljZSBiYXIgYW5kIGFsbC4gT3JkZXJlZCBhZnRlciB0aGUgZ2F0ZXMgc28gdGhlIHR5cGUgaXMgb24gb2ZmZXIgZmlyc3QuXG4gICAgICB2b2lkIHRoaXMuc2hvd1ZvbHVtZUFzSW1hZ2UoZGF0YXNldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEFueXRoaW5nIGVsc2UgbWVhbnMgYSBwdWJsaXNoZWQgdm9sdW1lIGltYWdlIGlzIG5vIGxvbmdlciB3aGF0IGlzIG9uIHNjcmVlbi5cbiAgICAgIC8vIEZvcmdldCBpdCwgb3IgY29taW5nIEJBQ0sgdG8gdGhlIHZvbHVtZSBkYXRhc2V0IHdvdWxkIHNob3J0LWNpcmN1aXQgb24gYVxuICAgICAgLy8gbWF0Y2hpbmcga2V5IGFuZCBsZWF2ZSB0aGUgb3RoZXIgZGF0YXNldCdzIHNsaWRlIHVwLlxuICAgICAgdGhpcy5kcm9wVm9sdW1lSW1hZ2UoKTtcbiAgICAgIGlmIChkYXRhc2V0ICYmICFkYXRhc2V0LmltYWdlUmVmKSB7XG4gICAgICAgIC8vIE5vIHJlZmVyZW5jZSBpbWFnZSBhbmQgbm8gdm9sdW1lOiB0aGUgb2JzZXJ2YXRpb25zIGFyZSBhbGwgdGhlcmUgaXMsIHNvIG9wZW5cbiAgICAgICAgLy8gb24gd2hpY2hldmVyIHNwYXRpYWwgbW9kZSB0aGVpciBjb29yZGluYXRlcyBzdXBwb3J0IOKAlCBsZWF2aW5nIHRoZSB0eXBlIGFsb25lXG4gICAgICAgIC8vIHN0cmFuZHMgdGhlIGhvc3Qgb24gdGhlIHByZXZpb3VzIHNsaWRlLiBBIG9uZS1wbGFuZSBhc3NheSBoYXMgbm8geiBhbmRcbiAgICAgICAgLy8gY2Fubm90IGJlIGEgY2xvdWQuXG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGhhczNkID8gUGxvdFR5cGUuU1BBVElBTF9PTUlDU18zRCA6IFBsb3RUeXBlLlNQQVRJQUxfT01JQ1M7XG4gICAgICAgIGlmICh0aGlzLmhvc3Quc2VsZWN0ZWRJZCgpICE9PSB0YXJnZXQpIHRoaXMuaG9zdC5zZWxlY3RQbG90VHlwZSh0YXJnZXQpO1xuICAgICAgICAvLyBTYW1lIG1vZGUsIGFub3RoZXIgaW1hZ2UtbGVzcyBkYXRhc2V0LCBub3RoaW5nIGxvYWRlZDogcmUtcGxvdCBzbyBpdHNcbiAgICAgICAgLy8gcGxhY2Vob2xkZXIgaW1hZ2UgaW5mbyAoYW5kIHdpdGggaXQgdGhlIHJlZ2lvbnMnIGtleSkgaXMgdGhpcyBkYXRhc2V0J3MuXG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLmhvc3QuaGFzSW1hZ2UoKSkgdGhpcy5ob3N0LnJlcGxvdCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDbGVhcmluZyB0aGUgZGF0YXNldCB3aGlsZSBhIHNwYXRpYWwgbW9kZSBpcyBhY3RpdmUgbGVhdmVzIGEgdHlwZSB0aGF0IGlzIG5vXG4gICAgLy8gbG9uZ2VyIG9mZmVyZWQg4oCUIHRoZSBob3N0IGZhbGxzIGJhY2ssIGFzIHR1cm5pbmcgdGVzdCBtb2RlIG9mZiBkb2VzLlxuICAgIHRoaXMuaG9zdC5zZXR0bGVkKCk7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhIGRhdGFzZXQncyByZWZlcmVuY2Ugdm9sdW1lIEFTIHRoZSBpbWFnZSwgYW5kIG9wZW4gdGhlIDJEIEltYWdlIHZpZXcgb24gaXQ6XG4gICAqIHRoZSBzbGljZSBiYXIgc2NydWJzIHosIGFuZCB0aGUgY29udHJhc3Qgd2luZG93LCBjb2xvcm1hcHMgYW5kIHJlZ2lvbiB0b29scyBhbGwgd29ya1xuICAgKiBiZWNhdXNlIHRoZSB2b2x1bWUgZ2VudWluZWx5IGlzIHRoZSBpbWFnZSBub3cuIFRoZSAzRCBjbG91ZCBzdGF5cyBvbmUgcGljayBhd2F5LlxuICAgKlxuICAgKiBLZXllZCBieSBkYXRhc2V0ICsgZ2VvbWV0cnk6IHRoZSBkYXRhc2V0IHN0cmVhbSByZS1lbWl0cyBvbiB0aGluZ3MgbGlrZSBhXG4gICAqIGNvbG91ci1jb2x1bW4gY2hhbmdlLCBhbmQgcmVidWlsZGluZyB0aGVuIHdvdWxkIHJlLWZldGNoIHRoZSB2b3hlbHMgYW5kIHRocm93IHRoZVxuICAgKiB1c2VyIGJhY2sgdG8gdGhlIG1pZGRsZSBzbGljZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2hvd1ZvbHVtZUFzSW1hZ2UoZGF0YXNldDogU3BhdGlhbERhdGFzZXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtZXRhID0gZGF0YXNldC52b2x1bWU7XG4gICAgaWYgKCFtZXRhIHx8ICF0aGlzLnBvcnQ/LmdldFZvbHVtZSkgcmV0dXJuO1xuICAgIGNvbnN0IGtleSA9IGAke2RhdGFzZXQuaWR9OiR7bWV0YS53aWR0aH14JHttZXRhLmhlaWdodH14JHttZXRhLmRlcHRofWA7XG4gICAgaWYgKGtleSA9PT0gdGhpcy52b2x1bWVJbWFnZUtleSkgcmV0dXJuO1xuICAgIC8vIENsYWltIHRoZSBrZXkgQkVGT1JFIGF3YWl0aW5nOiB0aGUgc3RyZWFtIGNhbiBlbWl0IGFnYWluIHdoaWxlIHRoZSB2b3hlbHMgYXJlIGluXG4gICAgLy8gZmxpZ2h0LCBhbmQgdHdvIGJ1aWxkcyBvZiB0aGUgc2FtZSB2b2x1bWUgd291bGQgcmFjZSB0byBwdWJsaXNoLlxuICAgIHRoaXMudm9sdW1lSW1hZ2VLZXkgPSBrZXk7XG4gICAgdGhpcy5ob3N0LnNldEltYWdlTG9hZGluZyh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYnVpbHQgPSBhd2FpdCBidWlsZFZvbHVtZVN0YWNrSW1hZ2UoZGF0YXNldCwgYXdhaXQgdGhpcy5wb3J0LmdldFZvbHVtZSgpKTtcbiAgICAgIC8vIEEgZGlmZmVyZW50IGRhdGFzZXQgd2FzIHNlbGVjdGVkIHdoaWxlIHRoaXMgb25lIGVuY29kZWQ6IGRyb3Agd2hhdCB3ZSBidWlsdC5cbiAgICAgIGlmICh0aGlzLnZvbHVtZUltYWdlS2V5ICE9PSBrZXkpIHtcbiAgICAgICAgYnVpbHQ/LnVybHMuZm9yRWFjaCgodSkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1KSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghYnVpbHQpIHtcbiAgICAgICAgdGhpcy52b2x1bWVJbWFnZUtleSA9IG51bGw7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIFBpY2sgdGhlIG1vZGUgZmlyc3Qgc28gdGhlIGltYWdlIGxhbmRzIGluIHRoZSB2aWV3IHRoYXQgd2lsbCBzaG93IGl0LlxuICAgICAgaWYgKHRoaXMuaG9zdC5zZWxlY3RlZElkKCkgIT09IFBsb3RUeXBlLklNQUdFKSB0aGlzLmhvc3Quc2VsZWN0UGxvdFR5cGUoUGxvdFR5cGUuSU1BR0UpO1xuICAgICAgdGhpcy5yZXZva2VWb2x1bWVJbWFnZVVybHMoKTtcbiAgICAgIHRoaXMudm9sdW1lSW1hZ2VVcmxzID0gYnVpbHQudXJscztcbiAgICAgIHRoaXMuaG9zdC5wdWJsaXNoSW1hZ2UoYnVpbHQuaW5mbyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBObyB2b2x1bWUgc2VydmVkIGFmdGVyIGFsbDogdGhlIGNsb3VkIGlzIHN0aWxsIHJlbmRlcmFibGUsIHNvIGZhbGwgYmFjayB0byBpdC5cbiAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIHJlZmVyZW5jZSB2b2x1bWUgdW5hdmFpbGFibGUg4oCUIGZhbGxpbmcgYmFjayB0byB0aGUgM0QgY2xvdWQnLCBlcnIpO1xuICAgICAgdGhpcy52b2x1bWVJbWFnZUtleSA9IG51bGw7XG4gICAgICBpZiAodGhpcy5oYXMzZCAmJiAhaXNTcGF0aWFsT21pY3MzZCh0aGlzLmhvc3QuYmFzZVBsb3RUeXBlKCkpKSB7XG4gICAgICAgIHRoaXMuaG9zdC5zZWxlY3RQbG90VHlwZShQbG90VHlwZS5TUEFUSUFMX09NSUNTXzNEKTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gT25seSB0aGUgYnVpbGQgc3RpbGwgb24gc2NyZWVuIChvciBvbmUgdGhhdCBmYWlsZWQgYW5kIHJlbGVhc2VkIGl0cyBrZXkpIG1heVxuICAgICAgLy8gZHJvcCB0aGUgb3ZlcmxheTogYSBuZXdlciB2b2x1bWUgYnVpbGQgdGhhdCBzdXBlcnNlZGVkIHRoaXMgb25lIGlzIHN0aWxsIGVuY29kaW5nLlxuICAgICAgaWYgKHRoaXMudm9sdW1lSW1hZ2VLZXkgPT09IGtleSB8fCB0aGlzLnZvbHVtZUltYWdlS2V5ID09PSBudWxsKSB0aGlzLmhvc3Quc2V0SW1hZ2VMb2FkaW5nKGZhbHNlKTtcbiAgICAgIHRoaXMuaG9zdC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEZvcmdldCB0aGUgcHVibGlzaGVkIHZvbHVtZSBpbWFnZSBzbyByZS1zZWxlY3RpbmcgdGhlIGRhdGFzZXQgcmVidWlsZHMgaXQuIFRoZVxuICAgKiAgVVJMcyBkZWxpYmVyYXRlbHkgc3RheSBhbGl2ZTogdGhlIGhvc3QgbWF5IHN0aWxsIGJlIGRpc3BsYXlpbmcgdGhhdCBpbWFnZSwgYW5kXG4gICAqICByZXZva2luZyB1bmRlciBpdCB3b3VsZCBicmVhayBldmVyeSBsYXRlciB0aWxlIHJlYWQuIFRoZXkgYXJlIGZyZWVkIHdoZW4gdGhlIG5leHRcbiAgICogIHZvbHVtZSByZXBsYWNlcyB0aGVtLCBvciBvbiB7QGxpbmsgZGlzcG9zZX0uICovXG4gIHByaXZhdGUgZHJvcFZvbHVtZUltYWdlKCk6IHZvaWQge1xuICAgIHRoaXMudm9sdW1lSW1hZ2VLZXkgPSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSByZXZva2VWb2x1bWVJbWFnZVVybHMoKTogdm9pZCB7XG4gICAgdGhpcy52b2x1bWVJbWFnZVVybHMuZm9yRWFjaCgodSkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1KSk7XG4gICAgdGhpcy52b2x1bWVJbWFnZVVybHMgPSBbXTtcbiAgfVxufVxuIl19
|