diff options
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 184 |
1 files changed, 104 insertions, 80 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f3a83f5a0..a77a28aa7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; import { FieldWaiting } from "../../../../fields/Field"; @@ -11,8 +11,8 @@ import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; import { DocumentViewProps } from "../../nodes/DocumentView"; -import { COLLECTION_BORDER_WIDTH } from "../CollectionView"; -import { CollectionViewBase } from "../CollectionViewBase"; +import { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView"; +import { CollectionSubView } from "../CollectionSubView"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; @@ -21,10 +21,14 @@ import v5 = require("uuid/v5"); import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; import { PreviewCursor } from "./PreviewCursor"; import { Timeline } from "../../nodes/Timeline" +import { DocumentManager } from "../../../util/DocumentManager"; +import { SelectionManager } from "../../../util/SelectionManager"; import { NumberField } from "../../../../fields/NumberField"; +import { Main } from "../../Main"; +import Measure from "react-measure"; @observer -export class CollectionFreeFormView extends CollectionViewBase { +export class CollectionFreeFormView extends CollectionSubView { public _canvasRef = React.createRef<HTMLDivElement>(); private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) @@ -41,15 +45,20 @@ export class CollectionFreeFormView extends CollectionViewBase { } public selectDocuments = (docs: Document[]) => { - this.props.CollectionView.SelectedDocs.length = 0; - docs.map(d => this.props.CollectionView.SelectedDocs.push(d.Id)); + SelectionManager.DeselectAll; + docs.map(doc => { + const dv = DocumentManager.Instance.getDocumentView(doc); + if (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) { + if (page === curPage || page === -1) { active.push(doc); } return active; @@ -60,46 +69,50 @@ export class CollectionFreeFormView extends CollectionViewBase { @observable public DownY: number = 0; @observable private _lastX: number = 0; @observable private _lastY: number = 0; + @observable private _pwidth: number = 0; + @observable private _pheight: number = 0; - @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0) } - @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0) } + @computed get panX(): number { return this.props.Document.GetNumber(KeyStore.PanX, 0); } + @computed get panY(): number { return this.props.Document.GetNumber(KeyStore.PanY, 0); } @computed get scale(): number { return this.props.Document.GetNumber(KeyStore.Scale, 1); } @computed get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's? @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } @computed get zoomScaling() { return this.props.Document.GetNumber(KeyStore.Scale, 1); } - @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) ? this.props.panelWidth() / 2 : 0; } // shift so pan position is at center of window for non-overlay collections - @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) ? this.props.panelHeight() / 2 : 0; }// shift so pan position is at center of window for non-overlay collections + @computed get centeringShiftX() { return !this.props.Document.GetNumber(KeyStore.NativeWidth, 0) ? this._pwidth / 2 : 0; } // shift so pan position is at center of window for non-overlay collections + @computed get centeringShiftY() { return !this.props.Document.GetNumber(KeyStore.NativeHeight, 0) ? this._pheight / 2 : 0; }// shift so pan position is at center of window for non-overlay collections @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { if (super.drop(e, de)) { - let droppedDocs = de.data.droppedDocuments as Document[]; - let xoff = de.data.xOffset as number || 0; - let yoff = de.data.yOffset as number || 0; - if (droppedDocs && droppedDocs.length) { - let screenX = de.x - xoff; - let screenY = de.y - yoff; - const [x, y] = this.getTransform().transformPoint(screenX, screenY); - let dragDoc = de.data.droppedDocuments[0]; - let dragX = dragDoc.GetNumber(KeyStore.X, 0); - let dragY = dragDoc.GetNumber(KeyStore.Y, 0); - droppedDocs.map(async d => { - let docX = d.GetNumber(KeyStore.X, 0); - let docY = d.GetNumber(KeyStore.Y, 0); - d.SetNumber(KeyStore.X, x + (docX - dragX)); - d.SetNumber(KeyStore.Y, y + (docY - dragY)); - let docW = await d.GetTAsync(KeyStore.Width, NumberField); - let docH = await d.GetTAsync(KeyStore.Height, NumberField); - if (!docW) { - d.SetNumber(KeyStore.Width, 300); - } - if (!docH) { - d.SetNumber(KeyStore.Height, 300); - } - this.bringToFront(d); - }) + if (de.data instanceof DragManager.DocumentDragData) { + let droppedDocs = de.data.droppedDocuments; + let xoff = de.data.xOffset as number || 0; + let yoff = de.data.yOffset as number || 0; + if (droppedDocs.length) { + let screenX = de.x - xoff; + let screenY = de.y - yoff; + const [x, y] = this.getTransform().transformPoint(screenX, screenY); + let dragDoc = droppedDocs[0]; + let dragX = dragDoc.GetNumber(KeyStore.X, 0); + let dragY = dragDoc.GetNumber(KeyStore.Y, 0); + droppedDocs.map(async d => { + let docX = d.GetNumber(KeyStore.X, 0); + let docY = d.GetNumber(KeyStore.Y, 0); + d.SetNumber(KeyStore.X, x + (docX - dragX)); + d.SetNumber(KeyStore.Y, y + (docY - dragY)); + let docW = await d.GetTAsync(KeyStore.Width, NumberField); + let docH = await d.GetTAsync(KeyStore.Height, NumberField); + if (!docW) { + d.SetNumber(KeyStore.Width, 300); + } + if (!docH) { + d.SetNumber(KeyStore.Height, 300); + } + this.bringToFront(d); + }); + } } return true; } @@ -115,15 +128,16 @@ export class CollectionFreeFormView extends CollectionViewBase { @action onPointerDown = (e: React.PointerEvent): void => { - if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling != 1)) || e.button == 0) && this.props.active()) { + if (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling !== 1)) || e.button === 0) && this.props.active()) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); this._lastX = this.DownX = e.pageX; this._lastY = this.DownY = e.pageY; - if (this.props.isSelected()) + if (this.props.isSelected()) { e.stopPropagation(); + } } } @@ -137,7 +151,7 @@ export class CollectionFreeFormView extends CollectionViewBase { @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble && this.props.active()) { - if ((!this.isAnnotationOverlay || this.zoomScaling != 1) && !e.shiftKey) { + if ((!this.isAnnotationOverlay || this.zoomScaling !== 1) && !e.shiftKey) { let x = this.props.Document.GetNumber(KeyStore.PanX, 0); let y = this.props.Document.GetNumber(KeyStore.PanY, 0); let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); @@ -166,17 +180,18 @@ export class CollectionFreeFormView extends CollectionViewBase { e.stopPropagation(); e.preventDefault(); } else { - // if (modes[e.deltaMode] == 'pixels') coefficient = 50; - // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height?? + // if (modes[e.deltaMode] === 'pixels') coefficient = 50; + // else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height?? let transform = this.getTransform(); let deltaScale = (1 - (e.deltaY / coefficient)); - if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay) + if (deltaScale * this.zoomScaling < 1 && this.isAnnotationOverlay) { deltaScale = 1 / this.zoomScaling; + } let [x, y] = transform.transformPoint(e.clientX, e.clientY); - let localTransform = this.getLocalTransform() - localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y) + let localTransform = this.getLocalTransform(); + localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y); // console.log(localTransform) this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale); @@ -186,6 +201,7 @@ export class CollectionFreeFormView extends CollectionViewBase { @action private SetPan(panX: number, panY: number) { + Main.Instance.SetTextDoc(undefined, undefined); var x1 = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / x1) * this.nativeWidth, Math.max(0, panX)); const newPanY = Math.min((1 - 1 / x1) * this.nativeHeight, Math.max(0, panY)); @@ -216,7 +232,7 @@ export class CollectionFreeFormView extends CollectionViewBase { } return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0); }).map((doc, index) => { - doc.SetNumber(KeyStore.ZIndex, index + 1) + doc.SetNumber(KeyStore.ZIndex, index + 1); }); } @@ -243,17 +259,20 @@ export class CollectionFreeFormView extends CollectionViewBase { getDocumentViewProps(document: Document): DocumentViewProps { return { Document: document, - AddDocument: this.props.addDocument, - RemoveDocument: this.props.removeDocument, + addDocument: this.props.addDocument, + removeDocument: this.props.removeDocument, + moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, isTopMost: false, - SelectOnLoad: document.Id == this._selectOnLoaded, + selectOnLoad: document.Id === this._selectOnLoaded, PanelWidth: document.Width, PanelHeight: document.Height, ContentScaling: this.noScaling, - ContainingCollectionView: this.props.CollectionView, - focus: this.focusDocument - } + ContainingCollectionView: undefined, + focus: this.focusDocument, + parentActive: this.props.active, + onActiveChanged: this.props.active, + }; } @computed @@ -261,10 +280,11 @@ export class CollectionFreeFormView extends CollectionViewBase { var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); return this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc).reduce((prev, doc) => { var page = doc.GetNumber(KeyStore.Page, -1); - if (page == curPage || page == -1) + if (page === curPage || page === -1) { prev.push(<CollectionFreeFormDocumentView key={doc.Id} {...this.getDocumentViewProps(doc)} />); + } return prev; - }, [] as JSX.Element[]) + }, [] as JSX.Element[]); } @computed @@ -280,9 +300,9 @@ export class CollectionFreeFormView extends CollectionViewBase { layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={() => false} select={() => { }} />); } - getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()) - getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH) - getLocalTransform = (): Transform => Transform.Identity.scale(1 / this.scale).translate(this.panX, this.panY); + getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()); + getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH); + getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY); noScaling = () => 1; childViews = () => this.views; @@ -293,31 +313,35 @@ export class CollectionFreeFormView extends CollectionViewBase { const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); return ( - <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`} - onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} - onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} - style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}> - <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} - addDocument={this.addDocument} removeDocument={this.props.removeDocument} - getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> - <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} - getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} > - <div className="collectionfreeformview" ref={this._canvasRef} - style={{ transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }}> - {this.backgroundView} - <CollectionFreeFormLinksView {...this.props}> - <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} > - {this.childViews} - </InkingCanvas> - </CollectionFreeFormLinksView> - <CollectionFreeFormRemoteCursors {...this.props} /> + <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height })}> + {({ measureRef }) => ( + <div className={`collectionfreeformview-measure`} ref={measureRef}> + <div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`} + onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} + onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} + style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}> + <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} + addDocument={this.addDocument} removeDocument={this.props.removeDocument} + getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> + <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} + getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} > + <div className="collectionfreeformview" ref={this._canvasRef} + style={{ transform: `translate(${dx}px, ${dy}px) scale(${this.zoomScaling}, ${this.zoomScaling}) translate(${panx}px, ${pany}px)` }}> + {this.backgroundView} + <CollectionFreeFormLinksView {...this.props}> + <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} > + {this.childViews} + </InkingCanvas> + </CollectionFreeFormLinksView> + <CollectionFreeFormRemoteCursors {...this.props} /> + </div> + {this.overlayView} + </PreviewCursor> + <Timeline /> + </MarqueeView> </div> - {this.overlayView} - </PreviewCursor> - <Timeline /> - </MarqueeView> - - </div> + </div>)} + </Measure> ); } }
\ No newline at end of file |
