aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx60
-rw-r--r--src/client/views/nodes/DocumentView.tsx82
-rw-r--r--src/new_fields/Doc.ts10
4 files changed, 80 insertions, 74 deletions
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 0a96676e3..14a9dc9d9 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -163,7 +163,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
</CollectionSchemaPreview>;
}
getDocHeight(d?: Doc) {
- if (!d || d.willMaximize) return 0;
+ if (!d) return 0;
let nw = NumCast(d.nativeWidth);
let nh = NumCast(d.nativeHeight);
if (!d.ignoreAspect && nw && nh) {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 9f0bd736d..19d4a6784 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,6 +1,6 @@
-import { computed } from "mobx";
+import { computed, action, observable, reaction, IReactionDisposer } from "mobx";
import { observer } from "mobx-react";
-import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
import { FieldValue, NumCast, StrCast, Cast } from "../../../new_fields/Types";
import { Transform } from "../../util/Transform";
import { DocComponent } from "../DocComponent";
@@ -8,7 +8,7 @@ import { percent2frac } from "../../../Utils"
import { DocumentView, DocumentViewProps, documentSchema } from "./DocumentView";
import "./CollectionFreeFormDocumentView.scss";
import React = require("react");
-import { Doc } from "../../../new_fields/Doc";
+import { Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
import { random } from "animejs";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
@@ -30,11 +30,12 @@ export const PositionDocument = makeInterface(documentSchema, positionSchema);
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, PositionDocument>(PositionDocument) {
+ _disposer: IReactionDisposer | undefined = undefined;
@computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg)`; }
- @computed get X() { return this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
- @computed get Y() { return this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
- @computed get width() { return this.Document.willMaximize ? 0 : this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.Document.width || 0; }
- @computed get height() { return this.Document.willMaximize ? 0 : this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.Document.height || 0; }
+ @computed get X() { return this._animx !== undefined ? this._animx : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
+ @computed get Y() { return this._animy !== undefined ? this._animy : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
+ @computed get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.Document[WidthSym](); }
+ @computed get height() { return this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.Document[HeightSym](); }
@computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); }
@computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); }
@computed get scaleToOverridingWidth() { return this.width / FieldValue(this.Document.width, this.width); }
@@ -54,26 +55,35 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
return undefined;
}
+ componentWillUnmount() {
+ this._disposer && this._disposer();
+ }
+ componentDidMount() {
+ this._disposer = reaction(() => this.props.Document.iconTarget,
+ () => {
+ const icon = this.props.Document.iconTarget ? Array.from(Cast(this.props.Document.iconTarget, listSpec("number"))!) : undefined;
+ if (icon) {
+ let target = this.props.ScreenToLocalTransform().transformPoint(icon[0], icon[1]);
+ if (icon[2] === 1) {
+ this._animx = target[0];
+ this._animy = target[1];
+ }
+ setTimeout(action(() => {
+ this._animx = icon[2] === 1 ? this.Document.x : target[0];
+ this._animy = icon[2] === 1 ? this.Document.y : target[1];
+ }), 25);
+ } else {
+ this._animx = this._animy = undefined;
+ }
+ }, { fireImmediately: true });
+ }
+
contentScaling = () => this.nativeWidth > 0 && !this.props.Document.ignoreAspect ? 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.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];
- });
- }
+ .scale(1 / this.contentScaling()).scale(1 / this.scaleToOverridingWidth);
borderRounding = () => {
let ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined;
@@ -97,6 +107,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
}
+ @observable _animx: number | undefined = undefined;
+ @observable _animy: number | undefined = undefined;
+
render() {
const hasPosition = this.props.x !== undefined || this.props.y !== undefined;
return (
@@ -110,7 +123,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
StrCast(this.layoutDoc.boxShadow, ""),
borderRadius: this.borderRounding(),
transform: this.transform,
- transition: hasPosition ? "transform 1s" : StrCast(this.layoutDoc.transition),
+ transition: this.props.Document.isIconAnimating ? "transform .5s" : hasPosition ? "transform 1s" : StrCast(this.layoutDoc.transition),
width: this.width,
height: this.height,
zIndex: this.Document.zIndex || 0,
@@ -121,7 +134,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
backgroundColor={this.clusterColorFunc}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
- animateBetweenIcon={this.animateBetweenIcon}
/>
</div>
);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f58587066..37c38cc04 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -102,7 +102,7 @@ export interface DocumentViewProps {
zoomToScale: (scale: number) => void;
backgroundColor: (doc: Doc) => string | undefined;
getScale: () => number;
- animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void;
+ animateBetweenIcon?: (maximize: boolean, target: number[]) => void;
ChromeHeight?: () => number;
}
@@ -115,7 +115,6 @@ export const documentSchema = createSchema({
opacity: "number",
hidden: "boolean",
onClick: ScriptField,
- willMaximize: "boolean",
ignoreAspect: "boolean",
autoHeight: "boolean",
isTemplate: "boolean",
@@ -148,7 +147,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
private _hitTemplateDrag = false;
private _mainCont = React.createRef<HTMLDivElement>();
private _dropDisposer?: DragManager.DragDropDisposer;
- private _animateToIconDisposer?: IReactionDisposer;
public get ContentDiv() { return this._mainCont.current; }
@computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
@@ -161,35 +159,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
handlers: { drop: this.drop.bind(this) }
});
}
- this._animateToIconDisposer = reaction(() => this.Document.isIconAnimating, (values) =>
- (values instanceof List) && this.animateBetweenIcon(values, values[2], values[3] ? true : false)
- , { fireImmediately: true });
DocumentManager.Instance.DocumentViews.push(this);
}
- animateBetweenIcon = (iconPos: number[], startTime: number, maximizing: boolean) => {
- this.props.animateBetweenIcon ? this.props.animateBetweenIcon(iconPos, startTime, maximizing) :
- DocumentView.animateBetweenIconFunc(this.props.Document, this.Document.width || 0, this.Document.height || 0, startTime, maximizing);
- }
-
- public static animateBetweenIconFunc = (doc: Doc, width: number, height: number, stime: number, maximizing: boolean, cb?: (progress: number) => void) => {
- setTimeout(() => {
- let now = Date.now();
- let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1;
- doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress;
- doc.height = progress === 1 ? height : maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress;
- cb && cb(progress);
- if (now < stime + 200) {
- DocumentView.animateBetweenIconFunc(doc, width, height, stime, maximizing, cb);
- }
- else {
- doc.isMinimized = !maximizing;
- doc.isIconAnimating = undefined;
- }
- doc.willMaximize = false;
- },
- 2);
- }
@action
componentDidUpdate() {
this._dropDisposer && this._dropDisposer();
@@ -201,7 +173,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
@action
componentWillUnmount() {
- this._animateToIconDisposer && this._animateToIconDisposer();
this._dropDisposer && this._dropDisposer();
DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
}
@@ -235,30 +206,45 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
}
- static _undoBatch?: UndoManager.Batch = undefined;
@action
public collapseTargetsToPoint = (scrpt: number[], expandedDocs: Doc[] | undefined): void => {
SelectionManager.DeselectAll();
if (expandedDocs) {
- if (!DocumentView._undoBatch) {
- DocumentView._undoBatch = UndoManager.StartBatch("iconAnimating");
- }
let isMinimized: boolean | undefined;
expandedDocs.map(maximizedDoc => {
- let iconAnimating = Cast(maximizedDoc.isIconAnimating, List);
- if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) {
- if (isMinimized === undefined) {
- isMinimized = BoolCast(maximizedDoc.isMinimized);
+ if (isMinimized === undefined) {
+ isMinimized = BoolCast(maximizedDoc.isMinimized);
+ }
+ let w = NumCast(maximizedDoc.width);
+ let h = NumCast(maximizedDoc.height);
+ let iconAnimating = maximizedDoc.isIconAnimating ? Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!) : undefined;
+ if (isMinimized || (iconAnimating && iconAnimating.length && iconAnimating[0] === 0)) {
+ // MAXIMIZE DOC
+ if (maximizedDoc.isMinimized) {
+ maximizedDoc.isIconAnimating = new List<number>([0, 0]);
+ maximizedDoc.isMinimized = false;
}
- maximizedDoc.willMaximize = isMinimized;
- maximizedDoc.isMinimized = false;
- maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]);
+ maximizedDoc.iconTarget = new List<number>([...scrpt, 1]);
+ setTimeout(() => {
+ maximizedDoc.isIconAnimating = new List<number>([w, h]);
+ setTimeout(() => {
+ if (maximizedDoc.isIconAnimating && Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!)[0] !== 0) {
+ maximizedDoc.isIconAnimating = undefined;
+ }
+ }, 750);
+ }, 0);
+ } else {
+ maximizedDoc.iconTarget = new List<number>([...scrpt, 0]);
+ // MINIMIZE DOC
+ maximizedDoc.isIconAnimating = new List<number>([0, 0]);
+ setTimeout(() => {
+ if (maximizedDoc.isIconAnimating && Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!)[0] === 0) {
+ maximizedDoc.isMinimized = true;
+ maximizedDoc.isIconAnimating = undefined;
+ }
+ }, 750);
}
});
- setTimeout(() => {
- DocumentView._undoBatch && DocumentView._undoBatch.end();
- DocumentView._undoBatch = undefined;
- }, 500);
}
}
@@ -791,8 +777,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) :
ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
- const nativeWidth = this.Document.willMaximize ? 0 : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%";
- const nativeHeight = this.Document.willMaximize ? 0 : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
+ const nativeWidth = this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%";
+ const nativeHeight = this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined;
const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.layoutDoc.showTitle;
const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.layoutDoc.showCaption;
@@ -800,6 +786,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document);
const borderRounding = this.Document.borderRounding || ruleRounding;
const localScale = this.props.ScreenToLocalTransform().Scale * fullDegree;
+ const iconAnimating = this.Document.isIconAnimating ? Array.from(Cast(this.Document.isIconAnimating, listSpec("number"))!) : undefined;
const searchHighlight = (!this.Document.searchFields ? (null) :
<div className="documentView-searchHighlight" style={{ width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
{this.Document.searchFields}
@@ -830,6 +817,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
<div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
ref={this._mainCont}
style={{
+ transition: iconAnimating ? "transform .5s" : StrCast(this.layoutDoc.transition),
pointerEvents: this.layoutDoc.isBackground && !this.isSelected() ? "none" : "all",
color: StrCast(this.layoutDoc.color),
outlineColor: ["transparent", "maroon", "maroon", "yellow"][fullDegree],
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 2434a439a..614babd3c 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -143,8 +143,14 @@ export class Doc extends RefField {
private [Self] = this;
private [SelfProxy]: any;
- public [WidthSym] = () => NumCast(this[SelfProxy].width); // bcz: is this the right way to access width/height? it didn't work with : this.width
- public [HeightSym] = () => NumCast(this[SelfProxy].height);
+ public [WidthSym] = () => {
+ let iconAnimating = this[SelfProxy].isIconAnimating ? Array.from(Cast(this[SelfProxy].isIconAnimating, listSpec("number"))!) : undefined;
+ return iconAnimating ? iconAnimating[0] : NumCast(this[SelfProxy].width);
+ }
+ public [HeightSym] = () => {
+ let iconAnimating = this[SelfProxy].isIconAnimating ? Array.from(Cast(this[SelfProxy].isIconAnimating, listSpec("number"))!) : undefined;
+ return iconAnimating ? iconAnimating[1] : NumCast(this[SelfProxy].height);
+ }
[ToScriptString]() {
return "invalid";