diff options
Diffstat (limited to 'src/client/views/nodes/DocuLinkBox.tsx')
-rw-r--r-- | src/client/views/nodes/DocuLinkBox.tsx | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx new file mode 100644 index 000000000..d73407903 --- /dev/null +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -0,0 +1,84 @@ +import { action, observable } from "mobx"; +import { observer } from "mobx-react"; +import { Doc } from "../../../new_fields/Doc"; +import { makeInterface } from "../../../new_fields/Schema"; +import { NumCast, StrCast, Cast } from "../../../new_fields/Types"; +import { Utils } from '../../../Utils'; +import { DocumentManager } from "../../util/DocumentManager"; +import { DragLinksAsDocuments } from "../../util/DragManager"; +import { DocComponent } from "../DocComponent"; +import "./DocuLinkBox.scss"; +import { FieldView, FieldViewProps } from "./FieldView"; +import React = require("react"); +import { DocumentType } from "../../documents/DocumentTypes"; +import { documentSchema } from "../../../new_fields/documentSchemas"; + +type DocLinkSchema = makeInterface<[typeof documentSchema]>; +const DocLinkDocument = makeInterface(documentSchema); + +@observer +export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(DocLinkDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocuLinkBox, fieldKey); } + _downx = 0; + _downy = 0; + @observable _x = 0; + @observable _y = 0; + @observable _selected = false; + _ref = React.createRef<HTMLDivElement>(); + + onPointerDown = (e: React.PointerEvent) => { + this._downx = e.clientX; + this._downy = e.clientY; + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointerup", this.onPointerUp); + (e.button === 0 && !e.ctrlKey) && e.stopPropagation(); + } + onPointerMove = action((e: PointerEvent) => { + let cdiv = this._ref && this._ref.current && this._ref.current.parentElement; + if (cdiv && (Math.abs(e.clientX - this._downx) > 5 || Math.abs(e.clientY - this._downy) > 5)) { + let bounds = cdiv.getBoundingClientRect(); + let pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY); + let separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); + let dragdist = Math.sqrt((pt[0] - this._downx) * (pt[0] - this._downx) + (pt[1] - this._downy) * (pt[1] - this._downy)); + if (separation > 100) { + DragLinksAsDocuments(this._ref.current!, pt[0], pt[1], Cast(this.props.Document[this.props.fieldKey], Doc) as Doc, this.props.Document); // Containging collection is the document, not a collection... hack. + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + } else if (dragdist > separation) { + this.props.Document[this.props.fieldKey + "_x"] = (pt[0] - bounds.left) / bounds.width * 100; + this.props.Document[this.props.fieldKey + "_y"] = (pt[1] - bounds.top) / bounds.height * 100; + } + } + }); + onPointerUp = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button === 2 || e.ctrlKey || !this.props.Document.isButton)) { + this.props.select(false); + } + } + onClick = (e: React.MouseEvent) => { + if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { + DocumentManager.Instance.FollowLink(this.props.Document, this.props.Document[this.props.fieldKey] as Doc, document => this.props.addDocTab(document, undefined, "inTab"), false); + } + e.stopPropagation(); + } + + render() { + let anchorDoc = Cast(this.props.Document[this.props.fieldKey], Doc); + let hasAnchor = anchorDoc instanceof Doc && anchorDoc.type === DocumentType.PDFANNO; + let y = NumCast(this.props.Document[this.props.fieldKey + "_y"], 100); + let x = NumCast(this.props.Document[this.props.fieldKey + "_x"], 100); + let c = StrCast(this.props.Document.backgroundColor, "lightblue"); + let anchor = this.props.fieldKey === "anchor1" ? "anchor2" : "anchor1"; + let timecode = this.props.Document[anchor + "Timecode"]; + let targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : ""); + return <div className="docuLinkBox-cont" onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} + ref={this._ref} style={{ + background: c, left: `calc(${x}% - 12.5px)`, top: `calc(${y}% - 12.5px)`, + transform: `scale(${hasAnchor ? 0.333 : 1 / this.props.ContentScaling()})` + }} />; + } +} |