blob: 8c3707bdf3343db5135fea69f81c8b9f43110ff8 [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 Condon28884332019-03-21 14:07:00 +000057 if (transform) {
58 container.attr('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.k + ')');
59 this.updateZoomState(<TopoZoomPrefs>{tx: transform.x, ty: transform.y, sc: transform.k});
60 }
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}