diff options
| author | tschicke-brown <tyler_schicke@brown.edu> | 2019-05-03 20:56:32 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-03 20:56:32 -0400 |
| commit | 1ccabe155cb4f23c0aa7e37f91cd4a303008b8c7 (patch) | |
| tree | 4b93ac202fe813033b6d07f7202ab217c0da79f8 /src/client/views/collections/collectionFreeForm | |
| parent | 95d89a193b25d19faf6da0af1412480a36fc9ebe (diff) | |
| parent | 070787b6be93dca4a43ec7e893ae4ac4b4d80e59 (diff) | |
Merge pull request #92 from browngraphicslab/newDocs
New docs
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
5 files changed, 216 insertions, 191 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 8cd6c7624..3b700b053 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,18 +1,18 @@ import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { KeyStore } from "../../../../fields/KeyStore"; import { Utils } from "../../../../Utils"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); +import { StrCast, NumCast, BoolCast } from "../../../../new_fields/Types"; +import { Doc, WidthSym, HeightSym } from "../../../../new_fields/Doc"; import { InkingControl } from "../../InkingControl"; export interface CollectionFreeFormLinkViewProps { - A: Document; - B: Document; - LinkDocs: Document[]; - addDocument: (document: Document, allowDuplicates?: boolean) => boolean; - removeDocument: (document: Document) => boolean; + A: Doc; + B: Doc; + LinkDocs: Doc[]; + addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument: (document: Doc) => boolean; } @observer @@ -22,14 +22,14 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo if (e.button === 0 && !InkingControl.Instance.selectedTool) { let a = this.props.A; let b = this.props.B; - let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Width() / 2); - let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Height() / 2); - let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Width() / 2); - let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Height() / 2); + let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); + let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); + let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); + let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); this.props.LinkDocs.map(l => { - let width = l.GetNumber(KeyStore.Width, 0); - l.SetNumber(KeyStore.X, (x1 + x2) / 2 - width / 2); - l.SetNumber(KeyStore.Y, (y1 + y2) / 2 + 10); + let width = l[WidthSym](); + l.x = (x1 + x2) / 2 - width / 2; + l.y = (y1 + y2) / 2 + 10; if (!this.props.removeDocument(l)) this.props.addDocument(l, false); }); e.stopPropagation(); @@ -40,10 +40,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo let l = this.props.LinkDocs; let a = this.props.A; let b = this.props.B; - let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Width() / 2); - let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.IsMinimized, false) ? 5 : a.Height() / 2); - let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Width() / 2); - let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.IsMinimized, false) ? 5 : b.Height() / 2); + let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / 2); + let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / 2); + let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / 2); + let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / 2); return ( <> <line key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine" diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index b97df7556..b34e0856e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,8 +1,5 @@ import { computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { KeyStore } from "../../../../fields/KeyStore"; -import { ListField } from "../../../../fields/ListField"; import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DocumentView } from "../../nodes/DocumentView"; @@ -10,54 +7,67 @@ import { CollectionViewProps } from "../CollectionSubView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); +import { Doc } from "../../../../new_fields/Doc"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types"; +import { listSpec } from "../../../../new_fields/Schema"; +import { List } from "../../../../new_fields/List"; +import { Id } from "../../../../new_fields/RefField"; @observer export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> { _brushReactionDisposer?: IReactionDisposer; componentDidMount() { - this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)), + this._brushReactionDisposer = reaction(() => Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).map(doc => NumCast(doc.x)), () => { - let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc.GetText(KeyStore.BackgroundLayout, "").indexOf("istogram") !== -1); + let views = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(doc => StrCast(doc.backgroundLayout, "").indexOf("istogram") !== -1); for (let i = 0; i < views.length; i++) { for (let j = 0; j < views.length; j++) { let srcDoc = views[j]; let dstDoc = views[i]; - let x1 = srcDoc.GetNumber(KeyStore.X, 0); - let x1w = srcDoc.GetNumber(KeyStore.Width, -1); - let x2 = dstDoc.GetNumber(KeyStore.X, 0); - let x2w = dstDoc.GetNumber(KeyStore.Width, -1); + let x1 = NumCast(srcDoc.x); + let x1w = NumCast(srcDoc.width, -1); + let x2 = NumCast(dstDoc.x); + let x2w = NumCast(dstDoc.width, -1); if (x1w < 0 || x2w < 0 || i === j) { continue; } let dstTarg = dstDoc; let srcTarg = srcDoc; - let findBrush = (field: ListField<Document>) => field.Data.findIndex(brush => { - let bdocs = brush ? brush.GetList(KeyStore.BrushingDocs, [] as Document[]) : []; + let findBrush = (field: List<Doc>) => field.findIndex(brush => { + let bdocs = brush ? Cast(brush.brushingDocs, listSpec(Doc), []) : []; return (bdocs.length && ((bdocs[0] === dstTarg && bdocs[1] === srcTarg)) ? true : false); }); - let brushAction = (field: ListField<Document>) => { + let brushAction = (field: List<Doc>) => { let found = findBrush(field); if (found !== -1) { console.log("REMOVE BRUSH " + srcTarg.Title + " " + dstTarg.Title); - field.Data.splice(found, 1); + field.splice(found, 1); } }; if (Math.abs(x1 + x1w - x2) < 20) { - let linkDoc: Document = new Document(); - linkDoc.SetText(KeyStore.Title, "Histogram Brush"); - linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title); - linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField); + 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: ListField<Document>) => { + brushAction = (field: List<Doc>) => { if (findBrush(field) === -1) { console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title); - (findBrush(field) === -1) && field.Data.push(linkDoc); + (findBrush(field) === -1) && field.push(linkDoc); } }; } - dstTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction); - srcTarg.GetOrCreateAsync(KeyStore.BrushingDocs, ListField, brushAction); + let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc)); + if (dstBrushDocs === undefined) { + dstTarg.brushingDocs = dstBrushDocs = new List<Doc>(); + } + let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc)); + if (srcBrushDocs === undefined) { + srcTarg.brushingDocs = srcBrushDocs = new List<Doc>(); + } + brushAction(dstBrushDocs); + brushAction(srcBrushDocs); } } @@ -70,15 +80,15 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP } documentAnchors(view: DocumentView) { let equalViews = [view]; - let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document); - if (containerDoc && containerDoc instanceof Document) { - equalViews.push(...DocumentManager.Instance.getDocumentViews(containerDoc.GetPrototype()!)); + let containerDoc = FieldValue(Cast(view.props.Document.annotationOn, Doc)); + if (containerDoc) { + equalViews = DocumentManager.Instance.getDocumentViews(containerDoc.proto!); } if (view.props.ContainingCollectionView) { - let collid = view.props.ContainingCollectionView.props.Document.Id; - this.props.Document.GetList(this.props.fieldKey, [] as Document[]). + let collid = view.props.ContainingCollectionView.props.Document[Id]; + Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []). filter(child => - child.Id === collid).map(view => + child[Id] === collid).map(view => DocumentManager.Instance.getDocumentViews(view).map(view => equalViews.push(view))); } @@ -90,12 +100,12 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { let srcViews = this.documentAnchors(connection.a); let targetViews = this.documentAnchors(connection.b); - let possiblePairs: { a: Document, b: Document, }[] = []; + let possiblePairs: { a: Doc, b: Doc, }[] = []; srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); possiblePairs.map(possiblePair => drawnPairs.reduce((found, drawnPair) => { let match = (possiblePair.a === drawnPair.a && possiblePair.b === drawnPair.b); - if (match && !drawnPair.l.reduce((found, link) => found || link.Id === connection.l.Id, false)) { + if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { drawnPair.l.push(connection.l); } return match || found; @@ -104,7 +114,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }) ); return drawnPairs; - }, [] as { a: Document, b: Document, l: Document[] }[]); + }, [] as { a: Doc, b: Doc, l: Doc[] }[]); return connections.map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} removeDocument={this.props.removeDocument} addDocument={this.props.addDocument} />); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx index cf0a6de00..036745eca 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx @@ -1,6 +1,5 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { KeyStore } from "../../../../fields/KeyStore"; import { CollectionViewProps, CursorEntry } from "../CollectionSubView"; import "./CollectionFreeFormView.scss"; import React = require("react"); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b931105d8..17c25c9db 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,5 @@ -import { action, computed } from "mobx"; +import { action, computed, trace } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { KeyStore } from "../../../../fields/KeyStore"; import { emptyFunction, returnFalse, returnOne } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; @@ -12,7 +10,7 @@ import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss" import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; -import { DocumentViewProps } from "../../nodes/DocumentView"; +import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; @@ -20,10 +18,23 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); -import { BooleanField } from "../../../../fields/BooleanField"; +import { createSchema, makeInterface, listSpec } from "../../../../new_fields/Schema"; +import { Doc, WidthSym, HeightSym } from "../../../../new_fields/Doc"; +import { FieldValue, Cast, NumCast } from "../../../../new_fields/Types"; +import { pageSchema } from "../../nodes/ImageBox"; +import { Id } from "../../../../new_fields/RefField"; + +export const panZoomSchema = createSchema({ + panX: "number", + panY: "number", + scale: "number" +}); + +type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema, typeof pageSchema]>; +const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema); @observer -export class CollectionFreeFormView extends CollectionSubView { +export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { public static RIGHT_BTN_DRAG = false; private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) private _lastX: number = 0; @@ -31,42 +42,38 @@ export class CollectionFreeFormView extends CollectionSubView { private get _pwidth() { return this.props.PanelWidth(); } private get _pheight() { return this.props.PanelHeight(); } - @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } - @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } + @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); } + @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } - private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's? - private panX = () => this.props.Document.GetNumber(KeyStore.PanX, 0); - private panY = () => this.props.Document.GetNumber(KeyStore.PanY, 0); - private zoomScaling = () => this.props.Document.GetNumber(KeyStore.Scale, 1); + private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } + private panX = () => FieldValue(this.Document.panX, 0); + private panY = () => FieldValue(this.Document.panY, 0); + private zoomScaling = () => FieldValue(this.Document.scale, 1); private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 : 0; // shift so pan position is at center of window for non-overlay collections private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); - private addLiveTextBox = (newBox: Document) => { - this._selectOnLoaded = newBox.Id;// track the new text box so we can give it a prop that tells it to focus itself when it's displayed + private addLiveTextBox = (newBox: Doc) => { + this._selectOnLoaded = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newBox, false); } - @action - private addDocument = (newBox: Document, allowDuplicates: boolean) => { + private addDocument = (newBox: Doc, allowDuplicates: boolean) => { this.props.addDocument(newBox, false); this.bringToFront(newBox); return true; } - private selectDocuments = (docs: Document[]) => { + private selectDocuments = (docs: Doc[]) => { SelectionManager.DeselectAll; docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).filter(dv => dv).map(dv => SelectionManager.SelectDoc(dv!, true)); } public getActiveDocuments = () => { - var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); - return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).reduce((active, doc) => { - var page = doc.GetNumber(KeyStore.Page, -1); - if (page === curPage || page === -1) { - active.push(doc); - } - return active; - }, [] as Document[]); + const curPage = FieldValue(this.Document.curPage, -1); + return FieldValue(this.children, [] as Doc[]).filter(doc => { + var page = NumCast(doc.page, -1); + return page === curPage || page === -1; + }); } @undoBatch @@ -75,22 +82,22 @@ export class CollectionFreeFormView extends CollectionSubView { if (super.drop(e, de) && de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { let dragDoc = de.data.droppedDocuments[0]; - let zoom = dragDoc.GetNumber(KeyStore.ZoomBasis, 1); + let zoom = NumCast(dragDoc.zoomBasis, 1); let [xp, yp] = this.getTransform().transformPoint(de.x, de.y); let x = xp - de.data.xOffset / zoom; let y = yp - de.data.yOffset / zoom; - let dropX = de.data.droppedDocuments[0].GetNumber(KeyStore.X, 0); - let dropY = de.data.droppedDocuments[0].GetNumber(KeyStore.Y, 0); + let dropX = NumCast(de.data.droppedDocuments[0].x); + let dropY = NumCast(de.data.droppedDocuments[0].y); de.data.droppedDocuments.map(d => { - d.SetNumber(KeyStore.X, x + (d.GetNumber(KeyStore.X, 0) - dropX)); - d.SetNumber(KeyStore.Y, y + (d.GetNumber(KeyStore.Y, 0) - dropY)); - if (!d.GetNumber(KeyStore.Width, 0)) { - d.SetNumber(KeyStore.Width, 300); + d.x = x + NumCast(d.x) - dropX; + d.y = y + NumCast(d.y) - dropY; + if (!NumCast(d.width)) { + d.width = 300; } - if (!d.GetNumber(KeyStore.Height, 0)) { - let nw = d.GetNumber(KeyStore.NativeWidth, 0); - let nh = d.GetNumber(KeyStore.NativeHeight, 0); - d.SetNumber(KeyStore.Height, nw && nh ? nh / nw * d.Width() : 300); + if (!NumCast(d.height)) { + let nw = NumCast(d.nativeWidth); + let nh = NumCast(d.nativeHeight); + d.height = nw && nh ? nh / nw * NumCast(d.width) : 300; } this.bringToFront(d); }); @@ -102,14 +109,8 @@ export class CollectionFreeFormView extends CollectionSubView { } @action - cleanupInteractions = () => { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - @action onPointerDown = (e: React.PointerEvent): void => { - let childSelected = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((childSelected, doc) => { + let childSelected = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), [] as Doc[]).filter(doc => doc).reduce((childSelected, doc) => { var dv = DocumentManager.Instance.getDocumentView(doc); return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); }, false); @@ -118,7 +119,8 @@ export class CollectionFreeFormView extends CollectionSubView { (e.button === 0 && e.altKey)) && (childSelected || this.props.active()))) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && (childSelected || this.props.active())))) { - this.cleanupInteractions(); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); document.addEventListener("pointerup", this.onPointerUp); this._lastX = e.pageX; @@ -127,26 +129,27 @@ export class CollectionFreeFormView extends CollectionSubView { } onPointerUp = (e: PointerEvent): void => { - this.cleanupInteractions(); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); } @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble) { - let x = this.props.Document.GetNumber(KeyStore.PanX, 0); - let y = this.props.Document.GetNumber(KeyStore.PanY, 0); - let docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]); + let x = Cast(this.props.Document.panX, "number", 0); + let y = Cast(this.props.Document.panY, "number", 0); + let docs = this.children || []; let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay) { - let minx = docs.length ? docs[0].GetNumber(KeyStore.X, 0) : 0; - let maxx = docs.length ? docs[0].Width() + minx : minx; - let miny = docs.length ? docs[0].GetNumber(KeyStore.Y, 0) : 0; - let maxy = docs.length ? docs[0].Height() + miny : miny; + let minx = docs.length ? Cast(docs[0].x, "number", 0) : 0; + let maxx = docs.length ? Cast(docs[0].width, "number", 0) + minx : minx; + let miny = docs.length ? Cast(docs[0].y, "number", 0) : 0; + let maxy = docs.length ? Cast(docs[0].height, "number", 0) + miny : miny; let ranges = docs.filter(doc => doc).reduce((range, doc) => { - let x = doc.GetNumber(KeyStore.X, 0); - let xe = x + doc.GetNumber(KeyStore.Width, 0); - let y = doc.GetNumber(KeyStore.Y, 0); - let ye = y + doc.GetNumber(KeyStore.Height, 0); + let x = Cast(doc.x, "number", 0); + let xe = x + Cast(doc.width, "number", 0); + let y = Cast(doc.y, "number", 0); + let ye = y + Cast(doc.height, "number", 0); 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]]); @@ -170,10 +173,10 @@ export class CollectionFreeFormView extends CollectionSubView { // if (!this.props.active()) { // return; // } - let childSelected = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((childSelected, doc) => { + let childSelected = (this.children || []).filter(doc => doc).some(doc => { var dv = DocumentManager.Instance.getDocumentView(doc); - return childSelected || (dv && SelectionManager.IsSelected(dv) ? true : false); - }, false); + return dv && SelectionManager.IsSelected(dv) ? true : false; + }); if (!this.props.isSelected() && !childSelected && !this.props.isTopMost) { return; } @@ -182,8 +185,8 @@ export class CollectionFreeFormView extends CollectionSubView { if (e.ctrlKey) { let deltaScale = (1 - (e.deltaY / coefficient)); - this.props.Document.SetNumber(KeyStore.NativeWidth, this.nativeWidth * deltaScale); - this.props.Document.SetNumber(KeyStore.NativeHeight, this.nativeHeight * deltaScale); + this.props.Document.nativeWidth = this.nativeWidth * deltaScale; + this.props.Document.nativeHeight = this.nativeHeight * deltaScale; e.stopPropagation(); e.preventDefault(); } else { @@ -198,7 +201,7 @@ export class CollectionFreeFormView extends CollectionSubView { let localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); let safeScale = Math.abs(localTransform.Scale); - this.props.Document.SetNumber(KeyStore.Scale, Math.abs(safeScale)); + this.props.Document.scale = Math.abs(safeScale); this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale); e.stopPropagation(); } @@ -209,9 +212,8 @@ export class CollectionFreeFormView extends CollectionSubView { var scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight, Math.max(0, panY)); - this.props.Document.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX); - this.props.Document.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY); - + this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX; + this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY; } @action @@ -223,30 +225,31 @@ export class CollectionFreeFormView extends CollectionSubView { onDragOver = (): void => { } - @action - bringToFront(doc: Document) { - let docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).slice(); - docs.sort((doc1, doc2) => { + bringToFront = (doc: Doc) => { + const docs = (this.children || []); + docs.slice().sort((doc1, doc2) => { if (doc1 === doc) return 1; if (doc2 === doc) return -1; - return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0); - }).map((doc, index) => doc.SetNumber(KeyStore.ZIndex, index + 1)); - doc.SetNumber(KeyStore.ZIndex, docs.length + 1); + return NumCast(doc1.zIndex) - NumCast(doc2.zIndex); + }).forEach((doc, index) => doc.zIndex = index + 1); + doc.zIndex = docs.length + 1; + return doc; } - focusDocument = (doc: Document) => { + focusDocument = (doc: Doc) => { SelectionManager.DeselectAll(); - this.props.Document.SetText(KeyStore.PanTransformType, "Ease"); + this.props.Document.panTransformType = "Ease"; this.setPan( - doc.GetNumber(KeyStore.X, 0) + doc.Width() / 2, - doc.GetNumber(KeyStore.Y, 0) + doc.Height() / 2); + NumCast(doc.x) + NumCast(doc.width) / 2, + NumCast(doc.y) + NumCast(doc.height) / 2); this.props.focus(this.props.Document); - if (this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease") { - setTimeout(() => this.props.Document.SetText(KeyStore.PanTransformType, "None"), 5000); // wait 5 seconds, then reset to false + if (this.props.Document.panTransformType === "Ease") { + setTimeout(() => this.props.Document.panTransformType = "None", 2000); // wait 3 seconds, then reset to false } } - getDocumentViewProps(document: Document): DocumentViewProps { + + getDocumentViewProps(document: Doc): DocumentViewProps { return { Document: document, toggleMinimized: emptyFunction, @@ -255,26 +258,29 @@ export class CollectionFreeFormView extends CollectionSubView { moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, isTopMost: false, - selectOnLoad: document.Id === this._selectOnLoaded, - PanelWidth: document.Width, - PanelHeight: document.Height, + selectOnLoad: document[Id] === this._selectOnLoaded, + PanelWidth: document[WidthSym], + PanelHeight: document[HeightSym], ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, focus: this.focusDocument, parentActive: this.props.active, whenActiveChanged: this.props.active, + bringToFront: this.bringToFront, }; } - @computed + @computed.struct get views() { - var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); - let docviews = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => { - var page = doc.GetNumber(KeyStore.Page, -1); + let curPage = FieldValue(this.Document.curPage, -1); + let docviews = (this.children || []).filter(doc => doc).reduce((prev, doc) => { + if (!FieldValue(doc)) return prev; + var page = NumCast(doc.page, -1); if (page === curPage || page === -1) { - let minim = doc.GetT(KeyStore.IsMinimized, BooleanField); - if (minim === undefined || (minim && !minim.Data)) - prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />); + let minim = Cast(doc.isMinimized, "boolean"); + if (minim === undefined || !minim) { + prev.push(<CollectionFreeFormDocumentView key={doc[Id]} {...this.getDocumentViewProps(doc)} />); + } } return prev; }, [] as JSX.Element[]); @@ -292,16 +298,11 @@ export class CollectionFreeFormView extends CollectionSubView { private childViews = () => [...this.views, <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />]; render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; - const easing = () => this.props.Document.GetText(KeyStore.PanTransformType, "") === "Ease"; + const easing = () => this.props.Document.panTransformType === "Ease"; return ( <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel} style={{ borderRadius: "inherit" }} onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} > - {/* <svg viewBox="0 0 180 18" style={{ top: "50%", opacity: 0.05, position: "absolute" }}> - <text y="15" > - {this.props.Document.Title} - </text> - </svg> */} <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}> @@ -313,7 +314,7 @@ export class CollectionFreeFormView extends CollectionSubView { {this.childViews} </InkingCanvas> </CollectionFreeFormLinksView> - <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> + {/* <CollectionFreeFormRemoteCursors {...this.props} key="remoteCursors" /> */} </CollectionFreeFormViewPannableContents> <CollectionFreeFormOverlayView {...this.getDocumentViewProps(this.props.Document)} {...this.props} /> </MarqueeView> @@ -325,9 +326,9 @@ export class CollectionFreeFormView extends CollectionSubView { @observer class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps> { @computed get overlayView() { - let overlayLayout = this.props.Document.GetText(KeyStore.OverlayLayout, ""); + let overlayLayout = Cast(this.props.Document.overlayLayout, "string", ""); return !overlayLayout ? (null) : - (<DocumentContentsView {...this.props} layoutKey={KeyStore.OverlayLayout} + (<DocumentContentsView {...this.props} layoutKey={"overlayLayout"} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />); } render() { @@ -338,9 +339,9 @@ class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps> { @observer class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps & { isSelected: () => boolean }> { @computed get backgroundView() { - let backgroundLayout = this.props.Document.GetText(KeyStore.BackgroundLayout, ""); + let backgroundLayout = Cast(this.props.Document.backgroundLayout, "string", ""); return !backgroundLayout ? (null) : - (<DocumentContentsView {...this.props} layoutKey={KeyStore.BackgroundLayout} + (<DocumentContentsView {...this.props} layoutKey={"backgroundLayout"} isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />); } render() { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index da1170759..8c81f6990 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,10 +1,6 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { FieldWaiting } from "../../../../fields/Field"; -import { InkField, StrokeData } from "../../../../fields/InkField"; -import { KeyStore } from "../../../../fields/KeyStore"; -import { Documents } from "../../../documents/Documents"; +import { Docs } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; @@ -14,16 +10,21 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; import React = require("react"); import { Utils } from "../../../../Utils"; +import { Doc } from "../../../../new_fields/Doc"; +import { NumCast, Cast } from "../../../../new_fields/Types"; +import { InkField, StrokeData } from "../../../../new_fields/InkField"; +import { Templates } from "../../Templates"; +import { List } from "../../../../new_fields/List"; interface MarqueeViewProps { getContainerTransform: () => Transform; getTransform: () => Transform; container: CollectionFreeFormView; - addDocument: (doc: Document, allowDuplicates: false) => boolean; - activeDocuments: () => Document[]; - selectDocuments: (docs: Document[]) => void; - removeDocument: (doc: Document) => boolean; - addLiveTextDocument: (doc: Document) => void; + addDocument: (doc: Doc, allowDuplicates: false) => boolean; + activeDocuments: () => Doc[]; + selectDocuments: (docs: Doc[]) => void; + removeDocument: (doc: Doc) => boolean; + addLiveTextDocument: (doc: Doc) => void; isSelected: () => boolean; } @@ -51,7 +52,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps> onKeyPress = (e: KeyboardEvent) => { //make textbox and add it to this collection let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); - let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); + let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); this.props.addLiveTextDocument(newBox); e.stopPropagation(); } @@ -67,8 +68,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); } - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action @@ -85,8 +87,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> e.preventDefault(); } } - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action @@ -99,17 +102,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps> this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]); } this.cleanupInteractions(true); - if (e.altKey) + if (e.altKey) { e.preventDefault(); + } } @action onClick = (e: React.MouseEvent): void => { if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { - if (this.props.isSelected()) { - PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); - } + PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); // let the DocumentView stopPropagation of this event when it selects this document } else { // why do we get a click event when the cursor have moved a big distance? // let's cut it off here so no one else has to deal with it. @@ -140,9 +142,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> if (e.key === "Backspace" || e.key === "Delete" || e.key == "d") { this._commandExecuted = true; this.marqueeSelect().map(d => this.props.removeDocument(d)); - let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - if (ink && ink !== FieldWaiting) { - this.marqueeInkDelete(ink.Data); + let ink = Cast(this.props.container.props.Document.ink, InkField); + if (ink) { + this.marqueeInkDelete(ink.inkData); } this.cleanupInteractions(false); e.stopPropagation(); @@ -152,35 +154,48 @@ export class MarqueeView extends React.Component<MarqueeViewProps> e.stopPropagation(); let bounds = this.Bounds; let selected = this.marqueeSelect().map(d => { - this.props.removeDocument(d); - d.SetNumber(KeyStore.X, d.GetNumber(KeyStore.X, 0) - bounds.left - bounds.width / 2); - d.SetNumber(KeyStore.Y, d.GetNumber(KeyStore.Y, 0) - bounds.top - bounds.height / 2); - d.SetNumber(KeyStore.Page, -1); + if (e.key !== "r") + 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; }); - let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined; - let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1); - let newCollection = Documents.FreeformDocument(selected, { + let ink = Cast(this.props.container.props.Document.ink, InkField); + let inkData = ink ? ink.inkData : undefined; + let zoomBasis = NumCast(this.props.container.props.Document.scale, 1); + let newCollection = Docs.FreeformDocument(selected, { x: bounds.left, y: bounds.top, - panx: 0, - pany: 0, + panX: 0, + panY: 0, borderRounding: e.key === "e" ? -1 : undefined, scale: zoomBasis, width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, - ink: inkData ? this.marqueeInkSelect(inkData) : undefined, + ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined, title: "a nested collection" }); this.marqueeInkDelete(inkData); // SelectionManager.DeselectAll(); if (e.key === "r") { - let summary = Documents.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - summary.GetPrototype()!.CreateLink(newCollection.GetPrototype()!); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + summary.maximizedDocs = new List<Doc>(selected); + // summary.doc1 = selected[0]; + // if (selected.length > 1) + // summary.doc2 = selected[1]; + // summary.templates = new List<string>([Templates.Summary.Layout]); this.props.addLiveTextDocument(summary); e.preventDefault(); + let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); + selected.map(maximizedDoc => { + let maxx = NumCast(maximizedDoc.x, undefined); + let maxy = NumCast(maximizedDoc.y, undefined); + let maxw = NumCast(maximizedDoc.width, undefined); + let maxh = NumCast(maximizedDoc.height, undefined); + maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]) + }); } else { this.props.addDocument(newCollection, false); @@ -194,9 +209,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps> let bounds = this.Bounds; let selected = this.marqueeSelect(); SelectionManager.DeselectAll(); - let summary = Documents.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + let summary = Docs.TextDocument({ x: bounds.left + bounds.width + 25, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); this.props.addLiveTextDocument(summary); - selected.map(select => summary.GetPrototype()!.CreateLink(select.GetPrototype()!)); + selected.forEach(select => Doc.MakeLink(summary.proto!, select.proto!)); this.cleanupInteractions(false); } @@ -231,19 +246,19 @@ export class MarqueeView extends React.Component<MarqueeViewProps> let idata = new Map(); ink.forEach((value: StrokeData, key: string, map: any) => !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value)); - this.props.container.props.Document.SetDataOnPrototype(KeyStore.Ink, idata, InkField); + Doc.SetOnPrototype(this.props.container.props.Document, "ink", new InkField(idata)); } } marqueeSelect() { let selRect = this.Bounds; - let selection: Document[] = []; + let selection: Doc[] = []; this.props.activeDocuments().map(doc => { - var z = doc.GetNumber(KeyStore.ZoomBasis, 1); - var x = doc.GetNumber(KeyStore.X, 0); - var y = doc.GetNumber(KeyStore.Y, 0); - var w = doc.Width() / z; - var h = doc.Height() / z; + var z = NumCast(doc.zoomBasis, 1); + var x = NumCast(doc.x); + var y = NumCast(doc.y); + var w = NumCast(doc.width) / z; + var h = NumCast(doc.height) / z; if (this.intersectRect({ left: x, top: y, width: w, height: h }, selRect)) { selection.push(doc); } |
