aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionFreeFormView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/CollectionFreeFormView.tsx')
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx255
1 files changed, 121 insertions, 134 deletions
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 26c8517b3..05de8dab9 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -1,25 +1,30 @@
+import { action, computed } from "mobx";
import { observer } from "mobx-react";
-import React = require("react");
-import { action, observable, computed } from "mobx";
-import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-import { DragManager } from "../../util/DragManager";
-import "./CollectionFreeFormView.scss";
-import { Utils } from "../../../Utils";
-import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
-import { SelectionManager } from "../../util/SelectionManager";
-import { Key, KeyStore } from "../../../fields/Key";
import { Document } from "../../../fields/Document";
-import { ListField } from "../../../fields/ListField";
-import { NumberField } from "../../../fields/NumberField";
-import { Documents } from "../../documents/Documents";
import { FieldWaiting } from "../../../fields/Field";
+import { KeyStore } from "../../../fields/KeyStore";
+import { ListField } from "../../../fields/ListField";
+import { TextField } from "../../../fields/TextField";
+import { DragManager } from "../../util/DragManager";
import { Transform } from "../../util/Transform";
+import { undoBatch } from "../../util/UndoManager";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionSchemaView } from "../collections/CollectionSchemaView";
+import { CollectionView } from "../collections/CollectionView";
+import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
import { DocumentView } from "../nodes/DocumentView";
+import { WebView } from "../nodes/WebView";
+import { FormattedTextBox } from "../nodes/FormattedTextBox";
+import { ImageBox } from "../nodes/ImageBox";
+import "./CollectionFreeFormView.scss";
+import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { CollectionViewBase } from "./CollectionViewBase";
+import React = require("react");
+import { Documents } from "../../documents/Documents";
+const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
@observer
export class CollectionFreeFormView extends CollectionViewBase {
- public static LayoutString(fieldKey: string = "DataKey") { return CollectionViewBase.LayoutString("CollectionFreeFormView", fieldKey); }
- private _containerRef = React.createRef<HTMLDivElement>();
private _canvasRef = React.createRef<HTMLDivElement>();
private _lastX: number = 0;
private _lastY: number = 0;
@@ -27,58 +32,35 @@ export class CollectionFreeFormView extends CollectionViewBase {
private _downY: number = 0;
private _borderColor: string = "red"
- constructor(props: CollectionViewProps) {
- super(props);
- }
-
- @computed
- get isAnnotationOverlay() { return this.props.CollectionFieldKey == KeyStore.Annotations; }
- @computed
- get nativeWidth() { return this.props.DocumentForCollection.GetNumber(KeyStore.NativeWidth, 0); }
- @computed
- get nativeHeight() { return this.props.DocumentForCollection.GetNumber(KeyStore.NativeHeight, 0); }
-
- @computed
- get zoomScaling() { return this.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1); }
-
- @computed
- get resizeScaling() { return this.isAnnotationOverlay ? this.props.DocumentForCollection.GetNumber(KeyStore.Width, 0) / this.nativeWidth : 1; }
+ @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.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); }
+ @undoBatch
@action
drop = (e: Event, de: DragManager.DropEvent) => {
+ super.drop(e, de);
const doc: DocumentView = de.data["document"];
- var me = this;
- if (doc.props.ContainingCollectionView && doc.props.ContainingCollectionView !== this) {
- doc.props.ContainingCollectionView.removeDocument(doc.props.Document);
- this.addDocument(doc.props.Document);
- }
const xOffset = de.data["xOffset"] as number || 0;
const yOffset = de.data["yOffset"] as number || 0;
//this should be able to use translate and scale methods on an Identity transform, no?
- const transform = me.getTransform();
+ const transform = this.getTransform();
const screenX = de.x - xOffset;
const screenY = de.y - yOffset;
const [x, y] = transform.transformPoint(screenX, screenY);
doc.props.Document.SetNumber(KeyStore.X, x);
doc.props.Document.SetNumber(KeyStore.Y, y);
this.bringToFront(doc);
- e.stopPropagation();
- }
-
- componentDidMount() {
- if (this._containerRef.current) {
- DragManager.MakeDropTarget(this._containerRef.current, {
- handlers: {
- drop: this.drop
- }
- });
- }
}
@action
onPointerDown = (e: React.PointerEvent): void => {
- if ((e.button === 2 && this.active) ||
+ if ((e.button === 2 && this.props.active()) ||
!e.defaultPrevented) {
document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
@@ -103,11 +85,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
onPointerMove = (e: PointerEvent): void => {
- if (!e.cancelBubble && this.active) {
+ if (!e.cancelBubble && this.props.active()) {
e.preventDefault();
e.stopPropagation();
- let x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
- let y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
+ let x = this.props.Document.GetNumber(KeyStore.PanX, 0);
+ let y = this.props.Document.GetNumber(KeyStore.PanY, 0);
let [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
this.SetPan(x + dx, y + dy);
@@ -120,7 +102,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
onPointerWheel = (e: React.WheelEvent): void => {
e.stopPropagation();
e.preventDefault();
- let modes = ['pixels', 'lines', 'page'];
let coefficient = 1000;
// if (modes[e.deltaMode] == 'pixels') coefficient = 50;
// else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height??
@@ -132,7 +113,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
let localTransform = this.getLocalTransform();
localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y)
- this.props.DocumentForCollection.SetNumber(KeyStore.Scale, localTransform.Scale);
+ this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale);
this.SetPan(localTransform.TranslateX, localTransform.TranslateY);
}
@@ -140,119 +121,125 @@ export class CollectionFreeFormView extends CollectionViewBase {
private SetPan(panX: number, panY: number) {
const newPanX = Math.max((1 - this.zoomScaling) * this.nativeWidth, Math.min(0, panX));
const newPanY = Math.max((1 - this.zoomScaling) * this.nativeHeight, Math.min(0, panY));
- this.props.DocumentForCollection.SetNumber(KeyStore.PanX, this.isAnnotationOverlay ? newPanX : panX);
- this.props.DocumentForCollection.SetNumber(KeyStore.PanY, this.isAnnotationOverlay ? newPanY : panY);
+ this.props.Document.SetNumber(KeyStore.PanX, false && this.isAnnotationOverlay ? newPanX : panX);
+ this.props.Document.SetNumber(KeyStore.PanY, false && this.isAnnotationOverlay ? newPanY : panY);
}
@action
onDrop = (e: React.DragEvent): void => {
- e.stopPropagation()
- e.preventDefault()
- let fReader = new FileReader()
- let file = e.dataTransfer.items[0].getAsFile();
- let that = this;
- const panx: number = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
- const pany: number = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
- let x = e.pageX - panx
- let y = e.pageY - pany
-
- fReader.addEventListener("load", action("drop", (event) => {
- if (fReader.result) {
- let url = "" + fReader.result;
- let doc = Documents.ImageDocument(url, {
- x: x, y: y
- })
- let docs = that.props.DocumentForCollection.GetT(KeyStore.Data, ListField);
- if (docs != FieldWaiting) {
- if (!docs) {
- docs = new ListField<Document>();
- that.props.DocumentForCollection.Set(KeyStore.Data, docs)
- }
- docs.Data.push(doc);
- }
- }
- }), false)
+ const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
+ const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
+ let transform = this.getTransform();
- if (file) {
- fReader.readAsDataURL(file)
- }
+ var pt = transform.transformPoint(e.pageX, e.pageY);
+ super.onDrop(e, { x: pt[0], y: pt[1] });
}
- onDragOver = (e: React.DragEvent): void => {
+ onDragOver = (): void => {
}
@action
bringToFront(doc: DocumentView) {
- const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
+ const { fieldKey: fieldKey, Document: Document } = this.props;
- const value: Document[] = Document.GetList<Document>(fieldKey, []);
- var topmost = value.reduce((topmost, d) => Math.max(d.GetNumber(KeyStore.ZIndex, 0), topmost), -1000);
- value.map(d => {
- var zind = d.GetNumber(KeyStore.ZIndex, 0);
- if (zind != topmost - 1 - (topmost - zind) && d != doc.props.Document) {
- d.SetData(KeyStore.ZIndex, topmost - 1 - (topmost - zind), NumberField);
+ const value: Document[] = Document.GetList<Document>(fieldKey, []).slice();
+ value.sort((doc1, doc2) => {
+ if (doc1 === doc.props.Document) {
+ return 1;
+ }
+ if (doc2 === doc.props.Document) {
+ return -1;
}
- })
+ return doc1.GetNumber(KeyStore.ZIndex, 0) - doc2.GetNumber(KeyStore.ZIndex, 0);
+ }).map((doc, index) => {
+ doc.SetNumber(KeyStore.ZIndex, index + 1)
+ });
+ }
- if (doc.props.Document.GetNumber(KeyStore.ZIndex, 0) != 0) {
- doc.props.Document.SetData(KeyStore.ZIndex, 0, NumberField);
+
+ @computed get backgroundLayout(): string | undefined {
+ let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
+ if (field && field !== "<Waiting>") {
+ return field.Data;
}
}
-
- @computed
- get translate(): [number, number] {
- const x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
- const y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
- return [x, y];
+ @computed get overlayLayout(): string | undefined {
+ let field = this.props.Document.GetT(KeyStore.OverlayLayout, TextField);
+ if (field && field !== "<Waiting>") {
+ return field.Data;
+ }
}
-
@computed
- get scale(): number {
- return this.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1);
- }
-
- getTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
+ get views() {
+ const { fieldKey, Document } = this.props;
+ const lvalue = Document.GetT<ListField<Document>>(fieldKey, ListField);
+ if (lvalue && lvalue != FieldWaiting) {
+ return lvalue.Data.map(doc => {
+ return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
+ AddDocument={this.props.addDocument}
+ RemoveDocument={this.props.removeDocument}
+ ScreenToLocalTransform={this.getTransform}
+ isTopMost={false}
+ ContentScaling={this.noScaling}
+ PanelWidth={doc.Width}
+ PanelHeight={doc.Height}
+ ContainingCollectionView={this.props.CollectionView} />);
+ })
+ }
+ return null;
}
- getLocalTransform = (): Transform => {
- const [x, y] = this.translate;
- return Transform.Identity.translate(-x, -y).scale(1 / this.scale);
+ @computed
+ get backgroundView() {
+ return !this.backgroundLayout ? (null) :
+ (<JsxParser
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
+ bindings={this.props.bindings}
+ jsx={this.backgroundLayout}
+ showWarnings={true}
+ onError={(test: any) => console.log(test)}
+ />);
}
+ @computed
+ get overlayView() {
+ return !this.overlayLayout ? (null) :
+ (<JsxParser
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+ bindings={this.props.bindings}
+ jsx={this.overlayLayout}
+ showWarnings={true}
+ onError={(test: any) => console.log(test)}
+ />);
+ }
+ getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).transform(this.getLocalTransform())
+ getLocalTransform = (): Transform => Transform.Identity.translate(-this.panX, -this.panY).scale(1 / this.scale);
+ noScaling = () => 1;
render() {
- const Document: Document = this.props.DocumentForCollection;
- const value: Document[] = Document.GetList<Document>(this.props.CollectionFieldKey, []);
- const panx: number = Document.GetNumber(KeyStore.PanX, 0);
- const pany: number = Document.GetNumber(KeyStore.PanY, 0);
- var me = this;
-
+ const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0);
+ const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0);
+ var overlay = this.overlayView ?
+ <div style={{ position: "absolute", width: "100%", height: "100%" }}>
+ {this.overlayView}
+ </div>
+ :
+ (null);
return (
<div className="collectionfreeformview-container"
onPointerDown={this.onPointerDown}
onWheel={this.onPointerWheel}
onContextMenu={(e) => e.preventDefault()}
- onDrop={this.onDrop}
+ onDrop={this.onDrop.bind(this)}
onDragOver={this.onDragOver}
- style={{
- borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
- }}
- ref={this._containerRef}>
+ style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px`, }}
+ ref={this.createDropTarget}>
<div className="collectionfreeformview"
- style={{ width: "100%", transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
+ style={{ transformOrigin: "left top", transform: ` translate(${panx}px, ${pany}px) scale(${this.zoomScaling}, ${this.zoomScaling})` }}
ref={this._canvasRef}>
-
- {this.props.BackgroundView ? this.props.BackgroundView() : null}
- {value.map(doc => {
- return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
- AddDocument={this.addDocument}
- RemoveDocument={this.removeDocument}
- ScreenToLocalTransform={this.getTransform}
- isTopMost={false}
- Scaling={1}
- ContainingCollectionView={this} DocumentView={this.props.ContainingDocumentView} />);
- })}
+ {this.backgroundView}
+ {this.views}
</div>
+ {this.overlayView}
</div>
);
}