Skip to content

Commit

Permalink
M1
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Mar 4, 2025
1 parent e823bee commit e12d254
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ export default class BoxRendererType extends FeatureRendererType {
...rest,
layout,
maxHeightReached: layout.maxHeightReached,
features: features.filter(f => !!layout.rectangles[f.uniqueId]),
features:
// floating layout has no rectangles
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
layout.rectangles !== undefined
? features.filter(f => !!layout.rectangles[f.uniqueId])
: features,
}
}

Expand Down
46 changes: 29 additions & 17 deletions plugins/lollipop/src/LollipopRenderer/Layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,44 @@ export class FloatingLayout {
}
this.width = width
}
discardRange() {
/* do nothing */
this.items = []
this.layout = new Map()
this.totalHeight = 0
}

items: LayoutItem[] = []

layout: LayoutMap = new Map()

layoutDirty = false

add(
uniqueId: string,
anchorLocation: number,
width: number,
height: number,
data: { score: number },
) {
this.items.push({ uniqueId, anchorLocation, width, height, data })
this.layoutDirty = true
this.items.push({
uniqueId,
anchorLocation,
width,
height,
data,
})
}

/**
* @returns Map of `uniqueId => {x,y,anchorLocation,width,height,data}`
*/
getLayout(configuration?: AnyConfigurationModel) {
if (!this.layoutDirty) {
return this.layout
}
if (!configuration) {
throw new Error('configuration object required')
return this.layout
// throw new Error('configuration object required')
}
// this.layout = new Map()
// this.totalHeight = 0
// console.log(this.items)

const minY = readConfObject(configuration, 'minStickLength')

Expand Down Expand Up @@ -97,7 +107,11 @@ export class FloatingLayout {
// record the entry and update the maxBottom
layoutEntries[i] = [
currentItem.uniqueId,
{ ...currentItem, x: start, y: top },
{
...currentItem,
x: start,
y: top,
},
]
if (bottom > maxBottom) {
maxBottom = bottom
Expand All @@ -108,14 +122,10 @@ export class FloatingLayout {
// if they don't fit, try to alternate them on 2 levels, then 3
this.totalHeight = maxBottom
this.layout = new Map(layoutEntries)
this.layoutDirty = false
return this.layout
}

getTotalHeight() {
if (this.layoutDirty) {
throw new Error('getTotalHeight does not work when the layout is dirty.')
}
return this.totalHeight
}

Expand All @@ -124,10 +134,10 @@ export class FloatingLayout {
}

toJSON() {
if (this.layoutDirty) {
throw new Error('toJSON does not work when the layout is dirty.')
return {
pairs: [...this.getLayout()],
totalHeight: this.getTotalHeight(),
}
return { pairs: [...this.getLayout()], totalHeight: this.getTotalHeight() }
}

static fromJSON() {
Expand Down Expand Up @@ -164,7 +174,9 @@ export class PrecomputedFloatingLayout {
getTotalHeight() {
return this.totalHeight
}

discardRange() {
/* do nothing */
}
static fromJSON(
json: ConstructorParameters<typeof PrecomputedFloatingLayout>[0],
) {
Expand Down
143 changes: 82 additions & 61 deletions plugins/lollipop/src/LollipopRenderer/components/Lollipop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,6 @@ const Lollipop = observer(function Lollipop(props: Record<string, any>) {
data: { radiusPx },
} = layoutRecord

const onFeatureMouseDown = (event: React.MouseEvent) => {
const { onFeatureMouseDown: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseEnter = (event: React.MouseEvent) => {
const { onFeatureMouseEnter: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseOut = (event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOut: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseOver = (event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOver: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseUp = (event: React.MouseEvent) => {
const { onFeatureMouseUp: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseLeave = (event: React.MouseEvent) => {
const { onFeatureMouseLeave: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureMouseMove = (event: React.MouseEvent) => {
const { onFeatureMouseMove: handler, feature } = props
return handler?.(event, feature.id())
}

const onFeatureClick = (event: React.MouseEvent) => {
const { onFeatureClick: handler, feature } = props
event.stopPropagation()
return handler?.(event, feature.id())
}

const styleOuter = {
fill: readConfObject(config, 'strokeColor', { feature }),
}
Expand All @@ -73,33 +32,95 @@ const Lollipop = observer(function Lollipop(props: Record<string, any>) {
cy={y + radiusPx}
r={radiusPx}
style={styleOuter}
onMouseDown={onFeatureMouseDown}
onMouseEnter={onFeatureMouseEnter}
onMouseOut={onFeatureMouseOut}
onMouseOver={onFeatureMouseOver}
onMouseUp={onFeatureMouseUp}
onMouseLeave={onFeatureMouseLeave}
onMouseMove={onFeatureMouseMove}
onClick={onFeatureClick}
onFocus={onFeatureMouseOver}
onBlur={onFeatureMouseOut}
onMouseDown={(event: React.MouseEvent) => {
const { onFeatureMouseDown: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseEnter={(event: React.MouseEvent) => {
const { onFeatureMouseEnter: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseOut={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOut: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseOver={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOver: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseUp={(event: React.MouseEvent) => {
const { onFeatureMouseUp: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseLeave={(event: React.MouseEvent) => {
const { onFeatureMouseLeave: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseMove={(event: React.MouseEvent) => {
const { onFeatureMouseMove: handler, feature } = props
return handler?.(event, feature.id())
}}
onClick={(event: React.MouseEvent) => {
const { onFeatureClick: handler, feature } = props
event.stopPropagation()
return handler?.(event, feature.id())
}}
onFocus={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOver: handler, feature } = props
return handler?.(event, feature.id())
}}
onBlur={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOut: handler, feature } = props
return handler?.(event, feature.id())
}}
/>
{radiusPx - strokeWidth <= 2 ? null : (
<circle
cx={anchorLocation}
cy={y + radiusPx}
r={radiusPx - strokeWidth}
style={styleInner}
onMouseDown={onFeatureMouseDown}
onMouseEnter={onFeatureMouseEnter}
onMouseOut={onFeatureMouseOut}
onMouseOver={onFeatureMouseOver}
onMouseUp={onFeatureMouseUp}
onMouseLeave={onFeatureMouseLeave}
onMouseMove={onFeatureMouseMove}
onClick={onFeatureClick}
onFocus={onFeatureMouseOver}
onBlur={onFeatureMouseOut}
onMouseDown={(event: React.MouseEvent) => {
const { onFeatureMouseDown: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseEnter={(event: React.MouseEvent) => {
const { onFeatureMouseEnter: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseOut={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOut: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseOver={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOver: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseUp={(event: React.MouseEvent) => {
const { onFeatureMouseUp: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseLeave={(event: React.MouseEvent) => {
const { onFeatureMouseLeave: handler, feature } = props
return handler?.(event, feature.id())
}}
onMouseMove={(event: React.MouseEvent) => {
const { onFeatureMouseMove: handler, feature } = props
return handler?.(event, feature.id())
}}
onClick={(event: React.MouseEvent) => {
const { onFeatureClick: handler, feature } = props
event.stopPropagation()
return handler?.(event, feature.id())
}}
onFocus={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOver: handler, feature } = props
return handler?.(event, feature.id())
}}
onBlur={(event: React.MouseEvent | React.FocusEvent) => {
const { onFeatureMouseOut: handler, feature } = props
return handler?.(event, feature.id())
}}
/>
)}
<ScoreText
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { FocusEvent, MouseEvent } from 'react'
import { Fragment } from 'react'
import { Fragment, useEffect, useState } from 'react'

import { readConfObject } from '@jbrowse/core/configuration'
import { bpToPx } from '@jbrowse/core/util'
Expand Down Expand Up @@ -74,6 +74,10 @@ const LollipopRendering = observer(function (props: Record<string, any>) {
const { onClick: handler } = props
return handler?.(event)
}
const [client, setClient] = useState(false)
useEffect(() => {
setClient(true)
}, [])

const {
regions,
Expand Down Expand Up @@ -114,27 +118,31 @@ const LollipopRendering = observer(function (props: Record<string, any>) {
onBlur={onMouseLeave}
onClick={onClick}
>
{records.map(layoutRecord => {
const feature = features.get(layoutRecord.data.featureId)
return (
<Fragment key={feature.id()}>
<Stick
key={`stick-${feature.id()}`}
{...props}
config={config}
layoutRecord={layoutRecord}
feature={feature}
/>
<Lollipop
key={`body-${feature.id()}`}
{...props}
layoutRecord={layoutRecord}
feature={feature}
selectedFeatureId={selectedFeatureId}
/>
</Fragment>
)
})}
{client ? (
<>
{records.map(layoutRecord => {
const feature = features.get(layoutRecord.data.featureId)
return (
<Fragment key={feature.id()}>
<Stick
key={`stick-${feature.id()}`}
{...props}
config={config}
layoutRecord={layoutRecord}
feature={feature}
/>
<Lollipop
key={`body-${feature.id()}`}
{...props}
layoutRecord={layoutRecord}
feature={feature}
selectedFeatureId={selectedFeatureId}
/>
</Fragment>
)
})}
</>
) : null}
</svg>
)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ export default function ScoreText({
}
return (
<text
style={{ fontSize: fontHeight, fill: contrastingTextColor(innerColor) }}
style={{
pointerEvents: 'none',
fontSize: fontHeight,
fill: contrastingTextColor(innerColor),
}}
x={anchorX}
y={y + radiusPx - fontHeight / 2.4}
textAnchor="middle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ exports[`no features 1`] = `
exports[`one feature 1`] = `
<div>
<svg
height="16.286652959662007"
height="27.573305919324014"
style="position: relative;"
width="333.3333333333333"
>
Expand All @@ -23,15 +23,15 @@ exports[`one feature 1`] = `
x1="0.7"
x2="0.7"
y1="0"
y2="16.286652959662007"
y2="27.573305919324014"
/>
<g
data-testid="one"
>
<title />
<circle
cx="0.7"
cy="10.643326479831003"
cy="21.92997943949301"
r="5.643326479831003"
style="fill: green;"
/>
Expand Down
Loading

0 comments on commit e12d254

Please sign in to comment.