@apollo-annotation/jbrowse-plugin-apollo 0.3.7 → 0.3.8
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/dist/index.esm.js +2371 -1642
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +2384 -1641
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +4387 -2952
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/package.json +15 -15
- package/src/ApolloInternetAccount/model.ts +48 -13
- package/src/BackendDrivers/CollaborationServerDriver.ts +23 -2
- package/src/ChangeManager.ts +33 -13
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +33 -31
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +60 -72
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +441 -180
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
- package/src/LinearApolloDisplay/stateModel/base.ts +34 -43
- package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +32 -261
- package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -343
- package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
- package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
- package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
- package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +481 -0
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +95 -38
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +221 -201
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -4
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +73 -97
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +49 -61
- package/src/TabularEditor/HybridGrid/Feature.tsx +16 -14
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
- package/src/components/AddAssembly.tsx +1 -1
- package/src/components/AddAssemblyAliases.tsx +1 -1
- package/src/components/AddChildFeature.tsx +5 -2
- package/src/components/AddFeature.tsx +9 -3
- package/src/components/AddRefSeqAliases.tsx +9 -9
- package/src/components/CopyFeature.tsx +3 -1
- package/src/components/CreateApolloAnnotation.tsx +1 -0
- package/src/components/DeleteAssembly.tsx +1 -1
- package/src/components/EditZoomThresholdDialog.tsx +69 -0
- package/src/components/FilterFeatures.tsx +7 -7
- package/src/components/FilterTranscripts.tsx +6 -6
- package/src/components/ImportFeatures.tsx +1 -1
- package/src/components/ManageChecks.tsx +1 -1
- package/src/components/MergeTranscripts.tsx +12 -15
- package/src/components/OntologyTermMultiSelect.tsx +11 -11
- package/src/components/OpenLocalFile.tsx +11 -7
- package/src/components/ViewCheckResults.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/config.ts +6 -0
- package/src/index.ts +42 -105
- package/src/makeDisplayComponent.tsx +0 -1
- package/src/menus/index.ts +1 -0
- package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +56 -47
- package/src/menus/topLevelMenuAdmin.ts +154 -0
- package/src/session/session.ts +162 -116
- package/src/util/annotationFeatureUtils.ts +15 -21
- package/src/util/displayUtils.ts +149 -0
- package/src/util/glyphUtils.ts +152 -0
- package/src/util/mouseEventsUtils.ts +32 -0
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
2
2
|
import { type MenuItem } from '@jbrowse/core/ui'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
type MousePositionWithFeatureAndGlyph,
|
|
7
|
-
} from '../stateModel/mouseEvents'
|
|
4
|
+
import { type MousePositionWithFeature } from '../../util'
|
|
5
|
+
import { type LinearApolloSixFrameDisplayMouseEvents } from '../stateModel/mouseEvents'
|
|
8
6
|
import { type LinearApolloSixFrameDisplayRendering } from '../stateModel/rendering'
|
|
9
7
|
import { type CanvasMouseEvent } from '../types'
|
|
10
8
|
|
|
@@ -30,25 +28,25 @@ export interface Glyph {
|
|
|
30
28
|
|
|
31
29
|
onMouseDown(
|
|
32
30
|
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
33
|
-
currentMousePosition:
|
|
31
|
+
currentMousePosition: MousePositionWithFeature,
|
|
34
32
|
event: CanvasMouseEvent,
|
|
35
33
|
): void
|
|
36
34
|
|
|
37
35
|
onMouseMove(
|
|
38
36
|
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
39
|
-
currentMousePosition:
|
|
37
|
+
currentMousePosition: MousePositionWithFeature,
|
|
40
38
|
event: CanvasMouseEvent,
|
|
41
39
|
): void
|
|
42
40
|
|
|
43
41
|
onMouseLeave(
|
|
44
42
|
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
45
|
-
currentMousePosition:
|
|
43
|
+
currentMousePosition: MousePositionWithFeature,
|
|
46
44
|
event: CanvasMouseEvent,
|
|
47
45
|
): void
|
|
48
46
|
|
|
49
47
|
onMouseUp(
|
|
50
48
|
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
51
|
-
currentMousePosition:
|
|
49
|
+
currentMousePosition: MousePositionWithFeature,
|
|
52
50
|
event: CanvasMouseEvent,
|
|
53
51
|
): void
|
|
54
52
|
|
|
@@ -57,7 +55,13 @@ export interface Glyph {
|
|
|
57
55
|
context: CanvasRenderingContext2D,
|
|
58
56
|
): void
|
|
59
57
|
|
|
58
|
+
getContextMenuItemsForFeature(
|
|
59
|
+
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
60
|
+
sourceFeature: AnnotationFeature,
|
|
61
|
+
): MenuItem[]
|
|
62
|
+
|
|
60
63
|
getContextMenuItems(
|
|
61
64
|
display: LinearApolloSixFrameDisplayMouseEvents,
|
|
65
|
+
currentMousePosition: MousePositionWithFeature,
|
|
62
66
|
): MenuItem[]
|
|
63
67
|
}
|
|
@@ -22,8 +22,9 @@ import { addDisposer, cast, getRoot, getSnapshot, types } from 'mobx-state-tree'
|
|
|
22
22
|
|
|
23
23
|
import { type ApolloInternetAccountModel } from '../../ApolloInternetAccount/model'
|
|
24
24
|
import { FilterFeatures } from '../../components/FilterFeatures'
|
|
25
|
-
import { type ApolloSessionModel } from '../../session'
|
|
25
|
+
import { type ApolloSessionModel, type HoveredFeature } from '../../session'
|
|
26
26
|
import { type ApolloRootModel } from '../../types'
|
|
27
|
+
import { EditZoomThresholdDialog } from '../../util/displayUtils'
|
|
27
28
|
|
|
28
29
|
const minDisplayHeight = 20
|
|
29
30
|
|
|
@@ -38,6 +39,8 @@ export function baseModelFactory(
|
|
|
38
39
|
graphical: true,
|
|
39
40
|
table: false,
|
|
40
41
|
showFeatureLabels: true,
|
|
42
|
+
showCheckResults: true,
|
|
43
|
+
zoomThreshold: 200,
|
|
41
44
|
heightPreConfig: types.maybe(
|
|
42
45
|
types.refinement(
|
|
43
46
|
'displayHeight',
|
|
@@ -74,10 +77,13 @@ export function baseModelFactory(
|
|
|
74
77
|
return 500
|
|
75
78
|
}
|
|
76
79
|
if (self.graphical) {
|
|
77
|
-
return 200
|
|
80
|
+
return self.showFeatureLabels ? 400 : 200
|
|
78
81
|
}
|
|
79
82
|
return 300
|
|
80
83
|
},
|
|
84
|
+
get zoomThresholdSetting() {
|
|
85
|
+
return self.zoomThreshold ?? getConf(self, 'zoomThreshold')
|
|
86
|
+
},
|
|
81
87
|
}))
|
|
82
88
|
.views((self) => ({
|
|
83
89
|
get rendererTypeName() {
|
|
@@ -98,7 +104,7 @@ export function baseModelFactory(
|
|
|
98
104
|
return regions
|
|
99
105
|
},
|
|
100
106
|
regionCannotBeRendered(/* region */) {
|
|
101
|
-
if (self.lgv && self.lgv.bpPerPx >=
|
|
107
|
+
if (self.lgv && self.lgv.bpPerPx >= self.zoomThreshold) {
|
|
102
108
|
return 'Zoom in to see annotations'
|
|
103
109
|
}
|
|
104
110
|
return
|
|
@@ -140,6 +146,10 @@ export function baseModelFactory(
|
|
|
140
146
|
return (self.session as unknown as ApolloSessionModel)
|
|
141
147
|
.apolloSelectedFeature
|
|
142
148
|
},
|
|
149
|
+
get hoveredFeature(): HoveredFeature | undefined {
|
|
150
|
+
return (self.session as unknown as ApolloSessionModel)
|
|
151
|
+
.apolloHoveredFeature
|
|
152
|
+
},
|
|
143
153
|
}))
|
|
144
154
|
.actions((self) => ({
|
|
145
155
|
setScrollTop(scrollTop: number) {
|
|
@@ -169,15 +179,21 @@ export function baseModelFactory(
|
|
|
169
179
|
toggleShowFeatureLabels() {
|
|
170
180
|
self.showFeatureLabels = !self.showFeatureLabels
|
|
171
181
|
},
|
|
182
|
+
toggleShowCheckResults() {
|
|
183
|
+
self.showCheckResults = !self.showCheckResults
|
|
184
|
+
},
|
|
172
185
|
updateFilteredFeatureTypes(types: string[]) {
|
|
173
186
|
self.filteredFeatureTypes = cast(types)
|
|
174
187
|
},
|
|
188
|
+
setZoomThresholdSetting({ zoomThreshold }: { zoomThreshold: number }) {
|
|
189
|
+
self.zoomThreshold = zoomThreshold
|
|
190
|
+
},
|
|
175
191
|
}))
|
|
176
192
|
.views((self) => {
|
|
177
193
|
const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self
|
|
178
194
|
return {
|
|
179
195
|
trackMenuItems() {
|
|
180
|
-
const { graphical, table, showFeatureLabels } = self
|
|
196
|
+
const { graphical, table, showFeatureLabels, showCheckResults } = self
|
|
181
197
|
return [
|
|
182
198
|
...superTrackMenuItems(),
|
|
183
199
|
{
|
|
@@ -216,6 +232,23 @@ export function baseModelFactory(
|
|
|
216
232
|
self.toggleShowFeatureLabels()
|
|
217
233
|
},
|
|
218
234
|
},
|
|
235
|
+
{
|
|
236
|
+
label: 'Check Results',
|
|
237
|
+
type: 'checkbox',
|
|
238
|
+
checked: showCheckResults,
|
|
239
|
+
onClick: () => {
|
|
240
|
+
self.toggleShowCheckResults()
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
label: 'Change zoom threshold',
|
|
245
|
+
onClick: () => {
|
|
246
|
+
getSession(self).queueDialog((handleClose) => [
|
|
247
|
+
EditZoomThresholdDialog,
|
|
248
|
+
{ model: self, handleClose },
|
|
249
|
+
])
|
|
250
|
+
},
|
|
251
|
+
},
|
|
219
252
|
],
|
|
220
253
|
},
|
|
221
254
|
{
|
|
@@ -249,6 +282,11 @@ export function baseModelFactory(
|
|
|
249
282
|
self.session as unknown as ApolloSessionModel
|
|
250
283
|
).apolloSetSelectedFeature(feature)
|
|
251
284
|
},
|
|
285
|
+
setHoveredFeature(hoveredFeature?: HoveredFeature) {
|
|
286
|
+
;(
|
|
287
|
+
self.session as unknown as ApolloSessionModel
|
|
288
|
+
).apolloSetHoveredFeature(hoveredFeature)
|
|
289
|
+
},
|
|
252
290
|
showFeatureDetailsWidget(
|
|
253
291
|
feature: AnnotationFeature,
|
|
254
292
|
customWidgetNameAndId?: [string, string],
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
type AnnotationFeature,
|
|
5
|
-
type TranscriptPartCoding,
|
|
6
|
-
} from '@apollo-annotation/mst'
|
|
3
|
+
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
7
4
|
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
8
5
|
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
9
6
|
import {
|
|
@@ -22,7 +19,6 @@ import { baseModelFactory } from './base'
|
|
|
22
19
|
export interface LayoutRow {
|
|
23
20
|
rowNum: number
|
|
24
21
|
feature: AnnotationFeature
|
|
25
|
-
cds: TranscriptPartCoding | null
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
export function layoutsModelFactory(
|
|
@@ -136,7 +132,7 @@ export function layoutsModelFactory(
|
|
|
136
132
|
featureLayout.set(rowNum, [])
|
|
137
133
|
}
|
|
138
134
|
const layoutRow = featureLayout.get(rowNum)
|
|
139
|
-
layoutRow?.push({ rowNum, feature
|
|
135
|
+
layoutRow?.push({ rowNum, feature })
|
|
140
136
|
const { children } = feature
|
|
141
137
|
if (!children) {
|
|
142
138
|
continue
|
|
@@ -158,7 +154,7 @@ export function layoutsModelFactory(
|
|
|
158
154
|
? self.geneTrackRowNums[0]
|
|
159
155
|
: self.geneTrackRowNums[1]
|
|
160
156
|
const layoutRow = featureLayout.get(rowNum)
|
|
161
|
-
layoutRow?.push({ rowNum, feature: exon
|
|
157
|
+
layoutRow?.push({ rowNum, feature: exon })
|
|
162
158
|
}
|
|
163
159
|
}
|
|
164
160
|
for (const cdsRow of cdsLocations) {
|
|
@@ -176,7 +172,7 @@ export function layoutsModelFactory(
|
|
|
176
172
|
featureLayout.set(rowNum, [])
|
|
177
173
|
}
|
|
178
174
|
const layoutRow = featureLayout.get(rowNum)
|
|
179
|
-
layoutRow?.push({ rowNum, feature: child
|
|
175
|
+
layoutRow?.push({ rowNum, feature: child })
|
|
180
176
|
}
|
|
181
177
|
}
|
|
182
178
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AnnotationFeature,
|
|
3
|
-
type TranscriptPartCoding,
|
|
4
|
-
} from '@apollo-annotation/mst'
|
|
1
|
+
import { type AnnotationFeature } from '@apollo-annotation/mst'
|
|
5
2
|
import {
|
|
6
3
|
LocationEndChange,
|
|
7
4
|
LocationStartChange,
|
|
@@ -9,56 +6,23 @@ import {
|
|
|
9
6
|
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
10
7
|
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
11
8
|
import { type MenuItem } from '@jbrowse/core/ui'
|
|
12
|
-
import {
|
|
9
|
+
import { getFrame } from '@jbrowse/core/util'
|
|
13
10
|
import { autorun } from 'mobx'
|
|
14
11
|
import { type Instance, addDisposer, cast } from 'mobx-state-tree'
|
|
15
12
|
import { type CSSProperties } from 'react'
|
|
16
13
|
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
import {
|
|
15
|
+
type Edge,
|
|
16
|
+
type MousePosition,
|
|
17
|
+
type MousePositionWithFeature,
|
|
18
|
+
getMousePosition,
|
|
19
|
+
getPropagatedLocationChanges,
|
|
20
|
+
isMousePositionWithFeature,
|
|
21
|
+
} from '../../util'
|
|
20
22
|
import { type CanvasMouseEvent } from '../types'
|
|
21
23
|
|
|
22
24
|
import { renderingModelFactory } from './rendering'
|
|
23
25
|
|
|
24
|
-
export interface FeatureAndGlyphUnderMouse {
|
|
25
|
-
cds: TranscriptPartCoding | null
|
|
26
|
-
feature: AnnotationFeature
|
|
27
|
-
topLevelFeature: AnnotationFeature
|
|
28
|
-
glyph: Glyph
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** extended information about the position of the mouse on the canvas, including the refName, bp, and displayedRegion number */
|
|
32
|
-
export interface MousePosition {
|
|
33
|
-
x: number
|
|
34
|
-
y: number
|
|
35
|
-
refName: string
|
|
36
|
-
bp: number
|
|
37
|
-
regionNumber: number
|
|
38
|
-
featureAndGlyphUnderMouse?: FeatureAndGlyphUnderMouse
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export type MousePositionWithFeatureAndGlyph = Required<MousePosition>
|
|
42
|
-
|
|
43
|
-
export function isMousePositionWithFeatureAndGlyph(
|
|
44
|
-
mousePosition: MousePosition,
|
|
45
|
-
): mousePosition is MousePositionWithFeatureAndGlyph {
|
|
46
|
-
return 'featureAndGlyphUnderMouse' in mousePosition
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function getMousePosition(
|
|
50
|
-
event: CanvasMouseEvent,
|
|
51
|
-
lgv: LinearGenomeViewModel,
|
|
52
|
-
): MousePosition {
|
|
53
|
-
const canvas = event.currentTarget
|
|
54
|
-
const { clientX, clientY } = event
|
|
55
|
-
const { left, top } = canvas.getBoundingClientRect()
|
|
56
|
-
const x = clientX - left
|
|
57
|
-
const y = clientY - top
|
|
58
|
-
const { coord: bp, index: regionNumber, refName } = lgv.pxToBp(x)
|
|
59
|
-
return { x, y, refName, bp, regionNumber }
|
|
60
|
-
}
|
|
61
|
-
|
|
62
26
|
export function mouseEventsModelIntermediateFactory(
|
|
63
27
|
pluginManager: PluginManager,
|
|
64
28
|
configSchema: AnyConfigurationSchemaType,
|
|
@@ -80,10 +44,9 @@ export function mouseEventsModelIntermediateFactory(
|
|
|
80
44
|
shrinkParent: boolean
|
|
81
45
|
} | null,
|
|
82
46
|
cursor: undefined as CSSProperties['cursor'] | undefined,
|
|
83
|
-
apolloHover: undefined as FeatureAndGlyphUnderMouse | undefined,
|
|
84
47
|
}))
|
|
85
48
|
.views((self) => ({
|
|
86
|
-
getMousePosition(event:
|
|
49
|
+
getMousePosition(event: React.MouseEvent): MousePosition {
|
|
87
50
|
const mousePosition = getMousePosition(event, self.lgv)
|
|
88
51
|
const { bp, regionNumber, y } = mousePosition
|
|
89
52
|
const row = Math.floor(y / self.apolloRowHeight) + 1
|
|
@@ -92,6 +55,11 @@ export function mouseEventsModelIntermediateFactory(
|
|
|
92
55
|
if (!layoutRow) {
|
|
93
56
|
return mousePosition
|
|
94
57
|
}
|
|
58
|
+
const { featureTypeOntology } =
|
|
59
|
+
self.session.apolloDataStore.ontologyManager
|
|
60
|
+
if (!featureTypeOntology) {
|
|
61
|
+
throw new Error('featureTypeOntology is undefined')
|
|
62
|
+
}
|
|
95
63
|
let foundFeature
|
|
96
64
|
if (self.geneTrackRowNums.includes(row)) {
|
|
97
65
|
foundFeature = layoutRow.find(
|
|
@@ -107,25 +75,44 @@ export function mouseEventsModelIntermediateFactory(
|
|
|
107
75
|
}
|
|
108
76
|
} else {
|
|
109
77
|
foundFeature = layoutRow.find((f) => {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
(featureID === undefined ||
|
|
116
|
-
!self.filteredTranscripts.includes(featureID))
|
|
78
|
+
const { feature } = f
|
|
79
|
+
const featureID = feature.attributes.get('gff_id')?.toString()
|
|
80
|
+
const isTranscript = featureTypeOntology.isTypeOf(
|
|
81
|
+
feature.type,
|
|
82
|
+
'transcript',
|
|
117
83
|
)
|
|
84
|
+
if (!isTranscript) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
for (const loc of feature.cdsLocations) {
|
|
88
|
+
for (const cds of loc) {
|
|
89
|
+
let rowNum: number = getFrame(
|
|
90
|
+
cds.min,
|
|
91
|
+
cds.max,
|
|
92
|
+
feature.strand ?? 1,
|
|
93
|
+
cds.phase,
|
|
94
|
+
)
|
|
95
|
+
rowNum = self.featureLabelSpacer(
|
|
96
|
+
rowNum < 0 ? -1 * rowNum + 5 : rowNum,
|
|
97
|
+
)
|
|
98
|
+
if (row === rowNum && bp >= cds.min && bp <= cds.max) {
|
|
99
|
+
return (
|
|
100
|
+
featureID === undefined ||
|
|
101
|
+
!self.filteredTranscripts.includes(featureID)
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return false
|
|
118
107
|
})
|
|
119
108
|
}
|
|
120
109
|
if (!foundFeature) {
|
|
121
110
|
return mousePosition
|
|
122
111
|
}
|
|
123
|
-
const { feature
|
|
124
|
-
const { topLevelFeature } = feature
|
|
125
|
-
const glyph = self.getGlyph(feature)
|
|
112
|
+
const { feature } = foundFeature
|
|
126
113
|
return {
|
|
127
114
|
...mousePosition,
|
|
128
|
-
|
|
115
|
+
feature,
|
|
129
116
|
}
|
|
130
117
|
},
|
|
131
118
|
}))
|
|
@@ -144,9 +131,6 @@ export function mouseEventsModelIntermediateFactory(
|
|
|
144
131
|
},
|
|
145
132
|
}))
|
|
146
133
|
.actions((self) => ({
|
|
147
|
-
setApolloHover(n?: (typeof self)['apolloHover']) {
|
|
148
|
-
self.apolloHover = n
|
|
149
|
-
},
|
|
150
134
|
setCursor(cursor?: CSSProperties['cursor']) {
|
|
151
135
|
if (self.cursor !== cursor) {
|
|
152
136
|
self.cursor = cursor
|
|
@@ -172,21 +156,25 @@ export function mouseEventsModelFactory(
|
|
|
172
156
|
mouseEventsModelIntermediateFactory(pluginManager, configSchema)
|
|
173
157
|
|
|
174
158
|
return LinearApolloSixFrameDisplayMouseEvents.views((self) => ({
|
|
175
|
-
contextMenuItems(
|
|
176
|
-
const {
|
|
177
|
-
if (!
|
|
159
|
+
contextMenuItems(event: React.MouseEvent<HTMLDivElement>): MenuItem[] {
|
|
160
|
+
const { hoveredFeature } = self
|
|
161
|
+
if (!hoveredFeature) {
|
|
178
162
|
return []
|
|
179
163
|
}
|
|
180
|
-
const
|
|
164
|
+
const mousePosition = self.getMousePosition(event)
|
|
165
|
+
const { topLevelFeature } = hoveredFeature.feature
|
|
181
166
|
const glyph = self.getGlyph(topLevelFeature)
|
|
182
|
-
|
|
167
|
+
if (isMousePositionWithFeature(mousePosition)) {
|
|
168
|
+
return glyph.getContextMenuItems(self, mousePosition)
|
|
169
|
+
}
|
|
170
|
+
return []
|
|
183
171
|
},
|
|
184
172
|
}))
|
|
185
173
|
.actions((self) => ({
|
|
186
174
|
// explicitly pass in a feature in case it's not the same as the one in
|
|
187
175
|
// mousePosition (e.g. if features are drawn overlapping).
|
|
188
176
|
startDrag(
|
|
189
|
-
mousePosition:
|
|
177
|
+
mousePosition: MousePositionWithFeature,
|
|
190
178
|
feature: AnnotationFeature,
|
|
191
179
|
edge: Edge,
|
|
192
180
|
shrinkParent = false,
|
|
@@ -251,12 +239,9 @@ export function mouseEventsModelFactory(
|
|
|
251
239
|
.actions((self) => ({
|
|
252
240
|
onMouseDown(event: CanvasMouseEvent) {
|
|
253
241
|
const mousePosition = self.getMousePosition(event)
|
|
254
|
-
if (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
mousePosition,
|
|
258
|
-
event,
|
|
259
|
-
)
|
|
242
|
+
if (isMousePositionWithFeature(mousePosition)) {
|
|
243
|
+
const glyph = self.getGlyph(mousePosition.feature)
|
|
244
|
+
glyph.onMouseDown(self, mousePosition, event)
|
|
260
245
|
}
|
|
261
246
|
},
|
|
262
247
|
onMouseMove(event: CanvasMouseEvent) {
|
|
@@ -266,38 +251,29 @@ export function mouseEventsModelFactory(
|
|
|
266
251
|
self.continueDrag(mousePosition, event)
|
|
267
252
|
return
|
|
268
253
|
}
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
mousePosition,
|
|
273
|
-
event,
|
|
274
|
-
)
|
|
254
|
+
if (isMousePositionWithFeature(mousePosition)) {
|
|
255
|
+
const glyph = self.getGlyph(mousePosition.feature)
|
|
256
|
+
glyph.onMouseMove(self, mousePosition, event)
|
|
275
257
|
} else {
|
|
276
|
-
self.
|
|
258
|
+
self.setHoveredFeature()
|
|
277
259
|
self.setCursor()
|
|
278
260
|
}
|
|
279
261
|
},
|
|
280
262
|
onMouseLeave(event: CanvasMouseEvent) {
|
|
281
263
|
self.setDragging()
|
|
282
|
-
self.
|
|
264
|
+
self.setHoveredFeature()
|
|
283
265
|
|
|
284
266
|
const mousePosition = self.getMousePosition(event)
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
mousePosition,
|
|
289
|
-
event,
|
|
290
|
-
)
|
|
267
|
+
if (isMousePositionWithFeature(mousePosition)) {
|
|
268
|
+
const glyph = self.getGlyph(mousePosition.feature)
|
|
269
|
+
glyph.onMouseLeave(self, mousePosition, event)
|
|
291
270
|
}
|
|
292
271
|
},
|
|
293
272
|
onMouseUp(event: CanvasMouseEvent) {
|
|
294
273
|
const mousePosition = self.getMousePosition(event)
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
mousePosition,
|
|
299
|
-
event,
|
|
300
|
-
)
|
|
274
|
+
if (isMousePositionWithFeature(mousePosition)) {
|
|
275
|
+
const glyph = self.getGlyph(mousePosition.feature)
|
|
276
|
+
glyph.onMouseUp(self, mousePosition, event)
|
|
301
277
|
} else {
|
|
302
278
|
self.setSelectedFeature()
|
|
303
279
|
}
|
|
@@ -329,11 +305,11 @@ export function mouseEventsModelFactory(
|
|
|
329
305
|
self.featuresHeight,
|
|
330
306
|
)
|
|
331
307
|
|
|
332
|
-
const { apolloDragging,
|
|
333
|
-
if (!
|
|
308
|
+
const { apolloDragging, hoveredFeature } = self
|
|
309
|
+
if (!hoveredFeature) {
|
|
334
310
|
return
|
|
335
311
|
}
|
|
336
|
-
const
|
|
312
|
+
const glyph = self.getGlyph(hoveredFeature.feature)
|
|
337
313
|
|
|
338
314
|
// draw mouseover hovers
|
|
339
315
|
glyph.drawHover(self, ctx)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
3
3
|
import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
|
|
4
4
|
import { doesIntersect2 } from '@jbrowse/core/util'
|
|
5
|
-
import { type Theme } from '@mui/material'
|
|
5
|
+
import { type Theme, createTheme } from '@mui/material'
|
|
6
6
|
import { autorun } from 'mobx'
|
|
7
7
|
import { type Instance, addDisposer, types } from 'mobx-state-tree'
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ import { type ApolloSessionModel } from '../../session'
|
|
|
10
10
|
|
|
11
11
|
import { layoutsModelFactory } from './layouts'
|
|
12
12
|
|
|
13
|
-
export function
|
|
13
|
+
export function renderingModelFactory(
|
|
14
14
|
pluginManager: PluginManager,
|
|
15
15
|
configSchema: AnyConfigurationSchemaType,
|
|
16
16
|
) {
|
|
@@ -23,11 +23,10 @@ export function renderingModelIntermediateFactory(
|
|
|
23
23
|
'LinearApolloSixFrameDisplayRendering',
|
|
24
24
|
)
|
|
25
25
|
.props({
|
|
26
|
-
sequenceRowHeight: 15,
|
|
27
26
|
apolloRowHeight: 20,
|
|
28
27
|
detailsMinHeight: 200,
|
|
29
28
|
detailsHeight: 200,
|
|
30
|
-
lastRowTooltipBufferHeight:
|
|
29
|
+
lastRowTooltipBufferHeight: 120,
|
|
31
30
|
isShown: true,
|
|
32
31
|
filteredTranscripts: types.array(types.string),
|
|
33
32
|
})
|
|
@@ -35,7 +34,7 @@ export function renderingModelIntermediateFactory(
|
|
|
35
34
|
canvas: null as HTMLCanvasElement | null,
|
|
36
35
|
overlayCanvas: null as HTMLCanvasElement | null,
|
|
37
36
|
collaboratorCanvas: null as HTMLCanvasElement | null,
|
|
38
|
-
theme:
|
|
37
|
+
theme: createTheme(),
|
|
39
38
|
}))
|
|
40
39
|
.views((self) => ({
|
|
41
40
|
get featuresHeight() {
|
|
@@ -70,6 +69,8 @@ export function renderingModelIntermediateFactory(
|
|
|
70
69
|
setTheme(theme: Theme) {
|
|
71
70
|
self.theme = theme
|
|
72
71
|
},
|
|
72
|
+
}))
|
|
73
|
+
.actions((self) => ({
|
|
73
74
|
afterAttach() {
|
|
74
75
|
addDisposer(
|
|
75
76
|
self,
|
|
@@ -130,69 +131,56 @@ export function renderingModelIntermediateFactory(
|
|
|
130
131
|
{ name: 'LinearApolloSixFrameDisplayRenderCollaborators' },
|
|
131
132
|
),
|
|
132
133
|
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
renderingModelIntermediateFactory(pluginManager, configSchema)
|
|
143
|
-
|
|
144
|
-
return LinearApolloSixFrameDisplayRendering.actions((self) => ({
|
|
145
|
-
afterAttach() {
|
|
146
|
-
addDisposer(
|
|
147
|
-
self,
|
|
148
|
-
autorun(
|
|
149
|
-
() => {
|
|
150
|
-
const { canvas, featureLayouts, featuresHeight, lgv } = self
|
|
151
|
-
if (!lgv.initialized || self.regionCannotBeRendered()) {
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
const { displayedRegions, dynamicBlocks } = lgv
|
|
134
|
+
addDisposer(
|
|
135
|
+
self,
|
|
136
|
+
autorun(
|
|
137
|
+
() => {
|
|
138
|
+
const { canvas, featureLayouts, featuresHeight, lgv } = self
|
|
139
|
+
if (!lgv.initialized || self.regionCannotBeRendered()) {
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
const { displayedRegions, dynamicBlocks } = lgv
|
|
155
143
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
144
|
+
const ctx = canvas?.getContext('2d')
|
|
145
|
+
if (!ctx) {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
ctx.clearRect(0, 0, dynamicBlocks.totalWidthPx, featuresHeight)
|
|
149
|
+
for (const [idx, featureLayout] of featureLayouts.entries()) {
|
|
150
|
+
const displayedRegion = displayedRegions[idx]
|
|
151
|
+
for (const [row, featureLayoutRow] of featureLayout.entries()) {
|
|
152
|
+
for (const { feature } of featureLayoutRow) {
|
|
153
|
+
if (!feature.looksLikeGene) {
|
|
154
|
+
continue
|
|
155
|
+
}
|
|
156
|
+
if (
|
|
157
|
+
!doesIntersect2(
|
|
158
|
+
displayedRegion.start,
|
|
159
|
+
displayedRegion.end,
|
|
160
|
+
feature.min,
|
|
161
|
+
feature.max,
|
|
162
|
+
)
|
|
163
|
+
) {
|
|
164
|
+
continue
|
|
165
|
+
}
|
|
166
|
+
const { topLevelFeature } = feature
|
|
167
|
+
const glyph = self.getGlyph(topLevelFeature)
|
|
168
|
+
if (glyph !== undefined) {
|
|
169
|
+
glyph.draw(ctx, topLevelFeature, row, self, idx)
|
|
170
|
+
}
|
|
182
171
|
}
|
|
183
172
|
}
|
|
184
173
|
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
}))
|
|
174
|
+
},
|
|
175
|
+
{ name: 'LinearApolloSixFrameDisplayRenderFeatures' },
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
},
|
|
179
|
+
}))
|
|
192
180
|
}
|
|
193
181
|
|
|
194
182
|
export type LinearApolloSixFrameDisplayRenderingModel = ReturnType<
|
|
195
|
-
typeof
|
|
183
|
+
typeof renderingModelFactory
|
|
196
184
|
>
|
|
197
185
|
// eslint disable because of
|
|
198
186
|
// https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
|