Skip to content

Commit

Permalink
Misc refactors for view container (#3994)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin authored Oct 20, 2023
1 parent 09163ea commit 400b77c
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 92 deletions.
48 changes: 6 additions & 42 deletions packages/app-core/src/ui/App/ViewContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
import React, { useEffect, useRef } from 'react'
import { IconButton, Paper, useTheme } from '@mui/material'
import React, { useEffect } from 'react'
import { Paper, useTheme } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { observer } from 'mobx-react'
import { getSession, useWidthSetter } from '@jbrowse/core/util'
import clsx from 'clsx'
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'
import { SessionWithFocusedViewAndDrawerWidgets } from '@jbrowse/core/util'

// icons
import CloseIcon from '@mui/icons-material/Close'
import MinimizeIcon from '@mui/icons-material/Minimize'
import AddIcon from '@mui/icons-material/Add'

// locals
import ViewMenu from './ViewMenu'
import ViewContainerTitle from './ViewContainerTitle'
import ViewHeader from './ViewHeader'

const useStyles = makeStyles()(theme => ({
viewContainer: {
overflow: 'hidden',
margin: theme.spacing(0.5),
padding: `0 ${theme.spacing(1)} ${theme.spacing(1)}`,
},
icon: {
color: theme.palette.secondary.contrastText,
},
grow: {
flexGrow: 1,
},
focusedView: {
background: theme.palette.secondary.main,
},
Expand All @@ -47,18 +34,11 @@ const ViewContainer = observer(function ({
onMinimize: () => void
children: React.ReactNode
}) {
const { classes } = useStyles()
const theme = useTheme()
const ref = useWidthSetter(view, theme.spacing(1))
const scrollRef = useRef<HTMLDivElement>(null)
const { classes, cx } = useStyles()
const session = getSession(view) as SessionWithFocusedViewAndDrawerWidgets

// scroll the view into view when first mounted. note: this effect will run
// only once, because of the empty array second param
useEffect(() => {
scrollRef.current?.scrollIntoView?.({ block: 'center' })
}, [])

useEffect(() => {
function handleSelectView(e: Event) {
if (e.target instanceof Element) {
Expand All @@ -80,30 +60,14 @@ const ViewContainer = observer(function ({
<Paper
ref={ref}
elevation={12}
className={clsx(
className={cx(
classes.viewContainer,
session.focusedViewId === view.id
? classes.focusedView
: classes.unfocusedView,
)}
>
<div ref={scrollRef} style={{ display: 'flex' }}>
<ViewMenu model={view} IconProps={{ className: classes.icon }} />
<div className={classes.grow} />

<ViewContainerTitle view={view} />
<div className={classes.grow} />
<IconButton data-testid="minimize_view" onClick={onMinimize}>
{view.minimized ? (
<AddIcon className={classes.icon} fontSize="small" />
) : (
<MinimizeIcon className={classes.icon} fontSize="small" />
)}
</IconButton>
<IconButton data-testid="close_view" onClick={onClose}>
<CloseIcon className={classes.icon} fontSize="small" />
</IconButton>
</div>
<ViewHeader view={view} onClose={onClose} onMinimize={onMinimize} />
<Paper>{children}</Paper>
</Paper>
)
Expand Down
66 changes: 66 additions & 0 deletions packages/app-core/src/ui/App/ViewHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useEffect, useRef } from 'react'
import { IconButton } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { observer } from 'mobx-react'
import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'

// icons
import CloseIcon from '@mui/icons-material/Close'
import MinimizeIcon from '@mui/icons-material/Minimize'
import AddIcon from '@mui/icons-material/Add'

// locals
import ViewMenu from './ViewMenu'
import ViewContainerTitle from './ViewContainerTitle'

const useStyles = makeStyles()(theme => ({
icon: {
color: theme.palette.secondary.contrastText,
},
grow: {
flexGrow: 1,
},
viewHeader: {
display: 'flex',
},
}))

const ViewHeader = observer(function ({
view,
onClose,
onMinimize,
}: {
view: IBaseViewModel
onClose: () => void
onMinimize: () => void
}) {
const { classes } = useStyles()
const scrollRef = useRef<HTMLDivElement>(null)

// scroll the view into view when first mounted. note: this effect will run
// only once, because of the empty array second param
useEffect(() => {
scrollRef.current?.scrollIntoView?.({ block: 'center' })
}, [])
return (
<div ref={scrollRef} className={classes.viewHeader}>
<ViewMenu model={view} IconProps={{ className: classes.icon }} />
<div className={classes.grow} />

<ViewContainerTitle view={view} />
<div className={classes.grow} />
<IconButton data-testid="minimize_view" onClick={onMinimize}>
{view.minimized ? (
<AddIcon className={classes.icon} fontSize="small" />
) : (
<MinimizeIcon className={classes.icon} fontSize="small" />
)}
</IconButton>
<IconButton data-testid="close_view" onClick={onClose}>
<CloseIcon className={classes.icon} fontSize="small" />
</IconButton>
</div>
)
})

export default ViewHeader
14 changes: 7 additions & 7 deletions packages/core/pluggableElementTypes/models/baseTrackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,19 @@ export function createBaseTrackConfig(pluginManager: PluginManager) {
type: string
displays: { type: string; displayId: string }[]
}
const displayTypes = new Set()
const { displays = [] } = snap
if (snap.trackId !== 'placeholderId') {
// Gets the displays on the track snapshot and the possible displays
// from the track type and adds any missing possible displays to the
// snapshot
displays.forEach(d => d && displayTypes.add(d.type))
const trackType = pluginManager.getTrackType(snap.type)
trackType.displayTypes.forEach(displayType => {
if (!displayTypes.has(displayType.name)) {
const configDisplayTypes = new Set(
displays.filter(d => !!d).map(d => d.type),
)
pluginManager.getTrackType(snap.type).displayTypes.forEach(d => {
if (!configDisplayTypes.has(d.name)) {
displays.push({
displayId: `${snap.trackId}-${displayType.name}`,
type: displayType.name,
displayId: `${snap.trackId}-${d.name}`,
type: d.name,
})
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { lazy, useEffect, useRef } from 'react'
import { Button, Paper, Typography } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { LoadingEllipses } from '@jbrowse/core/ui'
import { getSession } from '@jbrowse/core/util'
import { observer } from 'mobx-react'

// icons
Expand All @@ -11,7 +12,6 @@ import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'
import { LinearGenomeViewModel } from '..'
import TrackContainer from './TrackContainer'
import TracksContainer from './TracksContainer'
import { getSession } from '@jbrowse/core/util'

const ImportForm = lazy(() => import('./ImportForm'))

Expand All @@ -23,16 +23,45 @@ const useStyles = makeStyles()(theme => ({
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1),
},
rel: {
position: 'relative',
},
}))

function NoTracksActive({ model }: { model: LinearGenomeViewModel }) {
const { classes } = useStyles()
const { hideNoTracksActive } = model
return (
<Paper className={classes.note}>
{!hideNoTracksActive ? (
<>
<Typography>No tracks active.</Typography>
<Button
variant="contained"
color="primary"
onClick={() => model.activateTrackSelector()}
style={{ zIndex: 1000 }}
startIcon={<TrackSelectorIcon />}
>
Open track selector
</Button>
</>
) : (
<div style={{ height: '48px' }}></div>
)}
</Paper>
)
}

const LinearGenomeView = observer(({ model }: { model: LGV }) => {
const { tracks, error, initialized, hasDisplayedRegions } = model
const { classes } = useStyles()
const ref = useRef<HTMLDivElement>(null)
const session = getSession(model)
const { classes } = useStyles()

useEffect(() => {
// sets the focused view id based on a click within the LGV; necessary for subviews to be focused properly
// sets the focused view id based on a click within the LGV;
// necessary for subviews to be focused properly
function handleSelectView(e: Event) {
if (e.target instanceof Element && ref?.current?.contains(e.target)) {
session.setFocusedViewId?.(model.id)
Expand All @@ -58,29 +87,12 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
const HeaderComponent = model.HeaderComponent()

return (
<div style={{ position: 'relative' }} ref={ref}>
<div className={classes.rel} ref={ref}>
<HeaderComponent model={model} />
<MiniControlsComponent model={model} />
<TracksContainer model={model}>
{!tracks.length ? (
<Paper variant="outlined" className={classes.note}>
{!model.hideNoTracksActive ? (
<>
<Typography>No tracks active.</Typography>
<Button
variant="contained"
color="primary"
onClick={model.activateTrackSelector}
style={{ zIndex: 1000 }}
startIcon={<TrackSelectorIcon />}
>
Open track selector
</Button>
</>
) : (
<div style={{ height: '48px' }}></div>
)}
</Paper>
<NoTracksActive model={model} />
) : (
tracks.map(track => (
<TrackContainer key={track.id} model={model} track={track} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ const useStyles = makeStyles()({
position: 'absolute',
zIndex: 10,
},
rel: {
position: 'relative',
},
})

const HoverTooltip = observer(function ({
Expand Down Expand Up @@ -155,7 +158,7 @@ const OverviewRubberband = observer(function OverviewRubberband({

if (startX === undefined) {
return (
<div style={{ position: 'relative' }}>
<div className={classes.rel}>
{guideX !== undefined ? (
<HoverTooltip
model={model}
Expand Down Expand Up @@ -195,7 +198,7 @@ const OverviewRubberband = observer(function OverviewRubberband({
}

return (
<div style={{ position: 'relative' }}>
<div className={classes.rel}>
{leftBpOffset && rightBpOffset ? (
<RubberbandSpan
leftBpOffset={leftBpOffset}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
exports[`renders one track, one region 1`] = `
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down Expand Up @@ -560,11 +560,11 @@ exports[`renders one track, one region 1`] = `
exports[`renders two tracks, two regions 1`] = `
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down
13 changes: 3 additions & 10 deletions plugins/linear-genome-view/src/LinearGenomeView/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1522,22 +1522,15 @@ export function stateModelFactory(pluginManager: PluginManager) {
if (session.focusedViewId === self.id && (e.ctrlKey || e.metaKey)) {
if (e.code === 'ArrowLeft') {
e.preventDefault()
// pan left
self.slide(-0.9)
}
if (e.code === 'ArrowRight') {
} else if (e.code === 'ArrowRight') {
e.preventDefault()
// pan right
self.slide(0.9)
}
if (e.code === 'ArrowUp' && self.scaleFactor === 1) {
} else if (e.code === 'ArrowUp' && self.scaleFactor === 1) {
e.preventDefault()
// zoom in
self.zoom(self.bpPerPx / 2)
}
if (e.code === 'ArrowDown' && self.scaleFactor === 1) {
} else if (e.code === 'ArrowDown' && self.scaleFactor === 1) {
e.preventDefault()
// zoom out
self.zoom(self.bpPerPx * 2)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ exports[`<JBrowseLinearGenomeView /> renders successfully 1`] = `
class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-1ps6pg7-MuiPaper-root"
>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div>
<div
style="position: relative;"
class="css-1v4ghfe-rel"
>
<div
class="css-dznme2-rubberbandControl"
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5836,9 +5836,9 @@ available-typed-arrays@^1.0.5:
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==

aws-sdk@^2.1231.0:
version "2.1477.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1477.0.tgz#ec878ea5584fee217eb02ec8f6ebfd9ace47f908"
integrity sha512-DLsrKosrKRe5P1E+BcJAVpOXkma4oUOrcyBUridDmUhdf9k3jj5dnL1roFuDpTmNDDhK8a1tUgY3wmXoKQtv7A==
version "2.1478.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1478.0.tgz#30edc3a34fb0c40f30e5512e5e02c630ef849022"
integrity sha512-F+Ud9FxMD4rwvGbEXn7qc25Q19N4p+9klRjiH1llFLYssPw6TRtY464Cry/jG4OzuYkE/DsnhcwVFEJjGvMmuQ==
dependencies:
buffer "4.9.2"
events "1.1.1"
Expand Down

0 comments on commit 400b77c

Please sign in to comment.