Skip to content

Commit

Permalink
Add infrastructure for creating linear-genome-view sub-classes (#3227)
Browse files Browse the repository at this point in the history
* Infrastructure changes necessary for MLLV

* styles import theme and export components runtime

* export for external plugin runtime import

* update snaps

* snaps

* remove ternary and tsignore

snaps

* Update extendedName description

Co-authored-by: Colin <colin.diesh@gmail.com>
  • Loading branch information
carolinebridge and cmdcolin committed Sep 30, 2022
1 parent ef3f2c3 commit 106b50e
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 62 deletions.
4 changes: 3 additions & 1 deletion packages/core/PluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,10 @@ export default class PluginManager {
const displays = this.getElementTypesInGroup('display') as DisplayType[]
displays.forEach(display => {
// view may have already added the displayType in its callback
// see ViewType for description of extendedName
if (
display.viewType === newView.name &&
(display.viewType === newView.name ||
display.viewType === newView.extendedName) &&
!newView.displayTypes.includes(display)
) {
newView.addDisplayType(display)
Expand Down
10 changes: 10 additions & 0 deletions packages/core/pluggableElementTypes/ViewType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,24 @@ export default class ViewType extends PluggableElementBase {

displayTypes: DisplayType[] = []

// extendedName can be used for when you extend a given view type, and want
// to register all of that view types displays to yourself e.g. you create a
// linear-genome-view subtype, and want all the tracks that are compatible
// display types for the linear-genome-view to be compatible with your type
// also (without this, display types are only registered to a single view
// type)
extendedName?: string

constructor(stuff: {
name: string
ReactComponent: ViewReactComponent
stateModel: IAnyModelType
extendedName?: string
}) {
super(stuff)
this.ReactComponent = stuff.ReactComponent
this.stateModel = stuff.stateModel
this.extendedName = stuff.extendedName
if (!this.ReactComponent) {
throw new Error(`no ReactComponent defined for view ${this.name}`)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,15 @@ const Controls = ({ model }: { model: LGV }) => {
}

const LinearGenomeViewHeader = observer(({ model }: { model: LGV }) => {
return model.hideHeaderOverview ? (
<Controls model={model} />
) : (
<OverviewScaleBar model={model}>
return !model.hideHeader ? (
model.hideHeaderOverview ? (
<Controls model={model} />
</OverviewScaleBar>
)
) : (
<OverviewScaleBar model={model}>
<Controls model={model} />
</OverviewScaleBar>
)
) : null
})

export default LinearGenomeViewHeader
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import { observer } from 'mobx-react'

// locals
import { LinearGenomeViewModel } from '..'
import Header from './Header'
import TrackContainer from './TrackContainer'
import TracksContainer from './TracksContainer'
import ImportForm from './ImportForm'
import MiniControls from './MiniControls'
import GetSequenceDialog from './GetSequenceDialog'
import SearchResultsDialog from './SearchResultsDialog'

Expand Down Expand Up @@ -47,7 +45,7 @@ const useStyles = makeStyles()(theme => ({
}))

const LinearGenomeView = observer(({ model }: { model: LGV }) => {
const { tracks, error, hideHeader, initialized, hasDisplayedRegions } = model
const { tracks, error, initialized, hasDisplayedRegions } = model
const { classes } = useStyles()

if (!initialized && !error) {
Expand All @@ -61,6 +59,9 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
return <ImportForm model={model} />
}

const MiniControlsComponent = model.MiniControlsComponent()
const HeaderComponent = model.HeaderComponent()

return (
<div style={{ position: 'relative' }}>
{model.seqDialogDisplayed ? (
Expand All @@ -75,19 +76,8 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
handleClose={() => model.setSearchResults(undefined, undefined)}
/>
) : null}
{!hideHeader ? (
<Header model={model} />
) : (
<div
style={{
position: 'absolute',
right: 0,
zIndex: 1001,
}}
>
<MiniControls model={model} />
</div>
)}
<HeaderComponent model={model} />
<MiniControlsComponent model={model} />
<TracksContainer model={model}>
{!tracks.length ? (
<Paper variant="outlined" className={classes.note}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,48 @@ import { LinearGenomeViewModel } from '..'

const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
const { model } = props
const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor } = model
const { bpPerPx, maxBpPerPx, minBpPerPx, scaleFactor, hideHeader } = model
const [anchorEl, setAnchorEl] = useState<HTMLElement>()

return (
<Paper style={{ background: '#aaa7' }}>
<IconButton
color="secondary"
onClick={event => setAnchorEl(event.currentTarget)}
>
<ArrowDown fontSize="small" />
</IconButton>
return hideHeader ? (
<div style={{ position: 'absolute', right: '0px', zIndex: '1001' }}>
<Paper style={{ background: '#aaa7' }}>
<IconButton
color="secondary"
onClick={event => setAnchorEl(event.currentTarget)}
>
<ArrowDown fontSize="small" />
</IconButton>

<IconButton
data-testid="zoom_out"
onClick={() => model.zoom(bpPerPx * 2)}
disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1}
color="secondary"
>
<ZoomOut fontSize="small" />
</IconButton>
<IconButton
data-testid="zoom_in"
onClick={() => model.zoom(model.bpPerPx / 2)}
disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1}
color="secondary"
>
<ZoomIn fontSize="small" />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onMenuItemClick={(_, callback) => {
callback()
setAnchorEl(undefined)
}}
onClose={() => setAnchorEl(undefined)}
menuItems={model.menuItems()}
/>
</Paper>
)
<IconButton
data-testid="zoom_out"
onClick={() => model.zoom(bpPerPx * 2)}
disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1}
color="secondary"
>
<ZoomOut fontSize="small" />
</IconButton>
<IconButton
data-testid="zoom_in"
onClick={() => model.zoom(model.bpPerPx / 2)}
disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1}
color="secondary"
>
<ZoomIn fontSize="small" />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onMenuItemClick={(_, callback) => {
callback()
setAnchorEl(undefined)
}}
onClose={() => setAnchorEl(undefined)}
menuItems={model.menuItems()}
/>
</Paper>
</div>
) : null
})

export default MiniControls
24 changes: 22 additions & 2 deletions plugins/linear-genome-view/src/LinearGenomeView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { lazy } from 'react'
import React, { lazy } from 'react'
import { getConf, AnyConfigurationModel } from '@jbrowse/core/configuration'
import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'
import { Region } from '@jbrowse/core/util/types'
Expand Down Expand Up @@ -53,6 +53,10 @@ import { renderToSvg } from './components/LinearGenomeViewSvg'
import RefNameAutocomplete from './components/RefNameAutocomplete'
import SearchBox from './components/SearchBox'
import ExportSvgDlg from './components/ExportSvgDialog'
import MiniControls from './components/MiniControls'
import Header from './components/Header'
import ZoomControls from './components/ZoomControls'
import LinearGenomeView from './components/LinearGenomeView'

const SequenceSearchDialog = lazy(
() => import('./components/SequenceSearchDialog'),
Expand Down Expand Up @@ -192,6 +196,16 @@ export function stateModelFactory(pluginManager: PluginManager) {
},
}))
.views(self => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
MiniControlsComponent(): React.FC<any> {
return MiniControls
},

// eslint-disable-next-line @typescript-eslint/no-explicit-any
HeaderComponent(): React.FC<any> {
return Header
},

get assemblyErrors() {
const { assemblyManager } = getSession(self)
const { assemblyNames } = self
Expand Down Expand Up @@ -1220,7 +1234,13 @@ export function stateModelFactory(pluginManager: PluginManager) {
}))
}

export { renderToSvg, RefNameAutocomplete, SearchBox }
export {
renderToSvg,
RefNameAutocomplete,
SearchBox,
ZoomControls,
LinearGenomeView,
}
export type LinearGenomeViewStateModel = ReturnType<typeof stateModelFactory>
export type LinearGenomeViewModel = Instance<LinearGenomeViewStateModel>
export { default as ReactComponent } from './components/LinearGenomeView'
5 changes: 5 additions & 0 deletions plugins/linear-genome-view/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {
renderToSvg,
RefNameAutocomplete,
SearchBox,
ZoomControls,
LinearGenomeView,
} from './LinearGenomeView'

import {
Expand All @@ -45,6 +47,9 @@ export default class LinearGenomeViewPlugin extends Plugin {
BaseLinearDisplayComponent,
BaseLinearDisplay,
baseLinearDisplayConfigSchema,
SearchBox,
ZoomControls,
LinearGenomeView,
}

install(pluginManager: PluginManager) {
Expand Down

0 comments on commit 106b50e

Please sign in to comment.