changeset 392:7ef6c8089801

Additional interfaces, VerticalScaleRenderer & VerticalValueInspectorRenderer. Implement another subclass of WavesComponent, InspectableVerticallyBoundedComponent concerned with highlighting, change tracks and notes components accordingly. These class hierarchies make me feel a little ill.
author Lucas Thompson <dev@lucas.im>
date Thu, 01 Jun 2017 16:25:48 +0100
parents 511fafd13873
children a02e6ec4a9d2
files src/app/visualisations/notes/notes.component.ts src/app/visualisations/tracks/tracks.components.ts src/app/visualisations/waves-base.component.ts
diffstat 3 files changed, 65 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/app/visualisations/notes/notes.component.ts	Thu Jun 01 16:20:18 2017 +0100
+++ b/src/app/visualisations/notes/notes.component.ts	Thu Jun 01 16:25:48 2017 +0100
@@ -3,7 +3,8 @@
  */
 import {
   VerticallyBounded,
-  VerticallyBoundedWavesComponent
+  VerticallyBoundedWavesComponent,
+  VerticalScaleRenderer
 } from '../waves-base.component';
 import {
   ChangeDetectionStrategy,
@@ -18,7 +19,10 @@
   templateUrl: '../waves-template.html',
   styleUrls: ['../waves-template.css'],
   changeDetection: ChangeDetectionStrategy.OnPush,
-  providers: [{ provide: VerticallyBounded, useExisting: NotesComponent }]
+  providers: [
+    { provide: VerticallyBounded, useExisting: NotesComponent },
+    { provide: VerticalScaleRenderer, useExisting: NotesComponent }
+  ]
 })
 export class NotesComponent extends VerticallyBoundedWavesComponent<Note[]> {
   private currentVerticalRange: [number, number];
--- a/src/app/visualisations/tracks/tracks.components.ts	Thu Jun 01 16:20:18 2017 +0100
+++ b/src/app/visualisations/tracks/tracks.components.ts	Thu Jun 01 16:25:48 2017 +0100
@@ -2,8 +2,10 @@
  * Created by lucas on 30/05/2017.
  */
 import {
+  InspectableVerticallyBoundedComponent,
   VerticallyBounded,
-  VerticallyBoundedWavesComponent,
+  VerticalScaleRenderer,
+  VerticalValueInspectorRenderer,
 } from '../waves-base.component';
 import {
   ChangeDetectionStrategy,
@@ -19,10 +21,14 @@
   templateUrl: '../waves-template.html',
   styleUrls: ['../waves-template.css'],
   changeDetection: ChangeDetectionStrategy.OnPush,
-  providers: [{ provide: VerticallyBounded, useExisting: TracksComponent }]
+  providers: [
+    {provide: VerticallyBounded, useExisting: TracksComponent },
+    {provide: VerticalScaleRenderer, useExisting: TracksComponent},
+    {provide: VerticalValueInspectorRenderer, useExisting: TracksComponent},
+  ],
 })
 export class TracksComponent
-  extends VerticallyBoundedWavesComponent<TracksFeature> {
+  extends InspectableVerticallyBoundedComponent<TracksFeature> {
 
   private currentState: PlotLayerData[];
 
--- a/src/app/visualisations/waves-base.component.ts	Thu Jun 01 16:20:18 2017 +0100
+++ b/src/app/visualisations/waves-base.component.ts	Thu Jun 01 16:25:48 2017 +0100
@@ -13,9 +13,18 @@
 // has to be an abstract class vs as interface for Angular's DI
 export abstract class VerticallyBounded {
   abstract get range(): [number, number];
+}
+
+export abstract class VerticalScaleRenderer extends VerticallyBounded {
   abstract renderScale(range: [number, number]): void;
 }
 
+export abstract class VerticalValueInspectorRenderer
+  extends VerticalScaleRenderer {
+  // TODO how do I know these layers are actually 'describable'?
+  abstract renderInspector(range: [number, number]): void;
+}
+
 export abstract class WavesComponent<T extends ShapedFeatureData | AudioBuffer>
   implements AfterViewInit {
   @ViewChild('track') trackContainer: ElementRef;
@@ -46,6 +55,7 @@
   private mFeature: T;
   private id: string;
   protected abstract get featureLayers(): Layer[];
+  protected cachedFeatureLayers: Layer[];
   protected postAddMap: (value: Layer, index: number, array: Layer[]) => void;
   protected height: number;
   protected duration: number;
@@ -67,12 +77,12 @@
       return;
     }
     this.clearTimeline();
-    const layers = this.featureLayers;
-    for (const layer of layers) {
+    this.cachedFeatureLayers = this.featureLayers;
+    for (const layer of this.cachedFeatureLayers) {
       this.addLayer(layer);
     }
     if (this.postAddMap) {
-      layers.forEach(this.postAddMap);
+      this.cachedFeatureLayers.forEach(this.postAddMap);
     }
   }
 
@@ -176,7 +186,7 @@
 
 export abstract class VerticallyBoundedWavesComponent
 <T extends ShapedFeatureData> extends WavesComponent<T>
-  implements VerticallyBounded {
+  implements VerticalScaleRenderer {
   abstract range: [number, number];
 
   renderScale(range: [number, number]): void {
@@ -188,3 +198,39 @@
     }));
   }
 }
+
+export abstract class InspectableVerticallyBoundedComponent
+<T extends ShapedFeatureData> extends VerticallyBoundedWavesComponent<T>
+  implements VerticalValueInspectorRenderer {
+
+  private wrappedSeekHandler: OnSeekHandler;
+  private highlight: HighlightLayer;
+
+  @Input() set onSeek(handler: OnSeekHandler) {
+    this.wrappedSeekHandler = (x: number) => {
+      handler(x);
+      this.highlight.currentPosition = x;
+      this.highlight.update();
+    };
+  }
+
+  get onSeek(): OnSeekHandler {
+    return this.wrappedSeekHandler;
+  }
+
+
+  renderInspector(range: [number, number]): void {
+    this.highlight = new Waves.helpers.HighlightLayer(
+      this.cachedFeatureLayers,
+      {
+        opacity: 0.7,
+        height: this.height,
+        color: '#c33c54', // TODO pass in?
+        labelOffset: 38,
+        yDomain: range,
+        unit: ''// TODO
+      }
+    );
+    this.addLayer(this.highlight);
+  }
+}