import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; import { Highlight } from '../../../fields/DocSymbols'; import { List } from '../../../fields/List'; import { BoolCast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { LinkManager } from '../../util/LinkManager'; import { undoable } from '../../util/UndoManager'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { OpenWhere } from '../nodes/OpenWhere'; import { AnchorMenu } from './AnchorMenu'; import './Annotation.scss'; interface IRegionAnnotationProps { x: number; y: number; width: number; height: number; opacity: () => number; background: () => string; outline: () => string | undefined; } const RegionAnnotation = function (props: IRegionAnnotationProps) { return (
); }; interface IAnnotationProps extends FieldViewProps { annoDoc: Doc; containerDataDoc: Doc; fieldKey: string; pointerEvents?: () => Opt; } @observer export class Annotation extends ObservableReactComponent { constructor(props: any) { super(props); makeObservable(this); } @computed get linkHighlighted() { const found = LinkManager.Instance.getAllDirectLinks(this._props.annoDoc).find(link => { const a1 = Doc.getOppositeAnchor(link, this._props.annoDoc); return a1 && Doc.GetBrushStatus(DocCast(a1.annotationOn, a1)); }); return found; } deleteAnnotation = undoable(() => { const docAnnotations = DocListCast(this._props.containerDataDoc[this._props.fieldKey]); this._props.containerDataDoc[this._props.fieldKey] = new List(docAnnotations.filter(a => a !== this._props.annoDoc)); AnchorMenu.Instance.fadeOut(true); this._props.select(false); }, 'delete annotation'); pinToPres = undoable(() => this._props.pinToPres(this._props.annoDoc, {}), 'pin to pres'); makeTargetToggle = undoable(() => { this._props.annoDoc.followLinkToggle = !this._props.annoDoc.followLinkToggle }, "set link toggle"); // prettier-ignore isTargetToggler = () => BoolCast(this._props.annoDoc.followLinkToggle); showTargetTrail = undoable((anchor: Doc) => { const trail = DocCast(anchor.presentationTrail); if (trail) { Doc.ActivePresentation = trail; this._props.addDocTab(trail, OpenWhere.replaceRight); } }, 'show target trail'); @action onContextMenu = (e: React.MouseEvent) => { AnchorMenu.Instance.Status = 'annotation'; AnchorMenu.Instance.Delete = this.deleteAnnotation; AnchorMenu.Instance.Pinned = false; AnchorMenu.Instance.PinToPres = this.pinToPres; AnchorMenu.Instance.MakeTargetToggle = this.makeTargetToggle; AnchorMenu.Instance.IsTargetToggler = this.isTargetToggler; AnchorMenu.Instance.ShowTargetTrail = () => this.showTargetTrail(this._props.annoDoc); AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true); e.stopPropagation(); e.preventDefault(); }; @action onPointerDown = (e: React.PointerEvent) => { if (e.button === 2 || e.ctrlKey) { e.stopPropagation(); e.preventDefault(); } else if (e.button === 0) { e.stopPropagation(); DocumentView.FollowLink(undefined, this._props.annoDoc, false); } }; brushed = () => this._props.annoDoc && Doc.GetBrushHighlightStatus(this._props.annoDoc); opacity = () => (this.brushed() === Doc.DocBrushStatus.highlighted ? 0.5 : 1); outline = () => (this.linkHighlighted ? 'solid 1px lightBlue' : undefined); background = () => (this._props.annoDoc[Highlight] ? 'orange' : StrCast(this._props.annoDoc.backgroundColor)); render() { return (
{StrListCast(this._props.annoDoc.text_inlineAnnotations) .map(a => a.split?.(':')) .filter(fields => fields) .map(([x, y, width, height]) => (
{ Doc.BrushDoc(this._props.annoDoc); }} onPointerLeave={() => { Doc.UnBrushDoc(this._props.annoDoc); }}>
))}
); } }