aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-07-08 11:11:01 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-07-08 11:11:01 -0400
commit6145a7ef060aeb1b815b2da7acba4d8f9d2e2bdc (patch)
treeb63ceff150fe9e5f7383402a99da8d8f8f31cb05 /src/client/views/collections/collectionFreeForm
parent5ce2d59b4544a7473a910c121daf0c34d1546214 (diff)
parent400c525875af607dd76d7ec46949fedc418caabf (diff)
merged with master
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx82
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx20
3 files changed, 75 insertions, 29 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 169dbe540..7a22b7ec3 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,6 +1,6 @@
import { action, computed } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCastAsync, HeightSym, WidthSym } from "../../../../new_fields/Doc";
+import { Doc, DocListCastAsync, HeightSym, WidthSym, DocListCast } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { createSchema, makeInterface } from "../../../../new_fields/Schema";
@@ -27,12 +27,18 @@ import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import v5 = require("uuid/v5");
+import { ScriptField } from "../../../../new_fields/ScriptField";
+import { OverlayView, OverlayElementOptions } from "../../OverlayView";
+import { ScriptBox } from "../../ScriptBox";
+import { CompileScript } from "../../../util/Scripting";
export const panZoomSchema = createSchema({
panX: "number",
panY: "number",
- scale: "number"
+ scale: "number",
+ arrangeScript: ScriptField,
+ arrangeInit: ScriptField,
});
type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema, typeof pageSchema]>;
@@ -50,9 +56,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
@computed get nativeHeight() { return this.Document.nativeHeight || 0; }
public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
- private panX = () => this.props.fitToBox ? this.props.fitToBox[0] : this.Document.panX || 0;
- private panY = () => this.props.fitToBox ? this.props.fitToBox[1] : this.Document.panY || 0;
- private zoomScaling = () => this.props.fitToBox ? this.props.fitToBox[2] : this.Document.scale || 1;
+ private panX = () => this.props.fitToBox ? this.props.fitToBox()[0] : this.Document.panX || 0;
+ private panY = () => this.props.fitToBox ? this.props.fitToBox()[1] : this.Document.panY || 0;
+ private zoomScaling = () => this.props.fitToBox ? this.props.fitToBox()[2] : 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 + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform());
@@ -243,16 +249,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
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.panX = this.isAnnotationOverlay ? newPanX : panX;
- // this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
- this.props.Document.panX = panX;
+ this.props.Document.panX = this.isAnnotationOverlay ? newPanX : panX;
+ this.props.Document.panY = this.isAnnotationOverlay ? newPanY : panY;
+ // this.props.Document.panX = panX;
+ // this.props.Document.panY = panY;
if (this.props.Document.scrollY) {
this.props.Document.scrollY = panY;
- this.props.Document.panY = panY;
- }
- else {
-
- this.props.Document.panY = panY;
}
}
@@ -388,16 +390,36 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
};
}
+ getCalculatedPositions(script: ScriptField, params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, width?: number, height?: number, state?: any } {
+ const result = script.script.run(params);
+ if (!result.success) {
+ return {};
+ }
+ return result.result === undefined ? {} : result.result;
+ }
+
@computed.struct
get views() {
let curPage = FieldValue(this.Document.curPage, -1);
- let docviews = this.childDocs.reduce((prev, doc) => {
+ const initScript = this.Document.arrangeInit;
+ const script = this.Document.arrangeScript;
+ let state: any = undefined;
+ const docs = this.childDocs;
+ if (initScript) {
+ const initResult = initScript.script.run({ docs, collection: this.Document });
+ if (initResult.success) {
+ state = initResult.result;
+ }
+ }
+ let docviews = docs.reduce((prev, doc) => {
if (!(doc instanceof Doc)) return prev;
var page = NumCast(doc.page, -1);
if (Math.round(page) === Math.round(curPage) || page === -1) {
let minim = BoolCast(doc.isMinimized, false);
if (minim === undefined || !minim) {
- prev.push(<CollectionFreeFormDocumentView key={doc[Id]} {...this.getChildDocumentViewProps(doc)} />);
+ const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : {};
+ state = pos.state === undefined ? state : pos.state;
+ prev.push(<CollectionFreeFormDocumentView key={doc[Id]} x={pos.x} y={pos.y} width={pos.width} height={pos.height} {...this.getChildDocumentViewProps(doc)} />);
}
}
return prev;
@@ -438,6 +460,36 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
}
});
+ ContextMenu.Instance.addItem({
+ description: "Add freeform arrangement",
+ event: () => {
+ let addOverlay = (key: "arrangeScript" | "arrangeInit", options: OverlayElementOptions, params?: Record<string, string>, requiredType?: string) => {
+ let overlayDisposer: () => void;
+ const script = this.Document[key];
+ let originalText: string | undefined = undefined;
+ if (script) originalText = script.script.originalScript;
+ let scriptingBox = <ScriptBox initialText={originalText} onCancel={() => overlayDisposer()} onSave={(text, onError) => {
+ const script = CompileScript(text, {
+ params,
+ requiredType,
+ typecheck: false
+ });
+ if (!script.compiled) {
+ onError(script.errors.map(error => error.messageText).join("\n"));
+ return;
+ }
+ const docs = DocListCast(this.Document[this.props.fieldKey]);
+ docs.map(d => d.transition = "transform 1s");
+ this.Document[key] = new ScriptField(script);
+ overlayDisposer();
+ setTimeout(() => docs.map(d => d.transition = undefined), 1200);
+ }} />;
+ overlayDisposer = OverlayView.Instance.addElement(scriptingBox, options);
+ };
+ addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300 }, { collection: "Doc", docs: "Doc[]" }, undefined);
+ addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300 }, { doc: "Doc", index: "number", collection: "Doc", state: "any", docs: "Doc[]" }, "{x: number, y: number, width?: number, height?: number}");
+ }
+ });
}
private childViews = () => [
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 6e8ec8662..9fc2e44fb 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -21,6 +21,6 @@
white-space:nowrap;
}
.marquee-legend::after {
- content: "Press: c (collection), s (summary), r (replace) or Delete"
+ content: "Press: c (collection), s (summary), or Delete"
}
} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 2a78cda2f..4850c6218 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -44,14 +44,12 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
_commandExecuted = false;
@action
- cleanupInteractions = (all: boolean = false, rem_keydown: boolean = true) => {
+ cleanupInteractions = (all: boolean = false) => {
if (all) {
document.removeEventListener("pointerup", this.onPointerUp, true);
document.removeEventListener("pointermove", this.onPointerMove, true);
}
- if (rem_keydown) {
- document.removeEventListener("keydown", this.marqueeCommand, true);
- }
+ document.removeEventListener("keydown", this.marqueeCommand, true);
this._visible = false;
}
@@ -191,12 +189,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
}
this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
- mselect.length ? this.cleanupInteractions(true, false) : this.cleanupInteractions(true);
- }
- else {
- //console.log("invisible");
- this.cleanupInteractions(true);
}
+ //console.log("invisible");
+ this.cleanupInteractions(true);
if (e.altKey) {
e.preventDefault();
@@ -248,7 +243,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this.cleanupInteractions(false);
e.stopPropagation();
}
- if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e" || e.key === "p") {
+ if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e") {
this._commandExecuted = true;
e.stopPropagation();
e.preventDefault();
@@ -266,18 +261,17 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
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,
- borderRounding: e.key === "e" ? -1 : undefined,
+ borderRounding: e.key === "e" ? "100%" : undefined,
backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
width: bounds.width,
height: bounds.height,
ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined,
- title: e.key === "s" || e.key === "S" ? "-summary-" : e.key === "p" ? "-summary-" : "a nested collection",
+ title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
});
this.marqueeInkDelete(inkData);