import React = require('react'); import { action, computed } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { LinkFollower } from '../../util/LinkFollower'; import { undoBatch } from '../../util/UndoManager'; import { OpenWhere } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { AnchorMenu } from './AnchorMenu'; import './Annotation.scss'; interface IAnnotationProps extends FieldViewProps { anno: Doc; dataDoc: Doc; fieldKey: string; showInfo: (anno: Opt) => void; pointerEvents?: () => Opt; } @observer export class Annotation extends React.Component { render() { return (
{DocListCast(this.props.anno.textInlineAnnotations).map(a => ( ))}
); } } interface IRegionAnnotationProps extends IAnnotationProps { document: Doc; pointerEvents?: () => Opt; } @observer class RegionAnnotation extends React.Component { private _mainCont: React.RefObject = React.createRef(); @computed get annoTextRegion() { return Cast(this.props.document.annoTextRegion, Doc, null) || this.props.document; } @undoBatch deleteAnnotation = () => { const docAnnotations = DocListCast(this.props.dataDoc[this.props.fieldKey]); this.props.dataDoc[this.props.fieldKey] = new List(docAnnotations.filter(a => a !== this.annoTextRegion)); AnchorMenu.Instance.fadeOut(true); this.props.select(false); }; @undoBatch pinToPres = () => this.props.pinToPres(this.annoTextRegion, {}); @undoBatch makeTargretToggle = () => (this.annoTextRegion.followLinkToggle = !this.annoTextRegion.followLinkToggle); isTargetToggler = () => BoolCast(this.annoTextRegion.followLinkToggle); @undoBatch showTargetTrail = (anchor: Doc) => { const trail = DocCast(anchor.presTrail); if (trail) { Doc.ActivePresentation = trail; this.props.addDocTab(trail, OpenWhere.replaceRight); } }; @action onPointerDown = (e: React.PointerEvent) => { if (e.button === 2 || e.ctrlKey) { AnchorMenu.Instance.Status = 'annotation'; AnchorMenu.Instance.Delete = this.deleteAnnotation.bind(this); AnchorMenu.Instance.Pinned = false; AnchorMenu.Instance.PinToPres = this.pinToPres; AnchorMenu.Instance.MakeTargetToggle = this.makeTargretToggle; AnchorMenu.Instance.IsTargetToggler = this.isTargetToggler; AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this.annoTextRegion); AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); e.stopPropagation(); } else if (e.button === 0) { e.stopPropagation(); LinkFollower.FollowLink(undefined, this.annoTextRegion, false); } }; render() { const brushed = this.annoTextRegion && Doc.isBrushedHighlightedDegree(this.annoTextRegion); return (
{ Doc.BrushDoc(this.props.anno); this.props.showInfo(this.props.anno); })} onPointerLeave={action(() => { Doc.UnBrushDoc(this.props.anno); this.props.showInfo(undefined); })} onPointerDown={this.onPointerDown} style={{ left: NumCast(this.props.document.x), top: NumCast(this.props.document.y), width: NumCast(this.props.document._width), height: NumCast(this.props.document._height), opacity: brushed === Doc.DocBrushStatus.highlighted ? 0.5 : undefined, pointerEvents: this.props.pointerEvents?.() as any, outline: brushed === Doc.DocBrushStatus.linkHighlighted ? 'solid 1px lightBlue' : undefined, backgroundColor: brushed === Doc.DocBrushStatus.highlighted ? 'orange' : StrCast(this.props.document.backgroundColor), }} /> ); } }