diff options
author | Mohammad Amoush <mohammad_amoush@brown.edu> | 2019-07-16 18:03:12 -0400 |
---|---|---|
committer | Mohammad Amoush <mohammad_amoush@brown.edu> | 2019-07-16 18:03:12 -0400 |
commit | 1cedadbdf01c392ca9910e3ca18f3875d9a86fed (patch) | |
tree | 602608ba06b997cd3144395640e404a01f666291 /src/client/views/nodes/CollectionFreeFormDocumentView.tsx | |
parent | f70b95879e87a6bb61aaae5de29747d9474623a7 (diff) | |
parent | f18be9418b9237acd847eaf71adc034226c54695 (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into youtube-api-muhammed
Diffstat (limited to 'src/client/views/nodes/CollectionFreeFormDocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 175 |
1 files changed, 47 insertions, 128 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 499b83c0f..b09538d1a 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,19 +1,19 @@ -import { computed, IReactionDisposer, reaction, action } from "mobx"; +import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; -import { List } from "../../../new_fields/List"; -import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; -import { BoolCast, Cast, FieldValue, NumCast } from "../../../new_fields/Types"; -import { OmitKeys } from "../../../Utils"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { BoolCast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { Transform } from "../../util/Transform"; import { DocComponent } from "../DocComponent"; import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"; import "./DocumentView.scss"; import React = require("react"); -import { UndoManager } from "../../util/UndoManager"; -import { SelectionManager } from "../../util/SelectionManager"; +import { Doc } from "../../../new_fields/Doc"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { + x?: number; + y?: number; + width?: number; + height?: number; } const schema = createSchema({ @@ -27,20 +27,14 @@ const FreeformDocument = makeInterface(schema, positionSchema); @observer export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, FreeformDocument>(FreeformDocument) { - private _mainCont = React.createRef<HTMLDivElement>(); - _bringToFrontDisposer?: IReactionDisposer; - - @computed get transform() { - return `scale(${this.props.ContentScaling()}, ${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) scale(${this.zoom}, ${this.zoom}) `; - } - - @computed get X() { return FieldValue(this.Document.x, 0); } - @computed get Y() { return FieldValue(this.Document.y, 0); } + @computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) scale(${this.zoom}) `; } + @computed get X() { return this.props.x !== undefined ? this.props.x : this.Document.x || 0; } + @computed get Y() { return this.props.y !== undefined ? this.props.y : this.Document.y || 0; } + @computed get width(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : this.props.width !== undefined ? this.props.width : this.Document.width || 0; } + @computed get height(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : this.props.height !== undefined ? this.props.height : this.Document.height || 0; } @computed get zoom(): number { return 1 / FieldValue(this.Document.zoomBasis, 1); } @computed get nativeWidth(): number { return FieldValue(this.Document.nativeWidth, 0); } @computed get nativeHeight(): number { return FieldValue(this.Document.nativeHeight, 0); } - @computed get width(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : FieldValue(this.Document.width, 0); } - @computed get height(): number { return BoolCast(this.props.Document.willMaximize) ? 0 : FieldValue(this.Document.height, 0); } set width(w: number) { this.Document.width = w; @@ -54,135 +48,60 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF this.Document.width = this.nativeWidth / this.nativeHeight * h; } } + @computed get scaleToOverridingWidth() { return this.width / NumCast(this.props.Document.width, this.width); } contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; panelWidth = () => this.props.PanelWidth(); panelHeight = () => this.props.PanelHeight(); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) - .scale(1 / this.contentScaling()).scale(1 / this.zoom) - - @computed - get docView() { - return <DocumentView {...OmitKeys(this.props, ['zoomFade']).omit} - ContentScaling={this.contentScaling} - ScreenToLocalTransform={this.getTransform} - PanelWidth={this.panelWidth} - PanelHeight={this.panelHeight} - collapseToPoint={this.collapseToPoint} - />; - } - - componentDidMount() { - this._bringToFrontDisposer = reaction(() => this.props.Document.isIconAnimating, (values) => { - this.props.bringToFront(this.props.Document); - if (values instanceof List) { - let scrpt = this.props.ScreenToLocalTransform().transformPoint(values[0], values[1]); - this.animateBetweenIcon(true, scrpt, [this.Document.x || 0, this.Document.y || 0], - this.Document.width || 0, this.Document.height || 0, values[2], values[3] ? true : false); - } - }, { fireImmediately: true }); - } - - componentWillUnmount() { - if (this._bringToFrontDisposer) this._bringToFrontDisposer(); - } - - static _undoBatch?: UndoManager.Batch = undefined; - @action - public collapseToPoint = async (scrpt: number[], expandedDocs: Doc[] | undefined): Promise<void> => { - SelectionManager.DeselectAll(); - if (expandedDocs) { - if (!CollectionFreeFormDocumentView._undoBatch) { - CollectionFreeFormDocumentView._undoBatch = UndoManager.StartBatch("iconAnimating"); - } - let isMinimized: boolean | undefined; - expandedDocs.map(d => Doc.GetProto(d)).map(maximizedDoc => { - let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); - if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) { - if (isMinimized === undefined) { - isMinimized = BoolCast(maximizedDoc.isMinimized, false); - } - maximizedDoc.willMaximize = isMinimized; - maximizedDoc.isMinimized = false; - maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]); - } + .scale(1 / this.contentScaling()).scale(1 / this.zoom / this.scaleToOverridingWidth) + + animateBetweenIcon = (icon: number[], stime: number, maximizing: boolean) => { + this.props.bringToFront(this.props.Document); + let targetPos = [this.Document.x || 0, this.Document.y || 0]; + let iconPos = this.props.ScreenToLocalTransform().transformPoint(icon[0], icon[1]); + DocumentView.animateBetweenIconFunc(this.props.Document, + this.Document.width || 0, this.Document.height || 0, stime, maximizing, (progress: number) => { + let pval = maximizing ? + [iconPos[0] + (targetPos[0] - iconPos[0]) * progress, iconPos[1] + (targetPos[1] - iconPos[1]) * progress] : + [targetPos[0] + (iconPos[0] - targetPos[0]) * progress, targetPos[1] + (iconPos[1] - targetPos[1]) * progress]; + this.Document.x = progress === 1 ? targetPos[0] : pval[0]; + this.Document.y = progress === 1 ? targetPos[1] : pval[1]; }); - setTimeout(() => { - CollectionFreeFormDocumentView._undoBatch && CollectionFreeFormDocumentView._undoBatch.end(); - CollectionFreeFormDocumentView._undoBatch = undefined; - }, 500); - } - } - - animateBetweenIcon(first: boolean, icon: number[], targ: number[], width: number, height: number, stime: number, maximizing: boolean) { - - setTimeout(() => { - let now = Date.now(); - let progress = Math.min(1, (now - stime) / 200); - let pval = maximizing ? - [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] : - [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress]; - this.props.Document.width = maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress; - this.props.Document.height = maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress; - this.props.Document.x = pval[0]; - this.props.Document.y = pval[1]; - if (first) { - this.props.Document.proto!.willMaximize = false; - } - if (now < stime + 200) { - this.animateBetweenIcon(false, icon, targ, width, height, stime, maximizing); - } - else { - if (!maximizing) { - this.props.Document.proto!.isMinimized = true; - this.props.Document.x = targ[0]; - this.props.Document.y = targ[1]; - this.props.Document.width = width; - this.props.Document.height = height; - } - this.props.Document.proto!.isIconAnimating = undefined; - } - }, - 2); } borderRounding = () => { - let br = NumCast(this.props.Document.borderRounding); - return br >= 0 ? br : - NumCast(this.props.Document.nativeWidth) === 0 ? - Math.min(this.props.PanelWidth(), this.props.PanelHeight()) - : Math.min(this.Document.nativeWidth || 0, this.Document.nativeHeight || 0); + let br = StrCast(this.props.Document.layout instanceof Doc ? this.props.Document.layout.borderRounding : this.props.Document.borderRounding); + if (br.endsWith("%")) { + let percent = Number(br.substr(0, br.length - 1)) / 100; + let nativeDim = Math.min(NumCast(this.props.Document.nativeWidth), NumCast(this.props.Document.nativeHeight)); + let minDim = percent * (nativeDim ? nativeDim : Math.min(this.props.PanelWidth(), this.props.PanelHeight())); + return minDim; + } + return undefined; } render() { - let maximizedDoc = FieldValue(Cast(this.props.Document.maximizedDocs, listSpec(Doc))); - let zoomFade = 1; - //var zoom = doc.GetNumber(KeyStore.ZoomBasis, 1); - // let transform = this.getTransform().scale(this.contentScaling()).inverse(); - // var [sptX, sptY] = transform.transformPoint(0, 0); - // let [bptX, bptY] = transform.transformPoint(this.props.PanelWidth(), this.props.PanelHeight()); - // let w = bptX - sptX; - //zoomFade = area < 100 || area > 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1; - const screenWidth = Math.min(50 * NumCast(this.props.Document.nativeWidth, 0), 1800); - let fadeUp = .75 * screenWidth; - let fadeDown = (maximizedDoc ? .0075 : .075) * screenWidth; - // zoomFade = w < fadeDown /* || w > fadeUp */ ? Math.max(0.1, Math.min(1, 2 - (w < fadeDown ? Math.sqrt(Math.sqrt(fadeDown / w)) : w / fadeUp))) : 1; - return ( - <div className="collectionFreeFormDocumentView-container" ref={this._mainCont} + <div className="collectionFreeFormDocumentView-container" style={{ - opacity: zoomFade, - borderRadius: `${this.borderRounding()}px`, transformOrigin: "left top", + position: "absolute", + backgroundColor: "transparent", + borderRadius: this.borderRounding(), transform: this.transform, - pointerEvents: (zoomFade < 0.09 ? "none" : "all"), + transition: StrCast(this.props.Document.transition), width: this.width, height: this.height, - position: "absolute", zIndex: this.Document.zIndex || 0, - backgroundColor: "transparent" }} > - {this.docView} + <DocumentView {...this.props} + ContentScaling={this.contentScaling} + ScreenToLocalTransform={this.getTransform} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} + animateBetweenIcon={this.animateBetweenIcon} + /> </div> ); } |