blob: 96fbbfbef296d3d6cb84a8b2cc9bf4a602ffcd34 [file] [log] [blame]
Sean Condon0c577f62018-11-18 22:40:05 +00001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Sean Condon0d064ec2019-02-04 21:53:53 +000016import {
17 Directive,
18 ElementRef,
19 Input,
20 OnChanges,
21 OnInit,
22 SimpleChanges
23} from '@angular/core';
Sean Condon0c577f62018-11-18 22:40:05 +000024import * as d3 from 'd3';
Sean Condon14d442f2019-12-09 14:16:19 +000025import {TopoZoomPrefs} from './zoomutils';
26import {LogService} from '../log.service';
27import {PrefsService} from '../util/prefs.service';
Sean Condon0c577f62018-11-18 22:40:05 +000028
Sean Condon0d064ec2019-02-04 21:53:53 +000029const TOPO_ZOOM_PREFS = 'topo_zoom';
30
31const ZOOM_PREFS_DEFAULT: TopoZoomPrefs = <TopoZoomPrefs>{
32 tx: 0, ty: 0, sc: 1.0
33};
34
35/**
36 * A directive that takes care of Zooming and Panning the Topology view
37 *
38 * It wraps the D3 Pan and Zoom functionality
39 * See https://github.com/d3/d3-zoom/blob/master/README.md
40 */
Sean Condon0c577f62018-11-18 22:40:05 +000041@Directive({
42 selector: '[onosZoomableOf]'
43})
Sean Condon0d064ec2019-02-04 21:53:53 +000044export class ZoomableDirective implements OnChanges, OnInit {
Sean Condon0c577f62018-11-18 22:40:05 +000045 @Input() zoomableOf: ElementRef;
46
Sean Condon0d064ec2019-02-04 21:53:53 +000047 zoom: any; // The d3 zoom behaviour
Sean Condon1ae15802019-03-02 09:07:18 +000048 zoomCached: TopoZoomPrefs = <TopoZoomPrefs>{tx: 0, ty: 0, sc: 1.0};
Sean Condon0d064ec2019-02-04 21:53:53 +000049
Sean Condon0c577f62018-11-18 22:40:05 +000050 constructor(
51 private _element: ElementRef,
52 private log: LogService,
Sean Condon0d064ec2019-02-04 21:53:53 +000053 private ps: PrefsService
54 ) {
55 const container = d3.select(this._element.nativeElement);
56
57 const zoomed = () => {
58 const transform = d3.event.transform;
Sean Condonb0a196a2019-04-19 09:50:44 +010059 container.attr('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.k + ')');
60 this.updateZoomState(<TopoZoomPrefs>{tx: transform.x, ty: transform.y, sc: transform.k});
Sean Condon0d064ec2019-02-04 21:53:53 +000061 };
62
63 this.zoom = d3.zoom().on('zoom', zoomed);
64 }
65
66 ngOnInit() {
Sean Condon1ae15802019-03-02 09:07:18 +000067 this.zoomCached = this.ps.getPrefs(TOPO_ZOOM_PREFS, ZOOM_PREFS_DEFAULT);
Sean Condon0d064ec2019-02-04 21:53:53 +000068 const svg = d3.select(this.zoomableOf);
69
70 svg.call(this.zoom);
71
72 svg.transition().call(this.zoom.transform,
Sean Condon1ae15802019-03-02 09:07:18 +000073 d3.zoomIdentity.translate(this.zoomCached.tx, this.zoomCached.ty).scale(this.zoomCached.sc));
Sean Condon0d064ec2019-02-04 21:53:53 +000074 this.log.debug('Loaded topo_zoom_prefs',
Sean Condon1ae15802019-03-02 09:07:18 +000075 this.zoomCached.tx, this.zoomCached.ty, this.zoomCached.sc);
Sean Condon0d064ec2019-02-04 21:53:53 +000076
77 }
78
79 /**
80 * Updates the cache of zoom preferences locally and onwards to the PrefsService
81 */
Sean Condon1ae15802019-03-02 09:07:18 +000082 updateZoomState(zoomPrefs: TopoZoomPrefs): void {
83 this.zoomCached = zoomPrefs;
84 this.ps.setPrefs(TOPO_ZOOM_PREFS, zoomPrefs);
Sean Condon0d064ec2019-02-04 21:53:53 +000085 }
Sean Condon0c577f62018-11-18 22:40:05 +000086
Sean Condon91481822019-01-01 13:56:14 +000087 /**
88 * If the input object is changed then re-establish the zoom
89 */
Sean Condon0d064ec2019-02-04 21:53:53 +000090 ngOnChanges(changes: SimpleChanges): void {
91 if (changes['zoomableOf']) {
92 const svg = d3.select(changes['zoomableOf'].currentValue);
93 svg.call(this.zoom);
94 this.log.debug('Applying zoomable behaviour on', this.zoomableOf, this._element.nativeElement);
95 }
Sean Condon0c577f62018-11-18 22:40:05 +000096 }
97
Sean Condon91481822019-01-01 13:56:14 +000098 /**
Sean Condon1ae15802019-03-02 09:07:18 +000099 * Change the zoom level when a map is chosen in Topology view
100 *
101 * Animated to run over 750ms
102 */
Sean Condonff85fbe2019-03-16 14:28:46 +0000103 changeZoomLevel(zoomState: TopoZoomPrefs, fast?: boolean): void {
Sean Condon1ae15802019-03-02 09:07:18 +0000104 const svg = d3.select(this.zoomableOf);
Sean Condonff85fbe2019-03-16 14:28:46 +0000105 svg.transition().duration(fast ? 0 : 750).call(this.zoom.transform,
Sean Condon1ae15802019-03-02 09:07:18 +0000106 d3.zoomIdentity.translate(zoomState.tx, zoomState.ty).scale(zoomState.sc));
107 this.updateZoomState(zoomState);
108 this.log.debug('Pan to', zoomState.tx, zoomState.ty, 'and zoom to', zoomState.sc);
109 }
110
Sean Condon0c577f62018-11-18 22:40:05 +0000111}