aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2020-04-03 17:15:21 -0700
committerSam Wilkins <samwilkins333@gmail.com>2020-04-03 17:15:21 -0700
commita0e4ae65f81c62ac08761359e60b996f0e839559 (patch)
tree67a08d09fd1c7c722369dcef8c6ada7ccc54543a /src/client/views/collections
parent781c50b1dafffa7558e718fc4ff9b415139a87bf (diff)
parent7259b8562e8097ff5b6708cf15bb2f33e9efb148 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx8
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx4
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx3
-rw-r--r--src/client/views/collections/CollectionStaffView.tsx12
-rw-r--r--src/client/views/collections/CollectionSubView.tsx16
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx4
-rw-r--r--src/client/views/collections/CollectionView.tsx8
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx124
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx54
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx4
13 files changed, 130 insertions, 123 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 2ee39bc0d..4e1e76f39 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -513,7 +513,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
dragData.dropAction = doc.dropAction as dropActionType;
DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
}
- }
+ };
let rendered = false;
tab.buttonDisposer = reaction(() => ((view: Opt<DocumentView>) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)),
(views) => {
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 79b5d7bb7..f124fe21b 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -157,6 +157,8 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
Document: this.props.rowProps.original,
DataDoc: this.props.rowProps.original,
LibraryPath: [],
+ dropAction: "alias",
+ bringToFront: emptyFunction,
fieldKey: this.props.rowProps.column.id as string,
ContainingCollectionView: this.props.CollectionView,
ContainingCollectionDoc: this.props.CollectionView && this.props.CollectionView.props.Document,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a4502cced..981438513 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -51,8 +51,7 @@ const columnTypes: Map<string, ColumnType> = new Map([
@observer
export class CollectionSchemaView extends CollectionSubView(doc => doc) {
- private _mainCont?: HTMLDivElement;
- private _startPreviewWidth = 0;
+ private _previewCont?: HTMLDivElement;
private DIVIDER_WIDTH = 4;
@observable previewDoc: Doc | undefined = undefined;
@@ -64,7 +63,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
@computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
private createTarget = (ele: HTMLDivElement) => {
- this._mainCont = ele;
+ this._previewCont = ele;
super.CreateDropTarget(ele);
}
@@ -81,12 +80,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
}
onDividerDown = (e: React.PointerEvent) => {
- this._startPreviewWidth = this.previewWidth();
setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, action(() => this.toggleExpander()));
}
@action
onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
- const nativeWidth = this._mainCont!.getBoundingClientRect();
+ const nativeWidth = this._previewCont!.getBoundingClientRect();
const minWidth = 40;
const maxWidth = 1000;
const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9d5500e1a..076dd3629 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -63,7 +63,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap);
const style = this.isStackingView ? { width: width(), marginTop: this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` };
return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} >
- {this.getDisplayDoc(d, this.props.DataDoc, dxf, width)}
+ {this.getDisplayDoc(d, (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc, dxf, width)}
</div>;
});
}
@@ -106,7 +106,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
fields.delete(header);
sectionHeaders.splice(sectionHeaders.indexOf(header), 1);
changed = true;
- })
+ });
}
changed && setTimeout(action(() => { if (this.sectionHeaders) { this.sectionHeaders.length = 0; this.sectionHeaders.push(...sectionHeaders); } }), 0);
return fields;
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 646b433bf..0a48c95e4 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -131,7 +131,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0);
const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3;
newDoc.heading = heading;
- return this.props.parent.props.addDocument(newDoc);
+ this.props.parent.props.addDocument(newDoc);
+ return false;
}
@action
diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx
index 8c7e113b2..5b9a69bf7 100644
--- a/src/client/views/collections/CollectionStaffView.tsx
+++ b/src/client/views/collections/CollectionStaffView.tsx
@@ -1,22 +1,20 @@
import { CollectionSubView } from "./CollectionSubView";
-import { Transform } from "../../util/Transform";
import React = require("react");
import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx";
-import { Doc } from "../../../new_fields/Doc";
import { NumCast } from "../../../new_fields/Types";
import "./CollectionStaffView.scss";
import { observer } from "mobx-react";
@observer
export class CollectionStaffView extends CollectionSubView(doc => doc) {
- private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(0, -this._mainCont.current!.scrollTop);
- private _mainCont = React.createRef<HTMLDivElement>();
private _reactionDisposer: IReactionDisposer | undefined;
@observable private _staves = NumCast(this.props.Document.staves);
+ componentWillUnmount() {
+ this._reactionDisposer?.();
+ }
componentDidMount = () => {
- this._reactionDisposer = reaction(
- () => NumCast(this.props.Document.staves),
+ this._reactionDisposer = reaction(() => NumCast(this.props.Document.staves),
(staves) => runInAction(() => this._staves = staves)
);
@@ -47,7 +45,7 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) {
}
render() {
- return <div className="collectionStaffView" ref={this._mainCont}>
+ return <div className="collectionStaffView">
{this.staves}
{this.addStaffButton}
</div>;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 39621b75c..70927cf22 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,5 +1,4 @@
import { action, computed, IReactionDisposer, reaction } from "mobx";
-import * as rp from 'request-promise';
import CursorField from "../../../new_fields/CursorField";
import { Doc, DocListCast, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
@@ -107,7 +106,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).filter(pair => pair.layout);
- return validPairs.map(({ data, layout }) => ({ data, layout: layout! })); // this mapping is a bit of a hack to coerce types
+ return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
get childDocList() {
return Cast(this.dataField, listSpec(Doc));
@@ -124,8 +123,17 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
filterFacets[key][value] = modifiers;
}
- const dfield = this.dataField;
- const rawdocs = (dfield instanceof Doc) ? [dfield] : Cast(dfield, listSpec(Doc), this.props.Document.rootDocument && !this.props.annotationsKey ? [Cast(this.props.Document.rootDocument, Doc, null)] : []);
+ let rawdocs: (Doc | Promise<Doc>)[] = [];
+ if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list;
+ rawdocs = [this.dataField];
+ } else if (Cast(this.dataField, listSpec(Doc), null)) { // otherwise, if the collection data is a list, then use it.
+ rawdocs = Cast(this.dataField, listSpec(Doc), null);
+ } else { // Finally, if it's not a doc or a list and the document is a template, we try to render the root doc.
+ // For example, if an image doc is rendered with a slide template, the template will try to render the data field as a collection.
+ // Since the data field is actually an image, we set the list of documents to the singleton of root document's proto which will be an image.
+ const rootDoc = Cast(this.props.Document.rootDocument, Doc, null);
+ rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : [];
+ }
const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc);
const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 64832506b..4f77e8b0e 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -31,7 +31,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
componentDidMount() {
this.props.Document._freezeOnDrop = true;
const childDetailed = this.props.Document.childDetailed; // bcz: needs to be here to make sure the childDetailed layout template has been loaded when the first item is clicked;
- const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
+ const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(containingCollection.childDetailed, alias, 'layout_detailView'); alias.layoutKey='layout_detailedView'; alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "string", containingCollection: Doc.name, shiftKey: "boolean" });
this.props.Document._fitToBox = true;
if (!this.props.Document.onViewDefClick) {
@@ -146,7 +146,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
back
</button>
<EditableView {...newEditableViewProps} display={"inline"} menuCallback={this.menuCallback} />
- </div>
+ </div>;
}
render() {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index edb9fd930..df1770ffe 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -299,7 +299,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, doc)).filter(pair => pair.layout);
- return validPairs.map(({ data, layout }) => ({ data, layout: layout! })); // this mapping is a bit of a hack to coerce types
+ return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
get childDocList() {
return Cast(this.dataField, listSpec(Doc));
@@ -429,9 +429,9 @@ export class CollectionView extends Touchable<FieldViewProps> {
Document={facetCollection}
backgroundColor={this.filterBackground}
fieldKey={`${this.props.fieldKey}-filter`}
- moveDocument={(doc: Doc) => false}
- removeDocument={(doc: Doc) => false}
- addDocument={(doc: Doc) => false} />
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ addDocument={returnFalse} />
</div>
</div>;
}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 53ee4c547..2d565d9db 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -267,10 +267,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
if (collapsed) return null;
switch (this.props.type) {
- case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
default: return null;
}
}
@@ -355,7 +355,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
immediate: (source: Doc[]) => Doc.setChildLayout(this.target, source?.[0]),
initialize: emptyFunction,
};
- DragManager.StartButtonDrag([this._viewRef.current!], c.script, c.title,
+ DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title),
{ target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY);
return true;
}, emptyFunction, emptyFunction);
@@ -600,7 +600,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
togglePreview = () => {
const dividerWidth = 4;
const borderWidth = Number(COLLECTION_BORDER_WIDTH);
- const panelWidth = this.props.PanelWidth();
+ const panelWidth = this.props.CollectionView.props.PanelWidth();
const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 85b75f5cb..49ca024a2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, IReactionDisposer } from "mobx";
+import { computed } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
@@ -7,70 +7,12 @@ import { DocumentView } from "../../nodes/DocumentView";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
-import { Utils } from "../../../../Utils";
+import { Utils, emptyFunction } from "../../../../Utils";
import { SelectionManager } from "../../../util/SelectionManager";
import { DocumentType } from "../../../documents/DocumentTypes";
-import { StrCast } from "../../../../new_fields/Types";
@observer
export class CollectionFreeFormLinksView extends React.Component {
-
- _brushReactionDisposer?: IReactionDisposer;
- componentDidMount() {
- // this._brushReactionDisposer = reaction(
- // () => {
- // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
- // return { doclist: doclist ? doclist : [], xs: doclist.map(d => d.x) };
- // },
- // () => {
- // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
- // let views = doclist ? doclist.filter(doc => StrCast(doc.backgroundLayout).indexOf("istogram") !== -1) : [];
- // views.forEach((dstDoc, i) => {
- // views.forEach((srcDoc, j) => {
- // let dstTarg = dstDoc;
- // let srcTarg = srcDoc;
- // let x1 = NumCast(srcDoc.x);
- // let x2 = NumCast(dstDoc.x);
- // let x1w = NumCast(srcDoc.width, -1);
- // let x2w = NumCast(dstDoc.width, -1);
- // if (x1w < 0 || x2w < 0 || i === j) { }
- // else {
- // let findBrush = (field: (Doc | Promise<Doc>)[]) => field.findIndex(brush => {
- // let bdocs = brush instanceof Doc ? Cast(brush.brushingDocs, listSpec(Doc), []) : undefined;
- // return bdocs && bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false;
- // });
- // let brushAction = (field: (Doc | Promise<Doc>)[]) => {
- // let found = findBrush(field);
- // if (found !== -1) {
- // field.splice(found, 1);
- // }
- // };
- // if (Math.abs(x1 + x1w - x2) < 20) {
- // let linkDoc: Doc = new Doc();
- // linkDoc.title = "Histogram Brush";
- // linkDoc.linkDescription = "Brush between " + StrCast(srcTarg.title) + " and " + StrCast(dstTarg.Title);
- // linkDoc.brushingDocs = new List([dstTarg, srcTarg]);
-
- // brushAction = (field: (Doc | Promise<Doc>)[]) => {
- // if (findBrush(field) === -1) {
- // field.push(linkDoc);
- // }
- // };
- // }
- // if (dstTarg.brushingDocs === undefined) dstTarg.brushingDocs = new List<Doc>();
- // if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List<Doc>();
- // let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []);
- // let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []);
- // brushAction(dstBrushDocs);
- // brushAction(srcBrushDocs);
- // }
- // });
- // });
- // });
- }
- componentWillUnmount() {
- this._brushReactionDisposer && this._brushReactionDisposer();
- }
@computed
get uniqueConnections() {
const connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
@@ -87,8 +29,10 @@ export class CollectionFreeFormLinksView extends React.Component {
}
return drawnPairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]);
- return connections.filter(c => c.a.props.Document.type === DocumentType.LINK && StrCast(c.a.props.Document.layout).includes("DocuLinkBox")) // get rid of the filter to show links to documents in addition to document anchors
- .map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
+ return connections.filter(c =>
+ c.a.props.layoutKey && c.b.props.layoutKey && c.a.props.Document.type === DocumentType.LINK &&
+ c.a.props.bringToFront !== emptyFunction && c.b.props.bringToFront !== emptyFunction // this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed
+ ).map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
}
render() {
@@ -99,4 +43,60 @@ export class CollectionFreeFormLinksView extends React.Component {
{this.props.children}
</div>;
}
+ // _brushReactionDisposer?: IReactionDisposer;
+ // componentDidMount() {
+ // this._brushReactionDisposer = reaction(
+ // () => {
+ // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
+ // return { doclist: doclist ? doclist : [], xs: doclist.map(d => d.x) };
+ // },
+ // () => {
+ // let doclist = DocListCast(this.props.Document[this.props.fieldKey]);
+ // let views = doclist ? doclist.filter(doc => StrCast(doc.backgroundLayout).indexOf("istogram") !== -1) : [];
+ // views.forEach((dstDoc, i) => {
+ // views.forEach((srcDoc, j) => {
+ // let dstTarg = dstDoc;
+ // let srcTarg = srcDoc;
+ // let x1 = NumCast(srcDoc.x);
+ // let x2 = NumCast(dstDoc.x);
+ // let x1w = NumCast(srcDoc.width, -1);
+ // let x2w = NumCast(dstDoc.width, -1);
+ // if (x1w < 0 || x2w < 0 || i === j) { }
+ // else {
+ // let findBrush = (field: (Doc | Promise<Doc>)[]) => field.findIndex(brush => {
+ // let bdocs = brush instanceof Doc ? Cast(brush.brushingDocs, listSpec(Doc), []) : undefined;
+ // return bdocs && bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false;
+ // });
+ // let brushAction = (field: (Doc | Promise<Doc>)[]) => {
+ // let found = findBrush(field);
+ // if (found !== -1) {
+ // field.splice(found, 1);
+ // }
+ // };
+ // if (Math.abs(x1 + x1w - x2) < 20) {
+ // let linkDoc: Doc = new Doc();
+ // linkDoc.title = "Histogram Brush";
+ // linkDoc.linkDescription = "Brush between " + StrCast(srcTarg.title) + " and " + StrCast(dstTarg.Title);
+ // linkDoc.brushingDocs = new List([dstTarg, srcTarg]);
+
+ // brushAction = (field: (Doc | Promise<Doc>)[]) => {
+ // if (findBrush(field) === -1) {
+ // field.push(linkDoc);
+ // }
+ // };
+ // }
+ // if (dstTarg.brushingDocs === undefined) dstTarg.brushingDocs = new List<Doc>();
+ // if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List<Doc>();
+ // let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []);
+ // let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []);
+ // brushAction(dstBrushDocs);
+ // brushAction(srcBrushDocs);
+ // }
+ // });
+ // });
+ // });
+ // }
+ // componentWillUnmount() {
+ // this._brushReactionDisposer?.();
+ // }
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a0dd4f2de..2871fe192 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -500,36 +500,36 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@action
pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
- // I think it makes sense for the marquee menu to go away when panned. -syip2
- MarqueeOptionsMenu.Instance && MarqueeOptionsMenu.Instance.fadeOut(true);
+ // bcz: theres should be a better way of doing these than referencing these static instances directly
+ MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2
+ PDFMenu.Instance.fadeOut(true);
- let x = this.Document._panX || 0;
- let y = this.Document._panY || 0;
- const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout);
const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
- if (!this.isAnnotationOverlay && docs.length && this.childDataProvider(docs[0])) {
- PDFMenu.Instance.fadeOut(true);
- const minx = this.childDataProvider(docs[0]).x;
- const miny = this.childDataProvider(docs[0]).y;
- const maxx = this.childDataProvider(docs[0]).width + minx;
- const maxy = this.childDataProvider(docs[0]).height + miny;
- const ranges = docs.filter(doc => doc && this.childDataProvider(doc)).reduce((range, doc) => {
- const x = this.childDataProvider(doc).x;
- const y = this.childDataProvider(doc).y;
- const xe = this.childDataProvider(doc).width + x;
- const ye = this.childDataProvider(doc).height + y;
- return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
- [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
- }, [[minx, maxx], [miny, maxy]]);
-
- const cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1;
- const panelDim = [this.props.PanelWidth() * cscale / this.zoomScaling(), this.props.PanelHeight() * cscale / this.zoomScaling()];
- if (ranges[0][0] - dx > (this.panX() + panelDim[0] / 2)) x = ranges[0][1] + panelDim[0] / 2;
- if (ranges[0][1] - dx < (this.panX() - panelDim[0] / 2)) x = ranges[0][0] - panelDim[0] / 2;
- if (ranges[1][0] - dy > (this.panY() + panelDim[1] / 2)) y = ranges[1][1] + panelDim[1] / 2;
- if (ranges[1][1] - dy < (this.panY() - panelDim[1] / 2)) y = ranges[1][0] - panelDim[1] / 2;
+ let x = (this.Document._panX || 0) - dx;
+ let y = (this.Document._panY || 0) - dy;
+ if (!this.isAnnotationOverlay) {
+ // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds
+ const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout);
+ const measuredDocs = docs.filter(doc => doc && this.childDataProvider(doc)).map(doc => this.childDataProvider(doc));
+ if (measuredDocs.length) {
+ const ranges = measuredDocs.reduce(({ xrange, yrange }, { x, y, width, height }) => // computes range of content
+ ({
+ xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) },
+ yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) }
+ })
+ , {
+ xrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE },
+ yrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE }
+ });
+
+ const panelDim = [this.props.PanelWidth() / this.zoomScaling(), this.props.PanelHeight() / this.zoomScaling()];
+ if (ranges.xrange.min > (this.panX() + panelDim[0] / 2)) x = ranges.xrange.max + panelDim[0] / 2; // snaps pan position of range of content goes out of bounds
+ if (ranges.xrange.max < (this.panX() - panelDim[0] / 2)) x = ranges.xrange.min - panelDim[0] / 2;
+ if (ranges.yrange.min > (this.panY() + panelDim[1] / 2)) y = ranges.yrange.max + panelDim[1] / 2;
+ if (ranges.yrange.max < (this.panY() - panelDim[1] / 2)) y = ranges.yrange.min - panelDim[1] / 2;
+ }
}
- this.setPan(x - dx, y - dy);
+ this.setPan(x, y);
this._lastX = e.clientX;
this._lastY = e.clientY;
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 0f94bffd6..276a49570 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -4,7 +4,7 @@ import { Doc, DocListCast, DataSym, WidthSym, HeightSym } from "../../../../new_
import { InkField, InkData } from "../../../../new_fields/InkField";
import { List } from "../../../../new_fields/List";
import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField";
-import { Cast, NumCast, FieldValue } from "../../../../new_fields/Types";
+import { Cast, NumCast, FieldValue, StrCast } from "../../../../new_fields/Types";
import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
import { Utils } from "../../../../Utils";
import { Docs, DocUtils } from "../../../documents/Documents";
@@ -107,7 +107,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
});
} else if (!e.ctrlKey) {
FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : "";
- let tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" });
+ const tbox = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" });
const template = FormattedTextBox.DefaultLayout;
if (template instanceof Doc) {
tbox._width = NumCast(template._width);