diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/ScriptBox.tsx | 23 | ||||
-rw-r--r-- | src/client/views/ScriptingRepl.tsx | 31 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/ButtonBox.tsx | 6 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentIcon.tsx | 65 |
5 files changed, 94 insertions, 32 deletions
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index fa236c2da..d073945e5 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -3,11 +3,15 @@ import { observer } from "mobx-react"; import { observable, action } from "mobx"; import "./ScriptBox.scss"; +import { OverlayView } from "./OverlayView"; +import { DocumentIconContainer } from "./nodes/DocumentIcon"; +import { Opt } from "../../new_fields/Doc"; export interface ScriptBoxProps { onSave: (text: string, onError: (error: string) => void) => void; onCancel?: () => void; initialText?: string; + showDocumentIcons?: boolean; } @observer @@ -30,14 +34,31 @@ export class ScriptBox extends React.Component<ScriptBoxProps> { console.log(error); } + overlayDisposer?: () => void; + onFocus = () => { + if (this.overlayDisposer) { + this.overlayDisposer(); + } + this.overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 }); + } + + onBlur = () => { + this.overlayDisposer && this.overlayDisposer(); + } + render() { + let onFocus: Opt<() => void> = undefined, onBlur: Opt<() => void> = undefined; + if (this.props.showDocumentIcons) { + onFocus = this.onFocus; + onBlur = this.onBlur; + } return ( <div className="scriptBox-outerDiv"> <div className="scriptBox-toolbar"> <button onClick={e => { this.props.onSave(this._scriptText, this.onError); e.stopPropagation(); }}>Save</button> <button onClick={e => { this.props.onCancel && this.props.onCancel(); e.stopPropagation(); }}>Cancel</button> </div> - <textarea className="scriptBox-textarea" onChange={this.onChange} value={this._scriptText}></textarea> + <textarea className="scriptBox-textarea" onChange={this.onChange} value={this._scriptText} onFocus={onFocus} onBlur={onBlur}></textarea> </div> ); } diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 0cff145b6..e05195ca0 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -4,41 +4,16 @@ import { observable, action } from 'mobx'; import './ScriptingRepl.scss'; import { Scripting, CompileScript, ts, Transformer } from '../util/Scripting'; import { DocumentManager } from '../util/DocumentManager'; -import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; import { faCaretDown, faCaretRight } from '@fortawesome/free-solid-svg-icons'; +import { DocumentIconContainer } from './nodes/DocumentIcon'; library.add(faCaretDown); library.add(faCaretRight); @observer -export class DocumentIcon extends React.Component<{ view: DocumentView, index: number }> { - render() { - const view = this.props.view; - const transform = view.props.ScreenToLocalTransform().scale(view.props.ContentScaling()).inverse(); - const { x, y, width, height } = transform.transformBounds(0, 0, view.props.PanelWidth(), view.props.PanelHeight()); - - return ( - <div className="documentIcon-outerDiv" style={{ - position: "absolute", - transform: `translate(${x + width / 2}px, ${y}px)`, - }}> - <p>${this.props.index}</p> - </div> - ); - } -} - -@observer -export class DocumentIconContainer extends React.Component { - render() { - return DocumentManager.Instance.DocumentViews.map((dv, i) => <DocumentIcon key={i} index={i} view={dv} />); - } -} - -@observer export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () => void, value: { [key: string]: any }, name?: string }> { @observable collapsed = true; @@ -129,7 +104,7 @@ export class ScriptingRepl extends React.Component { if (ts.isParameter(node.parent)) { // delete knownVars[node.text]; } else if (isntPropAccess && isntPropAssign && !(node.text in knownVars) && !(node.text in globalThis)) { - const match = node.text.match(/\$([0-9]+)/); + const match = node.text.match(/\d([0-9]+)/); if (match) { const m = parseInt(match[1]); usedDocuments.push(m); @@ -153,7 +128,7 @@ export class ScriptingRepl extends React.Component { switch (e.key) { case "Enter": { const docGlobals: { [name: string]: any } = {}; - DocumentManager.Instance.DocumentViews.forEach((dv, i) => docGlobals[`$${i}`] = dv.props.Document); + DocumentManager.Instance.DocumentViews.forEach((dv, i) => docGlobals[`d${i}`] = dv.props.Document); const globals = Scripting.makeMutableGlobalsCopy(docGlobals); const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: "any" }, transformer: this.getTransformer(), globals }); if (!script.compiled) { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 0865058be..1859ebee7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -577,7 +577,6 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { return (null); } let resolvedDataDoc = this._document.layout instanceof Doc ? this._document : this._dataDoc; - console.log("pw = " + this.panelWidth() + "," + this.panelHeight() + " " + this.contentScaling()); return <DocumentView key={this._document[Id]} Document={this._document} DataDoc={resolvedDataDoc} diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index 744611661..d2c23fdab 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -14,6 +14,7 @@ import { Doc } from '../../../new_fields/Doc'; import './ButtonBox.scss'; import { observer } from 'mobx-react'; +import { DocumentIconContainer } from './DocumentIcon'; library.add(faEdit); @@ -51,7 +52,8 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt const script = CompileScript(text, { params: { this: Doc.name }, typecheck: false, - editable: true + editable: true, + transformer: DocumentIconContainer.getTransformer() }); if (!script.compiled) { onError(script.errors.map(error => error.messageText).join("\n")); @@ -59,7 +61,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt } this.Document.onClick = new ScriptField(script); overlayDisposer(); - }} />; + }} showDocumentIcons />; overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnClick` }); } }); diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx new file mode 100644 index 000000000..f56f5e829 --- /dev/null +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -0,0 +1,65 @@ +import { observer } from "mobx-react"; +import * as React from "react"; +import { DocumentView } from "./DocumentView"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Transformer, Scripting, ts } from "../../util/Scripting"; +import { Field } from "../../../new_fields/Doc"; + +@observer +export class DocumentIcon extends React.Component<{ view: DocumentView, index: number }> { + render() { + const view = this.props.view; + const transform = view.props.ScreenToLocalTransform().scale(view.props.ContentScaling()).inverse(); + const { x, y, width, height } = transform.transformBounds(0, 0, view.props.PanelWidth(), view.props.PanelHeight()); + + return ( + <div className="documentIcon-outerDiv" style={{ + position: "absolute", + transform: `translate(${x + width / 2}px, ${y}px)`, + }}> + <p>d{this.props.index}</p> + </div> + ); + } +} + +@observer +export class DocumentIconContainer extends React.Component { + public static getTransformer(): Transformer { + const usedDocuments = new Set<number>(); + return { + transformer: context => { + return root => { + function visit(node: ts.Node) { + node = ts.visitEachChild(node, visit, context); + + if (ts.isIdentifier(node)) { + const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node; + const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node; + const isntParameter = !ts.isParameter(node.parent); + if (isntPropAccess && isntPropAssign && isntParameter && !(node.text in globalThis)) { + const match = node.text.match(/d([0-9]+)/); + if (match) { + const m = parseInt(match[1]); + usedDocuments.add(m); + } + } + } + + return node; + } + return ts.visitNode(root, visit); + }; + }, + getVars() { + const docs = DocumentManager.Instance.DocumentViews; + const capturedVariables: { [name: string]: Field } = {}; + usedDocuments.forEach(index => capturedVariables[`d${index}`] = docs[index].props.Document); + return { capturedVariables }; + } + }; + } + render() { + return DocumentManager.Instance.DocumentViews.map((dv, i) => <DocumentIcon key={i} index={i} view={dv} />); + } +}
\ No newline at end of file |