dev@354
|
1 /**
|
dev@354
|
2 * Created by lucast on 26/05/2017.
|
dev@354
|
3 */
|
dev@354
|
4 import {ElementRef, Input} from '@angular/core';
|
dev@354
|
5 import {OnSeekHandler} from '../playhead/PlayHeadHelpers';
|
dev@354
|
6 import {attachTouchHandlerBodges} from './WavesJunk';
|
dev@354
|
7 import Waves from 'waves-ui-piper';
|
dev@376
|
8 import {countingIdProvider} from 'piper/client-stubs/WebWorkerStreamingClient';
|
dev@376
|
9
|
dev@376
|
10 const trackIdGenerator = countingIdProvider(0);
|
dev@354
|
11
|
dev@354
|
12 export abstract class WavesComponent {
|
dev@354
|
13 @Input() set width(width: number) {
|
dev@354
|
14 if (this.timeline) {
|
dev@354
|
15 requestAnimationFrame(() => {
|
dev@354
|
16 this.timeline.timeContext.visibleWidth = width;
|
dev@354
|
17 this.timeline.tracks.update();
|
dev@354
|
18 });
|
dev@354
|
19 }
|
dev@354
|
20 }
|
dev@354
|
21 @Input() timeline: Timeline;
|
dev@354
|
22 @Input() onSeek: OnSeekHandler;
|
dev@379
|
23 @Input() colour: string;
|
dev@354
|
24
|
dev@354
|
25 protected layers: Layer[];
|
dev@354
|
26 protected zoomOnMouseDown: number;
|
dev@354
|
27 protected offsetOnMouseDown: number;
|
dev@354
|
28 protected waveTrack: Track;
|
dev@376
|
29 private id: string;
|
dev@354
|
30
|
dev@354
|
31 constructor() {
|
dev@354
|
32 this.layers = [];
|
dev@376
|
33 this.id = trackIdGenerator.next().value;
|
dev@354
|
34 }
|
dev@354
|
35
|
dev@364
|
36 protected renderTimeline($el: ElementRef, duration?: number): Timeline {
|
dev@354
|
37 const track: HTMLElement = $el.nativeElement;
|
dev@354
|
38 track.innerHTML = '';
|
dev@354
|
39 const height: number = track.getBoundingClientRect().height;
|
dev@364
|
40 if (duration >= 0) {
|
dev@364
|
41 const width: number = track.getBoundingClientRect().width;
|
dev@364
|
42 this.timeline.pixelsPerSecond = width / duration;
|
dev@364
|
43 this.timeline.visibleWidth = width;
|
dev@364
|
44 }
|
dev@354
|
45 this.waveTrack = this.timeline.createTrack(
|
dev@354
|
46 track,
|
dev@354
|
47 height,
|
dev@376
|
48 this.id
|
dev@354
|
49 );
|
dev@354
|
50
|
dev@354
|
51 if ('ontouchstart' in window) {
|
dev@354
|
52 attachTouchHandlerBodges(
|
dev@354
|
53 $el.nativeElement,
|
dev@354
|
54 this.timeline
|
dev@354
|
55 );
|
dev@354
|
56 }
|
dev@356
|
57 this.resetTimelineState($el);
|
dev@354
|
58 }
|
dev@354
|
59
|
dev@354
|
60 // TODO can likely be removed, or use waves-ui methods
|
dev@356
|
61 protected clearTimeline($el: ElementRef): void {
|
dev@354
|
62 // loop through layers and remove them, waves-ui provides methods for this but it seems to not work properly
|
dev@354
|
63 const timeContextChildren = this.timeline.timeContext._children;
|
dev@354
|
64 for (const track of this.timeline.tracks) {
|
dev@354
|
65 if (track.layers.length === 0) { continue; }
|
dev@354
|
66 const trackLayers: Layer[] = Array.from(track.layers as Layer[]);
|
dev@354
|
67 while (trackLayers.length) {
|
dev@354
|
68 const layer: Layer = trackLayers.pop();
|
dev@354
|
69 if (this.layers.includes(layer)) {
|
dev@354
|
70 track.remove(layer);
|
dev@354
|
71 this.layers.splice(this.layers.indexOf(layer), 1);
|
dev@354
|
72 const index = timeContextChildren.indexOf(layer.timeContext);
|
dev@354
|
73 if (index >= 0) {
|
dev@354
|
74 timeContextChildren.splice(index, 1);
|
dev@354
|
75 }
|
dev@354
|
76 layer.destroy();
|
dev@354
|
77 }
|
dev@354
|
78 }
|
dev@354
|
79 }
|
dev@356
|
80 this.resetTimelineState($el);
|
dev@356
|
81 }
|
dev@356
|
82
|
dev@356
|
83 private resetTimelineState($el: ElementRef): void {
|
dev@356
|
84 const height = $el.nativeElement.getBoundingClientRect().height;
|
dev@356
|
85
|
dev@356
|
86 // time axis
|
dev@356
|
87 const timeAxis = new Waves.helpers.TimeAxisLayer({
|
dev@356
|
88 height: height,
|
dev@356
|
89 color: '#b0b0b0'
|
dev@356
|
90 });
|
dev@356
|
91 this.addLayer(timeAxis, this.waveTrack, this.timeline.timeContext, true);
|
dev@356
|
92 this.timeline.state = new Waves.states.CenteredZoomState(this.timeline);
|
dev@364
|
93 this.timeline.tracks.update(); // TODO this is problematic, shared state across components
|
dev@354
|
94 }
|
dev@354
|
95
|
dev@354
|
96
|
dev@354
|
97 // TODO can likely use methods in waves-ui directly
|
dev@354
|
98 protected addLayer(layer: Layer,
|
dev@364
|
99 track: Track,
|
dev@364
|
100 timeContext: any,
|
dev@364
|
101 isAxis: boolean = false): void {
|
dev@354
|
102 if (!layer.timeContext) {
|
dev@354
|
103 layer.setTimeContext(isAxis ?
|
dev@354
|
104 timeContext : new Waves.core.LayerTimeContext(timeContext));
|
dev@354
|
105 }
|
dev@354
|
106 track.add(layer);
|
dev@354
|
107 this.layers.push(layer);
|
dev@354
|
108 layer.render();
|
dev@354
|
109 layer.update();
|
dev@354
|
110 }
|
dev@354
|
111
|
dev@354
|
112 seekStart(): void {
|
dev@354
|
113 this.zoomOnMouseDown = this.timeline.timeContext.zoom;
|
dev@354
|
114 this.offsetOnMouseDown = this.timeline.timeContext.offset;
|
dev@354
|
115 }
|
dev@354
|
116
|
dev@354
|
117 seekEnd(x: number): void {
|
dev@354
|
118 const hasSameZoom: boolean = this.zoomOnMouseDown ===
|
dev@354
|
119 this.timeline.timeContext.zoom;
|
dev@354
|
120 const hasSameOffset: boolean = this.offsetOnMouseDown ===
|
dev@354
|
121 this.timeline.timeContext.offset;
|
dev@354
|
122 if (hasSameZoom && hasSameOffset) {
|
dev@354
|
123 this.seek(x);
|
dev@354
|
124 }
|
dev@354
|
125 }
|
dev@354
|
126
|
dev@354
|
127 seek(x: number): void {
|
dev@354
|
128 if (this.timeline) {
|
dev@354
|
129 const timeContext: any = this.timeline.timeContext;
|
dev@354
|
130 if (this.onSeek) {
|
dev@354
|
131 this.onSeek(timeContext.timeToPixel.invert(x) - timeContext.offset);
|
dev@354
|
132 }
|
dev@354
|
133 }
|
dev@354
|
134 }
|
dev@354
|
135 }
|