aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts31
-rw-r--r--src/client/util/DictationManager.ts2
-rw-r--r--src/client/util/DocumentManager.ts10
-rw-r--r--src/client/util/DragManager.ts18
-rw-r--r--src/client/util/InteractionUtils.scss4
-rw-r--r--src/client/util/InteractionUtils.tsx86
-rw-r--r--src/client/util/LinkManager.ts3
-rw-r--r--src/client/util/SelectionManager.ts9
8 files changed, 110 insertions, 53 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 37eaa5f5e..2b0b2c738 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -21,6 +21,7 @@ import { MainView } from "../views/MainView";
import { DocumentType } from "../documents/DocumentTypes";
import { SchemaHeaderField } from "../../fields/SchemaHeaderField";
import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView";
+import { LabelBox } from "../views/nodes/LabelBox";
export class CurrentUserUtils {
private static curr_id: string;
@@ -86,11 +87,11 @@ export class CurrentUserUtils {
});
}
- if (doc["template-button-link"] === undefined) {
+ if (doc["template-button-link"] === undefined) { // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to.
const linkTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created
Doc.GetProto(linkTemplate).layout =
"<div>" +
- " <FormattedTextBox {...props} height='{this._headerHeight||75}px' background='{this._headerColor||`lightBlue`}' fieldKey={'header'}/>" +
+ " <FormattedTextBox {...props} height='{this._headerHeight||75}px' background='{this._headerColor||`lightGray`}' fieldKey={'header'}/>" +
" <FormattedTextBox {...props} position='absolute' top='{(this._headerHeight||75)*scale}px' height='calc({100/scale}% - {this._headerHeight||75}px)' fieldKey={'text'}/>" +
"</div>";
linkTemplate.isTemplateDoc = makeTemplate(linkTemplate, true, "linkView");
@@ -305,16 +306,20 @@ export class CurrentUserUtils {
// setup templates for different document types when they are iconified from Document Decorations
static setupDefaultIconTemplates(doc: Doc) {
if (doc["template-icon-view"] === undefined) {
- const iconView = Docs.Create.TextDocument("", {
- title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
+ const iconView = Docs.Create.LabelDocument({
+ title: "icon", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimGray",
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
});
- Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
+ // Docs.Create.TextDocument("", {
+ // title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
+ // });
+ // Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
iconView.isTemplateDoc = makeTemplate(iconView);
doc["template-icon-view"] = new PrefetchProxy(iconView);
}
if (doc["template-icon-view-rtf"] === undefined) {
const iconRtfView = Docs.Create.LabelDocument({
- title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset",
+ title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
_width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
});
iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF);
@@ -334,11 +339,11 @@ export class CurrentUserUtils {
}
if (doc["template-icons"] === undefined) {
doc["template-icons"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc,
- doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc], { title: "icon templates", _height: 75 }));
+ doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-pdf"] as Doc], { title: "icon templates", _height: 75 }));
} else {
const templateIconsDoc = Cast(doc["template-icons"], Doc, null);
const requiredTypes = [doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc,
- doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc];
+ doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-pdf"] as Doc];
DocListCastAsync(templateIconsDoc.data).then(async curIcons => {
await Promise.all(curIcons!);
requiredTypes.map(ntype => Doc.AddDocToList(templateIconsDoc, "data", ntype));
@@ -567,7 +572,7 @@ export class CurrentUserUtils {
if (doc.myCatalog === undefined) {
doc.myCatalog = new PrefetchProxy(Docs.Create.SchemaDocument([], [], {
title: "CATALOG", _height: 1000, _fitWidth: true, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false,
- childDropAction: "alias", targetDropAction: "same", treeViewExpandedView: "layout", stayInCollection: true,
+ childDropAction: "alias", targetDropAction: "same", stayInCollection: true,
}));
}
return doc.myCatalog as Doc;
@@ -596,6 +601,7 @@ export class CurrentUserUtils {
if (doc["tabs-button-library"] === undefined) {
const libraryStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], {
title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
+ treeViewTruncateTitleWidth: 150,
lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
})) as any as Doc;
doc["tabs-button-library"] = new PrefetchProxy(Docs.Create.ButtonDocument({
@@ -748,11 +754,16 @@ export class CurrentUserUtils {
}
static async updateUserDocument(doc: Doc) {
+ doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode;
doc.title = Doc.CurrentUserEmail;
doc.activeInkPen = doc;
doc.activeInkColor = StrCast(doc.activeInkColor, "rgb(0, 0, 0)");
doc.activeInkWidth = StrCast(doc.activeInkWidth, "1");
- doc.activeInkBezier = StrCast(doc.activeInkBezier, "");
+ doc.activeInkBezier = StrCast(doc.activeInkBezier, "0");
+ doc.activeFillColor = StrCast(doc.activeFillColor, "none");
+ doc.activeArrowStart = StrCast(doc.activeArrowStart, "none");
+ doc.activeArrowEnd = StrCast(doc.activeArrowEnd, "none");
+ doc.activeDash = StrCast(doc.activeDash, "0");
doc.fontSize = NumCast(doc.fontSize, 12);
doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index d8a5657c3..28b1ca6cf 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -335,7 +335,7 @@ export namespace DictationManager {
const prompt = "Press alt + r to start dictating here...";
const head = 3;
const anchor = head + prompt.length;
- const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`;
+ const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"ordered_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`;
proto.data = new RichTextField(proseMirrorState);
proto.backgroundColor = "#eeffff";
target.props.addDocTab(newBox, "onRight");
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 78c05f572..fb5d1717e 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -130,7 +130,7 @@ export class DocumentManager {
willZoom: boolean, // whether to zoom doc to take up most of screen
createViewFunc = DocumentManager.addRightSplit, // how to create a view of the doc if it doesn't exist
docContext?: Doc, // context to load that should contain the target
- linkId?: string, // link that's being followed
+ linkDoc?: Doc, // link that's being followed
closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there
originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc
finished?: () => void
@@ -140,7 +140,7 @@ export class DocumentManager {
const highlight = () => {
const finalDocView = getFirstDocView(targetDoc);
if (finalDocView) {
- finalDocView.layoutDoc.scrollToLinkID = linkId;
+ finalDocView.layoutDoc.scrollToLinkID = linkDoc?.[Id];
Doc.linkFollowHighlight(finalDocView.props.Document);
}
};
@@ -170,7 +170,7 @@ export class DocumentManager {
const targetDocContextView = getFirstDocView(targetDocContext);
targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling
if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
- targetDocContext.panTransformType = "Ease";
+ targetDocContext._viewTransition = "transform 500ms";
targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom);
// now find the target document within the context
@@ -195,7 +195,7 @@ export class DocumentManager {
const finalDocView = getFirstDocView(targetDoc);
const finalDocContextView = getFirstDocView(targetDocContext);
setTimeout(() => // if not, wait a bit to see if the context can be loaded (e.g., a PDF). wait interval heurisitic tries to guess how we're animating based on what's just become visible
- this.jumpToDocument(targetDoc, willZoom, createViewFunc, undefined, linkId, true, undefined, finished), // pass true this time for closeContextIfNotFound
+ this.jumpToDocument(targetDoc, willZoom, createViewFunc, undefined, linkDoc, true, undefined, finished), // pass true this time for closeContextIfNotFound
finalDocView ? 0 : finalDocContextView ? 250 : 2000); // so call jump to doc again and if the doc isn't found, it will be created.
}, 0);
}
@@ -224,7 +224,7 @@ export class DocumentManager {
containerDoc.currentTimecode = targetTimecode;
const targetContext = await target?.context as Doc;
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
- DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc[Id], undefined, doc, finished);
+ DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc, undefined, doc, finished);
} else {
finished?.();
}
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 21564c92e..0db3963b2 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -19,8 +19,6 @@ export function SetupDrag(
docFunc: () => Doc | Promise<Doc> | undefined,
moveFunc?: DragManager.MoveFunction,
dropAction?: dropActionType,
- treeViewId?: string,
- dontHideOnDrop?: boolean,
dragStarted?: () => void
) {
const onRowMove = async (e: PointerEvent) => {
@@ -34,8 +32,6 @@ export function SetupDrag(
const dragData = new DragManager.DocumentDragData([doc]);
dragData.dropAction = dropAction;
dragData.moveDocument = moveFunc;
- dragData.treeViewId = treeViewId;
- dragData.dontHideOnDrop = dontHideOnDrop;
DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
dragStarted?.();
}
@@ -128,7 +124,7 @@ export namespace DragManager {
draggedDocuments: Doc[];
droppedDocuments: Doc[];
dragDivName?: string;
- treeViewId?: string;
+ treeViewDoc?: Doc;
dontHideOnDrop?: boolean;
offset: number[];
dropAction: dropActionType;
@@ -215,9 +211,11 @@ export namespace DragManager {
dragData.draggedDocuments.map(d => !dragData.isSelectionMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) :
docDragData.dropAction === "alias" ? Doc.MakeAlias(d) :
docDragData.dropAction === "copy" ? Doc.MakeDelegate(d) : d);
- docDragData.dropAction !== "same" && docDragData.droppedDocuments.forEach((drop: Doc, i: number) =>
- (dragData?.removeDropProperties || []).concat(Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), [])).map(prop => drop[prop] = undefined)
- );
+ docDragData.dropAction !== "same" && docDragData.droppedDocuments.forEach((drop: Doc, i: number) => {
+ const dragProps = Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []);
+ const remProps = (dragData?.removeDropProperties || []).concat(Array.from(dragProps));
+ remProps.map(prop => drop[prop] = undefined);
+ });
batch.end();
}
return e;
@@ -328,7 +326,7 @@ export namespace DragManager {
dragLabel.style.zIndex = "100001";
dragLabel.style.fontSize = "10";
dragLabel.style.position = "absolute";
- dragLabel.innerText = "press 'a' to embed on drop";
+ // dragLabel.innerText = "press 'a' to embed on drop"; // bcz: need to move this to a status bar
dragDiv.appendChild(dragLabel);
DragManager.Root().appendChild(dragDiv);
}
@@ -351,7 +349,7 @@ export namespace DragManager {
const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement;
const rect = ele.getBoundingClientRect();
const scaleX = rect.width / ele.offsetWidth,
- scaleY = rect.height / ele.offsetHeight;
+ scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
elesCont.left = Math.min(rect.left, elesCont.left);
elesCont.top = Math.min(rect.top, elesCont.top);
elesCont.right = Math.max(rect.right, elesCont.right);
diff --git a/src/client/util/InteractionUtils.scss b/src/client/util/InteractionUtils.scss
new file mode 100644
index 000000000..6707157d4
--- /dev/null
+++ b/src/client/util/InteractionUtils.scss
@@ -0,0 +1,4 @@
+.halo {
+ opacity: 0.2;
+ stroke: black;
+} \ No newline at end of file
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index df792c9c0..edeb461e0 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -1,6 +1,8 @@
import React = require("react");
import * as beziercurve from 'bezier-curve';
import * as fitCurve from 'fit-curve';
+import "./InteractionUtils.scss";
+import { Utils } from "../../Utils";
export namespace InteractionUtils {
export const MOUSETYPE = "mouse";
@@ -89,15 +91,17 @@ export namespace InteractionUtils {
return myTouches;
}
- export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: number, strokeWidth: number, bezier: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean) {
+ export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number,
+ color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
+ dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) {
let pts: { X: number; Y: number; }[] = [];
if (shape) { //if any of the shape are true
pts = makePolygon(shape, points);
}
else if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y === points[0].Y) {
//pointer is up (first and last points are the same)
- points.pop();
const newPoints = points.reduce((p, pts) => { p.push([pts.X, pts.Y]); return p; }, [] as number[][]);
+ newPoints.pop();
const bezierCurves = fitCurve(newPoints, parseInt(bezier));
for (const curve of bezierCurves) {
@@ -111,25 +115,55 @@ export namespace InteractionUtils {
}
const strpts = pts.reduce((acc: string, pt: { X: number, Y: number }) => acc +
`${(pt.X - left - width / 2) * scalex + width / 2},
- ${(pt.Y - top - width / 2) * scaley + width / 2} `, "");
+ ${(pt.Y - top - width / 2) * scaley + width / 2} `, "");
+ const dashArray = String(Number(width) * Number(dash));
+ const defGuid = Utils.GenerateGuid();
+ const arrowDim = Math.max(0.5, 8 / Math.log(Math.max(2, strokeWidth)));
+ return (<svg fill={fill === "none" ? color : fill}> {/* setting the svg fill sets the arrowhead fill */}
+ {nodefs ? (null) : <defs>
+ {arrowStart !== "dot" && arrowEnd !== "dot" ? (null) : <marker id={`dot${defGuid}`} orient="auto" overflow="visible">
+ <circle r={1} fill="context-stroke" />
+ </marker>}
+ {arrowStart !== "arrowHead" && arrowEnd !== "arrowHead" ? (null) : <marker id={`arrowHead${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
+ <polygon points={`${arrowDim} ${-Math.max(1, arrowDim / 2)}, ${arrowDim} ${Math.max(1, arrowDim / 2)}, -1 0`} />
+ </marker>}
+ {arrowStart !== "arrowEnd" && arrowEnd !== "arrowEnd" ? (null) : <marker id={`arrowEnd${defGuid}`} orient="auto" overflow="visible" refX="1.6" refY="0" markerWidth="10" markerHeight="7">
+ <polygon points={`${2 - arrowDim} ${-Math.max(1, arrowDim / 2)}, ${2 - arrowDim} ${Math.max(1, arrowDim / 2)}, 3 0`} />
+ </marker>}
+ </defs>}
- return (
<polyline
points={strpts}
style={{
- filter: drawHalo ? "url(#dangerShine)" : undefined,
- fill: "none",
+ filter: drawHalo ? "url(#inkSelectionHalo)" : undefined,
+ fill,
opacity: strokeWidth !== width ? 0.5 : undefined,
pointerEvents: pevents as any,
stroke: color ?? "rgb(0, 0, 0)",
strokeWidth: strokeWidth,
strokeLinejoin: "round",
- strokeLinecap: "round"
+ strokeLinecap: "round",
+ strokeDasharray: dashArray
}}
+ markerStart={`url(#${arrowStart + defGuid})`}
+ markerEnd={`url(#${arrowEnd + defGuid})`}
/>
- );
+
+ </svg>);
}
+ // export function makeArrow() {
+ // return (
+ // InkOptionsMenu.Instance.getColors().map(color => {
+ // const id1 = "arrowHeadTest" + color;
+ // console.log(color);
+ // <marker id={id1} orient="auto" overflow="visible" refX="0" refY="1" markerWidth="10" markerHeight="7">
+ // <polygon points="0 0, 3 1, 0 2" fill={"#" + color} />
+ // </marker>;
+ // })
+ // );
+ // }
+
export function makePolygon(shape: string, points: { X: number, Y: number }[]) {
if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y + 1 === points[0].Y) {
//pointer is up (first and last points are the same)
@@ -199,24 +233,24 @@ export namespace InteractionUtils {
}
points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((top - centerY), 2))) + centerX, Y: top });
return points;
- case "arrow":
- const x1 = left;
- const y1 = top;
- const x2 = right;
- const y2 = bottom;
- const L1 = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + (Math.pow(Math.abs(y1 - y2), 2)));
- const L2 = L1 / 5;
- const angle = 0.785398;
- const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle));
- const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle));
- const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle));
- const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle));
- points.push({ X: x1, Y: y1 });
- points.push({ X: x2, Y: y2 });
- points.push({ X: x3, Y: y3 });
- points.push({ X: x4, Y: y4 });
- points.push({ X: x2, Y: y2 });
- return points;
+ // case "arrow":
+ // const x1 = left;
+ // const y1 = top;
+ // const x2 = right;
+ // const y2 = bottom;
+ // const L1 = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + (Math.pow(Math.abs(y1 - y2), 2)));
+ // const L2 = L1 / 5;
+ // const angle = 0.785398;
+ // const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle));
+ // const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle));
+ // const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle));
+ // const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle));
+ // points.push({ X: x1, Y: y1 });
+ // points.push({ X: x2, Y: y2 });
+ // points.push({ X: x3, Y: y3 });
+ // points.push({ X: x4, Y: y4 });
+ // points.push({ X: x2, Y: y2 });
+ // return points;
case "line":
points.push({ X: left, Y: top });
points.push({ X: right, Y: bottom });
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 47b2541bd..0aec81ab0 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -70,6 +70,9 @@ export class LinkManager {
const protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null));
return protomatch1 || protomatch2 || Doc.AreProtosEqual(link, anchor);
});
+ DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => {
+ related.push(...LinkManager.Instance.getAllRelatedLinks(anno));
+ });
return related;
}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 05515e502..024532f90 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -3,6 +3,8 @@ import { Doc } from "../../fields/Doc";
import { DocumentView } from "../views/nodes/DocumentView";
import { computedFn } from "mobx-utils";
import { List } from "../../fields/List";
+import { Scripting } from "./Scripting";
+import { DocumentManager } from "./DocumentManager";
export namespace SelectionManager {
@@ -10,7 +12,6 @@ export namespace SelectionManager {
@observable IsDragging: boolean = false;
SelectedDocuments: ObservableMap<DocumentView, boolean> = new ObservableMap();
-
@action
SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
// if doc is not in SelectedDocuments, add it
@@ -82,3 +83,9 @@ export namespace SelectionManager {
}
}
+
+Scripting.addGlobal(function selectDoc(doc: any) {
+ const view = DocumentManager.Instance.getDocumentView(doc);
+ view && SelectionManager.SelectDoc(view, false);
+ //Doc.UserDoc().activeSelection = new List([doc]);
+}); \ No newline at end of file