blob: 956444411b315c851b6c7798b60c1304a0609906 [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 Condon1ae15802019-03-02 09:07:18 +000024import {LogService, PrefsService, TopoZoomPrefs} from 'gui2-fw-lib';
Sean Condon0c577f62018-11-18 22:40:05 +000025import * as d3 from 'd3';
26
Sean Condon0d064ec2019-02-04 21:53:53 +000027const TOPO_ZOOM_PREFS = 'topo_zoom';
28
29const ZOOM_PREFS_DEFAULT: TopoZoomPrefs = <TopoZoomPrefs>{
30 tx: 0, ty: 0, sc: 1.0
31};
32
33/**
34 * A directive that takes care of Zooming and Panning the Topology view
35 *
36 * It wraps the D3 Pan and Zoom functionality
37 * See https://github.com/d3/d3-zoom/blob/master/README.md
38 */
Sean Condon0c577f62018-11-18 22:40:05 +000039@Directive({
40 selector: '[onosZoomableOf]'
41})
Sean Condon0d064ec2019-02-04 21:53:53 +000042export class ZoomableDirective implements OnChanges, OnInit {
Sean Condon0c577f62018-11-18 22:40:05 +000043 @Input() zoomableOf: ElementRef;
44
Sean Condon0d064ec2019-02-04 21:53:53 +000045 zoom: any; // The d3 zoom behaviour
Sean Condon1ae15802019-03-02 09:07:18 +000046 zoomCached: TopoZoomPrefs = <TopoZoomPrefs>{tx: 0, ty: 0, sc: 1.0};
Sean Condon0d064ec2019-02-04 21:53:53 +000047
Sean Condon0c577f62018-11-18 22:40:05 +000048 constructor(
49 private _element: ElementRef,
50 private log: LogService,
Sean Condon0d064ec2019-02-04 21:53:53 +000051 private ps: PrefsService
52 ) {
53 const container = d3.select(this._element.nativeElement);
54
55 const zoomed = () => {
56 const transform = d3.event.transform;
Sean Condonb0a196a2019-04-19 09:50:44 +010057 container.attr('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.k + ')');
58 this.updateZoomState(<TopoZoomPrefs>{tx: transform.x, ty: transform.y, sc: transform.k});
Sean Condon0d064ec2019-02-04 21:53:53 +000059 };
60
61 this.zoom = d3.zoom().on('zoom', zoomed);
62 }
63
64 ngOnInit() {
Sean Condon1ae15802019-03-02 09:07:18 +000065 this.zoomCached = this.ps.getPrefs(TOPO_ZOOM_PREFS, ZOOM_PREFS_DEFAULT);
Sean Condon0d064ec2019-02-04 21:53:53 +000066 const svg = d3.select(this.zoomableOf);
67
68 svg.call(this.zoom);
69
70 svg.transition().call(this.zoom.transform,
Sean Condon1ae15802019-03-02 09:07:18 +000071 d3.zoomIdentity.translate(this.zoomCached.tx, this.zoomCached.ty).scale(this.zoomCached.sc));
Sean Condon0d064ec2019-02-04 21:53:53 +000072 this.log.debug('Loaded topo_zoom_prefs',
Sean Condon1ae15802019-03-02 09:07:18 +000073 this.zoomCached.tx, this.zoomCached.ty, this.zoomCached.sc);
Sean Condon0d064ec2019-02-04 21:53:53 +000074
75 }
76
77 /**
78 * Updates the cache of zoom preferences locally and onwards to the PrefsService
79 */
Sean Condon1ae15802019-03-02 09:07:18 +000080 updateZoomState(zoomPrefs: TopoZoomPrefs): void {
81 this.zoomCached = zoomPrefs;
82 this.ps.setPrefs(TOPO_ZOOM_PREFS, zoomPrefs);
Sean Condon0d064ec2019-02-04 21:53:53 +000083 }
Sean Condon0c577f62018-11-18 22:40:05 +000084
Sean Condon91481822019-01-01 13:56:14 +000085 /**
86 * If the input object is changed then re-establish the zoom
87 */
Sean Condon0d064ec2019-02-04 21:53:53 +000088 ngOnChanges(changes: SimpleChanges): void {
89 if (changes['zoomableOf']) {
90 const svg = d3.select(changes['zoomableOf'].currentValue);
91 svg.call(this.zoom);
92 this.log.debug('Applying zoomable behaviour on', this.zoomableOf, this._element.nativeElement);
93 }
Sean Condon0c577f62018-11-18 22:40:05 +000094 }
95
Sean Condon91481822019-01-01 13:56:14 +000096 /**
Sean Condon1ae15802019-03-02 09:07:18 +000097 * Change the zoom level when a map is chosen in Topology view
98 *
99 * Animated to run over 750ms
100 */
Sean Condonff85fbe2019-03-16 14:28:46 +0000101 changeZoomLevel(zoomState: TopoZoomPrefs, fast?: boolean): void {
Sean Condon1ae15802019-03-02 09:07:18 +0000102 const svg = d3.select(this.zoomableOf);
Sean Condonff85fbe2019-03-16 14:28:46 +0000103 svg.transition().duration(fast ? 0 : 750).call(this.zoom.transform,
Sean Condon1ae15802019-03-02 09:07:18 +0000104 d3.zoomIdentity.translate(zoomState.tx, zoomState.ty).scale(zoomState.sc));
105 this.updateZoomState(zoomState);
106 this.log.debug('Pan to', zoomState.tx, zoomState.ty, 'and zoom to', zoomState.sc);
107 }
108
Sean Condon0c577f62018-11-18 22:40:05 +0000109}