diff options
9 files changed, 223 insertions, 170 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 958ba0ce3..a0a6adab7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -534,10 +534,10 @@ export class MainView extends React.Component { } @computed get snapLines() { - return <div className="mainView-snapLines"> + return !Doc.UserDoc().showSnapLines ? (null) : <div className="mainView-snapLines"> <svg style={{ width: "100%", height: "100%" }}> - {/* {SnappingManager.horizSnapLines().map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} - {SnappingManager.vertSnapLines().map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} */} + {SnappingManager.horizSnapLines().map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} + {SnappingManager.vertSnapLines().map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} </svg> </div>; } diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 020a87b2e..fc48e0327 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -23,7 +23,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { @observable _childClickedScript: Opt<ScriptField>; componentDidMount() { if (this.layoutEngine() !== "pass" && this.layoutEngine() !== "starburst") { - this.Document._layoutEngine = "pass"; + this.Document._pileLayoutEngine = "pass"; } this._originalChrome = StrCast(this.layoutDoc._chromeStatus); this.layoutDoc._chromeStatus = "disabled"; @@ -34,7 +34,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { this.layoutDoc._chromeStatus = this._originalChrome; } - layoutEngine = () => StrCast(this.Document._layoutEngine); + layoutEngine = () => StrCast(this.Document._pileLayoutEngine); @computed get contents() { return <div className="collectionPileView-innards" style={{ pointerEvents: this.layoutEngine() === "starburst" ? undefined : "none" }} > @@ -53,7 +53,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { Doc.pileup(this.childDocs); this.layoutDoc._panX = 0; this.layoutDoc._panY = -10; - this.props.Document._layoutEngine = 'pass'; + this.props.Document._pileLayoutEngine = 'pass'; } else { const defaultSize = 25; this.layoutDoc._overflow = 'visible'; @@ -67,7 +67,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { } this.layoutDoc._panX = this.layoutDoc._panY = 0; this.layoutDoc._width = this.layoutDoc._height = defaultSize; - this.props.Document._layoutEngine = 'starburst'; + this.props.Document._pileLayoutEngine = 'starburst'; } }); diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index e4581eb46..03bd9a01a 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -8,10 +8,12 @@ z-index: 9001; transition: top .5s; background: lightgrey; + transform-origin: top left; .collectionViewChrome { display: flex; - padding-bottom: 10px; + padding-bottom: 1px; + height:32px; border-bottom: .5px solid rgb(180, 180, 180); overflow: hidden; @@ -21,12 +23,12 @@ .collectionViewBaseChrome-viewPicker { font-size: 75%; //text-transform: uppercase; - letter-spacing: 2px; + //letter-spacing: 2px; background: rgb(238, 238, 238); color: grey; outline-color: black; border: none; - padding: 12px 10px 11px 10px; + //padding: 12px 10px 11px 10px; } .collectionViewBaseChrome-viewPicker:active { @@ -47,6 +49,7 @@ .collectionViewBaseChrome-cmdPicker { margin-left: 3px; margin-right: 0px; + font-size: 75%; background: rgb(238, 238, 238); border: none; color: grey; @@ -56,6 +59,7 @@ background-color: gray; display: flex; flex-direction: row; + height:30px; .commandEntry-drop { color:white; width:25px; @@ -95,8 +99,8 @@ margin: auto; background: gray; color: white; - width: 40px; - height: 40px; + width: 30px; + height: 30px; align-items: center; justify-content: center; } @@ -195,8 +199,7 @@ .collectionTreeViewChrome-pivotField-label { vertical-align: center; padding-left: 10px; - padding-top: 10px; - padding-bottom: 10px; + margin:auto; } .collectionStackingViewChrome-pivotField, @@ -204,14 +207,15 @@ color: white; width:100%; min-width: 100px; - text-align: center; + display: flex; + align-items: center; background: rgb(238, 238, 238); .editable-view-input, input, .editableView-container-editing-oneLine, .editableView-container-editing { - padding: 12px 10px 11px 10px; + margin:auto; border: 0px; color: grey; text-align: center; @@ -235,6 +239,44 @@ } } +.collectionFreeFormViewChrome-cont { + width: 60px; + display: flex; + position: relative; + align-items: center; + .fwdKeyframe, .numKeyframe, .backKeyframe { + cursor: pointer; + position: absolute; + width: 20; + height: 30; + bottom: 0; + background: gray; + display: flex; + align-items: center; + color:white; + } + .backKeyframe { + left:0; + svg { + display:block; + margin:auto; + } + } + .numKeyframe { + left:20; + display: flex; + flex-direction: column; + padding: 5px; + } + .fwdKeyframe { + left:40; + svg { + display:block; + margin:auto; + } + } +} + .collectionSchemaViewChrome-cont { display: flex; font-size: 10.5px; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 8c4d53d63..29a3e559a 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -15,6 +15,7 @@ import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss"; import { CollectionViewType } from "./CollectionView"; import { CollectionView } from "./CollectionView"; import "./CollectionViewChromes.scss"; +import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { @@ -44,7 +45,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro initialize: emptyFunction, }; _narrativeCommand = { - params: ["target", "source"], title: "=> click clicked open view", + params: ["target", "source"], title: "=> child click view", script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])", immediate: (source: Doc[]) => this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]), initialize: emptyFunction, @@ -83,22 +84,16 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro private _viewRef = React.createRef<HTMLInputElement>(); @observable private _currentKey: string = ""; - componentDidMount = () => { - runInAction(() => { - // chrome status is one of disabled, collapsed, or visible. this determines initial state from document - const chromeStatus = this.props.CollectionView.props.Document._chromeStatus; - if (chromeStatus) { - if (chromeStatus === "disabled") { - throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!"); - } - else if (chromeStatus === "collapsed") { - if (this.props.collapse) { - this.props.collapse(true); - } - } - } - }); - } + componentDidMount = action(() => { + // chrome status is one of disabled, collapsed, or visible. this determines initial state from document + switch (this.props.CollectionView.props.Document._chromeStatus) { + case "disabled": + throw new Error("how did you get here, if chrome status is 'disabled' on a collection, a chrome shouldn't even be instantiated!"); + case "collapsed": + this.props.collapse?.(true); + break; + } + }) @undoBatch viewChanged = (e: React.ChangeEvent) => { @@ -197,10 +192,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro } } - subChrome = () => { + @computed get subChrome() { const collapsed = this.document._chromeStatus !== "enabled"; if (collapsed) return null; switch (this.props.type) { + case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />); case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />); case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />); case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />); @@ -236,7 +232,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro const vtype = this.props.CollectionView.collectionViewType; const c = { params: ["target"], title: vtype, - script: `this.target._viewType = ${StrCast(this.props.CollectionView.props.Document._viewType)}`, + script: `this.target._viewType = '${StrCast(this.props.CollectionView.props.Document._viewType)}'`, immediate: (source: Doc[]) => this.props.CollectionView.props.Document._viewType = Doc.getDocTemplate(source?.[0]), initialize: emptyFunction, }; @@ -254,14 +250,61 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro }, emptyFunction, emptyFunction); } + @computed get templateChrome() { + const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled"; + return <div className="collectionViewBaseChrome-template" ref={this.createDropTarget} style={{ display: collapsed ? "none" : undefined }}> + <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._commandRef} onPointerDown={this.dragCommandDown}> + <div className="commandEntry-drop"> + <FontAwesomeIcon icon="bullseye" size="2x" /> + </div> + <select + className="collectionViewBaseChrome-cmdPicker" + onPointerDown={stopPropagation} + onChange={this.commandChanged} + value={this._currentKey}> + <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={"empty"} value={""} /> + {this._buttonizableCommands.map(cmd => + <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={cmd.title} value={cmd.title}>{cmd.title}</option> + )} + </select> + </div> + </div>; + } + + @computed get viewModes() { + const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled"; + return <div className="collectionViewBaseChrome-viewModes" style={{ display: collapsed ? "none" : undefined }}> + <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._viewRef} onPointerDown={this.dragViewDown}> + <div className="commandEntry-drop"> + <FontAwesomeIcon icon="bullseye" size="2x" /> + </div> + <select + className="collectionViewBaseChrome-viewPicker" + onPointerDown={stopPropagation} + onChange={this.viewChanged} + value={StrCast(this.props.CollectionView.props.Document._viewType)}> + {Object.values(CollectionViewType).map(type => ["invalid", "docking"].includes(type) ? (null) : ( + <option + key={Utils.GenerateGuid()} + className="collectionViewBaseChrome-viewOption" + onPointerDown={stopPropagation} + value={type}> + {type[0].toUpperCase() + type.substring(1)} + </option> + ))} + </select> + </div> + </div>; + } + render() { const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled"; + const scale = Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform().Scale); return ( <div className="collectionViewChrome-cont" style={{ top: collapsed ? -70 : 0, height: collapsed ? 0 : undefined, - transform: collapsed ? "" : `scale(${Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform().Scale)})`, - transformOrigin: "top left", - width: `${this.props.PanelWidth() / Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform().Scale)}px` + transform: collapsed ? "" : `scale(${scale})`, + width: `${this.props.PanelWidth() / scale}px` }}> <div className="collectionViewChrome" style={{ border: "unset", pointerEvents: collapsed ? "none" : undefined }}> <div className="collectionViewBaseChrome"> @@ -276,52 +319,15 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro title="Collapse collection chrome" onClick={this.toggleCollapse}> <FontAwesomeIcon icon="caret-up" size="2x" /> </button> - <div className="collectionViewBaseChrome-viewModes" style={{ display: collapsed ? "none" : undefined }}> - <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._viewRef} onPointerDown={this.dragViewDown}> - <div className="commandEntry-drop"> - <FontAwesomeIcon icon="bullseye" size="2x"></FontAwesomeIcon> - </div> - <select - className="collectionViewBaseChrome-viewPicker" - onPointerDown={stopPropagation} - onChange={this.viewChanged} - value={StrCast(this.props.CollectionView.props.Document._viewType)}> - {Object.values(CollectionViewType).map(type => ["invalid", "docking"].includes(type) ? (null) : ( - <option - key={Utils.GenerateGuid()} - className="collectionViewBaseChrome-viewOption" - onPointerDown={stopPropagation} - value={type}> - {type[0].toUpperCase() + type.substring(1)} - </option> - ))} - </select> - </div> - </div> + {this.viewModes} <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: collapsed ? "none" : "grid" }}> <div className="collectionViewBaseChrome-filterIcon" onPointerDown={this.toggleViewSpecs} > <FontAwesomeIcon icon="filter" size="2x" /> </div> </div> - <div className="collectionViewBaseChrome-template" ref={this.createDropTarget} style={{ display: collapsed ? "none" : undefined }}> - <div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._commandRef} onPointerDown={this.dragCommandDown}> - <div className="commandEntry-drop"> - <FontAwesomeIcon icon="bullseye" size="2x" /> - </div> - <select - className="collectionViewBaseChrome-cmdPicker" - onPointerDown={stopPropagation} - onChange={this.commandChanged} - value={this._currentKey}> - <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={"empty"} value={""}>{""}</option> - {this._buttonizableCommands.map(cmd => - <option className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} key={cmd.title} value={cmd.title}>{cmd.title}</option> - )} - </select> - </div> - </div> + {this.templateChrome} </div> - {this.subChrome()} + {this.subChrome} </div> </div> ); @@ -329,6 +335,56 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro } @observer +export class CollectionFreeFormViewChrome extends React.Component<CollectionViewChromeProps> { + + get Document() { return this.props.CollectionView.props.Document; } + @computed get dataField() { + return this.props.CollectionView.props.Document[Doc.LayoutFieldKey(this.props.CollectionView.props.Document)]; + } + @computed get childDocs() { + return DocListCast(this.dataField); + } + @undoBatch + @action + nextKeyframe = (): void => { + const currentFrame = NumCast(this.Document.currentFrame); + if (currentFrame === undefined) { + this.Document.currentFrame = 0; + CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); + } + CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0); + this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1); + this.Document.lastFrame = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastFrame)); + } + @undoBatch + @action + prevKeyframe = (): void => { + const currentFrame = NumCast(this.Document.currentFrame); + if (currentFrame === undefined) { + this.Document.currentFrame = 0; + CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); + } + CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice()); + this.Document.currentFrame = Math.max(0, (currentFrame || 0) - 1); + } + render() { + return this.Document.isAnnotationOverlay ? (null) : + <div className="collectionFreeFormViewChrome-cont"> + <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}> + <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> + </div> + <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }} + onClick={action(() => this.Document.editing = !this.Document.editing)} > + {NumCast(this.Document.currentFrame)} + </div> + <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}> + <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> + </div> + </div>; + } +} + +@observer export class CollectionStackingViewChrome extends React.Component<CollectionViewChromeProps> { @observable private _currentKey: string = ""; @observable private suggestions: string[] = []; @@ -474,19 +530,20 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh @observer export class CollectionTreeViewChrome extends React.Component<CollectionViewChromeProps> { - get dataExtension() { - return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "_ext"] as Doc; + get sortAscending() { + return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"]; } - @computed private get descending() { - return this.dataExtension && Cast(this.dataExtension.sortAscending, "boolean", null); + set sortAscending(value) { + this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"] = value; + } + @computed private get ascending() { + return Cast(this.sortAscending, "boolean", null); } @action toggleSort = () => { - if (this.dataExtension) { - if (this.dataExtension.sortAscending) this.dataExtension.sortAscending = undefined; - else if (this.dataExtension.sortAscending === undefined) this.dataExtension.sortAscending = false; - else this.dataExtension.sortAscending = true; - } + if (this.sortAscending) this.sortAscending = undefined; + else if (this.sortAscending === undefined) this.sortAscending = false; + else this.sortAscending = true; } render() { @@ -496,7 +553,7 @@ export class CollectionTreeViewChrome extends React.Component<CollectionViewChro <div className="collectionTreeViewChrome-sortLabel"> Sort </div> - <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.descending === undefined ? "90" : this.descending ? "180" : "0"}deg)` }}> + <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.ascending === undefined ? "90" : this.ascending ? "180" : "0"}deg)` }}> <FontAwesomeIcon icon="caret-up" size="2x" color="white" /> </div> </button> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 5478a1c4a..d9011c9d3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -41,32 +41,6 @@ // touch action none means that the browser will handle none of the touch actions. this allows us to implement our own actions. touch-action: none; - .fwdKeyframe, .numKeyframe, .backKeyframe{ - cursor: pointer; - position: absolute; - width: 20; - height:20; - bottom:0; - background:gray; - } - .backKeyframe { - right:45; - svg { - display:block; - margin:auto; - } - } - .numKeyframe { - right:25; - text-align:center; - } - .fwdKeyframe { - right:5; - svg { - display:block; - margin:auto; - } - } .collectionfreeformview-placeholder { background: gray; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index cb1228fed..c753a703d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,7 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons"; import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faFileUpload, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons"; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, _allowStateChangesInsideComputed } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, _allowStateChangesInsideComputed, trace } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../fields/Doc"; @@ -118,12 +118,28 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P this.props.PanelWidth() / (this.contentBounds.r - this.contentBounds.x)) : this.Document.scale || 1) - private centeringShiftX = () => !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / this.contentScaling : 0; // shift so pan position is at center of window for non-overlay collections - private centeringShiftY = () => !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / this.contentScaling : 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()); - private getTransformOverlay = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1); - private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); - private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); + @computed get cachedCenteringShiftX(): number { + return !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / this.contentScaling : 0; // shift so pan position is at center of window for non-overlay collections + } + @computed get cachedCenteringShiftY(): number { + return !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / this.contentScaling : 0;// shift so pan position is at center of window for non-overlay collections + } + @computed get cachedGetLocalTransform(): Transform { + return Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY()); + } + @computed get cachedGetContainerTransform(): Transform { + return this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); + } + @computed get cachedGetTransform(): Transform { + return this.getTransformOverlay().translate(- this.cachedCenteringShiftX, - this.cachedCenteringShiftY).transform(this.cachedGetLocalTransform); + } + + private centeringShiftX = () => this.cachedCenteringShiftX; + private centeringShiftY = () => this.cachedCenteringShiftY; + private getTransform = () => this.cachedGetTransform.copy(); + private getLocalTransform = () => this.cachedGetLocalTransform.copy(); + private getContainerTransform = () => this.cachedGetContainerTransform.copy(); + private getTransformOverlay = () => this.getContainerTransform().translate(1, 1); private addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newBox); @@ -162,30 +178,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return retVal; }) - @undoBatch - @action - nextKeyframe = (): void => { - const currentFrame = this.Document.currentFrame; - if (currentFrame === undefined) { - this.Document.currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); - } - CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0); - this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1); - this.Document.lastFrame = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastFrame)); - } - @undoBatch - @action - prevKeyframe = (): void => { - const currentFrame = this.Document.currentFrame; - if (currentFrame === undefined) { - this.Document.currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); - } - CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice()); - this.Document.currentFrame = Math.max(0, (currentFrame || 0) - 1); - } - private selectDocuments = (docs: Doc[]) => { SelectionManager.DeselectAll(); docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).map(dv => dv && SelectionManager.SelectDoc(dv, true)); @@ -1219,6 +1211,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; optionItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" }); + optionItems.push({ description: "toggle snap line display", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" }); optionItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" }); optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); @@ -1397,18 +1390,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? this.placeholder : this.marqueeView} <CollectionFreeFormOverlayView elements={this.elementFunc} /> - {this.isAnnotationOverlay || !this.props.isSelected() || this.props.Document._viewType === CollectionViewType.Pile ? (null) : - <> - <div key="back" className="backKeyframe" onClick={this.prevKeyframe}> - <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> - </div> - <div key="num" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }} onClick={action(() => this.Document.editing = !this.Document.editing)} > - {NumCast(this.Document.currentFrame)} - </div> - <div key="fwd" className="fwdKeyframe" onClick={this.nextKeyframe}> - <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> - </div> - </>} + <div className={"pullpane-indicator"} style={{ display: this._pullDirection ? "block" : "none", diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index ed70ac9e8..cdfeeaa6b 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -357,10 +357,14 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque const selected = this.marqueeSelect(false); if (e instanceof KeyboardEvent ? e.key === "c" : true) { selected.map(action(d => { - //this.props.removeDocument(d); - d.x = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; - d.displayTimecode = undefined; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + const dx = NumCast(d.x); + const dy = NumCast(d.y); + delete d.x; + delete d.y; + delete d.activeFrame; + delete d.displayTimecode; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + d.x = dx - bounds.left - bounds.width / 2; + d.y = dy - bounds.top - bounds.height / 2; return d; })); this.props.removeDocument(selected); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 00d19752f..2de7b3460 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -965,9 +965,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu return this.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; } childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); - panelWidth = () => this.props.PanelWidth(); - panelHeight = () => this.props.PanelHeight(); - screenToLocalTransform = () => this.props.ScreenToLocalTransform(); @computed get contents() { TraceMobx(); return (<> @@ -988,10 +985,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument} - ScreenToLocalTransform={this.screenToLocalTransform} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} renderDepth={this.props.renderDepth} - PanelWidth={this.panelWidth} - PanelHeight={this.panelHeight} + PanelWidth={this.props.PanelWidth} + PanelHeight={this.props.PanelHeight} ignoreAutoHeight={this.props.ignoreAutoHeight} focus={this.props.focus} parentActive={this.props.parentActive} diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 56a543f46..9f1e99c77 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -62,11 +62,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const lastFrame = Cast(presTargetDoc.lastFrame, "number", null); const curFrame = NumCast(presTargetDoc.currentFrame); if (lastFrame !== undefined && curFrame < lastFrame) { - //const docs = DocListCast(presTargetDoc[Doc.LayoutFieldKey(presTargetDoc)]); presTargetDoc.transition = "all 1s"; setTimeout(() => presTargetDoc.transition = undefined, 1010); - // docs.forEach(doc => doc.transition = "all 1s"); - // setTimeout(() => docs.forEach(doc => doc.transition = undefined), 1010); presTargetDoc.currentFrame = curFrame + 1; } else if (this.childDocs[this.itemIndex + 1] !== undefined) { |