aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-09-22 17:16:18 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-09-22 17:16:18 -0400
commitf82458be8bc8beaab387cc2813b7b18c9b3caac2 (patch)
tree4d547ad7f2623257cc585e16df17c05c8979e06a /src/client/views/collections/collectionFreeForm
parentf529d7d22162689c08830418da67a89778111e16 (diff)
initial commit post master merge
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx474
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx78
5 files changed, 231 insertions, 331 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
index 2a64a7afb..cfd18ad35 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
@@ -1,8 +1,9 @@
.collectionfreeformlinkview-linkLine {
stroke: black;
transform: translate(10000px,10000px);
- // opacity: 0.5;
+ opacity: 0.8;
pointer-events: all;
+ stroke-width: 3px;
}
.collectionfreeformlinkview-linkCircle {
stroke: rgb(0,0,0);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 12771d11e..df089eb00 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -50,7 +50,6 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
return (
<>
<line key="linkLine" className="collectionfreeformlinkview-linkLine"
- style={{ strokeWidth: `${3}` }}
x1={`${x1}`} y1={`${y1}`}
x2={`${x2}`} y2={`${y2}`} />
{/* <circle key="linkCircle" className="collectionfreeformlinkview-linkCircle"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index a25627dd1..a81f5315a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -79,15 +79,15 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
if (containerDoc) {
equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.proto!);
}
- if (view.props.ContainingCollectionView) {
- let collid = view.props.ContainingCollectionView.props.Document[Id];
+ 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.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document);
+ return equalViews.filter(sv => sv.props.ContainingCollectionDoc === this.props.Document);
}
@computed
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f7bda0a26..eb738d783 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -8,10 +8,10 @@ import { Id } from "../../../../new_fields/FieldSymbols";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { createSchema, makeInterface } from "../../../../new_fields/Schema";
import { ScriptField } from "../../../../new_fields/ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../../new_fields/Types";
+import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue, DateCast } from "../../../../new_fields/Types";
import { emptyFunction, returnEmptyString, returnOne, Utils } from "../../../../Utils";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
-import { Docs } from "../../../documents/Documents";
+import { Docs, DocumentOptions } from "../../../documents/Documents";
import { DocumentType } from "../../../documents/DocumentTypes";
import { DocumentManager } from "../../../util/DocumentManager";
import { DragManager } from "../../../util/DragManager";
@@ -24,9 +24,9 @@ import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss"
import { ContextMenu } from "../../ContextMenu";
import { ContextMenuProps } from "../../ContextMenuItem";
import { InkingCanvas } from "../../InkingCanvas";
-import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
+import { CollectionFreeFormDocumentView, positionSchema } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentContentsView } from "../../nodes/DocumentContentsView";
-import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView";
+import { DocumentViewProps, documentSchema } from "../../nodes/DocumentView";
import { pageSchema } from "../../nodes/ImageBox";
import { OverlayElementOptions, OverlayView } from "../../OverlayView";
import PDFMenu from "../../pdf/PDFMenu";
@@ -51,6 +51,9 @@ export const panZoomSchema = createSchema({
scale: "number",
arrangeScript: ScriptField,
arrangeInit: ScriptField,
+ useClusters: "boolean",
+ isRuleProvider: "boolean",
+ fitToBox: "boolean"
});
export interface ViewDefBounds {
@@ -161,6 +164,7 @@ export namespace PivotView {
y={pos.y}
width={pos.width}
height={pos.height}
+ transition={"transform 1s"}
jitterRotation={NumCast(target.props.Document.jitterRotation)}
{...target.getChildDocumentViewProps(doc)}
/>,
@@ -181,8 +185,8 @@ export namespace PivotView {
}
-type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema, typeof pageSchema]>;
-const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema);
+type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof documentSchema, typeof positionSchema, typeof pageSchema]>;
+const PanZoomDocument = makeInterface(panZoomSchema, documentSchema, positionSchema, pageSchema);
@observer
export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@@ -190,35 +194,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
private _lastY: number = 0;
private get _pwidth() { return this.props.PanelWidth(); }
private get _pheight() { return this.props.PanelHeight(); }
- private inkKey = "ink";
- private _childLayoutDisposer?: IReactionDisposer;
- private _childDisposer?: IReactionDisposer;
-
- componentDidMount() {
- this._childDisposer = reaction(() => this.childDocs,
- async (childDocs) => {
- let childLayout = Cast(this.props.Document.childLayout, Doc) as Doc;
- childLayout && childDocs.map(async doc => {
- if (!Doc.AreProtosEqual(childLayout, (await doc).layout as Doc)) {
- Doc.ApplyTemplateTo(childLayout, doc, undefined);
- }
- });
- });
- this._childLayoutDisposer = reaction(() => Cast(this.props.Document.childLayout, Doc),
- async (childLayout) => {
- this.childDocs.map(async doc => {
- if (!Doc.AreProtosEqual(childLayout as Doc, (await doc).layout as Doc)) {
- Doc.ApplyTemplateTo(childLayout as Doc, doc, undefined);
- }
- });
- });
- }
- componentWillUnmount() {
- this._childDisposer && this._childDisposer();
- this._childLayoutDisposer && this._childLayoutDisposer();
- }
-
- get parentScaling() {
+ private get parentScaling() {
return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1;
}
@@ -249,7 +225,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
return res;
}
- @computed get fitToBox() { return this.props.fitToBox || this.props.Document.fitToBox; }
+ @computed get fitToBox() { return this.props.fitToBox || this.Document.fitToBox; }
@computed get nativeWidth() { return this.fitToBox ? 0 : this.Document.nativeWidth || 0; }
@computed get nativeHeight() { return this.fitToBox ? 0 : this.Document.nativeHeight || 0; }
public get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } // fieldExt will be "" or "annotation". should maybe generalize this, or make it more specific (ie, 'annotation' instead of 'fieldExt')
@@ -265,29 +241,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
private addLiveTextBox = (newBox: Doc) => {
FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
- newBox.heading = 1;
- for (let child of this.childDocs) {
- if (child.heading === 1) {
- newBox.heading = 2;
- }
+ let maxHeading = this.childDocs.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0);
+ let heading = maxHeading === 0 || this.childDocs.length === 0 ? 1 : maxHeading === 1 ? 2 : 0;
+ if (heading === 0) {
+ let sorted = this.childDocs.filter(d => d.type === DocumentType.TEXT && d.data_ext instanceof Doc && d.data_ext.lastModified).sort((a, b) => DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date > DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? 1 :
+ DateCast((Cast(a.data_ext, Doc) as Doc).lastModified).date < DateCast((Cast(b.data_ext, Doc) as Doc).lastModified).date ? -1 : 0);
+ heading = !sorted.length ? Math.max(1, maxHeading) : NumCast(sorted[sorted.length - 1].heading) === 1 ? 2 : NumCast(sorted[sorted.length - 1].heading);
}
- PromiseValue(Cast(this.props.Document.ruleProvider, Doc)).then(ruleProvider => {
- if (!ruleProvider) ruleProvider = this.props.Document;
- // saturation shift
- // let col = NumCast(ruleProvider["ruleColor_" + NumCast(newBox.heading)]);
- // let back = Utils.fromRGBAstr(StrCast(this.props.Document.backgroundColor));
- // let hsl = Utils.RGBToHSL(back.r, back.g, back.b);
- // let newcol = { h: hsl.h, s: hsl.s + col, l: hsl.l };
- // col && (Doc.GetProto(newBox).backgroundColor = Utils.toRGBAstr(Utils.HSLtoRGB(newcol.h, newcol.s, newcol.l)));
- // OR transparency set
- let col = StrCast(ruleProvider["ruleColor_" + NumCast(newBox.heading)]);
- (newBox.backgroundColor === newBox.defaultBackgroundColor) && col && (Doc.GetProto(newBox).backgroundColor = col);
-
- let round = StrCast(ruleProvider["ruleRounding_" + NumCast(newBox.heading)]);
- round && (Doc.GetProto(newBox).borderRounding = round);
- newBox.ruleProvider = ruleProvider;
- this.addDocument(newBox, false);
- });
+ !this.Document.isRuleProvider && (newBox.heading = heading);
+ this.addDocument(newBox, false);
}
private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
this.props.addDocument(newBox, false);
@@ -302,14 +264,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
public getActiveDocuments = () => {
const curPage = FieldValue(this.Document.curPage, -1);
- return this.childDocs.filter(doc => {
- var page = NumCast(doc.page, -1);
+ return this.childLayoutPairs.filter(pair => {
+ var page = NumCast(pair.layout.page, -1);
return page === curPage || page === -1;
- });
+ }).map(pair => pair.layout);
}
@computed get fieldExtensionDoc() {
- return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true");
+ return Doc.fieldExtensionDoc(this.props.DataDoc || this.props.Document, this.props.fieldKey);
}
intersectRect(r1: { left: number, top: number, width: number, height: number },
@@ -342,8 +304,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (de.data instanceof DragManager.DocumentDragData) {
if (de.data.droppedDocuments.length) {
let z = NumCast(de.data.droppedDocuments[0].z);
- let x = (z ? xpo : xp) - de.data.xOffset;
- let y = (z ? ypo : yp) - de.data.yOffset;
+ let x = (z ? xpo : xp) - de.data.offset[0];
+ let y = (z ? ypo : yp) - de.data.offset[1];
let dropX = NumCast(de.data.droppedDocuments[0].x);
let dropY = NumCast(de.data.droppedDocuments[0].y);
de.data.droppedDocuments.forEach(d => {
@@ -366,8 +328,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
else if (de.data instanceof DragManager.AnnotationDragData) {
if (de.data.dropDocument) {
let dragDoc = de.data.dropDocument;
- let x = xp - de.data.xOffset;
- let y = yp - de.data.yOffset;
+ let x = xp - de.data.offset[0];
+ let y = yp - de.data.offset[1];
let dropX = NumCast(de.data.dropDocument.x);
let dropY = NumCast(de.data.dropDocument.y);
dragDoc.x = x + NumCast(dragDoc.x) - dropX;
@@ -383,7 +345,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
tryDragCluster(e: PointerEvent) {
let probe = this.getTransform().transformPoint(e.clientX, e.clientY);
- let cluster = this.childDocs.reduce((cluster, cd) => {
+ let cluster = this.childLayoutPairs.map(pair => pair.layout).reduce((cluster, cd) => {
let cx = NumCast(cd.x) - this._clusterDistance;
let cy = NumCast(cd.y) - this._clusterDistance;
let cw = NumCast(cd.width) + 2 * this._clusterDistance;
@@ -394,7 +356,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
return cluster;
}, -1);
if (cluster !== -1) {
- let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster);
+ let eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => NumCast(cd.cluster) === cluster);
// hacky way to get a list of DocumentViews in the current view given a list of Documents in the current view
let prevSelected = SelectionManager.SelectedDocuments();
@@ -403,13 +365,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
SelectionManager.DeselectAll();
prevSelected.map(dv => SelectionManager.SelectDoc(dv, true));
- let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined));
+ let de = new DragManager.DocumentDragData(eles);
de.moveDocument = this.props.moveDocument;
const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0);
- const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top);
+ de.offset = this.getTransform().transformDirection(e.x - left, e.y - top);
de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined;
- de.xOffset = xoff;
- de.yOffset = yoff;
DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, e.clientX, e.clientY, {
handlers: { dragComplete: action(emptyFunction) },
hideSource: !de.dropAction
@@ -423,9 +383,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@undoBatch
@action
- updateClusters() {
+ updateClusters(useClusters: boolean) {
+ this.Document.useClusters = useClusters;
this.sets.length = 0;
- this.childDocs.map(c => {
+ this.childLayoutPairs.map(pair => pair.layout).map(c => {
let included = [];
for (let i = 0; i < this.sets.length; i++) {
for (let member of this.sets[i]) {
@@ -453,20 +414,21 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@undoBatch
@action
updateCluster(doc: Doc) {
+ let childLayouts = this.childLayoutPairs.map(pair => pair.layout);
if (this.props.Document.useClusters) {
this.sets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1));
let preferredInd = NumCast(doc.cluster);
doc.cluster = -1;
this.sets.map((set, i) => set.map(member => {
- if (doc.cluster === -1 && Doc.IndexOf(member, this.childDocs) !== -1 && this.boundsOverlap(doc, member)) {
+ if (doc.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && this.boundsOverlap(doc, member)) {
doc.cluster = i;
}
}));
- if (doc.cluster === -1 && preferredInd !== -1 && (!this.sets[preferredInd] || !this.sets[preferredInd].filter(member => Doc.IndexOf(member, this.childDocs) !== -1).length)) {
+ if (doc.cluster === -1 && preferredInd !== -1 && (!this.sets[preferredInd] || !this.sets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) {
doc.cluster = preferredInd;
}
this.sets.map((set, i) => {
- if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, this.childDocs) !== -1).length) {
+ if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
doc.cluster = i;
}
});
@@ -481,22 +443,22 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
getClusterColor = (doc: Doc) => {
- if (this.props.Document.useClusters) {
- let cluster = NumCast(doc.cluster);
+ let clusterColor = "";
+ let cluster = NumCast(doc.cluster);
+ if (this.Document.useClusters) {
if (this.sets.length <= cluster) {
- setTimeout(() => this.updateCluster(doc), 0);// this.updateClusters(), 0);
- return "";
+ setTimeout(() => this.updateCluster(doc), 0);
+ } else {
+ // choose a cluster color from a palette
+ let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"];
+ clusterColor = colors[cluster % colors.length];
+ let set = this.sets.length > cluster ? this.sets[cluster].filter(s => s.backgroundColor && (s.backgroundColor !== s.defaultBackgroundColor)) : undefined;
+ // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
+ set && set.filter(s => !s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
+ set && set.filter(s => s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
}
- let set = this.sets.length > cluster ? this.sets[cluster] : undefined;
- let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"];
- let clusterColor = colors[cluster % colors.length];
- set && set.filter(s => !s.isBackground).map(s =>
- s.backgroundColor && s.backgroundColor !== s.defaultBackgroundColor && (clusterColor = StrCast(s.backgroundColor)));
- set && set.filter(s => s.isBackground).map(s =>
- s.backgroundColor && s.backgroundColor !== s.defaultBackgroundColor && (clusterColor = StrCast(s.backgroundColor)));
- return clusterColor;
}
- return "";
+ return clusterColor;
}
@action
@@ -528,40 +490,39 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
let x = this.Document.panX || 0;
let y = this.Document.panY || 0;
- let docs = this.childDocs || [];
+ let docs = this.childLayoutPairs.map(pair => pair.layout);
let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
- // if (!this.isAnnotationOverlay) {
- // PDFMenu.Instance.fadeOut(true);
- // let minx = docs.length ? NumCast(docs[0].x) : 0;
- // let maxx = docs.length ? NumCast(docs[0].width) + minx : minx;
- // let miny = docs.length ? NumCast(docs[0].y) : 0;
- // let maxy = docs.length ? NumCast(docs[0].height) + miny : miny;
- // let ranges = docs.filter(doc => doc).reduce((range, doc) => {
- // let x = NumCast(doc.x);
- // let xe = x + NumCast(doc.width);
- // let y = NumCast(doc.y);
- // let ye = y + NumCast(doc.height);
- // 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]]);
- // let ink = Cast(this.fieldExtensionDoc.ink, InkField);
- // if (ink && ink.inkData) {
- // ink.inkData.forEach((value: StrokeData, key: string) => {
- // let bounds = InkingCanvas.StrokeRect(value);
- // ranges[0] = [Math.min(ranges[0][0], bounds.left), Math.max(ranges[0][1], bounds.right)];
- // ranges[1] = [Math.min(ranges[1][0], bounds.top), Math.max(ranges[1][1], bounds.bottom)];
- // });
- // }
-
- // let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling(),
- // this._pheight / this.zoomScaling());
- // let panelwidth = panelDim[0];
- // let panelheight = panelDim[1];
- // if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2;
- // if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2;
- // if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2;
- // if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2;
- // }
+ if (!this.isAnnotationOverlay) {
+ PDFMenu.Instance.fadeOut(true);
+ let minx = docs.length ? NumCast(docs[0].x) : 0;
+ let maxx = docs.length ? NumCast(docs[0].width) + minx : minx;
+ let miny = docs.length ? NumCast(docs[0].y) : 0;
+ let maxy = docs.length ? NumCast(docs[0].height) + miny : miny;
+ let ranges = docs.filter(doc => doc).reduce((range, doc) => {
+ let x = NumCast(doc.x);
+ let xe = x + NumCast(doc.width);
+ let y = NumCast(doc.y);
+ let ye = y + NumCast(doc.height);
+ 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]]);
+ let ink = Cast(this.fieldExtensionDoc.ink, InkField);
+ if (ink && ink.inkData) {
+ ink.inkData.forEach((value: StrokeData, key: string) => {
+ let bounds = InkingCanvas.StrokeRect(value);
+ ranges[0] = [Math.min(ranges[0][0], bounds.left), Math.max(ranges[0][1], bounds.right)];
+ ranges[1] = [Math.min(ranges[1][0], bounds.top), Math.max(ranges[1][1], bounds.bottom)];
+ });
+ }
+
+ let cscale = this.props.ContainingCollectionDoc ? NumCast(this.props.ContainingCollectionDoc.scale) : 1;
+ let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling() * cscale,
+ this._pheight / this.zoomScaling() * cscale);
+ 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;
+ }
this.setPan(x - dx, y - dy);
this._lastX = e.pageX;
this._lastY = e.pageY;
@@ -575,31 +536,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (BoolCast(this.props.Document.lockedPosition)) return;
if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming
e.stopPropagation();
- return;
}
-
- let childSelected = this.childDocs.some(doc => {
- var dv = DocumentManager.Instance.getDocumentView(doc);
- return dv && SelectionManager.IsSelected(dv) ? true : false;
- });
- if (!this.props.isSelected() && !childSelected && this.props.renderDepth > 0) {
- return;
- }
- e.stopPropagation();
-
- // bcz: this changes the nativewidth/height, but ImageBox will just revert it back to its defaults. need more logic to fix.
- // if (e.ctrlKey && this.props.Document.scrollHeight === undefined) {
- // let deltaScale = (1 - (e.deltaY / coefficient));
- // let nw = this.nativeWidth * deltaScale;
- // let nh = this.nativeHeight * deltaScale;
- // if (nw && nh) {
- // this.props.Document.nativeWidth = nw;
- // this.props.Document.nativeHeight = nh;
- // }
- // e.preventDefault();
- // }
- // else
- {
+ else if (this.props.active()) {
+ e.stopPropagation();
let deltaScale = e.deltaY > 0 ? (1 / 1.1) : 1.1;
if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) {
deltaScale = 1 / this.zoomScaling();
@@ -628,46 +567,38 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
@action
- onDrop = (e: React.DragEvent): void => {
+ onDrop = async (e: React.DragEvent): Promise<void> => {
var pt = this.getTransform().transformPoint(e.pageX, e.pageY);
- super.onDrop(e, { x: pt[0], y: pt[1] });
- }
-
- onDragOver = (): void => {
+ await super.onDrop(e, { x: pt[0], y: pt[1] });
}
bringToFront = (doc: Doc, sendToBack?: boolean) => {
if (sendToBack || doc.isBackground) {
doc.zIndex = 0;
- return;
}
- const docs = this.childDocs;
- docs.slice().sort((doc1, doc2) => {
- if (doc1 === doc) return 1;
- if (doc2 === doc) return -1;
- return NumCast(doc1.zIndex) - NumCast(doc2.zIndex);
- }).forEach((doc, index) => doc.zIndex = index + 1);
- doc.zIndex = docs.length + 1;
+ else {
+ const docs = this.childLayoutPairs.map(pair => pair.layout);
+ docs.slice().sort((doc1, doc2) => {
+ if (doc1 === doc) return 1;
+ if (doc2 === doc) return -1;
+ return NumCast(doc1.zIndex) - NumCast(doc2.zIndex);
+ }).forEach((doc, index) => doc.zIndex = index + 1);
+ doc.zIndex = docs.length + 1;
+ }
}
- focusDocument = (doc: Doc, willZoom: boolean, scale?: number) => {
- const panX = this.Document.panX;
- const panY = this.Document.panY;
- const id = this.Document[Id];
+ focusDocument = (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => boolean) => {
const state = HistoryUtil.getState();
- state.initializers = state.initializers || {};
// TODO This technically isn't correct if type !== "doc", as
// currently nothing is done, but we should probably push a new state
- if (state.type === "doc" && panX !== undefined && panY !== undefined) {
- const init = state.initializers[id];
+ if (state.type === "doc" && this.Document.panX !== undefined && this.Document.panY !== undefined) {
+ const init = state.initializers![this.Document[Id]];
if (!init) {
- state.initializers[id] = {
- panX, panY
- };
+ state.initializers![this.Document[Id]] = { panX: this.Document.panX, panY: this.Document.panY };
HistoryUtil.pushState(state);
- } else if (init.panX !== panX || init.panY !== panY) {
- init.panX = panX;
- init.panY = panY;
+ } else if (init.panX !== this.Document.panX || init.panY !== this.Document.panY) {
+ init.panX = this.Document.panX;
+ init.panY = this.Document.panY;
HistoryUtil.pushState(state);
}
}
@@ -675,8 +606,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
const newPanX = NumCast(doc.x) + NumCast(doc.width) / 2;
const newPanY = NumCast(doc.y) + NumCast(doc.height) / 2;
const newState = HistoryUtil.getState();
- (newState.initializers || (newState.initializers = {}))[id] = { panX: newPanX, panY: newPanY };
+ newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
HistoryUtil.pushState(newState);
+
+ let px = this.Document.panX;
+ let py = this.Document.panY;
+ let s = this.Document.scale;
this.setPan(newPanX, newPanY);
this.props.Document.panTransformType = "Ease";
@@ -684,7 +619,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (willZoom) {
this.setScaleToZoom(doc, scale);
}
-
+ console.log("Focused " + this.Document.title + " " + s);
+ afterFocus && setTimeout(() => {
+ if (afterFocus && afterFocus()) {
+ console.log("UnFocused " + this.Document.title + " " + s);
+ this.Document.panX = px;
+ this.Document.panY = py;
+ this.Document.scale = s;
+ }
+ }, 1000);
}
setScaleToZoom = (doc: Doc, scale: number = 0.5) => {
@@ -716,13 +659,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
addDocument: this.props.addDocument,
removeDocument: this.props.removeDocument,
moveDocument: this.props.moveDocument,
- onClick: this.props.onClick,
+ ruleProvider: this.Document.isRuleProvider && childLayout.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider, //bcz: hack! - currently ruleProviders apply to documents in nested colleciton, not direct children of themselves
+ onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them
ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
renderDepth: this.props.renderDepth + 1,
PanelWidth: childLayout[WidthSym],
PanelHeight: childLayout[HeightSym],
ContentScaling: returnOne,
ContainingCollectionView: this.props.CollectionView,
+ ContainingCollectionDoc: this.props.CollectionView.props.Document,
focus: this.focusDocument,
backgroundColor: this.getClusterColor,
parentActive: this.props.active,
@@ -741,6 +686,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
addDocument: this.props.addDocument,
removeDocument: this.props.removeDocument,
moveDocument: this.props.moveDocument,
+ ruleProvider: this.props.ruleProvider,
onClick: this.props.onClick,
ScreenToLocalTransform: this.getTransform,
renderDepth: this.props.renderDepth,
@@ -748,6 +694,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
PanelHeight: layoutDoc[HeightSym],
ContentScaling: returnOne,
ContainingCollectionView: this.props.CollectionView,
+ ContainingCollectionDoc: this.props.CollectionView.props.Document,
focus: this.focusDocument,
backgroundColor: returnEmptyString,
parentActive: this.props.active,
@@ -760,13 +707,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
};
}
- getCalculatedPositions(script: ScriptField, params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, z?: number, width?: number, height?: number, state?: any } {
- const result = script.script.run(params);
- if (!result.success) {
- return {};
+ getCalculatedPositions(params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, z?: number, width?: number, height?: number, transition?: string, state?: any } {
+ const script = this.Document.arrangeScript;
+ const result = script && script.script.run(params, console.log);
+ if (result && result.success) {
+ return { ...result, transition: "transform 1s" };
}
- let doc = params.doc;
- return result.result === undefined ? { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), z: Cast(doc.z, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") } : result.result;
+ return { x: Cast(params.doc.x, "number"), y: Cast(params.doc.y, "number"), z: Cast(params.doc.z, "number"), width: Cast(params.doc.width, "number"), height: Cast(params.doc.height, "number") };
}
viewDefsToJSX = (views: PivotView.PivotData[]) => {
@@ -829,14 +776,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (this.Document.usePivotLayout) return PivotView.elements(this);
let curPage = FieldValue(this.Document.curPage, -1);
const initScript = this.Document.arrangeInit;
- const script = this.Document.arrangeScript;
let state: any = undefined;
- let docs = this.childDocs;
- let overlayDocs = DocListCast(this.props.Document.localOverlays);
- overlayDocs && docs.push(...overlayDocs);
+ let pairs = this.childLayoutPairs;
let elements: ViewDefResult[] = [];
if (initScript) {
- const initResult = initScript.script.run({ docs, collection: this.Document });
+ const initResult = initScript.script.run({ docs: pairs.map(pair => pair.layout), collection: this.Document }, console.log);
if (initResult.success) {
const result = initResult.result;
const { state: scriptState, views } = result;
@@ -844,25 +788,19 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
elements = this.viewDefsToJSX(views);
}
}
- let docviews = docs.filter(doc => doc instanceof Doc).reduce((prev, doc) => {
- var page = NumCast(doc.page, -1);
- if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) {
- let minim = BoolCast(doc.isMinimized);
- if (minim === undefined || !minim) {
- const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) :
- { x: Cast(doc.x, "number"), y: Cast(doc.y, "number"), z: Cast(doc.z, "number"), width: Cast(doc.width, "number"), height: Cast(doc.height, "number") };
- state = pos.state === undefined ? state : pos.state;
- let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, doc);
- if (pair.layout && !(pair.data instanceof Promise)) {
- prev.push({
- ele: <CollectionFreeFormDocumentView key={doc[Id]}
- jitterRotation={NumCast(this.props.Document.jitterRotation)}
- x={script ? pos.x : undefined} y={script ? pos.y : undefined}
- width={script ? pos.width : undefined} height={script ? pos.height : undefined} {...this.getChildDocumentViewProps(pair.layout, pair.data)} />,
- bounds: { x: pos.x || 0, y: pos.y || 0, z: pos.z, width: NumCast(pos.width), height: NumCast(pos.height) }
- });
- }
- }
+ let docviews = pairs.reduce((prev, pair) => {
+ var page = NumCast(pair.layout.page, -1);
+ if (!pair.layout.isMinimized && ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1)) {
+ const pos = this.getCalculatedPositions({ doc: pair.layout, index: prev.length, collection: this.Document, docs: pairs.map(pair => pair.layout), state });
+ state = pos.state === undefined ? state : pos.state;
+ prev.push({
+ ele: <CollectionFreeFormDocumentView key={pair.layout[Id]}
+ ruleProvider={this.Document.isRuleProvider ? this.props.Document : this.props.ruleProvider}
+ jitterRotation={NumCast(this.props.Document.jitterRotation)}
+ transition={pos.transition} x={pos.x} y={pos.y} width={pos.width} height={pos.height}
+ {...this.getChildDocumentViewProps(pair.layout, pair.data)} />,
+ bounds: { x: pos.x || 0, y: pos.y || 0, z: pos.z, width: pos.width || 0, height: pos.height || 0 }
+ });
}
return prev;
}, elements);
@@ -872,22 +810,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@computed.struct
get views() {
- let source = this.elements;
- return source.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele);
+ return this.elements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele);
}
@computed.struct
get overlayViews() {
return this.elements.filter(ele => ele.bounds && ele.bounds.z).map(ele => ele.ele);
}
-
@action
onCursorMove = (e: React.PointerEvent) => {
super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY));
}
- fitToContainer = async () => this.props.Document.fitToBox = !this.fitToBox;
-
arrangeContents = async () => {
const docs = await DocListCastAsync(this.Document[this.props.fieldKey]);
UndoManager.RunInBatch(() => {
@@ -912,98 +846,86 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}, "arrange contents");
}
+ autoFormat = () => {
+ this.Document.isRuleProvider = !this.Document.isRuleProvider;
+ // find rule colorations when rule providing is turned on by looking at each document to see if it has a coloring -- if so, use it's color as the rule for its associated heading.
+ this.Document.isRuleProvider && this.childLayoutPairs.map(pair =>
+ // iterate over the children of a displayed document (or if the displayed document is a template, iterate over the children of that template)
+ DocListCast(pair.layout.layout instanceof Doc ? pair.layout.layout.data : pair.layout.data).map(heading => {
+ let headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, heading);
+ let headingLayout = headingPair.layout && (pair.layout.data_ext instanceof Doc) && (pair.layout.data_ext[`Layout[${headingPair.layout[Id]}]`] as Doc) || headingPair.layout;
+ if (headingLayout && NumCast(headingLayout.heading) > 0 && headingLayout.backgroundColor !== headingLayout.defaultBackgroundColor) {
+ Doc.GetProto(this.props.Document)["ruleColor_" + NumCast(headingLayout.heading)] = headingLayout.backgroundColor;
+ }
+ })
+ );
+ }
+
analyzeStrokes = async () => {
- let data = Cast(this.fieldExtensionDoc[this.inkKey], InkField);
- if (!data) {
- return;
+ let data = Cast(this.fieldExtensionDoc.ink, InkField);
+ if (data) {
+ CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.fieldExtensionDoc, ["inkAnalysis", "handwriting"], data.inkData);
}
- let relevantKeys = ["inkAnalysis", "handwriting"];
- CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.fieldExtensionDoc, relevantKeys, data.inkData);
}
onContextMenu = (e: React.MouseEvent) => {
let layoutItems: ContextMenuProps[] = [];
- if (this.childDocs.some(d => d.isTemplate)) {
- layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
+ if (this.childDocs.some(d => BoolCast(d.isTemplate))) {
+ layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
}
layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" });
- layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
- layoutItems.push({
- description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`,
- event: async () => {
- Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes
- Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white";
- this.props.Document.useClusters = !this.props.Document.useClusters;
- this.updateClusters();
- },
- icon: !this.props.Document.useClusters ? "braille" : "braille"
- });
- this.props.Document.useClusters && layoutItems.push({
- description: `${this.props.Document.clusterOverridesDefaultBackground ? "Use Default Backgrounds" : "Clusters Override Defaults"}`,
- event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground,
- icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard"
- });
+ layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: async () => this.Document.fitToBox = !this.fitToBox, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" });
+ layoutItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
+ layoutItems.push({ description: `${this.Document.isRuleProvider ? "Stop Auto Format" : "Auto Format"}`, event: this.autoFormat, icon: "chalkboard" });
layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" });
layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" });
layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" });
layoutItems.push({
- description: "Import document", icon: "upload", event: () => {
+ description: "Import document", icon: "upload", event: ({ x, y }) => {
const input = document.createElement("input");
input.type = "file";
input.accept = ".zip";
input.onchange = async _e => {
- const files = input.files;
- if (!files) return;
- const file = files[0];
- let formData = new FormData();
- formData.append('file', file);
- formData.append('remap', "true");
const upload = Utils.prepend("/uploadDoc");
- const response = await fetch(upload, { method: "POST", body: formData });
- const json = await response.json();
- if (json === "error") {
- return;
- }
- const doc = await DocServer.GetRefField(json);
- if (!doc || !(doc instanceof Doc)) {
- return;
+ let formData = new FormData();
+ const file = input.files && input.files[0];
+ if (file) {
+ formData.append('file', file);
+ formData.append('remap', "true");
+ const response = await fetch(upload, { method: "POST", body: formData });
+ const json = await response.json();
+ if (json !== "error") {
+ const doc = await DocServer.GetRefField(json);
+ if (doc instanceof Doc) {
+ const [xx, yy] = this.props.ScreenToLocalTransform().transformPoint(x, y);
+ doc.x = xx, doc.y = yy;
+ this.props.addDocument && this.props.addDocument(doc, false);
+ }
+ }
}
- const [x, y] = this.props.ScreenToLocalTransform().transformPoint(e.pageX, e.pageY);
- doc.x = x, doc.y = y;
- this.props.addDocument &&
- this.props.addDocument(doc, false);
};
input.click();
}
});
- let noteItems: ContextMenuProps[] = [];
- if (CurrentUserUtils.UserDocument) {
- let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data);
- notes.map((node, i) => noteItems.push({ description: (i + 1) + ": " + StrCast(node.title), event: () => this.createText(i), icon: "eye" }));
- }
- layoutItems.push({ description: "Add Note ...", subitems: noteItems, icon: "eye" });
+ layoutItems.push({
+ description: "Add Note ...",
+ subitems: DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data).map((note, i) => ({
+ description: (i + 1) + ": " + StrCast(note.title),
+ event: (args: { x: number, y: number }) => this.addLiveTextBox(Docs.Create.TextDocument({ width: 200, height: 100, x: this.getTransform().transformPoint(args.x, args.y)[0], y: this.getTransform().transformPoint(args.x, args.y)[1], autoHeight: true, layout: note, title: StrCast(note.title) })),
+ icon: "eye"
+ })) as ContextMenuProps[],
+ icon: "eye"
+ });
ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
}
- createText = (noteStyle: number) => {
- let pt = this.getTransform().transformPoint(ContextMenu.Instance.pageX, ContextMenu.Instance.pageY);
- if (CurrentUserUtils.UserDocument) {
- let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data);
- let text = Docs.Create.TextDocument({ width: 200, height: 100, x: pt[0], y: pt[1], autoHeight: true, title: StrCast(notes[noteStyle % notes.length].title) });
- text.layout = notes[noteStyle % notes.length];
- this.addLiveTextBox(text);
- }
- }
private childViews = () => [
<CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />,
...this.views
]
- private overlayChildViews = () => {
- return [...this.overlayViews];
- }
public static AddCustomLayout(doc: Doc, dataKey: string): () => void {
return () => {
@@ -1034,15 +956,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
render() {
+ // update the actual dimensions of the collection so that they can inquired (e.g., by a minimap)
this.props.Document.fitX = this.actualContentBounds && this.actualContentBounds.x;
this.props.Document.fitY = this.actualContentBounds && this.actualContentBounds.y;
this.props.Document.fitW = this.actualContentBounds && (this.actualContentBounds.r - this.actualContentBounds.x);
this.props.Document.fitH = this.actualContentBounds && (this.actualContentBounds.b - this.actualContentBounds.y);
+ // if fieldExt is set, then children will be stored in the extension document for the fieldKey.
+ // otherwise, they are stored in fieldKey. All annotations to this document are stored in the extension document
+ Doc.UpdateDocumentExtensionForField(this.props.DataDoc || this.props.Document, this.props.fieldKey);
const easing = () => this.props.Document.panTransformType === "Ease";
- Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
return (
<div className={"collectionfreeformview-container"} ref={this.createDropTarget} onWheel={this.onPointerWheel}
- onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onContextMenu={this.onContextMenu}>
+ onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu}>
<MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} isSelected={this.props.isSelected}
addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
@@ -1056,7 +981,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
<CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" />
</CollectionFreeFormViewPannableContents>
</MarqueeView>
- {this.overlayChildViews()}
+ {this.overlayViews}
<CollectionFreeFormOverlayView {...this.props} {...this.getDocumentViewProps(this.props.Document)} />
</div>
);
@@ -1077,7 +1002,6 @@ class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps &
@observer
class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps & { isSelected: () => boolean }> {
@computed get backgroundView() {
- let props = this.props;
return (<DocumentContentsView {...this.props} layoutKey={"backgroundLayout"}
renderDepth={this.props.renderDepth} isSelected={this.props.isSelected} select={emptyFunction} />);
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index fe48a3485..bbea4a555 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,28 +1,24 @@
-import * as htmlToImage from "html-to-image";
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc, FieldResult, DocListCast } from "../../../../new_fields/Doc";
-import { Id } from "../../../../new_fields/FieldSymbols";
+import { Doc, DocListCast } from "../../../../new_fields/Doc";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { List } from "../../../../new_fields/List";
+import { listSpec } from "../../../../new_fields/Schema";
+import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField";
+import { ComputedField } from "../../../../new_fields/ScriptField";
import { Cast, NumCast, StrCast } from "../../../../new_fields/Types";
+import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
import { Utils } from "../../../../Utils";
-import { DocServer } from "../../../DocServer";
import { Docs } from "../../../documents/Documents";
import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
import { InkingCanvas } from "../../InkingCanvas";
import { PreviewCursor } from "../../PreviewCursor";
-import { Templates } from "../../Templates";
import { CollectionViewType } from "../CollectionBaseView";
import { CollectionFreeFormView } from "./CollectionFreeFormView";
import "./MarqueeView.scss";
import React = require("react");
-import { SchemaHeaderField, RandomPastel } from "../../../../new_fields/SchemaHeaderField";
-import { string } from "prop-types";
-import { listSpec } from "../../../../new_fields/Schema";
-import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -232,18 +228,14 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
}
- get ink() {
- let container = this.props.container.props.Document;
- let containerKey = this.props.container.props.fieldKey;
- let extensionDoc = Doc.resolvedFieldDataDoc(container, containerKey, "true");
- return Cast(extensionDoc.ink, InkField);
+ get ink() { // ink will be stored on the extension doc for the field (fieldKey) where the container's data is stored.
+ let cprops = this.props.container.props;
+ return Cast(Doc.fieldExtensionDoc(cprops.Document, cprops.fieldKey).ink, InkField);
}
set ink(value: InkField | undefined) {
- let container = Doc.GetProto(this.props.container.props.Document);
- let containerKey = this.props.container.props.fieldKey;
- let extensionDoc = Doc.resolvedFieldDataDoc(container, containerKey, "true");
- extensionDoc.ink = value;
+ let cprops = this.props.container.props;
+ Doc.fieldExtensionDoc(cprops.Document, cprops.fieldKey).ink = value;
}
@undoBatch
@@ -287,7 +279,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let palette = Array.from(Cast(this.props.container.props.Document.colorPalette, listSpec("string")) as string[]);
let usedPaletted = new Map<string, number>();
[...this.props.activeDocuments(), this.props.container.props.Document].map(child => {
- let bg = StrCast(child.backgroundColor);
+ let bg = StrCast(child.layout instanceof Doc ? child.layout.backgroundColor : child.backgroundColor);
if (palette.indexOf(bg) !== -1) {
palette.splice(palette.indexOf(bg), 1);
if (usedPaletted.get(bg)) usedPaletted.set(bg, usedPaletted.get(bg)! + 1);
@@ -309,13 +301,13 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
defaultBackgroundColor: this.props.container.isAnnotationOverlay ? undefined : chosenColor,
width: bounds.width,
height: bounds.height,
- title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
+ title: "a nested collection",
});
let dataExtensionField = Doc.CreateDocumentExtensionForField(newCollection, "data");
dataExtensionField.ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined;
this.marqueeInkDelete(inkData);
- if (e.key === "s") {
+ if (e.key === "s" || e.key === "S") {
selected.map(d => {
this.props.removeDocument(d);
d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
@@ -324,39 +316,23 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return d;
});
newCollection.chromeStatus = "disabled";
- let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
- newCollection.proto!.summaryDoc = summary;
- selected = [newCollection];
+ let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+ Doc.GetProto(summary).summarizedDocs = new List<Doc>([newCollection]);
newCollection.x = bounds.left + bounds.width;
- summary.proto!.subBulletDocs = new List<Doc>(selected);
- summary.templates = new List<string>([Templates.Bullet.Layout]);
- let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" });
- container.viewType = CollectionViewType.Stacking;
- container.autoHeight = true;
- this.props.addLiveTextDocument(container);
- // });
- } else if (e.key === "S") {
- selected.map(d => {
- this.props.removeDocument(d);
- d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
- d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
- d.page = -1;
- return d;
- });
- newCollection.chromeStatus = "disabled";
- let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
- newCollection.proto!.summaryDoc = summary;
- selected = [newCollection];
- newCollection.x = bounds.left + bounds.width;
- //this.props.addDocument(newCollection, false);
- summary.proto!.summarizedDocs = new List<Doc>(selected);
- summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight"
- summary.autoHeight = true;
-
- this.props.addLiveTextDocument(summary);
+ Doc.GetProto(newCollection).summaryDoc = summary;
+ Doc.GetProto(newCollection).title = ComputedField.MakeFunction(`summaryTitle(this);`);
+ if (e.key === "s") { // summary is wrapped in an expand/collapse container that also contains the summarized documents in a free form view.
+ let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, chromeStatus: "disabled", title: "-summary-" });
+ container.viewType = CollectionViewType.Stacking;
+ container.autoHeight = true;
+ Doc.GetProto(summary).maximizeLocation = "inPlace"; // or "onRight"
+ this.props.addLiveTextDocument(container);
+ } else if (e.key === "S") { // the summary stands alone, but is linked to a collection of the summarized documents - set the OnCLick behavior to link follow to access them
+ Doc.GetProto(summary).maximizeLocation = "inTab"; // or "inPlace", or "onRight"
+ this.props.addLiveTextDocument(summary);
+ }
}
else {
- newCollection.ruleProvider = this.props.container.props.Document;
this.props.addDocument(newCollection, false);
this.props.selectDocuments([newCollection]);
}