UNPKG

@jbrowse/plugin-linear-genome-view

Version:

JBrowse 2 linear genome view

125 lines (124 loc) 4.03 kB
import { useCallback, useEffect, useState } from 'react'; import { getRelativeX } from './util'; export function useRangeSelect(ref, model, shiftOnly) { const [startX, setStartX] = useState(); const [currentX, setCurrentX] = useState(); const [anchorPosition, setAnchorPosition] = useState(); const [guideX, setGuideX] = useState(); const mouseDragging = startX !== undefined && anchorPosition === undefined; const handleClose = useCallback(() => { setAnchorPosition(undefined); setStartX(undefined); setCurrentX(undefined); }, []); useEffect(() => { function computeOffsets(offsetX) { if (startX === undefined) { return; } const leftPx = Math.min(startX, offsetX); const rightPx = Math.max(startX, offsetX); return { leftOffset: model.pxToBp(leftPx), rightOffset: model.pxToBp(rightPx), }; } function globalMouseMove(event) { if (ref.current && mouseDragging) { const relativeX = getRelativeX(event, ref.current); setCurrentX(relativeX); } } function globalMouseUp(event) { if (startX !== undefined && ref.current) { const { clientX, clientY } = event; const offsetX = getRelativeX(event, ref.current); if (Math.abs(offsetX - startX) <= 3) { handleClose(); return; } setAnchorPosition({ offsetX, clientX, clientY, }); const args = computeOffsets(offsetX); if (args) { model.setOffsets(args.leftOffset, args.rightOffset); } setGuideX(undefined); } } if (mouseDragging) { window.addEventListener('mousemove', globalMouseMove); window.addEventListener('mouseup', globalMouseUp); return () => { window.removeEventListener('mousemove', globalMouseMove); window.removeEventListener('mouseup', globalMouseUp); }; } return () => { }; }, [startX, mouseDragging, model, ref, handleClose]); function mouseDown(event) { if (shiftOnly && !event.shiftKey) { return; } event.preventDefault(); event.stopPropagation(); const relativeX = getRelativeX(event, ref.current); setStartX(relativeX); setCurrentX(relativeX); } function mouseMove(event) { if (shiftOnly) { if (event.shiftKey) { setGuideX(getRelativeX(event, ref.current)); } else { setGuideX(undefined); } } else { setGuideX(getRelativeX(event, ref.current)); } } function mouseOut() { setGuideX(undefined); } function handleMenuItemClick(_, callback) { callback(); handleClose(); } const open = Boolean(anchorPosition); if (startX === undefined) { return { open, guideX, mouseDown, mouseMove, mouseOut, handleMenuItemClick, }; } const right = anchorPosition ? anchorPosition.offsetX : currentX || 0; const left = Math.min(right, startX); const width = Math.abs(right - startX); const leftBpOffset = model.pxToBp(left); const rightBpOffset = model.pxToBp(left + width); const numOfBpSelected = Math.ceil(width * model.bpPerPx); return { open, rubberbandOn: true, mouseDown, mouseMove, mouseOut, handleClose, handleMenuItemClick, leftBpOffset, rightBpOffset, anchorPosition, numOfBpSelected, width, left, }; }