aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/util/DocumentManager.ts14
-rw-r--r--src/client/views/DocumentDecorations.tsx96
-rw-r--r--src/client/views/MainOverlayTextBox.scss1
-rw-r--r--src/client/views/MainOverlayTextBox.tsx30
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx79
-rw-r--r--src/client/views/collections/CollectionSubView.tsx38
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx10
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx119
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx31
-rw-r--r--src/fields/KeyStore.ts4
14 files changed, 215 insertions, 223 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b0bb74d89..0e6661819 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -54,6 +54,7 @@ export interface DocumentOptions {
viewType?: number;
backgroundColor?: string;
copyDraggedItems?: boolean;
+ documentText?: string;
}
export namespace Documents {
@@ -97,6 +98,7 @@ export namespace Documents {
if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); }
if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); }
if (options.page !== undefined) { doc.SetNumber(KeyStore.Page, options.page); }
+ if (options.documentText !== undefined) { doc.SetText(KeyStore.DocumentText, options.documentText); }
if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); }
if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); }
if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 3b5a5b470..56669fb79 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -38,11 +38,17 @@ export class DocumentManager {
toReturn = view;
return;
}
- let docSrc = doc.GetT(KeyStore.Prototype, Document);
- if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
- toReturn = view;
- }
});
+ if (!toReturn) {
+ DocumentManager.Instance.DocumentViews.map(view => {
+ let doc = view.props.Document;
+
+ let docSrc = doc.GetT(KeyStore.Prototype, Document);
+ if (docSrc && docSrc !== FieldWaiting && Object.is(docSrc, toFind)) {
+ toReturn = view;
+ }
+ });
+ }
return toReturn;
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1f5078c85..2af6cb353 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Key } from "../../fields/Key";
import { KeyStore } from "../../fields/KeyStore";
@@ -17,6 +17,7 @@ import { LinkMenu } from "./nodes/LinkMenu";
import React = require("react");
import { CompileScript } from "../util/Scripting";
import { IconBox } from "./nodes/IconBox";
+import { FieldValue, Field } from "../../fields/Field";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -33,6 +34,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
private _titleHeight = 20;
private _linkButton = React.createRef<HTMLDivElement>();
private _linkerButton = React.createRef<HTMLDivElement>();
+ private _downX = 0;
+ private _downY = 0;
+ @observable private _minimizedX = 0;
+ @observable private _minimizedY = 0;
//@observable private _title: string = this._documents[0].props.Document.Title;
@observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : "";
@observable private _fieldKey: Key = KeyStore.Title;
@@ -179,13 +184,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
document.removeEventListener("pointerup", this.onCloseUp);
}
}
- _downX = 0;
- _downY = 0;
+ @action
onMinimizeDown = (e: React.PointerEvent): void => {
e.stopPropagation();
if (e.button === 0) {
this._downX = e.pageX;
this._downY = e.pageY;
+ let selDoc = SelectionManager.SelectedDocuments()[0];
+ let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0);
+ this._minimizedX = selDocPos[0] + 12;
+ this._minimizedY = selDocPos[1] + 12;
document.removeEventListener("pointermove", this.onMinimizeMove);
document.addEventListener("pointermove", this.onMinimizeMove);
document.removeEventListener("pointerup", this.onMinimizeUp);
@@ -193,51 +201,58 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
}
}
- @observable _minimizedX = 0;
- @observable _minimizedY = 0;
@action
onMinimizeMove = (e: PointerEvent): void => {
e.stopPropagation();
- let dx = e.pageX - this._downX;
- let dy = e.pageY - this._downY;
- if (Math.abs(dx) > 4 || Math.abs(dy) > 4) {
- this._iconifying = true;
- let xf = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().scale(SelectionManager.SelectedDocuments()[0].props.ContentScaling()).inverse().transformPoint(0, 0);
- let dx = e.pageX - xf[0];
- let dy = e.pageY - xf[1];
- this._minimizedX = e.clientX;
- this._minimizedY = e.clientY;
- if (Math.abs(dx) < 20 && Math.abs(dy) < 20) {
- this._minimizedX = xf[0];
- this._minimizedY = xf[1];
- }
- SelectionManager.SelectedDocuments().map(dv => {
- let minDoc = dv.props.Document.Get(KeyStore.MinimizedDoc);
- if (minDoc instanceof Document) {
- let where = (dv.props.ScreenToLocalTransform()).scale(dv.props.ContentScaling()).transformPoint(this._minimizedX, this._minimizedY);
- let minDocument = minDoc as Document;
- minDocument.SetNumber(KeyStore.X, where[0] + dv.props.Document.GetNumber(KeyStore.X, 0));
- minDocument.SetNumber(KeyStore.Y, where[1] + dv.props.Document.GetNumber(KeyStore.Y, 0));
- }
- });
+ let moved = Math.abs(e.pageX - this._downX) > 4 || Math.abs(e.pageY - this._downY) > 4;
+ if (moved) {
+ let selDoc = SelectionManager.SelectedDocuments()[0];
+ let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0);
+ let snapped = Math.abs(e.pageX - selDocPos[0]) < 20 && Math.abs(e.pageY - selDocPos[1]) < 20;
+ this._minimizedX = snapped ? selDocPos[0] + 4 : e.clientX;
+ this._minimizedY = snapped ? selDocPos[1] - 18 : e.clientY;
+ let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd);
+ Promise.all(selectedDocs.map(async selDoc => await selDoc.getIconDoc())).then(minDocSet =>
+ this.moveIconDocs(SelectionManager.SelectedDocuments())
+ );
+ this._iconifying = snapped;
}
}
@action
onMinimizeUp = (e: PointerEvent): void => {
e.stopPropagation();
if (e.button === 0) {
- let dx = e.clientX - this._downX;
- let dy = e.clientY - this._downY;
- if (Math.abs(dx) < 4 && Math.abs(dy) < 4 && !this._iconifying) {
- SelectionManager.SelectedDocuments().map(dv => dv.minimize());
- SelectionManager.DeselectAll();
- } else {
- this._minimizedX = this._minimizedY = 0;
- }
document.removeEventListener("pointermove", this.onMinimizeMove);
document.removeEventListener("pointerup", this.onMinimizeUp);
+ let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd);
+ Promise.all(selectedDocs.map(async selDoc => await selDoc.getIconDoc())).then(minDocSet => {
+ let minDocs = minDocSet.filter(minDoc => minDoc instanceof Document).map(minDoc => minDoc as Document);
+ minDocs.map(minDoc => {
+ minDoc.SetNumber(KeyStore.X, minDocs[0].GetNumber(KeyStore.X, 0));
+ minDoc.SetNumber(KeyStore.Y, minDocs[0].GetNumber(KeyStore.Y, 0));
+ minDoc.SetData(KeyStore.LinkTags, minDocs, ListField);
+ if (this._iconifying && selectedDocs[0].props.removeDocument) {
+ selectedDocs[0].props.removeDocument(minDoc);
+ (minDoc.Get(KeyStore.MaximizedDoc, false) as Document)!.Set(KeyStore.MinimizedDoc, undefined);
+ }
+ });
+ runInAction(() => this._minimizedX = this._minimizedY = 0);
+ if (!this._iconifying) selectedDocs[0].toggleIcon();
+ this._iconifying = false;
+ });
}
- this._iconifying = false;
+ }
+ moveIconDocs(selViews: DocumentView[], minDocSet?: FieldValue<Field>[]) {
+ selViews.map(selDoc => {
+ let minDoc = selDoc.props.Document.Get(KeyStore.MinimizedDoc);
+ if (minDoc instanceof Document) {
+ let zoom = selDoc.props.Document.GetNumber(KeyStore.ZoomBasis, 1);
+ let where = (selDoc.props.ScreenToLocalTransform()).scale(selDoc.props.ContentScaling()).scale(1 / zoom).
+ transformPoint(this._minimizedX - 12, this._minimizedY - 12);
+ minDoc.SetNumber(KeyStore.X, where[0] + selDoc.props.Document.GetNumber(KeyStore.X, 0));
+ minDoc.SetNumber(KeyStore.Y, where[1] + selDoc.props.Document.GetNumber(KeyStore.Y, 0));
+ }
+ });
}
onPointerDown = (e: React.PointerEvent): void => {
@@ -418,17 +433,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
if (bounds.x === Number.MAX_VALUE || !seldoc) {
return (null);
}
- let selpos = this._minimizedX !== 0 || this._minimizedY !== 0 ?
- [this._minimizedX - 12 + (!this._iconifying ? 8 : 0), this._minimizedY - 12 + (!this._iconifying ? 28 : 0)] :
- [0, this._iconifying ? -18 : 0];
let minimizeIcon = (
- <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}
- style={{ transform: `translate(${selpos[0]}px,${selpos[1]}px)`, }}>
+ <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>
{SelectionManager.SelectedDocuments().length == 1 ? IconBox.DocumentIcon(SelectionManager.SelectedDocuments()[0].props.Document.GetText(KeyStore.Layout, "...")) : "..."}
</div>);
- if (this._iconifying) {
- return (<div className="documentDecorations-container" > {minimizeIcon} </div>);
- }
if (this.Hidden) {
return (null);
diff --git a/src/client/views/MainOverlayTextBox.scss b/src/client/views/MainOverlayTextBox.scss
index 697d68c8c..f6a746e63 100644
--- a/src/client/views/MainOverlayTextBox.scss
+++ b/src/client/views/MainOverlayTextBox.scss
@@ -7,6 +7,7 @@
overflow: visible;
top: 0;
left: 0;
+ pointer-events: none;
z-index: $mainTextInput-zindex;
.formattedTextBox-cont {
background-color: rgba(248, 6, 6, 0.001);
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 8cb01117c..2b72b09c6 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -21,8 +21,8 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
public static Instance: MainOverlayTextBox;
@observable public TextDoc?: Document = undefined;
public TextScroll: number = 0;
- private _textRect: any;
- private _textXf: Transform = Transform.Identity();
+ @observable _textRect: any;
+ @observable _textXf: () => Transform = () => Transform.Identity();
private _textFieldKey: Key = KeyStore.Data;
private _textColor: string | null = null;
private _textTargetDiv: HTMLDivElement | undefined;
@@ -35,14 +35,14 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
}
@action
- SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: Transform) {
+ SetTextDoc(textDoc?: Document, textFieldKey?: Key, div?: HTMLDivElement, tx?: () => Transform) {
if (this._textTargetDiv) {
this._textTargetDiv.style.color = this._textColor;
}
this.TextDoc = textDoc;
this._textFieldKey = textFieldKey!;
- this._textXf = tx ? tx : Transform.Identity();
+ this._textXf = tx ? tx : () => Transform.Identity();
this._textTargetDiv = div;
if (div) {
this._textColor = div.style.color;
@@ -71,9 +71,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
document.removeEventListener("pointermove", this.textBoxMove);
document.removeEventListener('pointerup', this.textBoxUp);
let dragData = new DragManager.DocumentDragData([this.TextDoc!]);
- const [left, top] = this._textXf
- .inverse()
- .transformPoint(0, 0);
+ const [left, top] = this._textXf.inverse().transformPoint(0, 0);
dragData.xOffset = e.clientX - left;
dragData.yOffset = e.clientY - top;
DragManager.StartDocumentDrag([this._textTargetDiv!], dragData, e.clientX, e.clientY, {
@@ -91,17 +89,15 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
render() {
if (this.TextDoc) {
- let x: number = this._textRect.x;
- let y: number = this._textRect.y;
- let w: number = this._textRect.width;
- let h: number = this._textRect.height;
- let t = this._textXf.transformPoint(0, 0);
- let s = this._textXf.transformPoint(1, 0);
- s[0] = Math.sqrt((s[0] - t[0]) * (s[0] - t[0]) + (s[1] - t[1]) * (s[1] - t[1]));
- return <div className="mainOverlayTextBox-textInput" style={{ pointerEvents: "none", transform: `translate(${x}px, ${y}px) scale(${1 / s[0]},${1 / s[0]})`, width: "auto", height: "auto" }} >
- <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll} style={{ pointerEvents: "none", transform: `scale(${1}, ${1})`, width: `${w * s[0]}px`, height: `${h * s[0]}px` }}>
+ let toScreenXf = this._textXf().inverse();
+ let pt = toScreenXf.transformPoint(0, 0);
+ let s = 1 / this._textXf().Scale;
+ return <div className="mainOverlayTextBox-textInput" style={{ transform: `translate(${pt[0]}px, ${pt[1]}px) scale(${s},${s})`, width: "auto", height: "auto" }} >
+ <div className="mainOverlayTextBox-textInput" onPointerDown={this.textBoxDown} ref={this._textProxyDiv} onScroll={this.textScroll}
+ style={{ width: `${this.TextDoc.Width()}px`, height: `${this.TextDoc.Height()}px` }}>
<FormattedTextBox fieldKey={this._textFieldKey} isOverlay={true} Document={this.TextDoc} isSelected={returnTrue} select={emptyFunction} isTopMost={true}
- selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ScreenToLocalTransform={() => this._textXf} focus={emptyDocFunction} />
+ selectOnLoad={true} ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue}
+ ScreenToLocalTransform={this._textXf} focus={emptyDocFunction} />
</div>
</ div>;
}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 4755b2d57..eec01bb3f 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -8,6 +8,7 @@ import { ListField } from '../../../fields/ListField';
import { NumberField } from '../../../fields/NumberField';
import { ContextMenu } from '../ContextMenu';
import { FieldViewProps } from '../nodes/FieldView';
+import { TextField } from '../../../fields/TextField';
export enum CollectionViewType {
Invalid,
@@ -87,56 +88,50 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
@action.bound
addDocument(doc: Document, allowDuplicates: boolean = false): boolean {
- let props = this.props;
- var curPage = props.Document.GetNumber(KeyStore.CurPage, -1);
+ var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1);
doc.SetOnPrototype(KeyStore.Page, new NumberField(curPage));
- if (true || this.isAnnotationOverlay) {
- doc.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1));
- }
if (curPage >= 0) {
- doc.SetOnPrototype(KeyStore.AnnotationOn, props.Document);
+ doc.SetOnPrototype(KeyStore.AnnotationOn, this.props.Document);
}
- if (props.Document.Get(props.fieldKey) instanceof Field) {
- //TODO This won't create the field if it doesn't already exist
- const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>());
- if (!this.createsCycle(doc, props.Document)) {
+ if (this.props.Document.Get(this.props.fieldKey) instanceof Field) {
+ const value = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ if (!this.createsCycle(doc, this.props.Document)) {
if (!value.some(v => v.Id === doc.Id) || allowDuplicates) {
value.push(doc);
+ doc.SetNumber(KeyStore.ZoomBasis, this.props.Document.GetNumber(KeyStore.Scale, 1));
}
- }
- else {
- return false;
- }
- } else {
- let proto = props.Document.GetPrototype();
- if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) {
- const field = new ListField([doc]);
- // const script = CompileScript(`
- // if(added) {
- // console.log("added " + field.Title + " " + doc.Title);
- // } else {
- // console.log("removed " + field.Title + " " + doc.Title);
- // }
- // `, {
- // addReturn: false,
- // params: {
- // field: Document.name,
- // added: "boolean"
- // },
- // capturedVariables: {
- // doc: this.props.Document
- // }
- // });
- // if (script.compiled) {
- // field.addScript(new ScriptField(script));
- // }
- props.Document.SetOnPrototype(props.fieldKey, field);
- }
- else {
- return false;
+ return true;
}
}
- return true;
+ // bcz: What is this code trying to do?
+ // else {
+ // let proto = props.Document.GetPrototype();
+ // if (!proto || proto === FieldWaiting || !this.createsCycle(proto, doc)) {
+ // const field = new ListField([doc]);
+ // // const script = CompileScript(`
+ // // if(added) {
+ // // console.log("added " + field.Title + " " + doc.Title);
+ // // } else {
+ // // console.log("removed " + field.Title + " " + doc.Title);
+ // // }
+ // // `, {
+ // // addReturn: false,
+ // // params: {
+ // // field: Document.name,
+ // // added: "boolean"
+ // // },
+ // // capturedVariables: {
+ // // doc: this.props.Document
+ // // }
+ // // });
+ // // if (script.compiled) {
+ // // field.addScript(new ScriptField(script));
+ // // }
+ // props.Document.SetOnPrototype(props.fieldKey, field);
+ // return true;
+ // }
+ // }
+ return false;
}
@action.bound
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5c3b2e586..ead559bd9 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -159,10 +159,7 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
e.preventDefault();
if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
- console.log("not good");
- let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 });
- htmlDoc.SetText(KeyStore.DocumentText, text);
- this.props.addDocument(htmlDoc, false);
+ this.props.addDocument(Documents.HtmlDocument(html, { ...options, width: 300, height: 300, documentText: text }), false);
return;
}
@@ -188,36 +185,17 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
let type = item.type;
if (item.kind === "file") {
let file = item.getAsFile();
- let formData = new FormData();
-
- if (file) {
- formData.append('file', file);
- }
let dropFileName = file ? file.name : "-empty-";
+ let formData = new FormData();
+ if (file) formData.append('file', file);
- let prom = fetch(upload, {
+ promises.push(fetch(upload, {
method: 'POST',
body: formData
- }).then(async (res: Response) => {
- (await res.json()).map(action((file: any) => {
- let path = window.location.origin + file;
- let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName });
-
- docPromise.then(action((doc?: Document) => {
- let docs = this.props.Document.GetT(KeyStore.Data, ListField);
- if (docs !== FieldWaiting) {
- if (!docs) {
- docs = new ListField<Document>();
- this.props.Document.Set(KeyStore.Data, docs);
- }
- if (doc) {
- docs.Data.push(doc);
- }
- }
- }));
- }));
- });
- promises.push(prom);
+ }).then(async (res: Response) =>
+ (await res.json()).map(action((file: any) =>
+ this.getDocumentFromType(type, window.location.origin + file, { ...options, nativeWidth: 600, width: 300, title: dropFileName }).
+ then(doc => doc && this.props.addDocument(doc, false))))));
}
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index cd74d3a84..ebdb0c75c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -18,7 +18,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
componentDidMount() {
this._brushReactionDisposer = reaction(() => this.props.Document.GetList(this.props.fieldKey, [] as Document[]).map(doc => doc.GetNumber(KeyStore.X, 0)),
() => {
- let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ let views = this.props.Document.GetList(this.props.fieldKey, [] as Document[]).filter(doc => doc.GetText(KeyStore.BackgroundLayout, "").indexOf("istogram") !== -1);
for (let i = 0; i < views.length; i++) {
for (let j = 0; j < views.length; j++) {
let srcDoc = views[j];
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e792e7985..69a3aac67 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -49,7 +49,6 @@ export class CollectionFreeFormView extends CollectionSubView {
this.addDocument(newBox, false);
}
private addDocument = (newBox: Document, allowDuplicates: boolean) => {
- newBox.SetNumber(KeyStore.Zoom, this.props.Document.GetNumber(KeyStore.Scale, 1));
return this.props.addDocument(this.bringToFront(newBox), false);
}
private selectDocuments = (docs: Document[]) => {
@@ -72,9 +71,13 @@ export class CollectionFreeFormView extends CollectionSubView {
@action
drop = (e: Event, de: DragManager.DropEvent) => {
if (super.drop(e, de) && de.data instanceof DragManager.DocumentDragData) {
- const [x, y] = this.getTransform().transformPoint(de.x - de.data.xOffset, de.y - de.data.yOffset);
if (de.data.droppedDocuments.length) {
let dragDoc = de.data.droppedDocuments[0];
+ let zoom = dragDoc.GetNumber(KeyStore.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 = dragDoc.GetNumber(KeyStore.X, 0);
let dropY = dragDoc.GetNumber(KeyStore.Y, 0);
de.data.droppedDocuments.map(d => {
@@ -204,7 +207,6 @@ export class CollectionFreeFormView extends CollectionSubView {
@action
setPan(panX: number, panY: number) {
- MainOverlayTextBox.Instance.SetTextDoc();
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));
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ddfda0768..fb4396c05 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -160,20 +160,20 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
});
let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField);
let inkData = ink && ink !== FieldWaiting ? ink.Data : undefined;
- //setTimeout(() => {
+ let zoomBasis = this.props.container.props.Document.GetNumber(KeyStore.Scale, 1);
let newCollection = Documents.FreeformDocument(selected, {
x: bounds.left,
y: bounds.top,
panx: 0,
pany: 0,
- width: bounds.width,
- height: bounds.height,
+ scale: zoomBasis,
+ width: bounds.width * zoomBasis,
+ height: bounds.height * zoomBasis,
ink: inkData ? this.marqueeInkSelect(inkData) : undefined,
title: "a nested collection"
});
this.props.addDocument(newCollection, false);
this.marqueeInkDelete(inkData);
- // }, 100);
this.cleanupInteractions();
SelectionManager.DeselectAll();
}
@@ -216,7 +216,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let selRect = this.Bounds;
let selection: Document[] = [];
this.props.activeDocuments().map(doc => {
- var z = doc.GetNumber(KeyStore.Zoom, 1);
+ 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;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 1d42b3899..12e5bdf1f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -20,7 +20,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
return `scale(${this.props.ContentScaling()}, ${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) scale(${this.zoom}, ${this.zoom}) `;
}
- @computed get zoom(): number { return 1 / this.props.Document.GetNumber(KeyStore.Zoom, 1); }
+ @computed get zoom(): number { return 1 / this.props.Document.GetNumber(KeyStore.ZoomBasis, 1); }
@computed get zIndex(): number { return this.props.Document.GetNumber(KeyStore.ZIndex, 0); }
@computed get width(): number { return this.props.Document.Width(); }
@computed get height(): number { return this.props.Document.Height(); }
@@ -56,7 +56,7 @@ export class CollectionFreeFormDocumentView extends React.Component<CollectionFr
.translate(-this.X, -this.Y)
.scale(1 / this.contentScaling()).scale(1 / this.zoom)
- contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1;
+ contentScaling = () => (this.nativeWidth > 0 ? this.width / this.nativeWidth : 1);
panelWidth = () => this.props.PanelWidth();
panelHeight = () => this.props.PanelHeight();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 65c104c98..0d396fd66 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -22,6 +22,8 @@ import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
import React = require("react");
import { TextField } from "../../../fields/TextField";
+import { string } from "prop-types";
+import { NumberField } from "../../../fields/NumberField";
export interface DocumentViewProps {
ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
@@ -81,6 +83,7 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
@observer
export class DocumentView extends React.Component<DocumentViewProps> {
+ static _incompleteAnimations: Map<string, boolean> = new Map<string, boolean>();
private _downX: number = 0;
private _downY: number = 0;
private _mainCont = React.createRef<HTMLDivElement>();
@@ -107,7 +110,10 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
e.stopPropagation();
} else {
- if (this.active) {
+ let maxdoc = this.props.Document.GetT(KeyStore.MaximizedDoc, Document);
+ if (this.active ||
+ maxdoc instanceof Document // bcz: need a better way of allowing a document to handle pointer events when its not active (ie. be a top-level widget)
+ ) {
e.stopPropagation();
document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
@@ -146,11 +152,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
if (this._mainCont.current) {
- const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+ const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
let dragData = new DragManager.DocumentDragData([this.props.Document]);
+ const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
dragData.aliasOnDrop = dropAliasOfDraggedDoc;
- dragData.xOffset = x - left;
- dragData.yOffset = y - top;
+ dragData.xOffset = xoff;
+ dragData.yOffset = yoff;
dragData.moveDocument = this.props.moveDocument;
DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, {
handlers: {
@@ -179,19 +186,16 @@ export class DocumentView extends React.Component<DocumentViewProps> {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
e.stopPropagation();
- if (!SelectionManager.IsSelected(this) && e.button !== 2)
- if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
- if (this.props.Document.Get(KeyStore.MaximizedDoc) instanceof Document) {
- this.props.Document.GetAsync(KeyStore.MaximizedDoc, maxdoc => {
- if (maxdoc instanceof Document) {
- this.props.addDocument && this.props.addDocument(maxdoc, false);
- this.toggleMinimize(maxdoc, this.props.Document);
- }
- });
- } else {
+ if (!SelectionManager.IsSelected(this) && e.button !== 2 &&
+ Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+ this.props.Document.GetTAsync(KeyStore.MaximizedDoc, Document).then(maxdoc => {
+ if (maxdoc instanceof Document) { // bcz: need a better way to associate behaviors with click events on widget-documents
+ this.props.addDocument && this.props.addDocument(maxdoc, false);
+ this.toggleIcon();
+ } else
SelectionManager.SelectDoc(this, e.ctrlKey);
- }
- }
+ });
+ }
}
stopPropagation = (e: React.SyntheticEvent) => {
e.stopPropagation();
@@ -202,9 +206,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
fieldsClicked = (e: React.MouseEvent): void => {
- if (this.props.addDocument) {
- this.props.addDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false);
- }
+ let kvp = Documents.KVPDocument(this.props.Document, { width: 300, height: 300 });
+ CollectionDockingView.Instance.AddRightSplit(kvp);
}
fullScreenClicked = (e: React.MouseEvent): void => {
CollectionDockingView.Instance.OpenFullScreen((this.props.Document.GetPrototype() as Document).MakeDelegate());
@@ -222,9 +225,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@action createIcon = (layoutString: string): Document => {
let iconDoc = Documents.IconDocument(layoutString);
+ iconDoc.SetText(KeyStore.Title, "ICON" + this.props.Document.Title)
iconDoc.SetBoolean(KeyStore.IsMinimized, false);
iconDoc.SetNumber(KeyStore.NativeWidth, 0);
iconDoc.SetNumber(KeyStore.NativeHeight, 0);
+ iconDoc.SetNumber(KeyStore.X, this.props.Document.GetNumber(KeyStore.X, 0));
+ iconDoc.SetNumber(KeyStore.Y, this.props.Document.GetNumber(KeyStore.Y, 0) - 24);
iconDoc.Set(KeyStore.Prototype, this.props.Document);
iconDoc.Set(KeyStore.MaximizedDoc, this.props.Document);
this.props.Document.Set(KeyStore.MinimizedDoc, iconDoc);
@@ -232,7 +238,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return iconDoc;
}
- animateTransition(icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
+ animateBetweenIcon(icon: number[], targ: number[], width: number, height: number, stime: number, target: Document, maximizing: boolean) {
setTimeout(() => {
let now = Date.now();
let progress = Math.min(1, (now - stime) / 200);
@@ -244,7 +250,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
target.SetNumber(KeyStore.X, pval[0]);
target.SetNumber(KeyStore.Y, pval[1]);
if (now < stime + 200) {
- this.animateTransition(icon, targ, width, height, stime, target, maximizing);
+ this.animateBetweenIcon(icon, targ, width, height, stime, target, maximizing);
}
else {
if (!maximizing) {
@@ -254,50 +260,53 @@ export class DocumentView extends React.Component<DocumentViewProps> {
target.SetNumber(KeyStore.Width, width);
target.SetNumber(KeyStore.Height, height);
}
- this._completed = true;
+ DocumentView._incompleteAnimations.set(target.Id, false);
}
},
2);
}
- _completed = true;
-
@action
- public toggleMinimize = (maximized: Document, minim: Document): void => {
+ public toggleIcon = async (): Promise<void> => {
SelectionManager.DeselectAll();
- if (maximized instanceof Document && this._completed) {
- this._completed = false;
- let minimized = maximized.GetBoolean(KeyStore.IsMinimized, false);
- maximized.SetBoolean(KeyStore.IsMinimized, false);
- this.animateTransition(
- [minim.GetNumber(KeyStore.X, 0), minim.GetNumber(KeyStore.Y, 0)],
- [maximized.GetNumber(KeyStore.X, 0), maximized.GetNumber(KeyStore.Y, 0)],
- maximized.GetNumber(KeyStore.Width, 0), maximized.GetNumber(KeyStore.Width, 0),
- Date.now(), maximized, minimized);
- }
+ let isMinimized: boolean | undefined;
+ let minDoc = await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document);
+ if (!minDoc) return;
+ let minimizedDocSet = await minDoc.GetTAsync(KeyStore.LinkTags, ListField);
+ if (!minimizedDocSet) return;
+ minimizedDocSet.Data.map(async minimizedDoc => {
+ if (minimizedDoc instanceof Document) {
+ this.props.addDocument && this.props.addDocument(minimizedDoc, false);
+ let maximizedDoc = await minimizedDoc.GetTAsync(KeyStore.MaximizedDoc, Document);
+ if (maximizedDoc instanceof Document && !DocumentView._incompleteAnimations.get(maximizedDoc.Id)) {
+ DocumentView._incompleteAnimations.set(maximizedDoc.Id, true);
+ isMinimized = isMinimized === undefined ? maximizedDoc.GetBoolean(KeyStore.IsMinimized, false) : isMinimized;
+ maximizedDoc.SetBoolean(KeyStore.IsMinimized, false);
+ let minx = await minimizedDoc.GetTAsync(KeyStore.X, NumberField);
+ let miny = await minimizedDoc.GetTAsync(KeyStore.Y, NumberField);
+ let maxx = await maximizedDoc.GetTAsync(KeyStore.X, NumberField);
+ let maxy = await maximizedDoc.GetTAsync(KeyStore.Y, NumberField);
+ let maxw = await maximizedDoc.GetTAsync(KeyStore.Width, NumberField);
+ let maxh = await maximizedDoc.GetTAsync(KeyStore.Height, NumberField);
+ if (minx !== undefined && miny !== undefined && maxx !== undefined && maxy !== undefined &&
+ maxw !== undefined && maxh !== undefined)
+ this.animateBetweenIcon(
+ [minx.Data, miny.Data], [maxx.Data, maxy.Data], maxw.Data, maxh.Data,
+ Date.now(), maximizedDoc, isMinimized);
+ }
+
+ }
+ })
}
@action
- public minimize = (): void => {
- this.props.Document.GetAsync(KeyStore.MinimizedDoc, mindoc => {
- if (mindoc === undefined) {
- this.props.Document.GetAsync(KeyStore.BackgroundLayout, field => {
- if (field instanceof TextField) {
- this.toggleMinimize(this.props.Document, this.createIcon(field.Data));
- }
- else this.props.Document.GetAsync(KeyStore.Layout, field => {
- if (field instanceof TextField) {
- this.createIcon(field.Data);
- this.toggleMinimize(this.props.Document, this.createIcon(field.Data));
- }
- });
- });
- }
- else if (mindoc instanceof Document) {
- this.props.addDocument && this.props.addDocument(mindoc, false);
- this.toggleMinimize(this.props.Document, mindoc);
- }
- });
+ public getIconDoc = async (): Promise<Document | undefined> => {
+ return await this.props.Document.GetTAsync(KeyStore.MinimizedDoc, Document).then(async mindoc =>
+ mindoc ? mindoc :
+ await this.props.Document.GetTAsync(KeyStore.BackgroundLayout, TextField).then(async field =>
+ (field instanceof TextField) ? this.createIcon(field.Data) :
+ await this.props.Document.GetTAsync(KeyStore.Layout, TextField).then(field =>
+ (field instanceof TextField) ? this.createIcon(field.Data) : undefined)));
}
@undoBatch
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 639dae30a..29ed2da13 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,4 +1,4 @@
-import { action, IReactionDisposer, reaction } from "mobx";
+import { action, IReactionDisposer, reaction, trace, computed } from "mobx";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
@@ -20,6 +20,7 @@ import { FieldView, FieldViewProps } from "./FieldView";
import "./FormattedTextBox.scss";
import React = require("react");
import { SelectionManager } from "../../util/SelectionManager";
+import { observer } from "mobx-react";
const { buildMenuItems } = require("prosemirror-example-setup");
const { menuBar } = require("prosemirror-menu");
@@ -44,6 +45,7 @@ export interface FormattedTextBoxOverlay {
isOverlay?: boolean;
}
+@observer
export class FormattedTextBox extends React.Component<(FieldViewProps & FormattedTextBoxOverlay)> {
public static LayoutString(fieldStr: string = "DataKey") {
return FieldView.LayoutString(FormattedTextBox, fieldStr);
@@ -108,34 +110,26 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
if (this._editorView) {
this._editorView.destroy();
}
- this.setupEditor(config, MainOverlayTextBox.Instance.TextDoc); // bcz: not sure why, but the order of events is such that this.props.Document hasn't updated yet, so without forcing the editor to the MainOverlayTextBox, it will display the previously focused textbox
+ this.setupEditor(config, this.props.Document);// MainOverlayTextBox.Instance.TextDoc); // bcz: not sure why, but the order of events is such that this.props.Document hasn't updated yet, so without forcing the editor to the MainOverlayTextBox, it will display the previously focused textbox
}
);
} else {
this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
- () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform()));
+ () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
}
+
this._reactionDisposer = reaction(
() => {
const field = this.props.Document ? this.props.Document.GetT(this.props.fieldKey, RichTextField) : undefined;
return field && field !== FieldWaiting ? field.Data : undefined;
},
- field => {
- if (field && this._editorView && !this._applyingChange) {
- this._editorView.updateState(
- EditorState.fromJSON(config, JSON.parse(field))
- );
- }
- }
+ field => field && this._editorView && !this._applyingChange &&
+ this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)))
);
this.setupEditor(config, this.props.Document);
}
- shouldComponentUpdate() {
- return false;
- }
-
private setupEditor(config: any, doc?: Document) {
let field = doc ? doc.GetT(this.props.fieldKey, RichTextField) : undefined;
if (this._ref.current) {
@@ -192,7 +186,9 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
onFocused = (e: React.FocusEvent): void => {
if (!this.props.isOverlay) {
- MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform());
+ if (MainOverlayTextBox.Instance.TextDoc != this.props.Document) {
+ MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform);
+ }
} else {
if (this._ref.current) {
this._ref.current.scrollTop = MainOverlayTextBox.Instance.TextScroll;
@@ -262,7 +258,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
// (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;
}
render() {
- let style = this.props.isSelected() || this.props.isOverlay ? "scroll" : "hidden";
+ let style = this.props.isOverlay ? "scroll" : "hidden";
return (
<div className={`formattedTextBox-cont-${style}`}
onKeyDown={this.onKeyPress}
@@ -273,8 +269,7 @@ export class FormattedTextBox extends React.Component<(FieldViewProps & Formatte
onContextMenu={this.specificContextMenu}
// tfs: do we need this event handler
onWheel={this.onPointerWheel}
- ref={this._ref}
- />
+ ref={this._ref} />
);
}
}
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index a347f8bcf..0a96beb50 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -15,7 +15,7 @@ export namespace KeyStore {
export const Width = new Key("Width");
export const Height = new Key("Height");
export const ZIndex = new Key("ZIndex");
- export const Zoom = new Key("Zoom");
+ export const ZoomBasis = new Key("ZoomBasis");
export const Data = new Key("Data");
export const Annotations = new Key("Annotations");
export const ViewType = new Key("ViewType");
@@ -51,7 +51,7 @@ export namespace KeyStore {
export const CopyDraggedItems = new Key("CopyDraggedItems");
export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight,
- Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
+ Width, Height, ZIndex, ZoomBasis, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys,
LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs,
LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection,
Archives, Workspaces, IsMinimized, MinimizedDoc, MaximizedDoc, CopyDraggedItems