diff options
-rw-r--r-- | src/client/views/OverlayView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/ScriptBox.scss | 17 | ||||
-rw-r--r-- | src/client/views/ScriptBox.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 69 |
4 files changed, 72 insertions, 33 deletions
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 72f1068ce..f8fc94274 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,6 +1,7 @@ import * as React from "react"; import { observer } from "mobx-react"; import { observable, action } from "mobx"; +import { Utils } from "../../Utils"; export type OverlayDisposer = () => void; @@ -15,7 +16,7 @@ export type OverlayElementOptions = { export class OverlayView extends React.Component { public static Instance: OverlayView; @observable.shallow - private _elements: { ele: JSX.Element, options: OverlayElementOptions }[] = []; + private _elements: { ele: JSX.Element, id: string, options: OverlayElementOptions }[] = []; constructor(props: any) { super(props); @@ -26,7 +27,7 @@ export class OverlayView extends React.Component { @action addElement(ele: JSX.Element, options: OverlayElementOptions): OverlayDisposer { - const eleWithPosition = { ele, options }; + const eleWithPosition = { ele, options, id: Utils.GenerateGuid() }; this._elements.push(eleWithPosition); return action(() => { const index = this._elements.indexOf(eleWithPosition); @@ -37,8 +38,8 @@ export class OverlayView extends React.Component { render() { return ( <div> - {this._elements.map(({ ele, options: { x, y, width, height } }) => ( - <div style={{ position: "absolute", transform: `translate(${x}px, ${y}px)`, width, height }}>{ele}</div> + {this._elements.map(({ ele, options: { x, y, width, height }, id }) => ( + <div key={id} style={{ position: "absolute", transform: `translate(${x}px, ${y}px)`, width, height }}>{ele}</div> ))} </div> ); diff --git a/src/client/views/ScriptBox.scss b/src/client/views/ScriptBox.scss new file mode 100644 index 000000000..28326624a --- /dev/null +++ b/src/client/views/ScriptBox.scss @@ -0,0 +1,17 @@ +.scriptBox-outerDiv { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.scriptBox-toolbar { + width: 100%; +} + +.scriptBox-textArea { + width: 100%; + height: 100%; + box-sizing: border-box; + resize: none; +}
\ No newline at end of file diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index aea9d52a4..fa236c2da 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -2,15 +2,23 @@ import * as React from "react"; import { observer } from "mobx-react"; import { observable, action } from "mobx"; +import "./ScriptBox.scss"; + export interface ScriptBoxProps { onSave: (text: string, onError: (error: string) => void) => void; onCancel?: () => void; + initialText?: string; } @observer export class ScriptBox extends React.Component<ScriptBoxProps> { @observable - private _scriptText: string = ""; + private _scriptText: string; + + constructor(props: ScriptBoxProps) { + super(props); + this._scriptText = props.initialText || ""; + } @action onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 23c0fdd0d..edd2fb1b0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -28,7 +28,7 @@ import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); import { ScriptField } from "../../../../new_fields/ScriptField"; -import { OverlayView } from "../../OverlayView"; +import { OverlayView, OverlayElementOptions } from "../../OverlayView"; import { ScriptBox } from "../../ScriptBox"; import { CompileScript } from "../../../util/Scripting"; @@ -36,7 +36,9 @@ 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]>; @@ -392,28 +394,34 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }; } - getCalculatedPositions(doc: Doc, index: number, collection: Doc): { x?: number, y?: number, width?: number, height?: number } | undefined { - const script = Cast(this.props.Document.arrangeScript, ScriptField); - if (!script) { - return undefined; - } - const result = script.script.run({ doc, index, collection }); + getCalculatedPositions(doc: Doc, index: number, collection: Doc, script: ScriptField, state: any): { x?: number, y?: number, width?: number, height?: number, state?: any } { + const result = script.script.run({ doc, index, collection, state }); if (!result.success) { - return undefined; + return {}; } - return result.result; + return result.result === undefined ? {} : result.result; } @computed.struct get views() { let curPage = FieldValue(this.Document.curPage, -1); + const initScript = this.Document.arrangeInit; + const script = this.Document.arrangeScript; + let state: any = undefined; + if (initScript) { + const initResult = initScript.script.run(); + if (initResult.success) { + state = initResult.result; + } + } let docviews = this.childDocs.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) { - const pos = this.getCalculatedPositions(doc, prev.length, this.Document) || {}; + const pos = script ? this.getCalculatedPositions(doc, prev.length, this.Document, script, 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)} />); } } @@ -458,23 +466,28 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ContextMenu.Instance.addItem({ description: "Add freeform arrangement", event: () => { - let overlayDisposer: () => void; - let scriptingBox = <ScriptBox onCancel={() => overlayDisposer()} onSave={(text, onError) => { - const script = CompileScript(text, { - params: { - doc: "Doc", index: "number", collection: "Doc" - }, - requiredType: "{x: number, y: number, width?: number, height?: number}", - typecheck: false - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - return; - } - this.props.Document.arrangeScript = new ScriptField(script); - overlayDisposer(); - }} />; - overlayDisposer = OverlayView.Instance.addElement(scriptingBox, { x: 100, y: 100, width: 200, height: 200 }); + 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; + } + this.Document[key] = new ScriptField(script); + overlayDisposer(); + }} />; + overlayDisposer = OverlayView.Instance.addElement(scriptingBox, options); + }; + addOverlay("arrangeInit", { x: 400, y: 100, width: 400, height: 300 }, undefined, undefined); + addOverlay("arrangeScript", { x: 400, y: 500, width: 400, height: 300 }, { doc: "Doc", index: "number", collection: "Doc", state:"any" }, "{x: number, y: number, width?: number, height?: number}"); } }); } |