aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-10-17 16:48:39 -0400
committerbob <bcz@cs.brown.edu>2019-10-17 16:48:39 -0400
commitfca8d503610f799ca0e4afcec114075456d411e0 (patch)
treecac4a76094e72dfc302f0118f763ce1753ab4053 /src
parentdcdefb2a5a80d3c4d5451d6c7fc7213565d5ea5f (diff)
switched links over to be a document
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts2
-rw-r--r--src/client/documents/DocumentTypes.ts1
-rw-r--r--src/client/documents/Documents.ts5
-rw-r--r--src/client/views/DocumentDecorations.tsx3
-rw-r--r--src/client/views/InkingControl.tsx2
-rw-r--r--src/client/views/nodes/DocuLinkBox.tsx (renamed from src/client/views/nodes/DocuLinkView.tsx)56
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx3
-rw-r--r--src/client/views/nodes/DocumentView.tsx31
8 files changed, 41 insertions, 62 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 66ed8be5d..7bb025e49 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -289,6 +289,8 @@ export function percent2frac(percent: string) {
export function numberRange(num: number) { return Array.from(Array(num)).map((v, i) => i); }
+export function returnTransparent() { return "transparent"; }
+
export function returnTrue() { return true; }
export function returnFalse() { return false; }
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 03178bbdb..ea37fc2f1 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -23,4 +23,5 @@ export enum DocumentType {
PRESELEMENT = "preselement",
QUERY = "search",
COLOR = "color",
+ DOCULINK = "doculink"
} \ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 62175cbe3..edc2ac653 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -47,6 +47,7 @@ import { LinkFollowBox } from "../views/linking/LinkFollowBox";
import { PresElementBox } from "../views/presentationview/PresElementBox";
import { QueryBox } from "../views/nodes/QueryBox";
import { ColorBox } from "../views/nodes/ColorBox";
+import { DocuLinkBox } from "../views/nodes/DocuLinkBox";
var requestImageSize = require('../util/request-image-size');
var path = require('path');
@@ -719,6 +720,10 @@ export namespace DocUtils {
linkDocProto.anchor2Context = target.ctx;
linkDocProto.anchor2Groups = new List<Doc>([]);
linkDocProto.anchor2Timecode = target.doc.currentTimecode;
+ linkDocProto.layoutKey1 = DocuLinkBox.LayoutString("anchor1");
+ linkDocProto.layoutKey2 = DocuLinkBox.LayoutString("anchor2");
+ linkDocProto.width = linkDocProto.height = 0;
+ linkDocProto.isBackground = true;
LinkManager.Instance.addLink(linkDocProto);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 927729487..6e8ba2d3d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -167,8 +167,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
get Bounds(): { x: number, y: number, b: number, r: number } {
let x = this._forceUpdate;
this._lastBox = SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
- if (documentView._selectedLink !== -1 ||
- documentView.props.renderDepth === 0 ||
+ if (documentView.props.renderDepth === 0 ||
Doc.AreProtosEqual(documentView.props.Document, CurrentUserUtils.UserDocument)) {
return bounds;
}
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 1aacdc8ec..c3a617ffe 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -81,7 +81,7 @@ export class InkingControl {
ruleProvider = (view.props.Document.heading && ruleProvider) ? ruleProvider : undefined;
ruleProvider && ((Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(view.props.Document.heading)] = Utils.toRGBAstr(color.rgb)));
}
- (!ruleProvider && targetDoc) && (view.setBackround(matchedColor));
+ (!ruleProvider && targetDoc) && (view.props.Document.backgroundColor = matchedColor);
return {
target: targetDoc,
diff --git a/src/client/views/nodes/DocuLinkView.tsx b/src/client/views/nodes/DocuLinkBox.tsx
index 622d41047..2e968a9f6 100644
--- a/src/client/views/nodes/DocuLinkView.tsx
+++ b/src/client/views/nodes/DocuLinkBox.tsx
@@ -1,32 +1,23 @@
import { action, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, Opt } from "../../../new_fields/Doc";
+import { Doc } from "../../../new_fields/Doc";
+import { makeInterface } from "../../../new_fields/Schema";
import { NumCast, StrCast } from "../../../new_fields/Types";
import { Utils } from '../../../Utils';
import { DocumentManager } from "../../util/DocumentManager";
+import { DragLinksAsDocuments } from "../../util/DragManager";
+import { DocComponent } from "../DocComponent";
+import { documentSchema } from "./DocumentView";
import "./DocumentView.scss";
+import { FieldView, FieldViewProps } from "./FieldView";
import React = require("react");
-import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
-import { UndoManager } from "../../util/UndoManager";
-
-interface DocuLinkViewProps {
- Document: Doc;
- isSelected: () => boolean;
- addDocTab: (doc: Doc, dataDoc: Opt<Doc>, where: string) => void;
- anchor: string;
- otherAnchor: string;
- scale: () => number;
- contentDiv: HTMLDivElement | null;
- link: Doc;
- index: number;
- selectedLink: () => number;
- selectLink: (id: number) => void;
- blacklist: Opt<Doc>
-}
+type DocLinkSchema = makeInterface<[typeof documentSchema]>;
+const DocLinkDocument = makeInterface(documentSchema);
@observer
-export class DocuLinkView extends React.Component<DocuLinkViewProps> {
+export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(DocLinkDocument) {
+ public static LayoutString(fieldKey: string, fieldExt?: string) { return FieldView.LayoutString(DocuLinkBox, fieldKey, fieldExt); }
_downx = 0;
_downy = 0;
@observable _x = 0;
@@ -44,18 +35,19 @@ export class DocuLinkView extends React.Component<DocuLinkViewProps> {
e.stopPropagation();
}
onPointerMove = action((e: PointerEvent) => {
- if (this.props.contentDiv && (Math.abs(e.clientX - this._downx) > 5 || Math.abs(e.clientY - this._downy) > 5)) {
- let bounds = this.props.contentDiv.getBoundingClientRect();
+ let cdiv = 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], this.props.Document, this.props.link);
+ DragLinksAsDocuments(this._ref.current!, pt[0], pt[1], this.props.ContainingCollectionDoc 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.link[this.props.anchor + "_x"] = (pt[0] - bounds.left) / bounds.width * 100;
- this.props.link[this.props.anchor + "_y"] = (pt[1] - bounds.top) / bounds.height * 100;
+ 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;
}
}
})
@@ -63,23 +55,23 @@ export class DocuLinkView extends React.Component<DocuLinkViewProps> {
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.selectLink(this.props.selectedLink() === this.props.index ? -1 : this.props.index);
+ 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)) {
- DocumentManager.Instance.FollowLink(this.props.link, this.props.link[this.props.anchor] as Doc, document => this.props.addDocTab(document, undefined, "inTab"), false);
+ 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 y = NumCast(this.props.link[this.props.anchor + "_y"], 100);
- let x = NumCast(this.props.link[this.props.anchor + "_x"], 100);
- let c = StrCast(this.props.link[this.props.anchor + "_background"], "lightblue");
- return <div onPointerDown={this.onPointerDown} onClick={this.onClick} title={StrCast((this.props.link[this.props.otherAnchor]! as Doc).title)} ref={this._ref} style={{
+ 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");
+ return <div onPointerDown={this.onPointerDown} onClick={this.onClick} title={StrCast((this.props.Document[this.props.fieldKey === "anchor1" ? "anchor2" : "anchor1"]! as Doc).title)} ref={this._ref} style={{
cursor: "default", position: "absolute", background: c, width: "25px", height: "25px", borderRadius: "20px", textAlign: "center", left: `calc(${x}% - 12.5px)`, top: `calc(${y}% - 12.5px)`,
- transform: `scale(${1 / this.props.scale()})`,
- border: this.props.selectedLink() === this.props.index && this.props.isSelected() ? "solid 3px black" : undefined
+ pointerEvents: "all",
+ transform: `scale(${1 / this.props.ContentScaling()})`,
}} />
}
}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 19ffdf0cd..4971e6ce5 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -26,6 +26,7 @@ import { PDFBox } from "./PDFBox";
import { PresBox } from "./PresBox";
import { QueryBox } from "./QueryBox";
import { ColorBox } from "./ColorBox";
+import { DocuLinkBox } from "./DocuLinkBox";
import { PresElementBox } from "../presentationview/PresElementBox";
import { VideoBox } from "./VideoBox";
import { WebBox } from "./WebBox";
@@ -104,7 +105,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
components={{
FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, FontIconBox: FontIconBox, ButtonBox, FieldView,
CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
- PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox, PresElementBox, QueryBox, ColorBox
+ PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox, PresElementBox, QueryBox, ColorBox, DocuLinkBox
}}
bindings={this.CreateBindings()}
jsx={this.finalLayout}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d8a1841b1..f2171dc2a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -9,7 +9,7 @@ import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schem
import { ScriptField } from '../../../new_fields/ScriptField';
import { BoolCast, Cast, NumCast, PromiseValue, StrCast, FieldValue } from "../../../new_fields/Types";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
-import { emptyFunction, returnTrue, Utils } from "../../../Utils";
+import { emptyFunction, returnTrue, Utils, returnTransparent } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs, DocUtils } from "../../documents/Documents";
import { ClientUtils } from '../../util/ClientUtils';
@@ -40,7 +40,6 @@ import SharingManager from '../../util/SharingManager';
import { Scripting } from '../../util/Scripting';
import { DictationOverlay } from '../DictationOverlay';
import { CollectionViewType } from '../collections/CollectionBaseView';
-import { DocuLinkView } from './DocuLinkView';
library.add(fa.faEdit);
library.add(fa.faTrash);
@@ -93,6 +92,7 @@ export interface DocumentViewProps {
getScale: () => number;
animateBetweenIcon?: (maximize: boolean, target: number[]) => void;
ChromeHeight?: () => number;
+ layoutKey?: string;
}
export const documentSchema = createSchema({
@@ -242,7 +242,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onPointerDown = (e: React.PointerEvent): void => {
if (e.nativeEvent.cancelBubble && e.button === 0) return;
- runInAction(() => this._selectedLink = -1);
this._downX = e.clientX;
this._downY = e.clientY;
this._hitTemplateDrag = false;
@@ -625,27 +624,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
isSelected={this.isSelected}
select={this.select}
onClick={this.onClickHandler}
- layoutKey="layout"
+ layoutKey={this.props.layoutKey || "layout"}
DataDoc={this.props.DataDoc} />);
}
- linkEndpoint = (linkDoc: Doc) => Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? "anchor1" : "anchor2";
- linkOtherEndpoint = (linkDoc: Doc) => Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? "anchor2" : "anchor1";
- public setBackround(color: string) {
- let selLink = this._selectedLink !== -1 && DocListCast(this.Document.links)[this._selectedLink];
- if (selLink) {
- let both = selLink["anchor1_background"] === selLink["anchor2_background"];
- selLink[this.linkEndpoint(selLink) + "_background"] = color;
- both && (selLink[this.linkOtherEndpoint(selLink) + "_background"] = color);
- } else {
- this.Document.backgroundColor = color;
- }
- }
- @observable _selectedLink = -1;
- selectLink = action((which: number) => {
- SelectionManager.SelectDoc(this, false);
- this._selectedLink = which;
- })
- selectedLink = () => this._selectedLink;
+ linkEndpoint = (linkDoc: Doc) => Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? "layoutKey1" : "layoutKey2";
render() {
if (!this.props.Document) return (null);
@@ -717,10 +699,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
onPointerEnter={() => Doc.BrushDoc(this.props.Document)} onPointerLeave={() => Doc.UnBrushDoc(this.props.Document)}
>
- {this.props.Document.links && DocListCast(this.props.Document.links).map((d, i) =>
- <DocuLinkView Document={this.props.Document} blacklist={this.props.ContainingCollectionDoc} anchor={this.linkEndpoint(d)} otherAnchor={this.linkOtherEndpoint(d)} addDocTab={this.props.addDocTab} contentDiv={this.ContentDiv}
- scale={this.props.ContentScaling}
- isSelected={this.isSelected} link={d} index={i} selectLink={this.selectLink} selectedLink={this.selectedLink} />)}
+ {this.props.Document.links && DocListCast(this.props.Document.links).map((d, i) => <DocumentView {...this.props} backgroundColor={returnTransparent} Document={d} layoutKey={this.linkEndpoint(d)} />)}
{!showTitle && !showCaption ?
this.Document.searchFields ?
(<div className="documentView-searchWrapper">