aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts37
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx26
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx31
-rw-r--r--src/client/views/nodes/DocumentView.tsx11
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx8
-rw-r--r--src/client/views/nodes/ImageBox.tsx1
-rw-r--r--src/fields/Document.ts58
9 files changed, 119 insertions, 57 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a92cf97fe..26167fab5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -74,12 +74,6 @@ export namespace Documents {
});
}
function assignOptions(doc: Document, options: DocumentOptions): Document {
- if (options.x !== undefined) { doc.SetNumber(KeyStore.X, options.x); }
- if (options.y !== undefined) { doc.SetNumber(KeyStore.Y, options.y); }
- if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); }
- if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
- if (options.nativeWidth !== undefined) { doc.SetNumber(KeyStore.NativeWidth, options.nativeWidth); }
- if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); }
if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); }
if (options.panx !== undefined) { doc.SetNumber(KeyStore.PanX, options.panx); }
if (options.pany !== undefined) { doc.SetNumber(KeyStore.PanY, options.pany); }
@@ -92,6 +86,15 @@ export namespace Documents {
if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); }
return doc;
}
+
+ function assignToDelegate(doc: Document, options: DocumentOptions): Document {
+ if (options.x !== undefined) { doc.SetNumber(KeyStore.X, options.x); }
+ if (options.y !== undefined) { doc.SetNumber(KeyStore.Y, options.y); }
+ if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); }
+ if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
+ return doc
+ }
+
function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document {
return assignOptions(new Document(protoId), { ...options, title: title, layout: layout });
}
@@ -132,7 +135,7 @@ export namespace Documents {
{ x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] });
}
function GetCollectionPrototype(): Document {
- return collProto ? collProto :
+ return collProto ? collProto.MakeDelegate() :
collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
{ panx: 0, pany: 0, scale: 1, width: 500, height: 500, layoutKeys: [KeyStore.Data] });
}
@@ -160,7 +163,7 @@ export namespace Documents {
export function ImageDocument(url: string, options: DocumentOptions = {}) {
return SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
- [new URL(url), ImageField]);
+ [new URL(url), ImageField]).MakeDelegate();
// let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
// [new URL(url), ImageField]);
// doc.SetText(KeyStore.Caption, "my caption...");
@@ -174,23 +177,27 @@ export namespace Documents {
export function AudioDocument(url: string, options: DocumentOptions = {}) {
return SetInstanceOptions(GetAudioPrototype(), options, [new URL(url), AudioField]);
}
+
export function TextDocument(options: DocumentOptions = {}) {
- return SetInstanceOptions(GetTextPrototype(), options, ["", TextField]);
+ return assignToDelegate(SetInstanceOptions(GetTextPrototype(), options, ["", TextField]).MakeDelegate(), options);
}
export function PdfDocument(url: string, options: DocumentOptions = {}) {
- return SetInstanceOptions(GetPdfPrototype(), options, [new URL(url), PDFField]);
+ return SetInstanceOptions(GetPdfPrototype(), options, [new URL(url), PDFField]).MakeDelegate();
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
- return SetInstanceOptions(GetWebPrototype(), options, [new URL(url), WebField]);
+ return SetInstanceOptions(GetWebPrototype(), options, [new URL(url), WebField]).MakeDelegate();
}
export function HtmlDocument(html: string, options: DocumentOptions = {}) {
- return SetInstanceOptions(GetWebPrototype(), options, [html, HtmlField]);
+ return SetInstanceOptions(GetWebPrototype(), options, [html, HtmlField]).MakeDelegate();
}
export function KVPDocument(document: Document, options: DocumentOptions = {}, id?: string) {
- return SetInstanceOptions(GetKVPPrototype(), options, document, id)
+ return SetInstanceOptions(GetKVPPrototype(), options, document, id).MakeDelegate()
}
- export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
- return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id)
+ export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string, makePrototype: boolean = true) {
+ if (!makePrototype) {
+ return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id)
+ }
+ return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, [documents, ListField], id).MakeDelegate()
}
export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id)
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 345371884..f6e19f6c9 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -74,7 +74,7 @@ Documents.initProtos(mainDocId, (res?: Document) => {
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => {
- mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
+ mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" }, undefined, false);
var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(mainfreeform)] }] };
mainContainer.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 9dc1ae847..5378678cc 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -88,15 +88,23 @@ export class CollectionFreeFormView extends CollectionViewBase {
@action
drop = (e: Event, de: DragManager.DropEvent) => {
super.drop(e, de);
- const docView: DocumentView = de.data["documentView"];
- let doc: Document = docView ? docView.props.Document : de.data["document"];
- if (doc) {
- let screenX = de.x - (de.data["xOffset"] as number || 0);
- let screenY = de.y - (de.data["yOffset"] as number || 0);
- const [x, y] = this.getTransform().transformPoint(screenX, screenY);
- doc.SetNumber(KeyStore.X, x);
- doc.SetNumber(KeyStore.Y, y);
- this.bringToFront(doc);
+ let screenX = de.x - (de.data["xOffset"] as number || 0);
+ let screenY = de.y - (de.data["yOffset"] as number || 0);
+ const [x, y] = this.getTransform().transformPoint(screenX, screenY);
+ if (!de.data["alias"]) {
+ const docView: DocumentView = de.data["documentView"];
+ let doc: Document = docView ? docView.props.Document : de.data["document"];
+ if (doc) {
+ doc.SetNumber(KeyStore.X, x);
+ doc.SetNumber(KeyStore.Y, y);
+ this.bringToFront(doc);
+ }
+ }
+ else {
+ let newDoc: Document = de.data["newDoc"]
+ newDoc.SetNumber(KeyStore.X, x)
+ newDoc.SetNumber(KeyStore.Y, y)
+ this.bringToFront(newDoc)
}
}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index d9b2722a6..40acf466e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -55,7 +55,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
value.push(doc);
} else {
- props.Document.SetData(props.fieldKey, [doc], ListField);
+ props.Document.SetOnPrototype(props.fieldKey, new ListField([doc]));
}
}
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index d9598aa72..7cccfaf05 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -3,7 +3,7 @@ import { Document } from "../../../fields/Document";
import { ListField } from "../../../fields/ListField";
import React = require("react");
import { KeyStore } from "../../../fields/KeyStore";
-import { FieldWaiting } from "../../../fields/Field";
+import { FieldWaiting, Field } from "../../../fields/Field";
import { undoBatch } from "../../util/UndoManager";
import { DragManager } from "../../util/DragManager";
import { DocumentView } from "../nodes/DocumentView";
@@ -45,17 +45,30 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
@undoBatch
@action
protected drop(e: Event, de: DragManager.DropEvent) {
- const docView: DocumentView = de.data["documentView"];
- const doc: Document = de.data["document"];
+ const docView: DocumentView = de.data["documentView"]
+ const doc: Document = de.data["document"]
+ if (de.data["alias"]) {
+ let newDoc = docView ? docView.props.Document.CreateAlias() : doc.CreateAlias()
+ de.data["newDoc"] = newDoc
+ let oldDoc = docView ? docView.props.Document : doc
+ oldDoc.GetAsync(KeyStore.Width, (f: Field) => {
+ newDoc.Set(KeyStore.Width, f)
+ })
+ oldDoc.GetAsync(KeyStore.Height, (f: Field) => {
+ newDoc.Set(KeyStore.Height, f)
+ })
+ }
- if (docView && (!docView.props.ContainingCollectionView || docView.props.ContainingCollectionView !== this.props.CollectionView)) {
- if (docView.props.RemoveDocument) {
- docView.props.RemoveDocument(docView.props.Document);
+ if (docView && docView.props.ContainingCollectionView && docView.props.ContainingCollectionView !== this.props.CollectionView) {
+ if (docView.props.RemoveDocument && !de.data["alias"]) {
+ docView.props.RemoveDocument(docView.props.Document)
}
- this.props.addDocument(docView.props.Document);
+ this.props.addDocument(de.data["alias"] ? de.data["newDoc"] : docView.props.Document)
} else if (doc) {
- this.props.removeDocument(doc);
- this.props.addDocument(doc);
+ if (!de.data["alias"]) {
+ this.props.removeDocument(doc)
+ }
+ this.props.addDocument(doc)
}
e.stopPropagation();
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7a43c34d0..84483ac55 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,6 +16,7 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie
import { ContextMenu } from "../ContextMenu";
import "./DocumentView.scss";
import React = require("react");
+import { props } from "bluebird";
import { DocumentContentsView } from "./DocumentContentsView";
import { Utils } from "../../../Utils";
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
@@ -93,7 +94,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
this._downY = e.clientY;
if (e.shiftKey && e.buttons === 2) {
if (this.props.isTopMost) {
- this.startDragging(e.pageX, e.pageY);
+ this.startDragging(e.pageX, e.pageY, e.ctrlKey);
}
else CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e);
e.stopPropagation();
@@ -150,18 +151,20 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
}
- startDragging(x: number, y: number) {
+ startDragging(x: number, y: number, ctrlPressed: boolean) {
if (this._mainCont.current) {
const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
let dragData: { [id: string]: any } = {};
dragData["documentView"] = this;
+ dragData["document"] = ctrlPressed ? this.props.Document.CreateAlias() : this.props.Document
dragData["xOffset"] = x - left;
dragData["yOffset"] = y - top;
+ dragData["alias"] = ctrlPressed
DragManager.StartDrag(this._mainCont.current, dragData, {
handlers: {
dragComplete: action(() => { }),
},
- hideSource: true
+ hideSource: !ctrlPressed
})
}
}
@@ -174,7 +177,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
document.removeEventListener("pointermove", this.onPointerMove)
document.removeEventListener("pointerup", this.onPointerUp);
if (!this.topMost || e.buttons == 2 || e.altKey) {
- this.startDragging(e.x, e.y);
+ this.startDragging(e.x, e.y, e.ctrlKey);
}
}
e.stopPropagation();
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d7026ed67..4bd5726f4 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -55,7 +55,9 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
if (this._editorView) {
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
- this.props.doc.SetData(this.props.fieldKey, JSON.stringify(state.toJSON()), RichTextField);
+ const { doc, fieldKey } = this.props;
+ doc.SetOnPrototype(fieldKey, new RichTextField(JSON.stringify(state.toJSON())))
+ // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField);
}
}
@@ -114,7 +116,9 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
@action
onChange(e: React.ChangeEvent<HTMLInputElement>) {
- this.props.doc.SetData(this.props.fieldKey, e.target.value, RichTextField);
+ const { fieldKey, doc } = this.props;
+ doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value))
+ // doc.SetData(fieldKey, e.target.value, RichTextField);
}
onPointerDown = (e: React.PointerEvent): void => {
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index cad8904d0..c12db1192 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -99,6 +99,7 @@ export class ImageBox extends React.Component<FieldViewProps> {
render() {
let field = this.props.doc.Get(this.props.fieldKey);
+ console.log(field)
let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif";
let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1);
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 25e239417..b7d6bcaa8 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -2,7 +2,7 @@ import { Key } from "./Key"
import { KeyStore } from "./KeyStore";
import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field"
import { NumberField } from "./NumberField";
-import { ObservableMap, computed, action } from "mobx";
+import { ObservableMap, computed, action, runInAction } from "mobx";
import { TextField } from "./TextField";
import { ListField } from "./ListField";
import { Server } from "../client/Server";
@@ -11,6 +11,7 @@ import { UndoManager } from "../client/util/UndoManager";
import { HtmlField } from "./HtmlField";
export class Document extends Field {
+ //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap();
public _proxies: ObservableMap<string, FieldId> = new ObservableMap();
@@ -119,9 +120,11 @@ export class Document extends Field {
* @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
*/
GetAsync(key: Key, callback: (field: Field) => void): boolean {
- //TODO: This should probably check if this.fields contains the key before calling Server.GetDocumentField
- //This currently doesn't deal with prototypes
- if (this._proxies.has(key.Id)) {
+ //TODO: This currently doesn't deal with prototypes
+ let field = this.fields.get(key.Id);
+ if (field && field.field) {
+ callback(field.field);
+ } else if (this._proxies.has(key.Id)) {
Server.GetDocumentField(this, key, callback);
return true;
}
@@ -207,25 +210,37 @@ export class Document extends Field {
}
@action
- Set(key: Key, field: Field | undefined): void {
+ SetOnPrototype(key: Key, field: Field | undefined): void {
+ this.GetAsync(KeyStore.Prototype, (f: Field) => {
+ (f as Document).Set(key, field)
+ })
+ }
+
+ @action
+ Set(key: Key, field: Field | undefined, setOnPrototype = false): void {
let old = this.fields.get(key.Id);
let oldField = old ? old.field : undefined;
- if (field) {
- this.fields.set(key.Id, { key, field });
- this._proxies.set(key.Id, field.Id)
- // Server.AddDocumentField(this, key, field);
- } else {
- this.fields.delete(key.Id);
- this._proxies.delete(key.Id)
- // Server.DeleteDocumentField(this, key);
+ if (setOnPrototype) {
+ this.SetOnPrototype(key, field)
+ }
+ else {
+ if (field) {
+ this.fields.set(key.Id, { key, field });
+ this._proxies.set(key.Id, field.Id)
+ // Server.AddDocumentField(this, key, field);
+ } else {
+ this.fields.delete(key.Id);
+ this._proxies.delete(key.Id)
+ // Server.DeleteDocumentField(this, key);
+ }
+ Server.UpdateField(this);
}
if (oldField || field) {
UndoManager.AddEvent({
- undo: () => this.Set(key, oldField),
- redo: () => this.Set(key, field)
+ undo: () => this.Set(key, oldField, setOnPrototype),
+ redo: () => this.Set(key, field, setOnPrototype)
})
}
- Server.UpdateField(this);
}
@action
@@ -265,6 +280,17 @@ export class Document extends Field {
return protos;
}
+ CreateAlias(id?: string): Document {
+ let alias = new Document(id)
+ this.GetAsync(KeyStore.Prototype, (f: Field) => {
+ alias.Set(KeyStore.Prototype, f)
+ })
+ alias.SetNumber(KeyStore.Width, 300)
+ alias.SetNumber(KeyStore.Height, 300)
+
+ return alias
+ }
+
MakeDelegate(id?: string): Document {
let delegate = new Document(id);