aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/Timeline.tsx
diff options
context:
space:
mode:
authorandrewdkim <adkim414@gmail.com>2019-07-08 17:01:33 -0400
committerandrewdkim <adkim414@gmail.com>2019-07-08 17:01:33 -0400
commit1e46be88a32dbf2196b58708834dfe138ff5aad2 (patch)
tree2bbbd66ca4b7fda8bbba6fc342e4436a1376c78f /src/client/views/nodes/Timeline.tsx
parent11326788a7212eca86e06ee8f2c9a4aa65ab6070 (diff)
scrubber change, keyframe mod, flyout features
Diffstat (limited to 'src/client/views/nodes/Timeline.tsx')
-rw-r--r--src/client/views/nodes/Timeline.tsx140
1 files changed, 109 insertions, 31 deletions
diff --git a/src/client/views/nodes/Timeline.tsx b/src/client/views/nodes/Timeline.tsx
index fd235fad3..1c51dbcad 100644
--- a/src/client/views/nodes/Timeline.tsx
+++ b/src/client/views/nodes/Timeline.tsx
@@ -1,12 +1,11 @@
import * as React from "react";
-import * as ReactDOM from "react-dom";
import "./Timeline.scss";
import { CollectionSubView } from "../collections/CollectionSubView";
import { Document, listSpec, createSchema, makeInterface, defaultSpec } from "../../../new_fields/Schema";
import { observer } from "mobx-react";
import { Track } from "./Track";
import { observable, reaction, action, IReactionDisposer, observe, IObservableArray, computed, toJS, Reaction, IObservableObject } from "mobx";
-import { Cast } from "../../../new_fields/Types";
+import { Cast, NumCast } from "../../../new_fields/Types";
import { SelectionManager } from "../../util/SelectionManager";
import { List } from "../../../new_fields/List";
import { Self } from "../../../new_fields/FieldSymbols";
@@ -16,29 +15,39 @@ import { faCircle, faPlayCircle, faBackward, faForward, faGripLines } from "@for
import { DocumentContentsView } from "./DocumentContentsView";
import { ContextMenuProps } from "../ContextMenuItem";
import { ContextMenu } from "../ContextMenu";
+import { string } from "prop-types";
export interface FlyoutProps {
x?: number;
y?: number;
display?: string;
- time?: number;
- duration?: number;
+ regiondata?:Doc;
+ regions?:List<Doc>;
}
@observer
export class Timeline extends CollectionSubView(Document) {
private readonly DEFAULT_CONTAINER_HEIGHT: number = 300;
+ private readonly DEFAULT_TICK_SPACING:number = 50;
private readonly MIN_CONTAINER_HEIGHT: number = 205;
private readonly MAX_CONTAINER_HEIGHT: number = 800;
-
- @observable private _tickSpacing = 50;
+
+ @observable private _isMinimized = false;
+ @observable private _tickSpacing = this.DEFAULT_TICK_SPACING;
@observable private _scrubberbox = React.createRef<HTMLDivElement>();
+ @observable private _scrubber = React.createRef<HTMLDivElement>();
@observable private _trackbox = React.createRef<HTMLDivElement>();
@observable private _titleContainer = React.createRef<HTMLDivElement>();
@observable private _timelineContainer = React.createRef<HTMLDivElement>();
+ @observable private _timeInput = React.createRef<HTMLInputElement>();
+ @observable private _durationInput = React.createRef<HTMLInputElement>();
+ @observable private _fadeInInput = React.createRef<HTMLInputElement>();
+ @observable private _fadeOutInput = React.createRef<HTMLInputElement>();
+
+
@observable private _currentBarX: number = 0;
@observable private _windSpeed: number = 1;
@observable private _isPlaying: boolean = false;
@@ -50,7 +59,7 @@ export class Timeline extends CollectionSubView(Document) {
@observable private _infoContainer = React.createRef<HTMLDivElement>();
@observable private _ticks: number[] = [];
- @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none" };
+ @observable private flyoutInfo: FlyoutProps = { x: 0, y: 0, display: "none", regiondata: new Doc(), regions: new List<Doc>()};
private block = false;
@@ -80,6 +89,10 @@ export class Timeline extends CollectionSubView(Document) {
document.addEventListener("pointerdown", this.closeFlyout);
}
+ @action
+ changeCurrentBarX = (x: number) => {
+ this._currentBarX = x;
+ }
@action
onFlyoutDown = (e: React.PointerEvent) => {
this.flyoutInfo.display = "block";
@@ -169,19 +182,7 @@ export class Timeline extends CollectionSubView(Document) {
this._currentBarX = offset;
}
- @action
- toTime = (time: number): string => {
- const inSeconds = time / 1000;
- let min: (string | number) = Math.floor(inSeconds / 60);
- let sec: (string | number) = inSeconds % 60;
-
- if (Math.floor(sec / 10) === 0) {
- sec = "0" + sec;
- }
- return `${min}:${sec}`;
-
- }
-
+
@action
onPanDown = (e: React.PointerEvent) => {
@@ -205,8 +206,6 @@ export class Timeline extends CollectionSubView(Document) {
titleContainer.scrollTop = titleContainer.scrollTop - e.movementY;
}
-
-
@action
onResizeDown = (e: React.PointerEvent) => {
e.preventDefault();
@@ -231,7 +230,24 @@ export class Timeline extends CollectionSubView(Document) {
}
}
- @observable private _isMinimized = false;
+ @action
+ onTimelineDown = (e:React.PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ document.addEventListener("pointermove", this.onTimelineMove);
+ document.addEventListener("pointerup", () => {document.removeEventListener("pointermove", this.onTimelineMove);});
+ }
+
+ @action
+ onTimelineMove = (e:PointerEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let timelineContainer = this._timelineContainer.current!;
+ timelineContainer.style.transform = `translate(${timelineContainer.getBoundingClientRect().left + 1}px, ${timelineContainer.getBoundingClientRect().top + 1}px)`;
+ console.log("mouse move!");
+ timelineContainer.style.width = "500px";
+ }
+
@action
minimize = (e: React.MouseEvent) => {
e.preventDefault();
@@ -246,6 +262,17 @@ export class Timeline extends CollectionSubView(Document) {
}
}
+ @action
+ toTime = (time: number): string => {
+ const inSeconds = time / 1000;
+ let min: (string | number) = Math.floor(inSeconds / 60);
+ let sec: (string | number) = inSeconds % 60;
+
+ if (Math.floor(sec / 10) === 0) {
+ sec = "0" + sec;
+ }
+ return `${min}:${sec}`;
+ }
@action
getFlyout = (props: FlyoutProps) => {
@@ -265,15 +292,63 @@ export class Timeline extends CollectionSubView(Document) {
}), icon: "pinterest"
});
ContextMenu.Instance.addItem({ description: "Timeline Funcs...", subitems: subitems });
+
+ }
+
+ @action
+ changeTime = (e: React.KeyboardEvent) => {
+ let time = this._timeInput.current!;
+ if (e.keyCode === 13){
+ if (!Number.isNaN(Number(time.value))){
+ this.flyoutInfo.regiondata!.position = Number(time.value) / 1000 * this._tickSpacing;
+ time.placeholder = time.value +"ms";
+ time.value = "";
+ }
+ }
+ }
+
+
+ @action
+ changeDuration = (e:React.KeyboardEvent) => {
+ let duration = this._durationInput.current!;
+ if (e.keyCode === 13){
+ if (!Number.isNaN(Number(duration.value))){
+ this.flyoutInfo.regiondata!.duration = Number(duration.value) / 1000 * this._tickSpacing;
+ duration.placeholder = duration.value +"ms";
+ duration.value = "";
+ }
+ }
+ }
+
+ @action
+ changeFadeIn = (e:React.KeyboardEvent) => {
+ let fadeIn = this._fadeInInput.current!;
+ if (e.keyCode === 13){
+ if (!Number.isNaN(Number(fadeIn.value))){
+ this.flyoutInfo.regiondata!.fadeIn = Number(fadeIn.value);
+ fadeIn.placeholder = fadeIn.value +"ms";
+ fadeIn.value = "";
+ }
+ }
}
+ @action
+ changeFadeOut = (e:React.KeyboardEvent) => {
+ let fadeOut = this._fadeOutInput.current!;
+ if (e.keyCode === 13){
+ if (!Number.isNaN(Number(fadeOut.value))){
+ this.flyoutInfo.regiondata!.fadeOut = Number(fadeOut.value);
+ fadeOut.placeholder = fadeOut.value +"ms";
+ fadeOut.value = "";
+ }
+ }
+ }
render() {
return (
<div>
<button className="minimize" onClick={this.minimize}>Minimize</button>
- <div className="timeline-container" style={{ height: `${this._containerHeight}px` }} ref={this._timelineContainer} onContextMenu={this.timelineContextMenu}>
- <div className="flyout-container" style={{ transform: `translate(${this.flyoutInfo.x}px, ${this.flyoutInfo.y}px)`, display: this.flyoutInfo.display }} onPointerDown={this.onFlyoutDown}>
+ <div className="flyout-container" style={{left:`${this.flyoutInfo.x}px`, top:`${this.flyoutInfo.y}px`, display: `${this.flyoutInfo.display!}` }} onPointerDown={this.onFlyoutDown}>
<FontAwesomeIcon className="flyout" icon="comment-alt" color="grey" />
<div className="text-container">
<p>Time:</p>
@@ -282,12 +357,15 @@ export class Timeline extends CollectionSubView(Document) {
<p>Fade-out</p>
</div>
<div className="input-container">
- <input type="text" placeholder={`${Math.round(this.flyoutInfo.time! / this._tickSpacing * 1000)}ms`} />
- <input type="text" placeholder={`${Math.round(this.flyoutInfo.duration! / this._tickSpacing * 1000)}ms`} />
- <input type="text" placeholder={`${Math.round(this.flyoutInfo.time! / this._tickSpacing * 1000)}ms`} />
- <input type="text" placeholder={`${Math.round(this.flyoutInfo.duration! / this._tickSpacing * 1000)}ms`} />
+ <input ref = {this._timeInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.position)/ this._tickSpacing * 1000)}ms`} onKeyDown={this.changeTime} />
+ <input ref = {this._durationInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.duration) / this._tickSpacing * 1000)}ms`} onKeyDown={this.changeDuration}/>
+ <input ref = {this._fadeInInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeIn))}ms`} onKeyDown={this.changeFadeIn}/>
+ <input ref = {this._fadeOutInput} type="text" placeholder={`${Math.round(NumCast(this.flyoutInfo.regiondata!.fadeOut))}ms`} onKeyDown={this.changeFadeOut}/>
+
</div>
+ <button onClick={action((e:React.MouseEvent)=>{this.flyoutInfo.regions!.splice(this.flyoutInfo.regions!.indexOf(this.flyoutInfo.regiondata!), 1); this.flyoutInfo.display = "none";})}>delete</button>
</div>
+ <div className="timeline-container" style={{ height: `${this._containerHeight}px` }} ref={this._timelineContainer} onContextMenu={this.timelineContextMenu} >
<div className="toolbox">
<div onClick={this.windBackward}> <FontAwesomeIcon icon={faBackward} size="2x" /> </div>
<div onClick={this.onPlay}> <FontAwesomeIcon icon={faPlayCircle} size="2x" /> </div>
@@ -304,12 +382,12 @@ export class Timeline extends CollectionSubView(Document) {
return <div className="tick" style={{ transform: `translate(${element / 1000 * this._tickSpacing}px)`, position: "absolute", pointerEvents: "none" }}> <p>{this.toTime(element)}</p></div>;
})}
</div>
- <div className="scrubber" onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
+ <div className="scrubber" ref={this._scrubber} onPointerDown={this.onScrubberDown} style={{ transform: `translate(${this._currentBarX}px)` }}>
<div className="scrubberhead"></div>
</div>
<div className="trackbox" ref={this._trackbox} onPointerDown={this.onPanDown}>
{this._nodes.map(doc => {
- return <Track node={(doc as any).value() as Doc} currentBarX={this._currentBarX} setFlyout={this.getFlyout} />;
+ return <Track node={(doc as any).value() as Doc} currentBarX={this._currentBarX} changeCurrentBarX = {this.changeCurrentBarX} setFlyout={this.getFlyout} />;
})}
</div>
</div>