Skip to content

Commit

Permalink
Start
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 4, 2024
1 parent 9358657 commit 205999e
Show file tree
Hide file tree
Showing 24 changed files with 2,586 additions and 2 deletions.
4 changes: 3 additions & 1 deletion plugins/variants/src/LinearVariantMatrixDisplay/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
import stateModelFactory from './model'
import configSchemaF from './configSchema'

export default (pluginManager: PluginManager) => {
export default function LinearVariantMatrixDisplayF(
pluginManager: PluginManager,
) {
pluginManager.addDisplayType(() => {
const configSchema = configSchemaF(pluginManager)
return new DisplayType({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react'
import { observer } from 'mobx-react'

// locals
import { WiggleDisplayModel } from '../models/model'
import RectBg from './RectBg'

const ColorLegend = observer(function ({
model,
rowHeight,
labelWidth,
exportSVG,
}: {
model: WiggleDisplayModel
rowHeight: number
labelWidth: number
exportSVG?: boolean
}) {
const {
needsCustomLegend,
needsScalebar,
needsFullHeightScalebar,
rowHeightTooSmallForScalebar,
renderColorBoxes,
sources,
} = model
const svgFontSize = Math.min(rowHeight, 12)
const canDisplayLabel = rowHeight > 11
const colorBoxWidth = renderColorBoxes ? 15 : 0
const legendWidth = labelWidth + colorBoxWidth + 5
const svgOffset = exportSVG ? 10 : 0
const extraOffset =
svgOffset || (needsScalebar && !rowHeightTooSmallForScalebar ? 50 : 0)

return sources ? (
<>
{
/* 0.25 for hanging letters like g */
needsFullHeightScalebar ? (
<RectBg
y={0}
x={extraOffset}
width={legendWidth}
height={(sources.length + 0.25) * rowHeight}
/>
) : null
}
{sources.map((source, idx) => {
const boxHeight = Math.min(20, rowHeight)
return (
<React.Fragment key={`${source.name}-${idx}`}>
{needsFullHeightScalebar ? null : (
<RectBg
y={idx * rowHeight + 1}
x={extraOffset}
width={legendWidth}
height={boxHeight}
/>
)}
{source.color ? (
<RectBg
y={idx * rowHeight + 1}
x={extraOffset}
width={colorBoxWidth}
height={needsCustomLegend ? rowHeight : boxHeight}
color={source.color}
/>
) : null}
{canDisplayLabel ? (
<text
y={idx * rowHeight + 13}
x={extraOffset + colorBoxWidth + 2}
fontSize={svgFontSize}
>
{source.name}
</text>
) : null}
</React.Fragment>
)
})}
</>
) : null
})

export default ColorLegend
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useRef } from 'react'
import {
Dialog,
DialogTitle,
IconButton,
Divider,
DialogProps,
Paper,
ScopedCssBaseline,
PaperProps,
} from '@mui/material'
import { observer } from 'mobx-react'
import { makeStyles } from 'tss-react/mui'
import Draggable from 'react-draggable'

// icons
import CloseIcon from '@mui/icons-material/Close'

const useStyles = makeStyles()(theme => ({
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500],
},
}))

function PaperComponent(props: PaperProps) {
const ref = useRef<HTMLDivElement>(null)
return (
<Draggable
nodeRef={ref}
cancel={'[class*="MuiDialogContent-root"]'}
// @ts-expect-error
onStart={arg => arg.target?.className?.includes('MuiDialogTitle')}
>
<Paper ref={ref} {...props} />
</Draggable>
)
}

const DraggableDialog = observer(function DraggableDialog(
props: DialogProps & { title: string },
) {
const { classes } = useStyles()
const { title, children, onClose } = props

return (
<Dialog {...props} PaperComponent={PaperComponent}>
<ScopedCssBaseline>
<DialogTitle style={{ cursor: 'move' }}>
{title}
{onClose ? (
<IconButton
className={classes.closeButton}
onClick={() => {
// @ts-expect-error
onClose()
}}
>
<CloseIcon />
</IconButton>
) : null}
</DialogTitle>
<Divider />
{children}
</ScopedCssBaseline>
</Dialog>
)
})

export default DraggableDialog
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react'
import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view'
import { observer } from 'mobx-react'

// locals
import { VariantDisplayModel } from '../models/model'
import YScaleBars from './YScaleBars'

const MultiLinearVariantDisplayComponent = observer(function (props: {
model: VariantDisplayModel
}) {
const { model } = props

return (
<div>
<BaseLinearDisplayComponent {...props} />
<YScaleBars model={model} />
</div>
)
})

export default MultiLinearVariantDisplayComponent
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { getFillProps } from '@jbrowse/core/util'
import React from 'react'

const RectBg = (props: {
x: number
y: number
width: number
height: number
color?: string
}) => {
const { color = 'rgb(255,255,255,0.8)' } = props
return <rect {...props} {...getFillProps(color)} />
}

export default RectBg
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react'
import { measureText, getContainingView } from '@jbrowse/core/util'
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
import { observer } from 'mobx-react'

// locals
import { WiggleDisplayModel } from '../models/model'
import RectBg from './RectBg'

type LGV = LinearGenomeViewModel

const ScoreLegend = observer(({ model }: { model: WiggleDisplayModel }) => {
const { ticks, scaleType } = model
const { width } = getContainingView(model) as LGV
const legend = `[${ticks?.values[0]}-${ticks?.values[1]}]${scaleType === 'log' ? ' (log scale)' : ''}`
const len = measureText(legend, 14)
const padding = 25
const xpos = width - len - padding
return (
<>
<RectBg y={0} x={xpos} width={len + 6} height={16} />
<text y={13} x={xpos}>
{legend}
</text>
</>
)
})

export default ScoreLegend
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { useState } from 'react'
import { Button, DialogContent, DialogActions } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import { useLocalStorage } from '@jbrowse/core/util'
import clone from 'clone'

// locals
import DraggableDialog from './DraggableDialog'
import { Source } from '../../util'
import SourcesGrid from './SourcesGrid'

const useStyles = makeStyles()({
content: {
minWidth: 800,
},
})

export default function SetColorDialog({
model,
handleClose,
}: {
model: {
sources?: Source[]
setLayout: (s: Source[]) => void
clearLayout: () => void
}
handleClose: () => void
}) {
const { classes } = useStyles()
const { sources } = model
const [currLayout, setCurrLayout] = useState(clone(sources || []))
const [showTips, setShowTips] = useLocalStorage('multiwiggle-showTips', true)
return (
<DraggableDialog
open
onClose={handleClose}
maxWidth="xl"
title={'Multi-wiggle color/arrangement editor'}
>
<DialogContent className={classes.content}>
<Button
variant="contained"
style={{ float: 'right' }}
onClick={() => {
setShowTips(!showTips)
}}
>
{showTips ? 'Hide tips' : 'Show tips'}
</Button>
<br />
{showTips ? (
<>
Helpful tips
<ul>
<li>You can select rows in the table with the checkboxes</li>
<li>
Multi-select is enabled with shift-click and control-click
</li>
<li>
The "Move selected items up/down" can re-arrange subtracks
</li>
<li>
Sorting the data grid itself can also re-arrange subtracks
</li>
<li>Changes are applied when you hit Submit</li>
<li>
You can click and drag the dialog box to move it on the screen
</li>
<li>
Columns in the table can be hidden using a vertical '...' menu
on the right side of each column
</li>
</ul>
</>
) : null}
<SourcesGrid
rows={currLayout}
onChange={setCurrLayout}
showTips={showTips}
/>
</DialogContent>
<DialogActions>
<Button
variant="contained"
type="submit"
color="inherit"
onClick={() => {
model.clearLayout()
setCurrLayout(model.sources || [])
}}
>
Clear custom settings
</Button>
<Button
variant="contained"
color="secondary"
onClick={() => {
handleClose()
setCurrLayout([...(model.sources || [])])
}}
>
Cancel
</Button>
<Button
variant="contained"
color="primary"
type="submit"
onClick={() => {
model.setLayout(currLayout)
handleClose()
}}
>
Submit
</Button>
</DialogActions>
</DraggableDialog>
)
}
Loading

0 comments on commit 205999e

Please sign in to comment.