import React = require('react'); import { action, computed, IReactionDisposer, observable, reaction, runInAction } 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, NumCast, StrCast } from '../../../fields/Types'; import { LinkFollower } from '../../util/LinkFollower'; import { undoBatch } from '../../util/UndoManager'; 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 makePushpin = () => (this.annoTextRegion.isPushpin = !this.annoTextRegion.isPushpin); isPushpin = () => BoolCast(this.annoTextRegion.isPushpin); @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.AddTag = this.addTag.bind(this); AnchorMenu.Instance.PinToPres = this.pinToPres; AnchorMenu.Instance.MakePushpin = this.makePushpin; AnchorMenu.Instance.IsPushpin = this.isPushpin; AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); e.stopPropagation(); } else if (e.button === 0) { e.stopPropagation(); LinkFollower.FollowLink(undefined, this.annoTextRegion, this.props, false); } }; addTag = (key: string, value: string): boolean => { const valNum = parseInt(value); this.annoTextRegion[key] = isNaN(valNum) ? value : valNum; return true; }; 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), }}>
); } }