higlass 1.13.5 → 2.0.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 +48 -54
- package/app/globals.d.ts +1 -1
- package/app/missing-types.d.ts +4 -1
- package/app/scripts/AddTrackDialog.jsx +11 -4
- package/app/scripts/AddTrackPositionMenu.jsx +28 -7
- package/app/scripts/Annotations1dTrack.js +90 -251
- package/app/scripts/Annotations2dTrack.js +12 -7
- package/app/scripts/Autocomplete.jsx +13 -28
- package/app/scripts/AxisPixi.js +6 -10
- package/app/scripts/BarTrack.js +3 -3
- package/app/scripts/BedLikeTrack.js +556 -449
- package/app/scripts/Button.jsx +1 -1
- package/app/scripts/CNVIntervalTrack.js +1 -1
- package/app/scripts/CenterTrack.jsx +8 -7
- package/app/scripts/Chromosome2DAnnotations.js +1 -1
- package/app/scripts/Chromosome2DLabels.js +1 -1
- package/app/scripts/ChromosomeGrid.js +49 -38
- package/app/scripts/ChromosomeInfo.js +1 -1
- package/app/scripts/CombinedTrack.js +3 -1
- package/app/scripts/ConfigTrackMenu.jsx +1 -1
- package/app/scripts/ConfigViewMenu.jsx +2 -2
- package/app/scripts/ContextMenuContainer.jsx +4 -2
- package/app/scripts/ContextMenuItem.jsx +14 -2
- package/app/scripts/CrossRule.js +1 -1
- package/app/scripts/CustomTrackDialog.jsx +2 -2
- package/app/scripts/Dialog.jsx +2 -2
- package/app/scripts/DragListeningDiv.jsx +1 -1
- package/app/scripts/DraggableDiv.jsx +2 -3
- package/app/scripts/ExportLinkDialog.jsx +1 -1
- package/app/scripts/FilledLine.js +349 -0
- package/app/scripts/GalleryTracks.jsx +77 -78
- package/app/scripts/GenomePositionSearchBox.jsx +184 -482
- package/app/scripts/HeatmapOptions.jsx +4 -2
- package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
- package/app/scripts/HiGlassComponent.jsx +515 -444
- package/app/scripts/HiGlassComponentContext.js +5 -0
- package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
- package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
- package/app/scripts/HorizontalChromosomeLabels.js +28 -22
- package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
- package/app/scripts/HorizontalHeatmapTrack.js +2 -2
- package/app/scripts/HorizontalMultivecTrack.js +6 -7
- package/app/scripts/HorizontalRule.js +1 -2
- package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
- package/app/scripts/HorizontalTiledPlot.jsx +9 -9
- package/app/scripts/LeftTrackModifier.js +4 -0
- package/app/scripts/ListWrapper.jsx +1 -2
- package/app/scripts/MapboxTilesTrack.js +1 -2
- package/app/scripts/Modal.jsx +2 -2
- package/app/scripts/MoveableTrack.jsx +10 -12
- package/app/scripts/NestedContextMenu.jsx +2 -1
- package/app/scripts/OSMTileIdsTrack.js +1 -1
- package/app/scripts/OverlayTrack.js +4 -4
- package/app/scripts/PixiTrack.js +27 -13
- package/app/scripts/PlotTypeChooser.jsx +3 -4
- package/app/scripts/SearchField.js +5 -5
- package/app/scripts/SeriesListItems.jsx +3 -4
- package/app/scripts/SeriesListMenu.jsx +95 -53
- package/app/scripts/SeriesListSubmenuMixin.jsx +2 -1
- package/app/scripts/SketchInlinePicker.jsx +2 -2
- package/app/scripts/SortableList.jsx +1 -1
- package/app/scripts/Tiled1DPixiTrack.js +4 -1
- package/app/scripts/TiledPixiTrack.js +244 -102
- package/app/scripts/TiledPlot.jsx +565 -118
- package/app/scripts/TilesetFinder.jsx +12 -4
- package/app/scripts/Track.js +1 -1
- package/app/scripts/TrackArea.jsx +4 -0
- package/app/scripts/TrackControl.jsx +2 -2
- package/app/scripts/TrackRenderer.jsx +32 -33
- package/app/scripts/ValueIntervalTrack.js +1 -1
- package/app/scripts/VerticalRule.js +2 -2
- package/app/scripts/VerticalTiledPlot.jsx +7 -7
- package/app/scripts/ViewConfigEditor.jsx +1 -1
- package/app/scripts/ViewContextMenu.jsx +53 -5
- package/app/scripts/ViewHeader.jsx +9 -9
- package/app/scripts/ViewportTracker2D.js +1 -1
- package/app/scripts/api.js +92 -12
- package/app/scripts/configs/available-track-types.js +1 -1
- package/app/scripts/configs/index.js +6 -1
- package/app/scripts/configs/positions-by-datatype.js +2 -2
- package/app/scripts/configs/primitives.js +2 -0
- package/app/scripts/configs/themes.js +0 -1
- package/app/scripts/configs/tracks-info-by-type.js +11 -8
- package/app/scripts/configs/tracks-info.js +3 -2
- package/app/scripts/d3-context-menu.js +3 -4
- package/app/scripts/data-fetchers/DataFetcher.js +35 -36
- package/app/scripts/data-fetchers/genbank-fetcher.js +13 -22
- package/app/scripts/data-fetchers/local-tile-fetcher.js +10 -8
- package/app/scripts/hglib.jsx +62 -71
- package/app/scripts/hocs/with-modal.jsx +32 -10
- package/app/scripts/hocs/with-pub-sub.js +12 -3
- package/app/scripts/hocs/with-theme.jsx +21 -14
- package/app/scripts/icons.jsx +3 -2
- package/app/scripts/mixwith.js +2 -2
- package/app/scripts/options-info.js +49 -11
- package/app/scripts/plugins/get-data-fetcher.js +2 -3
- package/app/scripts/services/chrom-info.js +32 -4
- package/app/scripts/services/element-resize-listener.js +2 -2
- package/app/scripts/services/index.js +0 -1
- package/app/scripts/services/tile-proxy.js +368 -285
- package/app/scripts/services/worker.js +31 -28
- package/app/scripts/test-helpers/index.js +2 -1
- package/app/scripts/test-helpers/test-helpers.jsx +157 -69
- package/app/scripts/types.ts +118 -47
- package/app/scripts/utils/LruCache.js +3 -2
- package/app/scripts/utils/assert.js +19 -0
- package/app/scripts/utils/background-task-scheduler.js +2 -0
- package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
- package/app/scripts/utils/copy-text-to-clipboard.js +36 -0
- package/app/scripts/utils/decompress.js +33 -0
- package/app/scripts/utils/default-tracks.js +46 -0
- package/app/scripts/utils/dict-items.js +1 -0
- package/app/scripts/utils/dict-keys.js +1 -0
- package/app/scripts/utils/dict-values.js +1 -0
- package/app/scripts/utils/expand-combined-tracks.js +11 -7
- package/app/scripts/utils/fill-in-min-widths.js +47 -21
- package/app/scripts/utils/flatten.js +0 -1
- package/app/scripts/utils/get-aggregation-function.js +1 -1
- package/app/scripts/utils/get-default-track-for-datatype.js +37 -10
- package/app/scripts/utils/get-default-tracks-for-datatype.ts +46 -0
- package/app/scripts/utils/get-higlass-components.js +27 -3
- package/app/scripts/utils/get-track-position-by-uid.js +8 -1
- package/app/scripts/utils/get-xylofon.js +12 -9
- package/app/scripts/utils/has-parent.js +5 -5
- package/app/scripts/utils/hex-string-to-int.js +1 -1
- package/app/scripts/utils/index.js +1 -0
- package/app/scripts/utils/interval-tree.js +222 -177
- package/app/scripts/utils/load-chrom-infos.js +4 -1
- package/app/scripts/utils/pixi-text-to-svg.js +5 -9
- package/app/scripts/utils/positioned-tracks-to-all-tracks.js +55 -0
- package/app/scripts/utils/range-query-2d.js +3 -3
- package/app/scripts/utils/reduce.js +12 -5
- package/app/scripts/utils/segments-to-rows.js +14 -11
- package/app/scripts/utils/svg-line.js +7 -8
- package/app/scripts/utils/type-guards.js +16 -7
- package/app/scripts/utils/visit-positioned-tracks.js +9 -4
- package/app/styles/AddTrackPositionMenu.module.scss +37 -0
- package/app/styles/HiGlass.module.scss +3 -1
- package/app/styles/d3-context-menu.css +0 -1
- package/app/styles/prism.css +1 -0
- package/dist/app/schema.json +525 -0
- package/dist/app/scripts/AddTrackDialog.d.ts +64 -0
- package/dist/app/scripts/AddTrackPositionMenu.d.ts +5 -0
- package/dist/app/scripts/Annotations1dTrack.d.ts +15 -0
- package/dist/app/scripts/Annotations2dTrack.d.ts +95 -0
- package/dist/app/scripts/ArrowheadDomainsTrack.d.ts +36 -0
- package/dist/app/scripts/Autocomplete.d.ts +102 -0
- package/dist/app/scripts/AxisPixi.d.ts +25 -0
- package/dist/app/scripts/BarTrack.d.ts +28 -0
- package/dist/app/scripts/BedLikeTrack.d.ts +84 -0
- package/dist/app/scripts/Button.d.ts +3 -0
- package/dist/app/scripts/CNVIntervalTrack.d.ts +12 -0
- package/dist/app/scripts/CenterTiledPlot.d.ts +3 -0
- package/dist/app/scripts/CenterTrack.d.ts +92 -0
- package/dist/app/scripts/Chromosome2DAnnotations.d.ts +10 -0
- package/dist/app/scripts/Chromosome2DLabels.d.ts +13 -0
- package/dist/app/scripts/ChromosomeGrid.d.ts +24 -0
- package/dist/app/scripts/ChromosomeInfo.d.ts +14 -0
- package/dist/app/scripts/CloseTrackMenu.d.ts +10 -0
- package/dist/app/scripts/CombinedTrack.d.ts +32 -0
- package/dist/app/scripts/ConfigTrackMenu.d.ts +10 -0
- package/dist/app/scripts/ConfigViewMenu.d.ts +34 -0
- package/dist/app/scripts/ConfigureSeriesMenu.d.ts +3 -0
- package/dist/app/scripts/ContextMenuContainer.d.ts +36 -0
- package/dist/app/scripts/ContextMenuItem.d.ts +34 -0
- package/dist/app/scripts/Cross.d.ts +3 -0
- package/dist/app/scripts/CrossRule.d.ts +24 -0
- package/dist/app/scripts/CustomTrackDialog.d.ts +17 -0
- package/dist/app/scripts/Dialog.d.ts +5 -0
- package/dist/app/scripts/DivergentBarTrack.d.ts +4 -0
- package/dist/app/scripts/DragListeningDiv.d.ts +32 -0
- package/dist/app/scripts/DraggableDiv.d.ts +63 -0
- package/dist/app/scripts/ExportLinkDialog.d.ts +21 -0
- package/dist/app/scripts/FilledLine.d.ts +5 -0
- package/dist/app/scripts/FixedTrack.d.ts +5 -0
- package/dist/app/scripts/GalleryTracks.d.ts +20 -0
- package/dist/app/scripts/GenomePositionSearchBox.d.ts +95 -0
- package/dist/app/scripts/HeatmapOptions.d.ts +30 -0
- package/dist/app/scripts/HeatmapTiledPixiTrack.d.ts +184 -0
- package/dist/app/scripts/HiGlassComponent.d.ts +762 -0
- package/dist/app/scripts/HiGlassComponentContext.d.ts +3 -0
- package/dist/app/scripts/HiGlassTrackComponent.d.ts +37 -0
- package/dist/app/scripts/Horizontal1dHeatmapTrack.d.ts +9 -0
- package/dist/app/scripts/Horizontal2DDomainsTrack.d.ts +21 -0
- package/dist/app/scripts/HorizontalChromosomeLabels.d.ts +47 -0
- package/dist/app/scripts/HorizontalGeneAnnotationsTrack.d.ts +25 -0
- package/dist/app/scripts/HorizontalHeatmapTrack.d.ts +12 -0
- package/dist/app/scripts/HorizontalItem.d.ts +3 -0
- package/dist/app/scripts/HorizontalLine1DPixiTrack.d.ts +23 -0
- package/dist/app/scripts/HorizontalMultivecTrack.d.ts +50 -0
- package/dist/app/scripts/HorizontalPoint1DPixiTrack.d.ts +5 -0
- package/dist/app/scripts/HorizontalRule.d.ts +22 -0
- package/dist/app/scripts/HorizontalTiled1DPixiTrack.d.ts +26 -0
- package/dist/app/scripts/HorizontalTiledPlot.d.ts +49 -0
- package/dist/app/scripts/HorizontalTrack.d.ts +6 -0
- package/dist/app/scripts/Id2DTiledPixiTrack.d.ts +10 -0
- package/dist/app/scripts/IdHorizontal1DTiledPixiTrack.d.ts +6 -0
- package/dist/app/scripts/IdVertical1DTiledPixiTrack.d.ts +7 -0
- package/dist/app/scripts/LeftAxisTrack.d.ts +9 -0
- package/dist/app/scripts/LeftTrackModifier.d.ts +29 -0
- package/dist/app/scripts/ListWrapper.d.ts +64 -0
- package/dist/app/scripts/MapboxTilesTrack.d.ts +9 -0
- package/dist/app/scripts/Modal.d.ts +5 -0
- package/dist/app/scripts/MoveableTrack.d.ts +18 -0
- package/dist/app/scripts/NestedContextMenu.d.ts +7 -0
- package/dist/app/scripts/OSMTileIdsTrack.d.ts +5 -0
- package/dist/app/scripts/OSMTilesTrack.d.ts +129 -0
- package/dist/app/scripts/OverlayTrack.d.ts +13 -0
- package/dist/app/scripts/PixiTrack.d.ts +174 -0
- package/dist/app/scripts/PlotTypeChooser.d.ts +25 -0
- package/dist/app/scripts/PopupMenu.d.ts +28 -0
- package/dist/app/scripts/RasterTilesTrack.d.ts +9 -0
- package/dist/app/scripts/RuleMixin.d.ts +2 -0
- package/dist/app/scripts/SVGTrack.d.ts +15 -0
- package/dist/app/scripts/SearchField.d.ts +13 -0
- package/dist/app/scripts/SeriesListItems.d.ts +2 -0
- package/dist/app/scripts/SeriesListMenu.d.ts +51 -0
- package/dist/app/scripts/SeriesListSubmenuMixin.d.ts +2 -0
- package/dist/app/scripts/SketchInlinePicker.d.ts +25 -0
- package/dist/app/scripts/SortableList.d.ts +22 -0
- package/dist/app/scripts/SquareMarkersTrack.d.ts +22 -0
- package/dist/app/scripts/Tiled1DPixiTrack.d.ts +60 -0
- package/dist/app/scripts/TiledPixiTrack.d.ts +369 -0
- package/dist/app/scripts/TiledPlot.d.ts +313 -0
- package/dist/app/scripts/TilesetFinder.d.ts +65 -0
- package/dist/app/scripts/TopAxisTrack.d.ts +9 -0
- package/dist/app/scripts/Track.d.ts +196 -0
- package/dist/app/scripts/TrackArea.d.ts +26 -0
- package/dist/app/scripts/TrackControl.d.ts +5 -0
- package/dist/app/scripts/TrackRenderer.d.ts +724 -0
- package/dist/app/scripts/UnknownPixiTrack.d.ts +7 -0
- package/dist/app/scripts/ValueIntervalTrack.d.ts +6 -0
- package/dist/app/scripts/VerticalItem.d.ts +3 -0
- package/dist/app/scripts/VerticalRule.d.ts +21 -0
- package/dist/app/scripts/VerticalTiled1DPixiTrack.d.ts +6 -0
- package/dist/app/scripts/VerticalTiledPlot.d.ts +50 -0
- package/dist/app/scripts/VerticalTrack.d.ts +6 -0
- package/dist/app/scripts/ViewConfigEditor.d.ts +53 -0
- package/dist/app/scripts/ViewContextMenu.d.ts +17 -0
- package/dist/app/scripts/ViewHeader.d.ts +75 -0
- package/dist/app/scripts/ViewportTracker2D.d.ts +17 -0
- package/dist/app/scripts/ViewportTracker2DPixi.d.ts +11 -0
- package/dist/app/scripts/ViewportTrackerHorizontal.d.ts +17 -0
- package/dist/app/scripts/ViewportTrackerVertical.d.ts +17 -0
- package/dist/app/scripts/api.d.ts +640 -0
- package/dist/app/scripts/configs/available-track-types.d.ts +2 -0
- package/dist/app/scripts/configs/colormaps.d.ts +2 -0
- package/dist/app/scripts/configs/datatype-to-track-type.d.ts +4 -0
- package/dist/app/scripts/configs/default-tracks-for-datatype.d.ts +38 -0
- package/dist/app/scripts/configs/dense-data-extrema-config.d.ts +2 -0
- package/dist/app/scripts/configs/globals.d.ts +5 -0
- package/dist/app/scripts/configs/index.d.ts +16 -0
- package/dist/app/scripts/configs/positions-by-datatype.d.ts +2 -0
- package/dist/app/scripts/configs/primitives.d.ts +20 -0
- package/dist/app/scripts/configs/themes.d.ts +3 -0
- package/dist/app/scripts/configs/tracks-info-by-type.d.ts +4 -0
- package/dist/app/scripts/configs/tracks-info.d.ts +24 -0
- package/dist/app/scripts/d3-context-menu.d.ts +2 -0
- package/dist/app/scripts/data-fetchers/DataFetcher.d.ts +151 -0
- package/dist/app/scripts/data-fetchers/genbank-fetcher.d.ts +86 -0
- package/dist/app/scripts/data-fetchers/index.d.ts +3 -0
- package/dist/app/scripts/data-fetchers/local-tile-fetcher.d.ts +47 -0
- package/dist/app/scripts/gosling-exports.d.ts +17 -0
- package/dist/app/scripts/hglib.d.ts +24 -0
- package/dist/app/scripts/hocs/with-modal.d.ts +19 -0
- package/dist/app/scripts/hocs/with-pub-sub.d.ts +22 -0
- package/dist/app/scripts/hocs/with-theme.d.ts +13 -0
- package/dist/app/scripts/icons.d.ts +161 -0
- package/dist/app/scripts/mixwith.d.ts +27 -0
- package/dist/app/scripts/options-info.d.ts +1355 -0
- package/dist/app/scripts/plugins/available-for-plugins.d.ts +2338 -0
- package/dist/app/scripts/plugins/get-data-fetcher.d.ts +2 -0
- package/dist/app/scripts/plugins/index.d.ts +2 -0
- package/dist/app/scripts/services/chrom-info.d.ts +10 -0
- package/dist/app/scripts/services/dom-event.d.ts +7 -0
- package/dist/app/scripts/services/element-resize-listener.d.ts +5 -0
- package/dist/app/scripts/services/index.d.ts +5 -0
- package/dist/app/scripts/services/tile-proxy.d.ts +180 -0
- package/dist/app/scripts/services/worker.d.ts +157 -0
- package/dist/app/scripts/symbol.d.ts +13 -0
- package/dist/app/scripts/test-helpers/index.d.ts +1 -0
- package/dist/app/scripts/test-helpers/test-helpers.d.ts +33 -0
- package/dist/app/scripts/track-utils.d.ts +73 -0
- package/dist/app/scripts/types.d.ts +199 -0
- package/dist/app/scripts/utils/DenseDataExtrema1D.d.ts +88 -0
- package/dist/app/scripts/utils/DenseDataExtrema2D.d.ts +97 -0
- package/dist/app/scripts/utils/LruCache.d.ts +44 -0
- package/dist/app/scripts/utils/abs-to-chr.d.ts +14 -0
- package/dist/app/scripts/utils/accessor-transposition.d.ts +14 -0
- package/dist/app/scripts/utils/add-arrays.d.ts +18 -0
- package/dist/app/scripts/utils/add-class.d.ts +8 -0
- package/dist/app/scripts/utils/add-event-listener-once.d.ts +11 -0
- package/dist/app/scripts/utils/assert.d.ts +17 -0
- package/dist/app/scripts/utils/background-task-scheduler.d.ts +47 -0
- package/dist/app/scripts/utils/base64-to-canvas.d.ts +9 -0
- package/dist/app/scripts/utils/chr-to-abs.d.ts +10 -0
- package/dist/app/scripts/utils/chrom-info-bisector.d.ts +4 -0
- package/dist/app/scripts/utils/clone-event.d.ts +12 -0
- package/dist/app/scripts/utils/color-domain-to-rgba-array.d.ts +13 -0
- package/dist/app/scripts/utils/color-to-hex.d.ts +9 -0
- package/dist/app/scripts/utils/color-to-rgba.d.ts +9 -0
- package/dist/app/scripts/utils/copy-text-to-clipboard.d.ts +2 -0
- package/dist/app/scripts/utils/data-to-genomic-loci.d.ts +11 -0
- package/dist/app/scripts/utils/debounce.d.ts +5 -0
- package/dist/app/scripts/utils/dec-to-hex-str.d.ts +8 -0
- package/dist/app/scripts/utils/decompress.d.ts +27 -0
- package/dist/app/scripts/utils/default-tracks.d.ts +3 -0
- package/dist/app/scripts/utils/dict-from-tuples.d.ts +11 -0
- package/dist/app/scripts/utils/dict-items.d.ts +18 -0
- package/dist/app/scripts/utils/dict-keys.d.ts +10 -0
- package/dist/app/scripts/utils/dict-values.d.ts +8 -0
- package/dist/app/scripts/utils/download.d.ts +7 -0
- package/dist/app/scripts/utils/expand-combined-tracks.d.ts +11 -0
- package/dist/app/scripts/utils/fake-pub-sub.d.ts +11 -0
- package/dist/app/scripts/utils/fill-in-min-widths.d.ts +44 -0
- package/dist/app/scripts/utils/flatten.d.ts +9 -0
- package/dist/app/scripts/utils/for-each.d.ts +9 -0
- package/dist/app/scripts/utils/forward-event.d.ts +7 -0
- package/dist/app/scripts/utils/genome-loci-to-pixels.d.ts +9 -0
- package/dist/app/scripts/utils/genomic-range-to-chromosome-chunks.d.ts +21 -0
- package/dist/app/scripts/utils/get-aggregation-function.d.ts +10 -0
- package/dist/app/scripts/utils/get-default-track-for-datatype.d.ts +21 -0
- package/dist/app/scripts/utils/get-default-tracks-for-datatype.d.ts +3 -0
- package/dist/app/scripts/utils/get-element-dim.d.ts +7 -0
- package/dist/app/scripts/utils/get-higlass-components.d.ts +7 -0
- package/dist/app/scripts/utils/get-track-by-uid.d.ts +7 -0
- package/dist/app/scripts/utils/get-track-conf-from-hgc.d.ts +10 -0
- package/dist/app/scripts/utils/get-track-obj-by-id.d.ts +2 -0
- package/dist/app/scripts/utils/get-track-position-by-uid.d.ts +13 -0
- package/dist/app/scripts/utils/get-xylofon.d.ts +2 -0
- package/dist/app/scripts/utils/gradient.d.ts +14 -0
- package/dist/app/scripts/utils/has-class.d.ts +8 -0
- package/dist/app/scripts/utils/has-parent.d.ts +9 -0
- package/dist/app/scripts/utils/hex-string-to-int.d.ts +14 -0
- package/dist/app/scripts/utils/index.d.ts +89 -0
- package/dist/app/scripts/utils/interval-tree.d.ts +109 -0
- package/dist/app/scripts/utils/into-the-void.d.ts +6 -0
- package/dist/app/scripts/utils/is-track-or-child-track.d.ts +7 -0
- package/dist/app/scripts/utils/is-track-range-selectable.d.ts +2 -0
- package/dist/app/scripts/utils/is-within.d.ts +12 -0
- package/dist/app/scripts/utils/lat-to-y.d.ts +9 -0
- package/dist/app/scripts/utils/lng-to-x.d.ts +8 -0
- package/dist/app/scripts/utils/load-chrom-infos.d.ts +8 -0
- package/dist/app/scripts/utils/map.d.ts +13 -0
- package/dist/app/scripts/utils/max-non-zero.d.ts +6 -0
- package/dist/app/scripts/utils/max.d.ts +10 -0
- package/dist/app/scripts/utils/min-non-zero.d.ts +6 -0
- package/dist/app/scripts/utils/min.d.ts +10 -0
- package/dist/app/scripts/utils/mod.d.ts +9 -0
- package/dist/app/scripts/utils/ndarray-assign.d.ts +2 -0
- package/dist/app/scripts/utils/ndarray-flatten.d.ts +2 -0
- package/dist/app/scripts/utils/ndarray-to-list.d.ts +2 -0
- package/dist/app/scripts/utils/numericify-version.d.ts +6 -0
- package/dist/app/scripts/utils/obj-vals.d.ts +8 -0
- package/dist/app/scripts/utils/or.d.ts +8 -0
- package/dist/app/scripts/utils/parse-chromsizes-rows.d.ts +34 -0
- package/dist/app/scripts/utils/pixi-text-to-svg.d.ts +2 -0
- package/dist/app/scripts/utils/positioned-tracks-to-all-tracks.d.ts +26 -0
- package/dist/app/scripts/utils/q.d.ts +18 -0
- package/dist/app/scripts/utils/rad-to-deg.d.ts +7 -0
- package/dist/app/scripts/utils/range-query-2d.d.ts +17 -0
- package/dist/app/scripts/utils/reduce.d.ts +14 -0
- package/dist/app/scripts/utils/rel-to-abs-chrom-pos.d.ts +10 -0
- package/dist/app/scripts/utils/remove-class.d.ts +7 -0
- package/dist/app/scripts/utils/reset-d3-brush-style.d.ts +10 -0
- package/dist/app/scripts/utils/rgb-to-hex.d.ts +8 -0
- package/dist/app/scripts/utils/scales-center-and-k.d.ts +12 -0
- package/dist/app/scripts/utils/scales-to-genome-loci.d.ts +3 -0
- package/dist/app/scripts/utils/segments-to-rows.d.ts +15 -0
- package/dist/app/scripts/utils/selected-items-to-cum-weights.d.ts +12 -0
- package/dist/app/scripts/utils/selected-items-to-size.d.ts +13 -0
- package/dist/app/scripts/utils/show-mouse-position.d.ts +54 -0
- package/dist/app/scripts/utils/some.d.ts +10 -0
- package/dist/app/scripts/utils/sum.d.ts +8 -0
- package/dist/app/scripts/utils/svg-line.d.ts +2 -0
- package/dist/app/scripts/utils/throttle-and-debounce.d.ts +33 -0
- package/dist/app/scripts/utils/tile-to-canvas.d.ts +9 -0
- package/dist/app/scripts/utils/timeout.d.ts +3 -0
- package/dist/app/scripts/utils/to-void.d.ts +3 -0
- package/dist/app/scripts/utils/total-track-pixel-height.d.ts +27 -0
- package/dist/app/scripts/utils/trim-trailing-slash.d.ts +7 -0
- package/dist/app/scripts/utils/type-guards.d.ts +36 -0
- package/dist/app/scripts/utils/value-to-color.d.ts +12 -0
- package/dist/app/scripts/utils/visit-positioned-tracks.d.ts +18 -0
- package/dist/app/scripts/utils/visit-tracks.d.ts +9 -0
- package/dist/esm.html +1 -3
- package/dist/hglib.js +86315 -100592
- package/dist/hglib.min.js +123 -131
- package/dist/higlass.mjs +88861 -103138
- package/dist/index.html +1 -3
- package/dist/package.json +134 -0
- package/package.json +25 -27
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { select, pointer } from 'd3-selection';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { ElementQueries, ResizeSensor } from 'css-element-queries';
|
|
5
4
|
import { scaleLinear } from 'd3-scale';
|
|
6
|
-
import
|
|
5
|
+
import { pointer, select } from 'd3-selection';
|
|
7
6
|
import * as PIXI from 'pixi.js';
|
|
8
|
-
import
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import createPubSub, { globalPubSub } from 'pub-sub-es';
|
|
9
|
+
import React from 'react';
|
|
9
10
|
import ReactGridLayout from 'react-grid-layout';
|
|
10
|
-
import
|
|
11
|
-
import vkbeautify from 'vkbeautify';
|
|
11
|
+
import slugid from 'slugid';
|
|
12
12
|
import parse from 'url-parse';
|
|
13
|
-
import
|
|
14
|
-
import clsx from 'clsx';
|
|
13
|
+
import vkbeautify from 'vkbeautify';
|
|
15
14
|
|
|
16
|
-
import TiledPlot from './TiledPlot';
|
|
17
|
-
import GenomePositionSearchBox from './GenomePositionSearchBox';
|
|
18
|
-
import ExportLinkDialog from './ExportLinkDialog';
|
|
19
|
-
import ViewHeader from './ViewHeader';
|
|
20
15
|
import ChromosomeInfo from './ChromosomeInfo';
|
|
16
|
+
import ExportLinkDialog from './ExportLinkDialog';
|
|
17
|
+
import GenomePositionSearchBox from './GenomePositionSearchBox';
|
|
18
|
+
import TiledPlot from './TiledPlot';
|
|
21
19
|
import ViewConfigEditor from './ViewConfigEditor';
|
|
20
|
+
import ViewHeader from './ViewHeader';
|
|
22
21
|
|
|
23
|
-
import createSymbolIcon from './symbol';
|
|
24
|
-
import { all as icons } from './icons';
|
|
25
22
|
import createApi from './api';
|
|
23
|
+
import { all as icons } from './icons';
|
|
24
|
+
import createSymbolIcon from './symbol';
|
|
26
25
|
|
|
26
|
+
import { Provider as ModalProvider } from './hocs/with-modal';
|
|
27
27
|
// Higher-order components
|
|
28
28
|
import { Provider as PubSubProvider } from './hocs/with-pub-sub';
|
|
29
|
-
import { Provider as ModalProvider } from './hocs/with-modal';
|
|
30
29
|
import { Provider as ThemeProvider } from './hocs/with-theme';
|
|
31
30
|
|
|
31
|
+
import HiGlassComponentContext from './HiGlassComponentContext';
|
|
32
|
+
|
|
32
33
|
// Services
|
|
33
34
|
import {
|
|
34
35
|
chromInfo,
|
|
35
36
|
createDomEvent,
|
|
37
|
+
requestsInFlight,
|
|
36
38
|
setTileProxyAuthHeader,
|
|
37
39
|
tileProxy,
|
|
38
|
-
requestsInFlight,
|
|
39
40
|
} from './services';
|
|
40
41
|
|
|
41
42
|
// Utils
|
|
@@ -61,38 +62,40 @@ import {
|
|
|
61
62
|
toVoid,
|
|
62
63
|
visitPositionedTracks,
|
|
63
64
|
} from './utils';
|
|
65
|
+
import positionedTracksToAllTracks from './utils/positioned-tracks-to-all-tracks';
|
|
64
66
|
|
|
65
67
|
// Configs
|
|
66
68
|
import {
|
|
67
|
-
DEFAULT_SERVER,
|
|
68
69
|
DEFAULT_CONTAINER_PADDING_X,
|
|
69
70
|
DEFAULT_CONTAINER_PADDING_Y,
|
|
71
|
+
DEFAULT_SERVER,
|
|
70
72
|
DEFAULT_VIEW_MARGIN,
|
|
71
73
|
DEFAULT_VIEW_PADDING,
|
|
72
74
|
GLOBALS,
|
|
73
|
-
MOUSE_TOOL_MOVE,
|
|
74
|
-
MOUSE_TOOL_SELECT,
|
|
75
75
|
LOCATION_LISTENER_PREFIX,
|
|
76
76
|
LONG_DRAG_TIMEOUT,
|
|
77
|
+
MOUSE_TOOL_MOVE,
|
|
78
|
+
MOUSE_TOOL_SELECT,
|
|
79
|
+
MOUSE_TOOL_TRACK_SELECT,
|
|
77
80
|
SHORT_DRAG_TIMEOUT,
|
|
81
|
+
SIZE_MODE_BOUNDED,
|
|
82
|
+
SIZE_MODE_BOUNDED_OVERFLOW,
|
|
83
|
+
SIZE_MODE_DEFAULT,
|
|
84
|
+
SIZE_MODE_OVERFLOW,
|
|
85
|
+
SIZE_MODE_SCROLL,
|
|
78
86
|
THEME_DARK,
|
|
79
87
|
THEME_LIGHT,
|
|
80
88
|
TRACKS_INFO_BY_TYPE,
|
|
81
89
|
} from './configs';
|
|
82
90
|
|
|
83
91
|
// Styles
|
|
84
|
-
import styles from '../styles/HiGlass.module.scss';
|
|
85
|
-
import stylesMTHeader from '../styles/ViewHeader.module.scss';
|
|
86
|
-
|
|
87
|
-
import '../styles/HiGlass.scss'; // eslint-disable-line no-unused-vars
|
|
92
|
+
import styles from '../styles/HiGlass.module.scss';
|
|
93
|
+
import stylesMTHeader from '../styles/ViewHeader.module.scss';
|
|
94
|
+
import '../styles/HiGlass.scss';
|
|
88
95
|
|
|
89
96
|
const NUM_GRID_COLUMNS = 12;
|
|
90
97
|
const DEFAULT_NEW_VIEW_HEIGHT = 12;
|
|
91
98
|
const VIEW_HEADER_HEIGHT = 20;
|
|
92
|
-
const SIZE_MODE_DEFAULT = 'default';
|
|
93
|
-
const SIZE_MODE_BOUNDED = 'bounded';
|
|
94
|
-
const SIZE_MODE_OVERFLOW = 'overflow';
|
|
95
|
-
const SIZE_MODE_SCROLL = 'scroll';
|
|
96
99
|
|
|
97
100
|
class HiGlassComponent extends React.Component {
|
|
98
101
|
constructor(props) {
|
|
@@ -106,6 +109,8 @@ class HiGlassComponent extends React.Component {
|
|
|
106
109
|
);
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
this.topDivRef = React.createRef();
|
|
113
|
+
|
|
109
114
|
this.pubSub = createPubSub();
|
|
110
115
|
this.domEvent = createDomEvent(this.pubSub);
|
|
111
116
|
|
|
@@ -116,11 +121,14 @@ class HiGlassComponent extends React.Component {
|
|
|
116
121
|
this.resizeSensor = null;
|
|
117
122
|
|
|
118
123
|
this.uid = slugid.nice();
|
|
124
|
+
/** @type {Record<string, import('./TiledPlot').TiledPlot> */
|
|
119
125
|
this.tiledPlots = {};
|
|
120
126
|
this.genomePositionSearchBoxes = {};
|
|
121
127
|
|
|
122
128
|
// keep track of the xScales of each Track Renderer
|
|
129
|
+
/** @type {Record<string, import('./TrackRenderer').Scale>} */
|
|
123
130
|
this.xScales = {};
|
|
131
|
+
/** @type {Record<string, import('./TrackRenderer').Scale>} */
|
|
124
132
|
this.yScales = {};
|
|
125
133
|
this.projectionXDomains = {};
|
|
126
134
|
this.projectionYDomains = {};
|
|
@@ -144,7 +152,6 @@ class HiGlassComponent extends React.Component {
|
|
|
144
152
|
// between views
|
|
145
153
|
this.zoomLocks = {};
|
|
146
154
|
this.locationLocks = {};
|
|
147
|
-
|
|
148
155
|
// axis-specific location lock
|
|
149
156
|
this.locationLocksAxisWise = { x: {}, y: {} };
|
|
150
157
|
|
|
@@ -160,7 +167,7 @@ class HiGlassComponent extends React.Component {
|
|
|
160
167
|
|
|
161
168
|
// allow a different PIXI to be passed in case the
|
|
162
169
|
// caller wants to use a different version
|
|
163
|
-
GLOBALS.PIXI =
|
|
170
|
+
GLOBALS.PIXI = props.options?.PIXI || PIXI;
|
|
164
171
|
|
|
165
172
|
this.viewMarginTop =
|
|
166
173
|
+props.options.viewMarginTop >= 0
|
|
@@ -210,7 +217,9 @@ class HiGlassComponent extends React.Component {
|
|
|
210
217
|
this.viewconfLoaded = false;
|
|
211
218
|
|
|
212
219
|
const { viewConfig } = this.props;
|
|
213
|
-
const views = this.
|
|
220
|
+
const views = this.processViewConfig(
|
|
221
|
+
JSON.parse(JSON.stringify(this.props.viewConfig)),
|
|
222
|
+
);
|
|
214
223
|
|
|
215
224
|
if (props.options.authToken) {
|
|
216
225
|
setTileProxyAuthHeader(props.options.authToken);
|
|
@@ -237,6 +246,9 @@ class HiGlassComponent extends React.Component {
|
|
|
237
246
|
case MOUSE_TOOL_SELECT:
|
|
238
247
|
mouseTool = MOUSE_TOOL_SELECT;
|
|
239
248
|
break;
|
|
249
|
+
case MOUSE_TOOL_TRACK_SELECT:
|
|
250
|
+
mouseTool = MOUSE_TOOL_TRACK_SELECT;
|
|
251
|
+
break;
|
|
240
252
|
default:
|
|
241
253
|
break;
|
|
242
254
|
}
|
|
@@ -291,10 +303,12 @@ class HiGlassComponent extends React.Component {
|
|
|
291
303
|
typedEditable: undefined,
|
|
292
304
|
mouseOverOverlayUid: null,
|
|
293
305
|
mouseTool,
|
|
306
|
+
overTrackChooser: null,
|
|
294
307
|
isDarkTheme: false,
|
|
295
|
-
rangeSelection1dSize: [0,
|
|
308
|
+
rangeSelection1dSize: [0, Number.POSITIVE_INFINITY],
|
|
296
309
|
rangeSelectionToInt: false,
|
|
297
310
|
modal: null,
|
|
311
|
+
sizeMode: this.props.options?.sizeMode,
|
|
298
312
|
};
|
|
299
313
|
|
|
300
314
|
// monitor whether this element is attached to the DOM so that
|
|
@@ -350,6 +364,7 @@ class HiGlassComponent extends React.Component {
|
|
|
350
364
|
this.closeModalBound = this.closeModal.bind(this);
|
|
351
365
|
this.handleEditViewConfigBound = this.handleEditViewConfig.bind(this);
|
|
352
366
|
this.onScrollHandlerBound = this.onScrollHandler.bind(this);
|
|
367
|
+
this.viewUidToNameBound = this.viewUidToName.bind(this);
|
|
353
368
|
|
|
354
369
|
// for typed shortcuts (e.g. e-d-i-t) to toggle editable
|
|
355
370
|
this.typedText = '';
|
|
@@ -370,7 +385,6 @@ class HiGlassComponent extends React.Component {
|
|
|
370
385
|
);
|
|
371
386
|
}
|
|
372
387
|
|
|
373
|
-
// eslint-disable-next-line camelcase
|
|
374
388
|
UNSAFE_componentWillMount() {
|
|
375
389
|
this.domEvent.register('keydown', document);
|
|
376
390
|
this.domEvent.register('keyup', document);
|
|
@@ -422,12 +436,11 @@ class HiGlassComponent extends React.Component {
|
|
|
422
436
|
}
|
|
423
437
|
|
|
424
438
|
get sizeMode() {
|
|
425
|
-
|
|
426
|
-
return typeof this.props.options.sizeMode === 'undefined'
|
|
439
|
+
return typeof this.state.sizeMode === 'undefined'
|
|
427
440
|
? this.props.options.bounded
|
|
428
441
|
? 'bounded'
|
|
429
442
|
: SIZE_MODE_DEFAULT
|
|
430
|
-
: this.
|
|
443
|
+
: this.state.sizeMode;
|
|
431
444
|
}
|
|
432
445
|
|
|
433
446
|
setBroadcastMousePositionGlobally(isBroadcastMousePositionGlobally = false) {
|
|
@@ -476,9 +489,9 @@ class HiGlassComponent extends React.Component {
|
|
|
476
489
|
waitForDOMAttachment(callback) {
|
|
477
490
|
if (!this.mounted) return;
|
|
478
491
|
|
|
479
|
-
const thisElement =
|
|
492
|
+
const thisElement = this.topDivRef.current;
|
|
480
493
|
|
|
481
|
-
if (document.body.contains(thisElement)) {
|
|
494
|
+
if (thisElement && document.body.contains(thisElement)) {
|
|
482
495
|
callback();
|
|
483
496
|
} else {
|
|
484
497
|
requestAnimationFrame(() => this.waitForDOMAttachment(callback));
|
|
@@ -491,7 +504,8 @@ class HiGlassComponent extends React.Component {
|
|
|
491
504
|
// in focus, everything is drawn at the top and overlaps. When it gains
|
|
492
505
|
// focus we need to redraw everything in its proper place
|
|
493
506
|
this.mounted = true;
|
|
494
|
-
this.element =
|
|
507
|
+
this.element = this.topDivRef.current;
|
|
508
|
+
|
|
495
509
|
window.addEventListener('focus', this.boundRefreshView);
|
|
496
510
|
|
|
497
511
|
Object.values(this.state.views).forEach((view) => {
|
|
@@ -514,30 +528,27 @@ class HiGlassComponent extends React.Component {
|
|
|
514
528
|
autoResize: true,
|
|
515
529
|
};
|
|
516
530
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (versionNumber === 4) {
|
|
520
|
-
console.warn(
|
|
521
|
-
'Deprecation warning: please update Pixi.js to version 5 or above!',
|
|
522
|
-
);
|
|
523
|
-
if (this.props.options.renderer === 'canvas') {
|
|
524
|
-
this.pixiRenderer = new GLOBALS.PIXI.CanvasRenderer(rendererOptions);
|
|
525
|
-
} else {
|
|
526
|
-
this.pixiRenderer = new GLOBALS.PIXI.WebGLRenderer(rendererOptions);
|
|
527
|
-
}
|
|
528
|
-
} else {
|
|
529
|
-
if (versionNumber < 4) {
|
|
531
|
+
switch (PIXI.VERSION[0]) {
|
|
532
|
+
case '4':
|
|
530
533
|
console.warn(
|
|
531
|
-
'Deprecation warning: please update Pixi.js to version 5
|
|
532
|
-
'This version of Pixi.js is unsupported. Good luck 🤞',
|
|
534
|
+
'Deprecation warning: please update Pixi.js to version 5!',
|
|
533
535
|
);
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
536
|
+
if (this.props.options.renderer === 'canvas') {
|
|
537
|
+
this.pixiRenderer = new GLOBALS.PIXI.CanvasRenderer(rendererOptions);
|
|
538
|
+
} else {
|
|
539
|
+
this.pixiRenderer = new GLOBALS.PIXI.WebGLRenderer(rendererOptions);
|
|
540
|
+
}
|
|
541
|
+
break;
|
|
542
|
+
// case '5':
|
|
543
|
+
// case '6':
|
|
544
|
+
// case '7': // Gosling uses PIXI.js v7
|
|
545
|
+
default:
|
|
546
|
+
if (this.props.options.renderer === 'canvas') {
|
|
547
|
+
this.pixiRenderer = new GLOBALS.PIXI.CanvasRenderer(rendererOptions);
|
|
548
|
+
} else {
|
|
549
|
+
this.pixiRenderer = new GLOBALS.PIXI.Renderer(rendererOptions);
|
|
550
|
+
}
|
|
551
|
+
break;
|
|
541
552
|
}
|
|
542
553
|
|
|
543
554
|
// PIXI.RESOLUTION=2;
|
|
@@ -545,7 +556,6 @@ class HiGlassComponent extends React.Component {
|
|
|
545
556
|
|
|
546
557
|
// keep track of the width and height of this element, because it
|
|
547
558
|
// needs to be reflected in the size of our drawing surface
|
|
548
|
-
// eslint-disable-next-line react/no-did-mount-set-state
|
|
549
559
|
this.setState({
|
|
550
560
|
svgElement: this.svgElement,
|
|
551
561
|
canvasElement: this.canvasElement,
|
|
@@ -585,61 +595,19 @@ class HiGlassComponent extends React.Component {
|
|
|
585
595
|
return this.tiledPlots[viewUid].trackRenderer;
|
|
586
596
|
}
|
|
587
597
|
|
|
588
|
-
/**
|
|
589
|
-
* Check if the passed in viewConfig is remote (i.e. is a string).
|
|
590
|
-
* If it is, fetch it before proceeding
|
|
591
|
-
*/
|
|
592
|
-
loadIfRemoteViewConfig(viewConfig) {
|
|
593
|
-
let views = {};
|
|
594
|
-
if (typeof viewConfig === 'string') {
|
|
595
|
-
// Load external viewConfig
|
|
596
|
-
tileProxy.json(
|
|
597
|
-
viewConfig,
|
|
598
|
-
(error, remoteViewConfig) => {
|
|
599
|
-
viewConfig = remoteViewConfig;
|
|
600
|
-
this.setState({
|
|
601
|
-
views: this.processViewConfig(
|
|
602
|
-
JSON.parse(JSON.stringify(remoteViewConfig)),
|
|
603
|
-
),
|
|
604
|
-
viewConfig: remoteViewConfig,
|
|
605
|
-
});
|
|
606
|
-
this.unsetOnLocationChange.forEach(
|
|
607
|
-
({ viewId, callback, callbackId }) => {
|
|
608
|
-
this.onLocationChange(viewId, callback, callbackId);
|
|
609
|
-
},
|
|
610
|
-
);
|
|
611
|
-
},
|
|
612
|
-
this.pubSub,
|
|
613
|
-
);
|
|
614
|
-
} else {
|
|
615
|
-
views = this.processViewConfig(JSON.parse(JSON.stringify(viewConfig)));
|
|
616
|
-
if (this.mounted) {
|
|
617
|
-
this.setState({
|
|
618
|
-
viewConfig,
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
return views;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// eslint-disable-next-line camelcase
|
|
627
598
|
UNSAFE_componentWillReceiveProps(newProps) {
|
|
628
|
-
|
|
599
|
+
if (this.mounted) {
|
|
600
|
+
this.setState({ viewConfig: newProps.viewConfig });
|
|
601
|
+
}
|
|
602
|
+
const viewsByUid = this.processViewConfig(
|
|
603
|
+
JSON.parse(JSON.stringify(newProps.viewConfig)),
|
|
604
|
+
);
|
|
629
605
|
|
|
630
606
|
if (newProps.options.authToken !== this.prevAuthToken) {
|
|
631
607
|
// we go a new auth token so we should reload everything
|
|
632
608
|
setTileProxyAuthHeader(newProps.options.authToken);
|
|
633
609
|
|
|
634
|
-
|
|
635
|
-
const trackRenderer = this.getTrackRenderer(viewId);
|
|
636
|
-
const trackDefinitions = JSON.parse(trackRenderer.prevTrackDefinitions);
|
|
637
|
-
|
|
638
|
-
// this will remove all the tracks and then recreate them
|
|
639
|
-
// re-requesting all tiles with the new auth key
|
|
640
|
-
trackRenderer.syncTrackObjects([]);
|
|
641
|
-
trackRenderer.syncTrackObjects(trackDefinitions);
|
|
642
|
-
}
|
|
610
|
+
this.reload();
|
|
643
611
|
|
|
644
612
|
this.prevAuthToken = newProps.options.authToken;
|
|
645
613
|
}
|
|
@@ -655,7 +623,6 @@ class HiGlassComponent extends React.Component {
|
|
|
655
623
|
});
|
|
656
624
|
}
|
|
657
625
|
|
|
658
|
-
// eslint-disable-next-line camelcase
|
|
659
626
|
UNSAFE_componentWillUpdate() {
|
|
660
627
|
// let width = this.element.clientWidth;
|
|
661
628
|
// let height = this.element.clientHeight;
|
|
@@ -663,6 +630,20 @@ class HiGlassComponent extends React.Component {
|
|
|
663
630
|
this.pixiRenderer.render(this.pixiRoot);
|
|
664
631
|
}
|
|
665
632
|
|
|
633
|
+
reload() {
|
|
634
|
+
for (const viewId of this.iterateOverViews()) {
|
|
635
|
+
const trackRenderer = this.getTrackRenderer(viewId);
|
|
636
|
+
if (!trackRenderer) continue;
|
|
637
|
+
|
|
638
|
+
const trackDefinitions = JSON.parse(trackRenderer.prevTrackDefinitions);
|
|
639
|
+
|
|
640
|
+
// this will remove all the tracks and then recreate them
|
|
641
|
+
// re-requesting all tiles with the new auth key
|
|
642
|
+
trackRenderer.syncTrackObjects([]);
|
|
643
|
+
trackRenderer.syncTrackObjects(trackDefinitions);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
666
647
|
componentDidUpdate() {
|
|
667
648
|
this.setTheme(this.props.options.theme, this.props.options.isDarkTheme);
|
|
668
649
|
|
|
@@ -765,13 +746,15 @@ class HiGlassComponent extends React.Component {
|
|
|
765
746
|
}
|
|
766
747
|
|
|
767
748
|
fitPixiToParentContainer() {
|
|
768
|
-
|
|
769
|
-
|
|
749
|
+
const element = this.topDivRef.current;
|
|
750
|
+
|
|
751
|
+
if (!element || !element.parentNode) {
|
|
752
|
+
// console.warn('No parentNode:', element);
|
|
770
753
|
return;
|
|
771
754
|
}
|
|
772
755
|
|
|
773
|
-
const width =
|
|
774
|
-
const height =
|
|
756
|
+
const width = element.parentNode.clientWidth;
|
|
757
|
+
const height = element.parentNode.clientHeight;
|
|
775
758
|
|
|
776
759
|
this.pixiMask.beginFill(0xffffff).drawRect(0, 0, width, height).endFill();
|
|
777
760
|
|
|
@@ -804,10 +787,7 @@ class HiGlassComponent extends React.Component {
|
|
|
804
787
|
const trackOptions = track.options ? track.options : {};
|
|
805
788
|
|
|
806
789
|
if (this.props.options.defaultTrackOptions) {
|
|
807
|
-
if (
|
|
808
|
-
this.props.options.defaultTrackOptions.trackSpecific &&
|
|
809
|
-
this.props.options.defaultTrackOptions.trackSpecific[track.type]
|
|
810
|
-
) {
|
|
790
|
+
if (this.props.options.defaultTrackOptions.trackSpecific?.[track.type]) {
|
|
811
791
|
// track specific options take precedence over all options
|
|
812
792
|
|
|
813
793
|
const options =
|
|
@@ -834,11 +814,9 @@ class HiGlassComponent extends React.Component {
|
|
|
834
814
|
}
|
|
835
815
|
|
|
836
816
|
if (trackInfo.defaultOptions) {
|
|
837
|
-
const defaultThemeOptions =
|
|
838
|
-
trackInfo.defaultOptionsByTheme
|
|
839
|
-
|
|
840
|
-
? trackInfo.defaultOptionsByTheme[this.theme]
|
|
841
|
-
: {};
|
|
817
|
+
const defaultThemeOptions = trackInfo.defaultOptionsByTheme?.[this.theme]
|
|
818
|
+
? trackInfo.defaultOptionsByTheme[this.theme]
|
|
819
|
+
: {};
|
|
842
820
|
|
|
843
821
|
const defaultOptions = {
|
|
844
822
|
...trackInfo.defaultOptions,
|
|
@@ -1106,7 +1084,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1106
1084
|
iterateOverViews() {
|
|
1107
1085
|
const viewIds = [];
|
|
1108
1086
|
|
|
1109
|
-
for (const viewId
|
|
1087
|
+
for (const viewId of Object.keys(this.state.views)) {
|
|
1110
1088
|
viewIds.push(viewId);
|
|
1111
1089
|
}
|
|
1112
1090
|
|
|
@@ -1136,6 +1114,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1136
1114
|
* Iterate over all the tracks in this component.
|
|
1137
1115
|
*/
|
|
1138
1116
|
iterateOverTracks() {
|
|
1117
|
+
/** @type {Array<{ viewId: string, trackId: string, track: import('./types').UnknownTrackConfig }>}*/
|
|
1139
1118
|
const allTracks = [];
|
|
1140
1119
|
for (const viewId in this.state.views) {
|
|
1141
1120
|
const { tracks } = this.state.views[viewId];
|
|
@@ -1164,6 +1143,10 @@ class HiGlassComponent extends React.Component {
|
|
|
1164
1143
|
this.setState({ mouseTool });
|
|
1165
1144
|
}
|
|
1166
1145
|
|
|
1146
|
+
setSizeMode(sizeMode) {
|
|
1147
|
+
this.setState({ sizeMode });
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1167
1150
|
/**
|
|
1168
1151
|
* Checks if a track's value scale is locked with another track
|
|
1169
1152
|
*/
|
|
@@ -1209,6 +1192,9 @@ class HiGlassComponent extends React.Component {
|
|
|
1209
1192
|
)
|
|
1210
1193
|
// filter out stale locks with non-existant tracks
|
|
1211
1194
|
.filter((track) => track)
|
|
1195
|
+
// Filter out tracks that don't have values scales (e.g. chromosome tracks).
|
|
1196
|
+
// The .originalTrack check covers LeftTrackModifier style tracks.
|
|
1197
|
+
.filter((track) => track.valueScale || track.originalTrack?.valueScale)
|
|
1212
1198
|
// if the track is a LeftTrackModifier we want the originalTrack
|
|
1213
1199
|
.map((track) =>
|
|
1214
1200
|
track.originalTrack === undefined ? track : track.originalTrack,
|
|
@@ -1234,14 +1220,16 @@ class HiGlassComponent extends React.Component {
|
|
|
1234
1220
|
|
|
1235
1221
|
if (
|
|
1236
1222
|
minValues.length === 0 ||
|
|
1237
|
-
minValues.filter((x) => x === null || x ===
|
|
1223
|
+
minValues.filter((x) => x === null || x === Number.POSITIVE_INFINITY)
|
|
1224
|
+
.length > 0
|
|
1238
1225
|
) {
|
|
1239
1226
|
return null; // Data hasn't loaded completely
|
|
1240
1227
|
}
|
|
1241
1228
|
|
|
1242
1229
|
if (
|
|
1243
1230
|
maxValues.length === 0 ||
|
|
1244
|
-
maxValues.filter((x) => x === null || x ===
|
|
1231
|
+
maxValues.filter((x) => x === null || x === Number.NEGATIVE_INFINITY)
|
|
1232
|
+
.length > 0
|
|
1245
1233
|
) {
|
|
1246
1234
|
return null; // Data hasn't loaded completely
|
|
1247
1235
|
}
|
|
@@ -1395,7 +1383,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1395
1383
|
* Event handler is called with parameters (xScale, yScale)
|
|
1396
1384
|
*/
|
|
1397
1385
|
addDraggingChangedListener(viewUid, listenerUid, eventHandler) {
|
|
1398
|
-
if (!this.draggingChangedListeners
|
|
1386
|
+
if (!(viewUid in this.draggingChangedListeners)) {
|
|
1399
1387
|
this.draggingChangedListeners[viewUid] = {};
|
|
1400
1388
|
}
|
|
1401
1389
|
|
|
@@ -1412,10 +1400,10 @@ class HiGlassComponent extends React.Component {
|
|
|
1412
1400
|
* @param listenerUid: The uid of the listener itself.
|
|
1413
1401
|
*/
|
|
1414
1402
|
removeDraggingChangedListener(viewUid, listenerUid) {
|
|
1415
|
-
if (this.draggingChangedListeners
|
|
1403
|
+
if (viewUid in this.draggingChangedListeners) {
|
|
1416
1404
|
const listeners = this.draggingChangedListeners[viewUid];
|
|
1417
1405
|
|
|
1418
|
-
if (listeners
|
|
1406
|
+
if (listenerUid in listeners) {
|
|
1419
1407
|
// make sure the listener doesn't think we're still
|
|
1420
1408
|
// dragging
|
|
1421
1409
|
listeners[listenerUid](false);
|
|
@@ -1561,7 +1549,10 @@ class HiGlassComponent extends React.Component {
|
|
|
1561
1549
|
this.canvasElement.width,
|
|
1562
1550
|
this.canvasElement.height,
|
|
1563
1551
|
);
|
|
1564
|
-
|
|
1552
|
+
|
|
1553
|
+
img.src = `data:image/svg+xml;base64,${btoa(
|
|
1554
|
+
unescape(encodeURIComponent(svgString)),
|
|
1555
|
+
)}`;
|
|
1565
1556
|
img.onload = () => {
|
|
1566
1557
|
const targetCanvas = document.createElement('canvas');
|
|
1567
1558
|
// TODO: I have no idea why dimensions are doubled!
|
|
@@ -1605,7 +1596,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1605
1596
|
const lockGroup = this.zoomLocks[uid];
|
|
1606
1597
|
const lockGroupItems = dictItems(lockGroup);
|
|
1607
1598
|
|
|
1608
|
-
// eslint-disable-next-line no-unused-vars
|
|
1609
1599
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1610
1600
|
this.xScales[uid],
|
|
1611
1601
|
this.yScales[uid],
|
|
@@ -1624,7 +1614,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1624
1614
|
continue;
|
|
1625
1615
|
}
|
|
1626
1616
|
|
|
1627
|
-
// eslint-disable-next-line no-unused-vars
|
|
1628
1617
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1629
1618
|
this.xScales[key],
|
|
1630
1619
|
this.yScales[key],
|
|
@@ -1656,7 +1645,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1656
1645
|
|
|
1657
1646
|
// notify the listeners of all locked views that the scales of
|
|
1658
1647
|
// this view have changed
|
|
1659
|
-
if (this.scalesChangedListeners
|
|
1648
|
+
if (key in this.scalesChangedListeners) {
|
|
1660
1649
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1661
1650
|
x(newXScale, newYScale);
|
|
1662
1651
|
});
|
|
@@ -1669,7 +1658,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1669
1658
|
const lockGroup = this.locationLocks[uid];
|
|
1670
1659
|
const lockGroupItems = dictItems(lockGroup);
|
|
1671
1660
|
|
|
1672
|
-
// eslint-disable-next-line no-unused-vars
|
|
1673
1661
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1674
1662
|
this.xScales[uid],
|
|
1675
1663
|
this.yScales[uid],
|
|
@@ -1683,7 +1671,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1683
1671
|
continue;
|
|
1684
1672
|
}
|
|
1685
1673
|
|
|
1686
|
-
// eslint-disable-next-line no-unused-vars
|
|
1687
1674
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1688
1675
|
this.xScales[key],
|
|
1689
1676
|
this.yScales[key],
|
|
@@ -1718,7 +1705,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1718
1705
|
|
|
1719
1706
|
// notify the listeners of all locked views that the scales of
|
|
1720
1707
|
// this view have changed
|
|
1721
|
-
if (this.scalesChangedListeners
|
|
1708
|
+
if (key in this.scalesChangedListeners) {
|
|
1722
1709
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1723
1710
|
x(newXScale, newYScale);
|
|
1724
1711
|
});
|
|
@@ -1734,7 +1721,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1734
1721
|
// this means the x axis of this view (uid) is locked to the y axis of another view
|
|
1735
1722
|
const lockCrossAxis = this.locationLocksAxisWise.x[uid].axis !== 'x';
|
|
1736
1723
|
|
|
1737
|
-
// eslint-disable-next-line no-unused-vars
|
|
1738
1724
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1739
1725
|
this.xScales[uid],
|
|
1740
1726
|
this.yScales[uid],
|
|
@@ -1748,7 +1734,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1748
1734
|
continue;
|
|
1749
1735
|
}
|
|
1750
1736
|
|
|
1751
|
-
// eslint-disable-next-line no-unused-vars
|
|
1752
1737
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1753
1738
|
this.xScales[key],
|
|
1754
1739
|
this.yScales[key],
|
|
@@ -1781,7 +1766,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1781
1766
|
|
|
1782
1767
|
// notify the listeners of all locked views that the scales of
|
|
1783
1768
|
// this view have changed
|
|
1784
|
-
if (this.scalesChangedListeners
|
|
1769
|
+
if (key in this.scalesChangedListeners) {
|
|
1785
1770
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1786
1771
|
x(newXScale, newYScale);
|
|
1787
1772
|
});
|
|
@@ -1797,7 +1782,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1797
1782
|
// this means the y axis of this view (uid) is locked to the x axis of another view
|
|
1798
1783
|
const lockCrossAxis = this.locationLocksAxisWise.y[uid].axis !== 'y';
|
|
1799
1784
|
|
|
1800
|
-
// eslint-disable-next-line no-unused-vars
|
|
1801
1785
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1802
1786
|
this.xScales[uid],
|
|
1803
1787
|
this.yScales[uid],
|
|
@@ -1811,7 +1795,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1811
1795
|
continue;
|
|
1812
1796
|
}
|
|
1813
1797
|
|
|
1814
|
-
// eslint-disable-next-line no-unused-vars
|
|
1815
1798
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1816
1799
|
this.xScales[key],
|
|
1817
1800
|
this.yScales[key],
|
|
@@ -1844,7 +1827,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1844
1827
|
|
|
1845
1828
|
// notify the listeners of all locked views that the scales of
|
|
1846
1829
|
// this view have changed
|
|
1847
|
-
if (this.scalesChangedListeners
|
|
1830
|
+
if (key in this.scalesChangedListeners) {
|
|
1848
1831
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1849
1832
|
x(newXScale, newYScale);
|
|
1850
1833
|
});
|
|
@@ -2105,7 +2088,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2105
2088
|
};
|
|
2106
2089
|
|
|
2107
2090
|
this.addCallbacks(toView, newTrack);
|
|
2108
|
-
this.handleTrackAdded(toView, newTrack, position, hostTrack);
|
|
2091
|
+
this.handleTrackAdded(toView, newTrack, position, null, hostTrack);
|
|
2109
2092
|
}
|
|
2110
2093
|
this.setState({
|
|
2111
2094
|
chooseTrackHandler: null,
|
|
@@ -2125,12 +2108,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2125
2108
|
const targetXScale = this.xScales[uid1];
|
|
2126
2109
|
const targetYScale = this.yScales[uid1];
|
|
2127
2110
|
|
|
2128
|
-
// eslint-disable-next-line no-unused-vars
|
|
2129
2111
|
const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
|
|
2130
2112
|
targetXScale,
|
|
2131
2113
|
targetYScale,
|
|
2132
2114
|
);
|
|
2133
|
-
|
|
2115
|
+
|
|
2134
2116
|
const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
|
|
2135
2117
|
sourceXScale,
|
|
2136
2118
|
sourceYScale,
|
|
@@ -2155,12 +2137,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2155
2137
|
const targetXScale = this.xScales[uid1];
|
|
2156
2138
|
const targetYScale = this.yScales[uid1];
|
|
2157
2139
|
|
|
2158
|
-
// eslint-disable-next-line no-unused-vars
|
|
2159
2140
|
const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
|
|
2160
2141
|
targetXScale,
|
|
2161
2142
|
targetYScale,
|
|
2162
2143
|
);
|
|
2163
|
-
|
|
2144
|
+
|
|
2164
2145
|
const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
|
|
2165
2146
|
sourceXScale,
|
|
2166
2147
|
sourceYScale,
|
|
@@ -2180,9 +2161,10 @@ class HiGlassComponent extends React.Component {
|
|
|
2180
2161
|
*
|
|
2181
2162
|
* We just need to close the menu here.
|
|
2182
2163
|
*/
|
|
2183
|
-
handleTrackPositionChosen(viewUid, position) {
|
|
2164
|
+
handleTrackPositionChosen(viewUid, position, extent) {
|
|
2184
2165
|
this.setState({
|
|
2185
2166
|
addTrackPosition: position,
|
|
2167
|
+
addTrackExtent: extent,
|
|
2186
2168
|
addTrackPositionView: viewUid,
|
|
2187
2169
|
});
|
|
2188
2170
|
}
|
|
@@ -2194,7 +2176,8 @@ class HiGlassComponent extends React.Component {
|
|
|
2194
2176
|
updateRowHeight() {
|
|
2195
2177
|
if (
|
|
2196
2178
|
!this.props.options ||
|
|
2197
|
-
this.sizeMode !== SIZE_MODE_BOUNDED
|
|
2179
|
+
(this.sizeMode !== SIZE_MODE_BOUNDED &&
|
|
2180
|
+
this.sizeMode !== SIZE_MODE_BOUNDED_OVERFLOW) ||
|
|
2198
2181
|
this.props.options.pixelPreciseMarginPadding
|
|
2199
2182
|
) {
|
|
2200
2183
|
// not bounded so we don't need to update the row height
|
|
@@ -2204,9 +2187,34 @@ class HiGlassComponent extends React.Component {
|
|
|
2204
2187
|
// const width = this.element.parentNode.clientWidth;
|
|
2205
2188
|
const height = this.element.parentNode.clientHeight;
|
|
2206
2189
|
|
|
2207
|
-
let maxHeight =
|
|
2190
|
+
let maxHeight = 1;
|
|
2191
|
+
let perTrackRowHeight = 0;
|
|
2192
|
+
|
|
2208
2193
|
for (const view of dictValues(this.state.views)) {
|
|
2209
2194
|
maxHeight = Math.max(maxHeight, view.layout.y + view.layout.h);
|
|
2195
|
+
|
|
2196
|
+
const topTrackHeights = view.tracks.top
|
|
2197
|
+
.filter((x) => x.height)
|
|
2198
|
+
.map((x) => x.height)
|
|
2199
|
+
.reduce((a, b) => a + b, 0);
|
|
2200
|
+
const bottomTrackHeights = view.tracks.bottom
|
|
2201
|
+
.filter((x) => x.height)
|
|
2202
|
+
.map((x) => x.height)
|
|
2203
|
+
.reduce((a, b) => a + b, 0);
|
|
2204
|
+
|
|
2205
|
+
// centerTrackHeight is excluded because center tracks
|
|
2206
|
+
// are resized to fit into the remaining part of the view
|
|
2207
|
+
// const centerTrackHeight = view.tracks.center
|
|
2208
|
+
// .filter(x => x.height)
|
|
2209
|
+
// .map(x => x.height)
|
|
2210
|
+
// .reduce((a, b) => a + b, 0);
|
|
2211
|
+
|
|
2212
|
+
perTrackRowHeight = Math.ceil(
|
|
2213
|
+
Math.max(
|
|
2214
|
+
perTrackRowHeight,
|
|
2215
|
+
(topTrackHeights + bottomTrackHeights) / view.layout.h,
|
|
2216
|
+
),
|
|
2217
|
+
);
|
|
2210
2218
|
}
|
|
2211
2219
|
|
|
2212
2220
|
this.handleDragStart();
|
|
@@ -2217,43 +2225,23 @@ class HiGlassComponent extends React.Component {
|
|
|
2217
2225
|
const marginHeight = MARGIN_HEIGHT * maxHeight - 1;
|
|
2218
2226
|
const availableHeight = height - marginHeight;
|
|
2219
2227
|
|
|
2220
|
-
//
|
|
2221
|
-
|
|
2222
|
-
//
|
|
2228
|
+
// if we're bounded, then maxHeight * rowHeight = availableHeight
|
|
2229
|
+
// but the catch is that if we have tracks that would be larger
|
|
2230
|
+
// than the largest div, we have to adjust the height to make sure
|
|
2231
|
+
// all of them are visible
|
|
2232
|
+
// to do that, we have to go view by view and calculate the heights
|
|
2233
|
+
// of the top and bottom sections and then divide that by the view's height
|
|
2234
|
+
// if there's a center track
|
|
2223
2235
|
|
|
2224
|
-
const
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
// const {
|
|
2228
|
-
// totalWidth,
|
|
2229
|
-
// totalHeight,
|
|
2230
|
-
// topHeight,
|
|
2231
|
-
// bottomHeight,
|
|
2232
|
-
// leftWidth,
|
|
2233
|
-
// rightWidth,
|
|
2234
|
-
// centerWidth,
|
|
2235
|
-
// centerHeight,
|
|
2236
|
-
// minNecessaryHeight
|
|
2237
|
-
// } = this.calculateViewDimensions(view);
|
|
2238
|
-
|
|
2239
|
-
// // If the view is bounded, then we always fit everything inside the container
|
|
2240
|
-
// //
|
|
2241
|
-
// // It used to be that if the viewconfig was too long, we just let it overflow,
|
|
2242
|
-
// // but I think it's better that it's always contained.
|
|
2243
|
-
|
|
2244
|
-
// /*
|
|
2245
|
-
// if (minNecessaryHeight > view.layout.h * (prospectiveRowHeight + MARGIN_HEIGHT)) {
|
|
2246
|
-
// // we don't have space for one of the containers, so let them exceed the bounds
|
|
2247
|
-
// // of the box
|
|
2248
|
-
// chosenRowHeight = currentRowHeight;
|
|
2249
|
-
// break;
|
|
2250
|
-
// }
|
|
2251
|
-
// */
|
|
2252
|
-
// }
|
|
2236
|
+
const prospectiveRowHeight = Math.floor(availableHeight / maxHeight); // maxHeight is the number of
|
|
2237
|
+
// rows necessary to display this view
|
|
2238
|
+
const chosenRowHeight = Math.max(prospectiveRowHeight, perTrackRowHeight);
|
|
2253
2239
|
|
|
2254
|
-
this.
|
|
2255
|
-
|
|
2256
|
-
|
|
2240
|
+
if (this.topDivRef.current) {
|
|
2241
|
+
this.setState({
|
|
2242
|
+
rowHeight: chosenRowHeight,
|
|
2243
|
+
});
|
|
2244
|
+
}
|
|
2257
2245
|
}
|
|
2258
2246
|
|
|
2259
2247
|
/**
|
|
@@ -2299,11 +2287,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2299
2287
|
return TRACKS_INFO_BY_TYPE[trackType];
|
|
2300
2288
|
}
|
|
2301
2289
|
|
|
2302
|
-
if (this.pluginTracks
|
|
2290
|
+
if (this.pluginTracks?.[trackType]) {
|
|
2303
2291
|
return this.pluginTracks[trackType].config;
|
|
2304
2292
|
}
|
|
2305
2293
|
|
|
2306
|
-
if (window.higlassTracksByType
|
|
2294
|
+
if (window.higlassTracksByType?.[trackType]) {
|
|
2307
2295
|
return window.higlassTracksByType[trackType].config;
|
|
2308
2296
|
}
|
|
2309
2297
|
|
|
@@ -2317,7 +2305,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2317
2305
|
|
|
2318
2306
|
forceRefreshView() {
|
|
2319
2307
|
// force everything to rerender
|
|
2320
|
-
this.setState(this.state);
|
|
2308
|
+
this.setState(this.state);
|
|
2321
2309
|
}
|
|
2322
2310
|
|
|
2323
2311
|
refreshView(timeout = SHORT_DRAG_TIMEOUT) {
|
|
@@ -2474,8 +2462,8 @@ class HiGlassComponent extends React.Component {
|
|
|
2474
2462
|
: defaultCenterWidth;
|
|
2475
2463
|
}
|
|
2476
2464
|
|
|
2477
|
-
|
|
2478
|
-
|
|
2465
|
+
centerHeight = height;
|
|
2466
|
+
centerWidth = width;
|
|
2479
2467
|
}
|
|
2480
2468
|
} else if (
|
|
2481
2469
|
((view.tracks.top && dictValues(view.tracks.top).length > 1) ||
|
|
@@ -2535,29 +2523,30 @@ class HiGlassComponent extends React.Component {
|
|
|
2535
2523
|
}
|
|
2536
2524
|
|
|
2537
2525
|
calculateZoomLimits(view, initialXDomain) {
|
|
2538
|
-
const limits = [0,
|
|
2526
|
+
const limits = [0, Number.POSITIVE_INFINITY];
|
|
2539
2527
|
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2528
|
+
if ('zoomLimits' in view) {
|
|
2529
|
+
const diffX = initialXDomain[1] - initialXDomain[0];
|
|
2530
|
+
const viewConfLimit = view.zoomLimits;
|
|
2543
2531
|
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2532
|
+
if (viewConfLimit.length !== 2) {
|
|
2533
|
+
return limits;
|
|
2534
|
+
}
|
|
2547
2535
|
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2536
|
+
if (viewConfLimit[0] !== null && viewConfLimit[0] > 0) {
|
|
2537
|
+
const upperLimit = diffX / viewConfLimit[0];
|
|
2538
|
+
limits[1] = Math.max(upperLimit, 1);
|
|
2539
|
+
if (upperLimit < 1) {
|
|
2540
|
+
console.warn(`Invalid zoom limits. Lower limit set to ${diffX}`);
|
|
2541
|
+
}
|
|
2553
2542
|
}
|
|
2554
|
-
}
|
|
2555
2543
|
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2544
|
+
if (viewConfLimit[1] !== null && viewConfLimit[1] > viewConfLimit[0]) {
|
|
2545
|
+
const lowerLimit = diffX / viewConfLimit[1];
|
|
2546
|
+
limits[0] = Math.min(lowerLimit, 1);
|
|
2547
|
+
if (lowerLimit > 1) {
|
|
2548
|
+
console.warn(`Invalid zoom limits. Upper limit set to ${diffX}`);
|
|
2549
|
+
}
|
|
2561
2550
|
}
|
|
2562
2551
|
}
|
|
2563
2552
|
return limits;
|
|
@@ -2690,6 +2679,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2690
2679
|
|
|
2691
2680
|
if (hostTrack.type === 'combined') {
|
|
2692
2681
|
hostTrack.contents.push(newTrack);
|
|
2682
|
+
hostTrack.uid = slugid.nice();
|
|
2693
2683
|
|
|
2694
2684
|
if (newTrack.type === 'heatmap') {
|
|
2695
2685
|
// For stacked heatmaps we will adjust some options automatically for convenience
|
|
@@ -2716,6 +2706,8 @@ class HiGlassComponent extends React.Component {
|
|
|
2716
2706
|
this.setState((prevState) => ({
|
|
2717
2707
|
views: prevState.views,
|
|
2718
2708
|
}));
|
|
2709
|
+
|
|
2710
|
+
this.triggerViewChangeDb();
|
|
2719
2711
|
}
|
|
2720
2712
|
|
|
2721
2713
|
handleNoTrackAdded() {
|
|
@@ -2723,6 +2715,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2723
2715
|
// we've already added the track, remove the add track dialog
|
|
2724
2716
|
this.setState({
|
|
2725
2717
|
addTrackPosition: null,
|
|
2718
|
+
addTrackExtent: null,
|
|
2726
2719
|
});
|
|
2727
2720
|
}
|
|
2728
2721
|
}
|
|
@@ -2735,11 +2728,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2735
2728
|
* @param position: The position the track is being added to
|
|
2736
2729
|
* @param host: If this track is being added to another track
|
|
2737
2730
|
*/
|
|
2738
|
-
handleTracksAdded(viewId, newTracks, position, host) {
|
|
2731
|
+
handleTracksAdded(viewId, newTracks, position, extent, host) {
|
|
2739
2732
|
this.storeTrackSizes(viewId);
|
|
2740
2733
|
|
|
2741
2734
|
for (const newTrack of newTracks) {
|
|
2742
|
-
this.handleTrackAdded(viewId, newTrack, position, host);
|
|
2735
|
+
this.handleTrackAdded(viewId, newTrack, position, extent, host);
|
|
2743
2736
|
}
|
|
2744
2737
|
}
|
|
2745
2738
|
|
|
@@ -2808,7 +2801,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2808
2801
|
* @returns {Object}: A trackConfig (\{ uid: "", width: x \})
|
|
2809
2802
|
* describing this track
|
|
2810
2803
|
*/
|
|
2811
|
-
handleTrackAdded(viewId, newTrack, position, host = null) {
|
|
2804
|
+
handleTrackAdded(viewId, newTrack, position, extent = null, host = null) {
|
|
2812
2805
|
this.addDefaultTrackOptions(newTrack);
|
|
2813
2806
|
|
|
2814
2807
|
// make sure the new track has a uid
|
|
@@ -2825,6 +2818,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2825
2818
|
// we've already added the track, remove the add track dialog
|
|
2826
2819
|
this.setState({
|
|
2827
2820
|
addTrackPosition: null,
|
|
2821
|
+
addTrackExtent: null,
|
|
2828
2822
|
});
|
|
2829
2823
|
}
|
|
2830
2824
|
|
|
@@ -2835,16 +2829,18 @@ class HiGlassComponent extends React.Component {
|
|
|
2835
2829
|
}
|
|
2836
2830
|
|
|
2837
2831
|
newTrack.position = position;
|
|
2838
|
-
|
|
2832
|
+
if (extent) {
|
|
2833
|
+
newTrack.options.extent = extent;
|
|
2834
|
+
}
|
|
2839
2835
|
const trackInfo = this.getTrackInfo(newTrack.type);
|
|
2840
2836
|
|
|
2841
2837
|
newTrack.width =
|
|
2842
2838
|
trackInfo.defaultWidth ||
|
|
2843
|
-
|
|
2839
|
+
trackInfo.defaultOptions?.minWidth ||
|
|
2844
2840
|
this.minVerticalWidth;
|
|
2845
2841
|
newTrack.height =
|
|
2846
2842
|
trackInfo.defaultHeight ||
|
|
2847
|
-
|
|
2843
|
+
trackInfo.defaultOptions?.minHeight ||
|
|
2848
2844
|
this.minHorizontalHeight;
|
|
2849
2845
|
|
|
2850
2846
|
const { tracks } = this.state.views[viewId];
|
|
@@ -3006,7 +3002,10 @@ class HiGlassComponent extends React.Component {
|
|
|
3006
3002
|
totalTrackHeight += MARGIN_HEIGHT;
|
|
3007
3003
|
const rowHeight = this.state.rowHeight + MARGIN_HEIGHT;
|
|
3008
3004
|
|
|
3009
|
-
if (
|
|
3005
|
+
if (
|
|
3006
|
+
this.sizeMode !== SIZE_MODE_BOUNDED &&
|
|
3007
|
+
this.sizeMode !== SIZE_MODE_BOUNDED_OVERFLOW
|
|
3008
|
+
) {
|
|
3010
3009
|
view.layout.h = Math.ceil(totalTrackHeight / rowHeight);
|
|
3011
3010
|
}
|
|
3012
3011
|
}
|
|
@@ -3195,7 +3194,15 @@ class HiGlassComponent extends React.Component {
|
|
|
3195
3194
|
*
|
|
3196
3195
|
* Done in place.
|
|
3197
3196
|
*
|
|
3198
|
-
* @param
|
|
3197
|
+
* @param {string} viewUid
|
|
3198
|
+
* @param {{
|
|
3199
|
+
* type: string;
|
|
3200
|
+
* uid: string;
|
|
3201
|
+
* fromViewUid: string;
|
|
3202
|
+
* registerViewportChanged: (string: trackId, listener: () => void) => void;
|
|
3203
|
+
* removeViewportChanged: (string: trackId) => void;
|
|
3204
|
+
* removeScalesChangedListener: (string: trackId) => void;
|
|
3205
|
+
* }} track A view with tracks.
|
|
3199
3206
|
*/
|
|
3200
3207
|
addCallbacks(viewUid, track) {
|
|
3201
3208
|
const trackInfo = this.getTrackInfo(track.type);
|
|
@@ -3203,7 +3210,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3203
3210
|
track.type === 'viewport-projection-center' ||
|
|
3204
3211
|
track.type === 'viewport-projection-horizontal' ||
|
|
3205
3212
|
track.type === 'viewport-projection-vertical' ||
|
|
3206
|
-
|
|
3213
|
+
trackInfo?.projection
|
|
3207
3214
|
) {
|
|
3208
3215
|
const fromView = track.fromViewUid;
|
|
3209
3216
|
|
|
@@ -3399,7 +3406,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3399
3406
|
const locksByViewUid = {};
|
|
3400
3407
|
|
|
3401
3408
|
for (const viewUid of dictKeys(locks)) {
|
|
3402
|
-
let lockUid = locks[viewUid]
|
|
3409
|
+
let lockUid = locks[viewUid]?.uid;
|
|
3403
3410
|
|
|
3404
3411
|
if (!lockUid) {
|
|
3405
3412
|
// otherwise, assign this locationLock its own uid
|
|
@@ -3425,23 +3432,18 @@ class HiGlassComponent extends React.Component {
|
|
|
3425
3432
|
return { locksByViewUid, locksDict };
|
|
3426
3433
|
}
|
|
3427
3434
|
|
|
3428
|
-
getViewsAsJson() {
|
|
3435
|
+
getViewsAsJson(views) {
|
|
3429
3436
|
const newJson = JSON.parse(JSON.stringify(this.state.viewConfig));
|
|
3430
|
-
newJson.views = Object.values(this.state.views).map((k) => {
|
|
3437
|
+
newJson.views = Object.values(views || this.state.views).map((k) => {
|
|
3431
3438
|
const newView = JSON.parse(JSON.stringify(k));
|
|
3432
3439
|
|
|
3433
3440
|
visitPositionedTracks(newView.tracks, (track) => {
|
|
3434
3441
|
if (track.server) {
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
const hostString = window.location.host;
|
|
3441
|
-
const { protocol } = window.location;
|
|
3442
|
-
const newUrl = `${protocol}//${hostString}${url.pathname}`;
|
|
3443
|
-
|
|
3444
|
-
track.server = newUrl;
|
|
3442
|
+
if (!URL.canParse(track.server)) {
|
|
3443
|
+
// Not a valid URL, so we'll extend the current one
|
|
3444
|
+
const url = new URL(window.location);
|
|
3445
|
+
url.pathname = track.server;
|
|
3446
|
+
track.server = url.href;
|
|
3445
3447
|
}
|
|
3446
3448
|
}
|
|
3447
3449
|
|
|
@@ -3455,6 +3457,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3455
3457
|
// so the `projectionXDomain` field must be used.
|
|
3456
3458
|
track.projectionXDomain = this.projectionXDomains[k.uid][track.uid];
|
|
3457
3459
|
}
|
|
3460
|
+
|
|
3458
3461
|
if (
|
|
3459
3462
|
(track.type === 'viewport-projection-center' ||
|
|
3460
3463
|
track.type === 'viewport-projection-vertical') &&
|
|
@@ -3482,8 +3485,10 @@ class HiGlassComponent extends React.Component {
|
|
|
3482
3485
|
delete track.datatype;
|
|
3483
3486
|
delete track.maxWidth;
|
|
3484
3487
|
delete track.datafile;
|
|
3488
|
+
delete track.filetype;
|
|
3485
3489
|
delete track.binsPerDimension;
|
|
3486
3490
|
delete track.resolutions;
|
|
3491
|
+
delete track.row_infos;
|
|
3487
3492
|
delete track.aggregationModes;
|
|
3488
3493
|
});
|
|
3489
3494
|
|
|
@@ -3639,7 +3644,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3639
3644
|
* User clicked on the "Add View" button. We'll duplicate the last
|
|
3640
3645
|
* view.
|
|
3641
3646
|
*/
|
|
3642
|
-
handleAddView(view) {
|
|
3647
|
+
handleAddView(view, newViewParams, noUpdate) {
|
|
3643
3648
|
const views = dictValues(this.state.views);
|
|
3644
3649
|
const lastView = view;
|
|
3645
3650
|
|
|
@@ -3679,11 +3684,14 @@ class HiGlassComponent extends React.Component {
|
|
|
3679
3684
|
|
|
3680
3685
|
const jsonString = JSON.stringify(lastView);
|
|
3681
3686
|
|
|
3682
|
-
|
|
3687
|
+
let newView = JSON.parse(jsonString); // ghetto copy
|
|
3683
3688
|
|
|
3684
3689
|
newView.initialXDomain = this.xScales[newView.uid].domain();
|
|
3685
3690
|
newView.initialYDomain = this.yScales[newView.uid].domain();
|
|
3686
3691
|
|
|
3692
|
+
if (newViewParams) {
|
|
3693
|
+
newView = { ...newView, ...newViewParams };
|
|
3694
|
+
}
|
|
3687
3695
|
// place this new view below all the others
|
|
3688
3696
|
|
|
3689
3697
|
[[newView.layout.x, newView.layout.y]] = potentialPositions;
|
|
@@ -3692,47 +3700,38 @@ class HiGlassComponent extends React.Component {
|
|
|
3692
3700
|
newView.uid = slugid.nice();
|
|
3693
3701
|
newView.layout.i = newView.uid;
|
|
3694
3702
|
|
|
3703
|
+
this.xScales[newView.uid] = scaleLinear().domain(newView.initialXDomain);
|
|
3704
|
+
this.yScales[newView.uid] = scaleLinear().domain(newView.initialYDomain);
|
|
3705
|
+
|
|
3695
3706
|
visitPositionedTracks(newView.tracks, (track) => {
|
|
3696
3707
|
this.addCallbacks(newView.uid, track);
|
|
3697
3708
|
});
|
|
3698
3709
|
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
views[newView.uid] = newView;
|
|
3703
|
-
return { views };
|
|
3704
|
-
});
|
|
3705
|
-
}
|
|
3710
|
+
const createNewViews = (prevViews) => {
|
|
3711
|
+
const _views = JSON.parse(JSON.stringify(prevViews));
|
|
3712
|
+
_views[newView.uid] = newView;
|
|
3706
3713
|
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
* newAssembly: string
|
|
3724
|
-
* The new assembly it should display coordinates for
|
|
3725
|
-
*
|
|
3726
|
-
* Returns
|
|
3727
|
-
* -------
|
|
3728
|
-
*
|
|
3729
|
-
* Nothing
|
|
3730
|
-
*/
|
|
3731
|
-
const { views } = this.state;
|
|
3714
|
+
return _views;
|
|
3715
|
+
};
|
|
3716
|
+
|
|
3717
|
+
let newViews = null;
|
|
3718
|
+
|
|
3719
|
+
if (!noUpdate) {
|
|
3720
|
+
this.setState((prevState) => {
|
|
3721
|
+
newViews = createNewViews(prevState.views);
|
|
3722
|
+
|
|
3723
|
+
return {
|
|
3724
|
+
views: newViews,
|
|
3725
|
+
};
|
|
3726
|
+
});
|
|
3727
|
+
} else {
|
|
3728
|
+
newViews = createNewViews(this.state.views);
|
|
3729
|
+
}
|
|
3732
3730
|
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3731
|
+
return {
|
|
3732
|
+
newViewUid: newView.uid,
|
|
3733
|
+
newViewconf: this.getViewsAsJson(newViews),
|
|
3734
|
+
};
|
|
3736
3735
|
}
|
|
3737
3736
|
|
|
3738
3737
|
createGenomePostionSearchBoxEntry(
|
|
@@ -3891,7 +3890,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3891
3890
|
if (
|
|
3892
3891
|
otherTrack.type === 'heatmap' &&
|
|
3893
3892
|
otherTrack.uid !== track.uid &&
|
|
3894
|
-
otherTrack.options.extent
|
|
3893
|
+
otherTrack.options.extent === 'full'
|
|
3895
3894
|
) {
|
|
3896
3895
|
// Automatically change the extent of the other track to
|
|
3897
3896
|
// `lower-left``
|
|
@@ -3936,7 +3935,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3936
3935
|
if (
|
|
3937
3936
|
otherTrack.type === 'heatmap' &&
|
|
3938
3937
|
otherTrack.uid !== track.uid &&
|
|
3939
|
-
otherTrack.options.extent
|
|
3938
|
+
otherTrack.options.extent === 'full'
|
|
3940
3939
|
) {
|
|
3941
3940
|
// Automatically change the extent of the other track to
|
|
3942
3941
|
// `upper-right``
|
|
@@ -4025,7 +4024,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4025
4024
|
'right',
|
|
4026
4025
|
'bottom',
|
|
4027
4026
|
]) {
|
|
4028
|
-
if (v.tracks
|
|
4027
|
+
if (trackOrientation in (v.tracks ?? {})) {
|
|
4029
4028
|
// filter out invalid tracks
|
|
4030
4029
|
v.tracks[trackOrientation] = v.tracks[trackOrientation].filter((t) =>
|
|
4031
4030
|
this.isTrackValid(t, viewUidsSet),
|
|
@@ -4049,6 +4048,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4049
4048
|
processViewConfig(viewConfig) {
|
|
4050
4049
|
let { views } = viewConfig;
|
|
4051
4050
|
let viewsByUid = {};
|
|
4051
|
+
let maxHeight = 1;
|
|
4052
4052
|
|
|
4053
4053
|
if (!viewConfig.views || viewConfig.views.length === 0) {
|
|
4054
4054
|
console.warn('No views provided in viewConfig');
|
|
@@ -4102,6 +4102,25 @@ class HiGlassComponent extends React.Component {
|
|
|
4102
4102
|
}
|
|
4103
4103
|
|
|
4104
4104
|
visitPositionedTracks(v.tracks, (track) => {
|
|
4105
|
+
if (this.state?.views?.[v.uid]) {
|
|
4106
|
+
// This whole song and dance is to ensure that if the higlass
|
|
4107
|
+
// viewer is reinstantiated all of the tileset info meta that
|
|
4108
|
+
// is stored with the track gets passed on.
|
|
4109
|
+
// Necessary to make sure that the "Zoom Limit" option still
|
|
4110
|
+
// functions.
|
|
4111
|
+
const existingTrack = getTrackByUid(
|
|
4112
|
+
this.state.views[v.uid].tracks,
|
|
4113
|
+
track.uid,
|
|
4114
|
+
);
|
|
4115
|
+
|
|
4116
|
+
if (existingTrack) {
|
|
4117
|
+
track.maxZoom = existingTrack.maxZoom;
|
|
4118
|
+
track.resolutions = existingTrack.resolutions;
|
|
4119
|
+
track.binsPerDimension = existingTrack.binsPerDimension;
|
|
4120
|
+
track.maxWidth = existingTrack.maxWidth;
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4105
4124
|
if (!track.uid) track.uid = slugid.nice();
|
|
4106
4125
|
|
|
4107
4126
|
this.addCallbacks(v.uid, track);
|
|
@@ -4119,6 +4138,18 @@ class HiGlassComponent extends React.Component {
|
|
|
4119
4138
|
} else {
|
|
4120
4139
|
v.layout = this.generateViewLayout(v);
|
|
4121
4140
|
}
|
|
4141
|
+
|
|
4142
|
+
maxHeight = Math.max(maxHeight, v.layout.y + v.layout.h);
|
|
4143
|
+
});
|
|
4144
|
+
|
|
4145
|
+
// we want to scale up the height of each view so that the maxHeight
|
|
4146
|
+
// is closer to 12
|
|
4147
|
+
const TARGET_MAX_HEIGHT = 12;
|
|
4148
|
+
const multiplier = Math.ceil(TARGET_MAX_HEIGHT / maxHeight);
|
|
4149
|
+
|
|
4150
|
+
views.forEach((v) => {
|
|
4151
|
+
v.layout.h *= multiplier;
|
|
4152
|
+
v.layout.y *= multiplier;
|
|
4122
4153
|
});
|
|
4123
4154
|
|
|
4124
4155
|
this.deserializeZoomLocks(viewConfig);
|
|
@@ -4152,8 +4183,12 @@ class HiGlassComponent extends React.Component {
|
|
|
4152
4183
|
this.apiPublish('rangeSelection', range);
|
|
4153
4184
|
}
|
|
4154
4185
|
|
|
4155
|
-
offViewChange(
|
|
4156
|
-
this.viewChangeListener.
|
|
4186
|
+
offViewChange(callback) {
|
|
4187
|
+
const index = this.viewChangeListener.indexOf(callback);
|
|
4188
|
+
|
|
4189
|
+
if (index > -1) {
|
|
4190
|
+
this.viewChangeListener.splice(index, 1);
|
|
4191
|
+
}
|
|
4157
4192
|
}
|
|
4158
4193
|
|
|
4159
4194
|
onViewChange(callback) {
|
|
@@ -4161,9 +4196,8 @@ class HiGlassComponent extends React.Component {
|
|
|
4161
4196
|
}
|
|
4162
4197
|
|
|
4163
4198
|
triggerViewChange() {
|
|
4164
|
-
this.
|
|
4165
|
-
|
|
4166
|
-
);
|
|
4199
|
+
const viewsString = this.getViewsAsString();
|
|
4200
|
+
this.viewChangeListener.forEach((callback) => callback(viewsString));
|
|
4167
4201
|
}
|
|
4168
4202
|
|
|
4169
4203
|
getGenomeLocation(viewId) {
|
|
@@ -4355,7 +4389,10 @@ class HiGlassComponent extends React.Component {
|
|
|
4355
4389
|
(listenerId) => listenerId.indexOf(LOCATION_LISTENER_PREFIX) === 0,
|
|
4356
4390
|
)
|
|
4357
4391
|
.map((listenerId) =>
|
|
4358
|
-
parseInt(
|
|
4392
|
+
Number.parseInt(
|
|
4393
|
+
listenerId.slice(LOCATION_LISTENER_PREFIX.length + 1),
|
|
4394
|
+
10,
|
|
4395
|
+
),
|
|
4359
4396
|
)
|
|
4360
4397
|
.reduce((max, value) => Math.max(max, value), 0) + 1;
|
|
4361
4398
|
}
|
|
@@ -4408,11 +4445,11 @@ class HiGlassComponent extends React.Component {
|
|
|
4408
4445
|
* @param {object} e Event object.
|
|
4409
4446
|
*/
|
|
4410
4447
|
mouseMoveHandler(e) {
|
|
4411
|
-
if (!this.
|
|
4448
|
+
if (!this.topDivRef.current || this.state.modal) return;
|
|
4412
4449
|
|
|
4413
4450
|
const absX = e.clientX;
|
|
4414
4451
|
const absY = e.clientY;
|
|
4415
|
-
const relPos = pointer(e, this.
|
|
4452
|
+
const relPos = pointer(e, this.topDivRef.current);
|
|
4416
4453
|
// We need to add the scrollTop
|
|
4417
4454
|
relPos[1] += this.scrollTop;
|
|
4418
4455
|
const hoveredTiledPlot = this.getTiledPlotAtPosition(absX, absY);
|
|
@@ -4450,15 +4487,13 @@ class HiGlassComponent extends React.Component {
|
|
|
4450
4487
|
const evt = {
|
|
4451
4488
|
x: relPos[0],
|
|
4452
4489
|
y: relPos[1],
|
|
4453
|
-
relTrackX:
|
|
4454
|
-
|
|
4455
|
-
relTrackY:
|
|
4456
|
-
hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4490
|
+
relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
|
|
4491
|
+
relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4457
4492
|
dataX,
|
|
4458
4493
|
dataY,
|
|
4459
4494
|
// See below why we need these derived boolean values
|
|
4460
|
-
isFrom2dTrack: !!
|
|
4461
|
-
isFromVerticalTrack: !!
|
|
4495
|
+
isFrom2dTrack: !!hoveredTrack?.is2d,
|
|
4496
|
+
isFromVerticalTrack: !!hoveredTrack?.flipText,
|
|
4462
4497
|
track: hoveredTrack,
|
|
4463
4498
|
origEvt: e,
|
|
4464
4499
|
sourceUid: this.uid,
|
|
@@ -4536,13 +4571,12 @@ class HiGlassComponent extends React.Component {
|
|
|
4536
4571
|
showHoverMenu(evt) {
|
|
4537
4572
|
// each track should have a function that returns an HTML representation
|
|
4538
4573
|
// of the data at a give position
|
|
4539
|
-
const mouseOverHtml =
|
|
4540
|
-
evt.track
|
|
4541
|
-
|
|
4542
|
-
: '';
|
|
4574
|
+
const mouseOverHtml = evt.track?.getMouseOverHtml
|
|
4575
|
+
? evt.track.getMouseOverHtml(evt.relTrackX, evt.relTrackY)
|
|
4576
|
+
: '';
|
|
4543
4577
|
|
|
4544
4578
|
if (evt.track !== this.prevMouseHoverTrack) {
|
|
4545
|
-
if (this.prevMouseHoverTrack
|
|
4579
|
+
if (this.prevMouseHoverTrack?.stopHover) {
|
|
4546
4580
|
this.prevMouseHoverTrack.stopHover();
|
|
4547
4581
|
}
|
|
4548
4582
|
}
|
|
@@ -4551,7 +4585,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4551
4585
|
|
|
4552
4586
|
if (this.zooming) return;
|
|
4553
4587
|
|
|
4554
|
-
const data = mouseOverHtml
|
|
4588
|
+
const data = mouseOverHtml?.length ? [1] : [];
|
|
4555
4589
|
|
|
4556
4590
|
// try to select the mouseover div
|
|
4557
4591
|
let mouseOverDiv = select('body')
|
|
@@ -4639,7 +4673,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4639
4673
|
|
|
4640
4674
|
const hoveredTiledPlot = this.getTiledPlotAtPosition(absX, absY);
|
|
4641
4675
|
|
|
4642
|
-
const relPos = pointer(nativeEvent, this.
|
|
4676
|
+
const relPos = pointer(nativeEvent, this.topDivRef.current);
|
|
4643
4677
|
relPos[1] += this.scrollTop;
|
|
4644
4678
|
|
|
4645
4679
|
const hoveredTracks = hoveredTiledPlot
|
|
@@ -4663,10 +4697,8 @@ class HiGlassComponent extends React.Component {
|
|
|
4663
4697
|
]
|
|
4664
4698
|
: relPos;
|
|
4665
4699
|
|
|
4666
|
-
const relTrackX =
|
|
4667
|
-
|
|
4668
|
-
const relTrackY =
|
|
4669
|
-
hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1];
|
|
4700
|
+
const relTrackX = hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0];
|
|
4701
|
+
const relTrackY = hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1];
|
|
4670
4702
|
|
|
4671
4703
|
for (const track of this.iterateOverTracks()) {
|
|
4672
4704
|
const trackObj = getTrackObjById(
|
|
@@ -4765,7 +4797,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4765
4797
|
mouseDownHandler(evt) {}
|
|
4766
4798
|
|
|
4767
4799
|
onScrollHandler() {
|
|
4768
|
-
if (this.
|
|
4800
|
+
if (this.sizeMode !== SIZE_MODE_SCROLL) return;
|
|
4769
4801
|
this.scrollTop = this.scrollContainer.scrollTop;
|
|
4770
4802
|
this.pixiStage.y = -this.scrollTop;
|
|
4771
4803
|
this.pubSub.publish('app.scroll', this.scrollTop);
|
|
@@ -4817,17 +4849,18 @@ class HiGlassComponent extends React.Component {
|
|
|
4817
4849
|
this.props.zoomFixed ||
|
|
4818
4850
|
this.props.options.zoomFixed ||
|
|
4819
4851
|
this.state.viewConfig.zoomFixed ||
|
|
4820
|
-
this.
|
|
4821
|
-
|
|
4852
|
+
this.sizeMode === SIZE_MODE_SCROLL ||
|
|
4853
|
+
view?.zoomFixed
|
|
4822
4854
|
);
|
|
4823
4855
|
}
|
|
4824
4856
|
|
|
4825
4857
|
/**
|
|
4826
4858
|
* Handle trackDimensionsModified events
|
|
4827
|
-
*
|
|
4828
|
-
* settings.
|
|
4829
|
-
* settings.
|
|
4830
|
-
* settings.
|
|
4859
|
+
* @param {Object} settings
|
|
4860
|
+
* @param {string} settings.viewId = id of the view
|
|
4861
|
+
* @param {string} settings.trackId = id of the track
|
|
4862
|
+
* @param {number} settings.height = new height of the track or undefined if current height should remain
|
|
4863
|
+
* @param {nmber} settings.width = new width of the track or undefined if current width should remain
|
|
4831
4864
|
*/
|
|
4832
4865
|
trackDimensionsModifiedHandler(settings) {
|
|
4833
4866
|
const view = this.state.views[settings.viewId];
|
|
@@ -4853,15 +4886,12 @@ class HiGlassComponent extends React.Component {
|
|
|
4853
4886
|
}
|
|
4854
4887
|
|
|
4855
4888
|
wheelHandler(evt) {
|
|
4856
|
-
if (this.state.modal || this.
|
|
4857
|
-
return;
|
|
4889
|
+
if (this.state.modal || this.sizeMode === SIZE_MODE_SCROLL) return;
|
|
4858
4890
|
|
|
4859
4891
|
// The event forwarder wasn't written for React's SyntheticEvent
|
|
4860
4892
|
const nativeEvent = evt.nativeEvent || evt;
|
|
4861
4893
|
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
if (!hasParent(nativeEvent.target, this.topDiv)) {
|
|
4894
|
+
if (!hasParent(nativeEvent.target, this.topDivRef.current)) {
|
|
4865
4895
|
// ignore events that don't come from within the
|
|
4866
4896
|
// HiGlass container
|
|
4867
4897
|
return;
|
|
@@ -4900,14 +4930,8 @@ class HiGlassComponent extends React.Component {
|
|
|
4900
4930
|
const evtToPublish = {
|
|
4901
4931
|
x: relPos[0],
|
|
4902
4932
|
y: relPos[1],
|
|
4903
|
-
relTrackX:
|
|
4904
|
-
|
|
4905
|
-
? relTrackPos[1]
|
|
4906
|
-
: relTrackPos[0],
|
|
4907
|
-
relTrackY:
|
|
4908
|
-
hoveredTrack && hoveredTrack.flipText
|
|
4909
|
-
? relTrackPos[0]
|
|
4910
|
-
: relTrackPos[1],
|
|
4933
|
+
relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
|
|
4934
|
+
relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4911
4935
|
track: hoveredTrack,
|
|
4912
4936
|
origEvt: nativeEvent,
|
|
4913
4937
|
sourceUid: this.uid,
|
|
@@ -4918,6 +4942,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4918
4942
|
this.apiPublish('wheel', evtToPublish);
|
|
4919
4943
|
}
|
|
4920
4944
|
|
|
4945
|
+
const isTargetCanvas = evt.target === this.canvasElement;
|
|
4921
4946
|
if (nativeEvent.forwarded || isTargetCanvas) {
|
|
4922
4947
|
evt.stopPropagation();
|
|
4923
4948
|
evt.preventDefault();
|
|
@@ -4941,6 +4966,24 @@ class HiGlassComponent extends React.Component {
|
|
|
4941
4966
|
}
|
|
4942
4967
|
}
|
|
4943
4968
|
|
|
4969
|
+
/** Convert a viewUid to a view name so that when we create
|
|
4970
|
+
* viewport projects, we can show which view they refer to.
|
|
4971
|
+
* The name is usually a single letter like 'A'
|
|
4972
|
+
* The view's name will also be visible in the header. */
|
|
4973
|
+
viewUidToName(viewUid) {
|
|
4974
|
+
const views = Object.keys(this.state.views);
|
|
4975
|
+
|
|
4976
|
+
for (let i = 0; i < views.length; i++) {
|
|
4977
|
+
if (views[i] === viewUid) {
|
|
4978
|
+
// Starting from A and then onwards. God help us if there's
|
|
4979
|
+
// more than 52 views
|
|
4980
|
+
return String.fromCharCode(65 + i);
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4984
|
+
return 'UU';
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4944
4987
|
render() {
|
|
4945
4988
|
this.tiledAreasDivs = {};
|
|
4946
4989
|
this.tiledAreas = <div className={styles['tiled-area']} />;
|
|
@@ -4988,24 +5031,32 @@ class HiGlassComponent extends React.Component {
|
|
|
4988
5031
|
this.tiledPlots[view.uid] = c;
|
|
4989
5032
|
}}
|
|
4990
5033
|
// Custom props
|
|
5034
|
+
addTrackExtent={
|
|
5035
|
+
this.state.addTrackPositionView === view.uid
|
|
5036
|
+
? this.state.addTrackExtent
|
|
5037
|
+
: null
|
|
5038
|
+
}
|
|
4991
5039
|
addTrackPosition={
|
|
4992
5040
|
this.state.addTrackPositionView === view.uid
|
|
4993
5041
|
? this.state.addTrackPosition
|
|
4994
5042
|
: null
|
|
4995
5043
|
}
|
|
4996
5044
|
addTrackPositionMenuPosition={addTrackPositionMenuPosition}
|
|
5045
|
+
apiPublish={this.apiPublish}
|
|
4997
5046
|
canvasElement={this.state.canvasElement}
|
|
4998
5047
|
chooseTrackHandler={
|
|
4999
5048
|
this.state.chooseTrackHandler
|
|
5000
|
-
? (trackId) =>
|
|
5049
|
+
? (trackId, evt) =>
|
|
5050
|
+
this.state.chooseTrackHandler(view.uid, trackId, evt)
|
|
5001
5051
|
: null
|
|
5002
5052
|
}
|
|
5003
5053
|
customDialog={this.state.customDialog}
|
|
5004
5054
|
closeCustomDialog={() => this.closeCustomDialog()}
|
|
5005
5055
|
chromInfoPath={view.chromInfoPath}
|
|
5006
5056
|
disableTrackMenu={this.isTrackMenuDisabled()}
|
|
5007
|
-
draggingHappening={this.state.draggingHappening
|
|
5057
|
+
draggingHappening={this.state.draggingHappening}
|
|
5008
5058
|
editable={this.isEditable()}
|
|
5059
|
+
genomePositionSearchBox={this.genomePositionSearchBoxes[view.uid]}
|
|
5009
5060
|
getLockGroupExtrema={(uid) =>
|
|
5010
5061
|
this.getLockGroupExtrema(view.uid, uid)
|
|
5011
5062
|
}
|
|
@@ -5036,20 +5087,30 @@ class HiGlassComponent extends React.Component {
|
|
|
5036
5087
|
}
|
|
5037
5088
|
onNoTrackAdded={this.handleNoTrackAdded.bind(this)}
|
|
5038
5089
|
onRangeSelection={this.rangeSelectionHandler.bind(this)}
|
|
5039
|
-
onResizeTrack={
|
|
5090
|
+
onResizeTrack={() => {
|
|
5091
|
+
this.adjustLayoutToTrackSizes(view);
|
|
5092
|
+
this.triggerViewChangeDb();
|
|
5093
|
+
}}
|
|
5040
5094
|
onScalesChanged={(x, y) => this.handleScalesChanged(view.uid, x, y)}
|
|
5041
5095
|
onTrackOptionsChanged={(trackId, options) =>
|
|
5042
5096
|
this.handleTrackOptionsChanged(view.uid, trackId, options)
|
|
5043
5097
|
}
|
|
5044
5098
|
onTrackPositionChosen={this.handleTrackPositionChosen.bind(this)}
|
|
5045
|
-
onTracksAdded={(newTracks, position, host) =>
|
|
5046
|
-
this.handleTracksAdded(
|
|
5099
|
+
onTracksAdded={(newTracks, position, extent, host) =>
|
|
5100
|
+
this.handleTracksAdded(
|
|
5101
|
+
view.uid,
|
|
5102
|
+
newTracks,
|
|
5103
|
+
position,
|
|
5104
|
+
extent,
|
|
5105
|
+
host,
|
|
5106
|
+
)
|
|
5047
5107
|
}
|
|
5048
5108
|
onUnlockValueScale={(uid) =>
|
|
5049
5109
|
this.handleUnlockValueScale(view.uid, uid)
|
|
5050
5110
|
}
|
|
5051
5111
|
onValueScaleChanged={(uid) => this.syncValueScales(view.uid, uid)}
|
|
5052
5112
|
overlays={view.overlays}
|
|
5113
|
+
overTrackChooser={this.state.overTrackChooser}
|
|
5053
5114
|
paddingBottom={this.viewPaddingBottom}
|
|
5054
5115
|
paddingLeft={this.viewPaddingLeft}
|
|
5055
5116
|
paddingRight={this.viewPaddingRight}
|
|
@@ -5069,6 +5130,9 @@ class HiGlassComponent extends React.Component {
|
|
|
5069
5130
|
setCentersFunction={(c) => {
|
|
5070
5131
|
this.setCenters[view.uid] = c;
|
|
5071
5132
|
}}
|
|
5133
|
+
setOverTrackChooser={(val) =>
|
|
5134
|
+
this.setState({ overTrackChooser: val })
|
|
5135
|
+
}
|
|
5072
5136
|
svgElement={this.state.svgElement}
|
|
5073
5137
|
tracks={view.tracks}
|
|
5074
5138
|
trackSourceServers={this.state.viewConfig.trackSourceServers}
|
|
@@ -5086,62 +5150,67 @@ class HiGlassComponent extends React.Component {
|
|
|
5086
5150
|
/>
|
|
5087
5151
|
);
|
|
5088
5152
|
|
|
5089
|
-
const
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
view.genomePositionSearchBox.autocompleteServer
|
|
5103
|
-
}
|
|
5104
|
-
chromInfoId={view.genomePositionSearchBox.chromInfoId}
|
|
5105
|
-
chromInfoPath={view.genomePositionSearchBox.chromInfoPath}
|
|
5106
|
-
chromInfoServer={view.genomePositionSearchBox.chromInfoServer}
|
|
5107
|
-
hideAvailableAssemblies={
|
|
5108
|
-
view.genomePositionSearchBox.hideAvailableAssemblies
|
|
5109
|
-
}
|
|
5110
|
-
isFocused={isFocused}
|
|
5111
|
-
// the chromInfoId is either specified in the viewconfig or guessed based on
|
|
5112
|
-
// the visible tracks (see createGenomePositionSearchBoxEntry)
|
|
5113
|
-
onFocus={onFocus}
|
|
5114
|
-
onGeneSearch={this.geneSearchHandler.bind(this)}
|
|
5115
|
-
onSelectedAssemblyChanged={(x, y, server) =>
|
|
5116
|
-
this.handleSelectedAssemblyChanged(view.uid, x, y, server)
|
|
5117
|
-
}
|
|
5118
|
-
registerViewportChangedListener={(listener) =>
|
|
5119
|
-
this.addScalesChangedListener(view.uid, view.uid, listener)
|
|
5120
|
-
}
|
|
5121
|
-
removeViewportChangedListener={() =>
|
|
5122
|
-
this.removeScalesChangedListener(view.uid, view.uid)
|
|
5123
|
-
}
|
|
5124
|
-
setCenters={(centerX, centerY, k, animateTime) =>
|
|
5125
|
-
this.setCenters[view.uid](
|
|
5126
|
-
centerX,
|
|
5127
|
-
centerY,
|
|
5128
|
-
k,
|
|
5129
|
-
false,
|
|
5130
|
-
animateTime,
|
|
5131
|
-
)
|
|
5132
|
-
}
|
|
5133
|
-
trackSourceServers={this.state.viewConfig.trackSourceServers}
|
|
5134
|
-
twoD={
|
|
5135
|
-
!!(
|
|
5136
|
-
view.tracks.left.length ||
|
|
5137
|
-
view.tracks.right.length ||
|
|
5138
|
-
view.tracks.center.length
|
|
5139
|
-
)
|
|
5140
|
-
}
|
|
5141
|
-
/>
|
|
5142
|
-
);
|
|
5143
|
-
};
|
|
5153
|
+
const looseTracks = positionedTracksToAllTracks(view.tracks);
|
|
5154
|
+
const annotationTracks = looseTracks.filter(
|
|
5155
|
+
(x) =>
|
|
5156
|
+
x.type === 'horizontal-gene-annotations' ||
|
|
5157
|
+
x.type === 'vertical-gene-annotations' ||
|
|
5158
|
+
x.type === 'gene-annotations',
|
|
5159
|
+
);
|
|
5160
|
+
const chromSizesTracks = looseTracks.filter(
|
|
5161
|
+
(x) =>
|
|
5162
|
+
x.type === 'horizontal-chromosome-labels' ||
|
|
5163
|
+
x.type === 'vertical-chromosome-labels' ||
|
|
5164
|
+
x.type === 'chromosome-labels',
|
|
5165
|
+
);
|
|
5144
5166
|
|
|
5167
|
+
const getGenomePositionSearchBox = (isFocused, onFocus) => (
|
|
5168
|
+
<GenomePositionSearchBox
|
|
5169
|
+
// Reserved props
|
|
5170
|
+
key={`gpsb${view.uid}`}
|
|
5171
|
+
ref={(c) => {
|
|
5172
|
+
this.genomePositionSearchBoxes[view.uid] = c;
|
|
5173
|
+
}}
|
|
5174
|
+
// Custom props
|
|
5175
|
+
autocompleteId={
|
|
5176
|
+
annotationTracks.length === 1
|
|
5177
|
+
? annotationTracks[0].tilesetUid
|
|
5178
|
+
: null
|
|
5179
|
+
}
|
|
5180
|
+
autocompleteServer={
|
|
5181
|
+
annotationTracks.length === 1 ? annotationTracks[0].server : null
|
|
5182
|
+
}
|
|
5183
|
+
chromInfoId={
|
|
5184
|
+
chromSizesTracks.length ? chromSizesTracks[0].tilesetUid : null
|
|
5185
|
+
}
|
|
5186
|
+
chromInfoServer={
|
|
5187
|
+
chromSizesTracks.length ? chromSizesTracks[0].server : null
|
|
5188
|
+
}
|
|
5189
|
+
isFocused={isFocused}
|
|
5190
|
+
// the chromInfoId is either specified in the viewconfig or guessed based on
|
|
5191
|
+
// the visible tracks (see createGenomePositionSearchBoxEntry)
|
|
5192
|
+
onFocus={onFocus}
|
|
5193
|
+
registerViewportChangedListener={(listener) =>
|
|
5194
|
+
this.addScalesChangedListener(view.uid, view.uid, listener)
|
|
5195
|
+
}
|
|
5196
|
+
removeViewportChangedListener={() =>
|
|
5197
|
+
this.removeScalesChangedListener(view.uid, view.uid)
|
|
5198
|
+
}
|
|
5199
|
+
setCenters={(centerX, centerY, k, animateTime) =>
|
|
5200
|
+
this.setCenters[view.uid](centerX, centerY, k, false, animateTime)
|
|
5201
|
+
}
|
|
5202
|
+
trackSourceServers={this.state.viewConfig.trackSourceServers}
|
|
5203
|
+
twoD={true}
|
|
5204
|
+
error={
|
|
5205
|
+
(chromSizesTracks.length === 0 &&
|
|
5206
|
+
'no chromosome track present') ||
|
|
5207
|
+
(chromSizesTracks.length >= 2 &&
|
|
5208
|
+
'multiple chromosome tracks present') ||
|
|
5209
|
+
(annotationTracks.length >= 2 &&
|
|
5210
|
+
'multiple annotation tracks present')
|
|
5211
|
+
}
|
|
5212
|
+
/>
|
|
5213
|
+
);
|
|
5145
5214
|
const multiTrackHeader =
|
|
5146
5215
|
this.isEditable() &&
|
|
5147
5216
|
!this.isViewHeaderDisabled() &&
|
|
@@ -5151,10 +5220,7 @@ class HiGlassComponent extends React.Component {
|
|
|
5151
5220
|
this.viewHeaders[view.uid] = c;
|
|
5152
5221
|
}}
|
|
5153
5222
|
getGenomePositionSearchBox={getGenomePositionSearchBox}
|
|
5154
|
-
isGenomePositionSearchBoxVisible={
|
|
5155
|
-
view.genomePositionSearchBox &&
|
|
5156
|
-
view.genomePositionSearchBox.visible
|
|
5157
|
-
}
|
|
5223
|
+
isGenomePositionSearchBoxVisible={true}
|
|
5158
5224
|
mouseTool={this.state.mouseTool}
|
|
5159
5225
|
onAddView={() => this.handleAddView(view)}
|
|
5160
5226
|
onClearView={() => this.handleClearView(view.uid)}
|
|
@@ -5194,8 +5260,8 @@ class HiGlassComponent extends React.Component {
|
|
|
5194
5260
|
onTogglePositionSearchBox={this.handleTogglePositionSearchBox.bind(
|
|
5195
5261
|
this,
|
|
5196
5262
|
)}
|
|
5197
|
-
onTrackPositionChosen={(position) =>
|
|
5198
|
-
this.handleTrackPositionChosen(view.uid, position)
|
|
5263
|
+
onTrackPositionChosen={(position, extent) =>
|
|
5264
|
+
this.handleTrackPositionChosen(view.uid, position, extent)
|
|
5199
5265
|
}
|
|
5200
5266
|
onUnlockLocation={(uid) =>
|
|
5201
5267
|
this.handleUnlock(uid, this.locationLocks)
|
|
@@ -5229,16 +5295,17 @@ class HiGlassComponent extends React.Component {
|
|
|
5229
5295
|
) : null;
|
|
5230
5296
|
|
|
5231
5297
|
return (
|
|
5232
|
-
<div
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5298
|
+
<div key={view.uid}>
|
|
5299
|
+
<div
|
|
5300
|
+
ref={(c) => {
|
|
5301
|
+
this.tiledAreasDivs[view.uid] = c;
|
|
5302
|
+
}}
|
|
5303
|
+
className={styles['tiled-area']}
|
|
5304
|
+
>
|
|
5305
|
+
{multiTrackHeader}
|
|
5306
|
+
{tiledPlot}
|
|
5307
|
+
{overlay}
|
|
5308
|
+
</div>
|
|
5242
5309
|
</div>
|
|
5243
5310
|
);
|
|
5244
5311
|
});
|
|
@@ -5307,14 +5374,13 @@ class HiGlassComponent extends React.Component {
|
|
|
5307
5374
|
return (
|
|
5308
5375
|
<div
|
|
5309
5376
|
key={this.uid}
|
|
5310
|
-
ref={
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
this.
|
|
5317
|
-
this.props.options.sizeMode === SIZE_MODE_SCROLL,
|
|
5377
|
+
ref={this.topDivRef}
|
|
5378
|
+
className={clsx('higlass', styles.higlass, {
|
|
5379
|
+
[styles['higlass-dark-theme']]: this.theme === THEME_DARK,
|
|
5380
|
+
[styles['higlass-container-overflow']]:
|
|
5381
|
+
this.sizeMode === SIZE_MODE_OVERFLOW ||
|
|
5382
|
+
this.sizeMode === SIZE_MODE_BOUNDED_OVERFLOW ||
|
|
5383
|
+
this.sizeMode === SIZE_MODE_SCROLL,
|
|
5318
5384
|
})}
|
|
5319
5385
|
onMouseLeave={this.onMouseLeaveHandlerBound}
|
|
5320
5386
|
onMouseMove={this.mouseMoveHandlerBound}
|
|
@@ -5322,55 +5388,60 @@ class HiGlassComponent extends React.Component {
|
|
|
5322
5388
|
<PubSubProvider value={this.pubSub}>
|
|
5323
5389
|
<ModalProvider value={this.modal}>
|
|
5324
5390
|
<ThemeProvider value={this.theme}>
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
key={this.uid}
|
|
5328
|
-
ref={(c) => {
|
|
5329
|
-
this.canvasElement = c;
|
|
5330
|
-
}}
|
|
5331
|
-
onClick={this.canvasClickHandlerBound}
|
|
5332
|
-
className={styles['higlass-canvas']}
|
|
5333
|
-
/>
|
|
5334
|
-
<div
|
|
5335
|
-
ref={(c) => {
|
|
5336
|
-
this.scrollContainer = c;
|
|
5337
|
-
}}
|
|
5338
|
-
className={clsx('higlass-scroll-container', {
|
|
5339
|
-
'higlass-scroll-container-overflow':
|
|
5340
|
-
this.props.options.sizeMode === SIZE_MODE_OVERFLOW,
|
|
5341
|
-
'higlass-scroll-container-scroll':
|
|
5342
|
-
this.props.options.sizeMode === SIZE_MODE_SCROLL,
|
|
5343
|
-
})}
|
|
5344
|
-
onScroll={this.onScrollHandlerBound}
|
|
5391
|
+
<HiGlassComponentContext.Provider
|
|
5392
|
+
value={{ viewUidToName: this.viewUidToNameBound }}
|
|
5345
5393
|
>
|
|
5394
|
+
{this.state.modal}
|
|
5395
|
+
<canvas
|
|
5396
|
+
key={this.uid}
|
|
5397
|
+
ref={(c) => {
|
|
5398
|
+
this.canvasElement = c;
|
|
5399
|
+
}}
|
|
5400
|
+
onClick={this.canvasClickHandlerBound}
|
|
5401
|
+
className={styles['higlass-canvas']}
|
|
5402
|
+
/>
|
|
5346
5403
|
<div
|
|
5347
5404
|
ref={(c) => {
|
|
5348
|
-
this.
|
|
5405
|
+
this.scrollContainer = c;
|
|
5349
5406
|
}}
|
|
5350
|
-
className={clsx(
|
|
5351
|
-
'higlass-
|
|
5352
|
-
|
|
5353
|
-
|
|
5407
|
+
className={clsx('higlass-scroll-container', {
|
|
5408
|
+
[styles['higlass-scroll-container-overflow']]:
|
|
5409
|
+
this.sizeMode === SIZE_MODE_OVERFLOW ||
|
|
5410
|
+
this.sizeMode === SIZE_MODE_BOUNDED_OVERFLOW,
|
|
5411
|
+
[styles['higlass-scroll-container-scroll']]:
|
|
5412
|
+
this.sizeMode === SIZE_MODE_SCROLL,
|
|
5413
|
+
})}
|
|
5414
|
+
onScroll={this.onScrollHandlerBound}
|
|
5354
5415
|
>
|
|
5355
|
-
|
|
5416
|
+
<div
|
|
5417
|
+
ref={(c) => {
|
|
5418
|
+
this.divDrawingSurface = c;
|
|
5419
|
+
}}
|
|
5420
|
+
className={clsx(
|
|
5421
|
+
'higlass-drawing-surface',
|
|
5422
|
+
styles['higlass-drawing-surface'],
|
|
5423
|
+
)}
|
|
5424
|
+
>
|
|
5425
|
+
{gridLayout}
|
|
5426
|
+
</div>
|
|
5427
|
+
<svg
|
|
5428
|
+
ref={(c) => {
|
|
5429
|
+
this.svgElement = c;
|
|
5430
|
+
}}
|
|
5431
|
+
style={{
|
|
5432
|
+
// inline the styles so they aren't overriden by other css
|
|
5433
|
+
// on the web page
|
|
5434
|
+
position: 'absolute',
|
|
5435
|
+
width: '100%',
|
|
5436
|
+
height: '100%',
|
|
5437
|
+
left: 0,
|
|
5438
|
+
top: 0,
|
|
5439
|
+
pointerEvents: 'none',
|
|
5440
|
+
}}
|
|
5441
|
+
className={styles['higlass-svg']}
|
|
5442
|
+
/>
|
|
5356
5443
|
</div>
|
|
5357
|
-
|
|
5358
|
-
ref={(c) => {
|
|
5359
|
-
this.svgElement = c;
|
|
5360
|
-
}}
|
|
5361
|
-
className={styles['higlass-svg']}
|
|
5362
|
-
style={{
|
|
5363
|
-
// inline the styles so they aren't overriden by other css
|
|
5364
|
-
// on the web page
|
|
5365
|
-
position: 'absolute',
|
|
5366
|
-
width: '100%',
|
|
5367
|
-
height: '100%',
|
|
5368
|
-
left: 0,
|
|
5369
|
-
top: 0,
|
|
5370
|
-
pointerEvents: 'none',
|
|
5371
|
-
}}
|
|
5372
|
-
/>
|
|
5373
|
-
</div>
|
|
5444
|
+
</HiGlassComponentContext.Provider>
|
|
5374
5445
|
</ThemeProvider>
|
|
5375
5446
|
</ModalProvider>
|
|
5376
5447
|
</PubSubProvider>
|