diff options
12 files changed, 50 insertions, 97 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index edc2ac653..d979e0a3f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -724,6 +724,7 @@ export namespace DocUtils { linkDocProto.layoutKey2 = DocuLinkBox.LayoutString("anchor2"); linkDocProto.width = linkDocProto.height = 0; linkDocProto.isBackground = true; + linkDocProto.isButton = true; LinkManager.Instance.addLink(linkDocProto); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index e23ac55c2..fc406c6ab 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,6 +9,7 @@ import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; import { Scripting } from './Scripting'; import { SelectionManager } from './SelectionManager'; +import { DocumentType } from '../documents/DocumentTypes'; export class DocumentManager { @@ -110,14 +111,18 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { + console.log("START"); let pairs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || Doc.IsBrushed(dv.props.Document)).reduce((pairs, dv) => { + console.log("DOC = " + dv.props.Document.title + " " + dv.props.Document.layout); let linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); pairs.push(...linksList.reduce((pairs, link) => { if (link) { let linkToDoc = LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); if (linkToDoc) { DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { - pairs.push({ a: dv, b: docView1, l: link }); + if (dv.props.Document.type !== DocumentType.LINK || dv.props.layoutKey !== docView1.props.layoutKey) { + pairs.push({ a: dv, b: docView1, l: link }); + } }); } } diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 8a668e8d8..35c0f023f 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -79,7 +79,7 @@ export class LinkManager { let related = LinkManager.Instance.getAllLinks().filter(link => { let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); - return protomatch1 || protomatch2; + return protomatch1 || protomatch2 || Doc.AreProtosEqual(link, anchor); }); return related; } @@ -244,8 +244,10 @@ export class LinkManager { public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined { if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) { return Cast(linkDoc.anchor2, Doc, null); - } else { + } else if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor2, Doc, null))) { return Cast(linkDoc.anchor1, Doc, null); + } else if (Doc.AreProtosEqual(anchor, linkDoc)) { + return linkDoc; } } } diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 95c7b2683..9869e24d1 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -12,6 +12,7 @@ import { Transform } from "../util/Transform"; import { CollectionFreeFormDocumentView } from "./nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "./nodes/DocumentContentsView"; import { NumCast } from "../../new_fields/Types"; +import { CollectionFreeFormLinksView } from "./collections/collectionFreeForm/CollectionFreeFormLinksView"; export type OverlayDisposer = () => void; @@ -206,6 +207,7 @@ export class OverlayView extends React.Component { <div> {this._elements} </div> + <CollectionFreeFormLinksView key="freeformLinks" /> {this.overlayDocs} </div> ); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index cfd18ad35..1f1bca2f2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -1,6 +1,5 @@ .collectionfreeformlinkview-linkLine { stroke: black; - transform: translate(10000px,10000px); opacity: 0.8; pointer-events: all; stroke-width: 3px; @@ -8,13 +7,11 @@ .collectionfreeformlinkview-linkCircle { stroke: rgb(0,0,0); opacity: 0.5; - transform: translate(10000px,10000px); pointer-events: all; cursor: pointer; } .collectionfreeformlinkview-linkText { stroke: rgb(0,0,0); opacity: 0.5; - transform: translate(10000px,10000px); pointer-events: all; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index a59fda6d9..4e1faccd7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,63 +1,30 @@ import { observer } from "mobx-react"; -import { Doc, HeightSym, WidthSym } from "../../../../new_fields/Doc"; -import { BoolCast, NumCast, StrCast } from "../../../../new_fields/Types"; -import { InkingControl } from "../../InkingControl"; +import { Doc } from "../../../../new_fields/Doc"; +import { Utils } from '../../../../Utils'; +import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); +import { DocumentType } from "../../../documents/DocumentTypes"; export interface CollectionFreeFormLinkViewProps { - A: Doc; - B: Doc; + A: DocumentView; + B: DocumentView; LinkDocs: Doc[]; - addDocument: (document: Doc) => boolean; - removeDocument: (document: Doc) => boolean; } @observer export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFormLinkViewProps> { - onPointerDown = (e: React.PointerEvent) => { - if (e.button === 0 && !InkingControl.Instance.selectedTool) { - let a = this.props.A; - let b = this.props.B; - let x1 = NumCast(a.x) + (BoolCast(a.isMinimized) ? 5 : a[WidthSym]() / 2); - let y1 = NumCast(a.y) + (BoolCast(a.isMinimized) ? 5 : a[HeightSym]() / 2); - let x2 = NumCast(b.x) + (BoolCast(b.isMinimized) ? 5 : b[WidthSym]() / 2); - let y2 = NumCast(b.y) + (BoolCast(b.isMinimized) ? 5 : b[HeightSym]() / 2); - // this.props.LinkDocs.map(l => { - // let width = l[WidthSym](); - // l.x = (x1 + x2) / 2 - width / 2; - // l.y = (y1 + y2) / 2 + 10; - // if (!this.props.removeDocument(l)) this.props.addDocument(l, false); - // }); - e.stopPropagation(); - e.preventDefault(); - } - } render() { - // let l = this.props.LinkDocs; - let a = this.props.A.layout instanceof Doc ? this.props.A.layout : this.props.A; - let b = this.props.B.layout instanceof Doc ? this.props.B.layout : this.props.B; - let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / 2); - let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / 2); - let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / 2); - let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / 2); - let text = ""; - // let first = this.props.LinkDocs[0]; - // if (this.props.LinkDocs.length === 1) text += first.title + (first.linkDescription ? "(" + StrCast(first.linkDescription) + ")" : ""); - // else text = "-multiple-"; - return ( - <> - <line key="linkLine" className="collectionfreeformlinkview-linkLine" - x1={`${x1}`} y1={`${y1}`} - x2={`${x2}`} y2={`${y2}`} /> - {/* <circle key="linkCircle" className="collectionfreeformlinkview-linkCircle" - cx={(x1 + x2) / 2} cy={(y1 + y2) / 2} r={8} onPointerDown={this.onPointerDown} /> */} - <text key="linkText" textAnchor="middle" className="collectionfreeformlinkview-linkText" x={`${(x1 + x2) / 2}`} y={`${(y1 + y2) / 2}`}> - {text} - </text> - </> - ); + let acont = this.props.A.props.Document.type === DocumentType.LINK ? this.props.A.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + let bcont = this.props.B.props.Document.type === DocumentType.LINK ? this.props.B.ContentDiv!.getElementsByClassName("docuLinkBox-cont") : []; + let a = (acont.length ? acont[0] : this.props.A.ContentDiv!).getBoundingClientRect(); + let b = (bcont.length ? bcont[0] : this.props.B.ContentDiv!).getBoundingClientRect(); + let pt1 = Utils.getNearestPointInPerimeter(a.left, a.top, a.width, a.height, b.left + b.width / 2, b.top + b.height / 2); + let pt2 = Utils.getNearestPointInPerimeter(b.left, b.top, b.width, b.height, a.left + a.width / 2, a.top + a.height / 2); + return (<line key="linkLine" className="collectionfreeformlinkview-linkLine" + x1={`${pt1[0]}`} y1={`${pt1[1]}`} + x2={`${pt2[0]}`} y2={`${pt2[1]}`} />); } }
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss index 30e158603..cb5cef29c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss @@ -1,10 +1,9 @@ .collectionfreeformlinksview-svgCanvas{ - transform: translate(-10000px,-10000px); position: absolute; top: 0; left: 0; - width: 20000px; - height: 20000px; + width: 100%; + height: 100%; pointer-events: none; } .collectionfreeformlinksview-container { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 189981e35..cf0e55ccf 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,17 +1,17 @@ import { computed, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast } from "../../../../new_fields/Doc"; +import { Doc } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; -import { Cast, FieldValue } from "../../../../new_fields/Types"; import { DocumentManager } from "../../../util/DocumentManager"; import { DocumentView } from "../../nodes/DocumentView"; -import { CollectionViewProps } from "../CollectionSubView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); +import { Utils } from "../../../../Utils"; +import { SelectionManager } from "../../../util/SelectionManager"; @observer -export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> { +export class CollectionFreeFormLinksView extends React.Component { _brushReactionDisposer?: IReactionDisposer; componentDidMount() { @@ -71,35 +71,18 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP this._brushReactionDisposer(); } } - documentAnchors(view: DocumentView) { - let equalViews = [view]; - let containerDoc = FieldValue(Cast(view.props.Document.annotationOn, Doc)); - if (containerDoc) { - equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.proto!); - } - if (view.props.ContainingCollectionDoc) { - let collid = view.props.ContainingCollectionDoc[Id]; - DocListCast(this.props.Document[this.props.fieldKey]). - filter(child => - child[Id] === collid).map(view => - DocumentManager.Instance.getDocumentViews(view).map(view => - equalViews.push(view))); - } - return equalViews.filter(sv => sv.props.ContainingCollectionDoc === this.props.Document); - } - @computed get uniqueConnections() { let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { - let srcViews = this.documentAnchors(connection.a); - let targetViews = this.documentAnchors(connection.b); + let srcViews = [connection.a]; + let targetViews = [connection.b]; - let possiblePairs: { a: Doc, b: Doc, }[] = []; - srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); + let possiblePairs: { a: DocumentView, b: DocumentView, }[] = []; + srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv, b: tv }))); possiblePairs.map(possiblePair => { if (!drawnPairs.reduce((found, drawnPair) => { - let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b)); - let match2 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.b) && Doc.AreProtosEqual(possiblePair.b, drawnPair.a)); + let match1 = (Doc.AreProtosEqual(possiblePair.a.props.Document, drawnPair.a.props.Document) && Doc.AreProtosEqual(possiblePair.b.props.Document, drawnPair.b.props.Document)); + let match2 = (Doc.AreProtosEqual(possiblePair.a.props.Document, drawnPair.b.props.Document) && Doc.AreProtosEqual(possiblePair.b.props.Document, drawnPair.a.props.Document)); let match = match1 || match2; if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { drawnPair.l.push(connection.l); @@ -110,16 +93,15 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP } }); return drawnPairs; - }, [] as { a: Doc, b: Doc, l: Doc[] }[]); - return connections.map(c => <CollectionFreeFormLinkView key={c.l.reduce((p, l) => p + l[Id], "")} A={c.a} B={c.b} LinkDocs={c.l} - removeDocument={this.props.removeDocument} addDocument={this.props.addDocument} />); + }, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]); + return connections.map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />); } render() { return ( <div className="collectionfreeformlinksview-container"> <svg className="collectionfreeformlinksview-svgCanvas"> - {this.uniqueConnections} + {SelectionManager.GetIsDragging() ? (null) : this.uniqueConnections} </svg> {this.props.children} </div> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 5dccb5bf0..b3270d507 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -705,11 +705,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} isAnnotationOverlay={this.isAnnotationOverlay}> <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY} easing={this.easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}> - <CollectionFreeFormLinksView {...this.props} key="freeformLinks"> - <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} AnnotationDocument={this.fieldExtensionDoc} inkFieldKey={"ink"} > - {this.childViews} - </InkingCanvas> - </CollectionFreeFormLinksView> + <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} AnnotationDocument={this.fieldExtensionDoc} inkFieldKey={"ink"} > + {this.childViews} + </InkingCanvas> <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> </CollectionFreeFormViewPannableContents> </MarqueeView> diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index 8c41b9d4f..f56bf4ad3 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -54,12 +54,12 @@ export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(Doc 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)) { + 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)) { + 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(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6775655eb..0bcaa99aa 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -697,7 +697,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu opacity: this.Document.opacity }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} - onPointerEnter={() => Doc.BrushDoc(this.props.Document)} onPointerLeave={() => Doc.UnBrushDoc(this.props.Document)} + onPointerEnter={() => { Doc.UnBrushAllDocs(); Doc.BrushDoc(this.props.Document); }} onPointerLeave={() => Doc.UnBrushDoc(this.props.Document)} > {this.props.Document.links && DocListCast(this.props.Document.links).map((d, i) => <div style={{ pointerEvents: "none", position: "absolute", transformOrigin: "top left", width: "100%", height: "100%", transform: `scale(${this.props.Document.fitWidth ? 1 : 1 / this.props.ContentScaling()})` }}> <DocumentView {...this.props} backgroundColor={returnTransparent} Document={d} layoutKey={this.linkEndpoint(d)} /> </div>)} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 04f310785..26355d0e7 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -734,7 +734,7 @@ export namespace Doc { } export function UnBrushAllDocs() { - manager.BrushedDoc.clear(); + brushManager.BrushedDoc.clear(); } export function setChildLayout(target: Doc, source?: Doc) { |