blob: 0484384104136ede2773f7c7ee3f1bbf0e9692fe [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';
24import {LogService, PrefsService} from 'gui2-fw-lib';
Sean Condon0c577f62018-11-18 22:40:05 +000025import * as d3 from 'd3';
26
Sean Condon0d064ec2019-02-04 21:53:53 +000027
28/**
29 * Model of the Zoom preferences
30 */
31export interface TopoZoomPrefs {
32 tx: number;
33 ty: number;
34 sc: number;
35}
36
37const TOPO_ZOOM_PREFS = 'topo_zoom';
38
39const ZOOM_PREFS_DEFAULT: TopoZoomPrefs = <TopoZoomPrefs>{
40 tx: 0, ty: 0, sc: 1.0
41};
42
43/**
44 * A directive that takes care of Zooming and Panning the Topology view
45 *
46 * It wraps the D3 Pan and Zoom functionality
47 * See https://github.com/d3/d3-zoom/blob/master/README.md
48 */
Sean Condon0c577f62018-11-18 22:40:05 +000049@Directive({
50 selector: '[onosZoomableOf]'
51})
Sean Condon0d064ec2019-02-04 21:53:53 +000052export class ZoomableDirective implements OnChanges, OnInit {
Sean Condon0c577f62018-11-18 22:40:05 +000053 @Input() zoomableOf: ElementRef;
54
Sean Condon0d064ec2019-02-04 21:53:53 +000055 zoom: any; // The d3 zoom behaviour
56
Sean Condon0c577f62018-11-18 22:40:05 +000057 constructor(
58 private _element: ElementRef,
59 private log: LogService,
Sean Condon0d064ec2019-02-04 21:53:53 +000060 private ps: PrefsService
61 ) {
62 const container = d3.select(this._element.nativeElement);
63
64 const zoomed = () => {
65 const transform = d3.event.transform;
66 container.attr('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.k + ')');
67 this.updateZoomState(transform.x, transform.y, transform.k);
68 };
69
70 this.zoom = d3.zoom().on('zoom', zoomed);
71 }
72
73 ngOnInit() {
74 const zoomState: TopoZoomPrefs = this.ps.getPrefs(TOPO_ZOOM_PREFS, ZOOM_PREFS_DEFAULT);
75 const svg = d3.select(this.zoomableOf);
76
77 svg.call(this.zoom);
78
79 svg.transition().call(this.zoom.transform,
80 d3.zoomIdentity.translate(zoomState.tx, zoomState.ty).scale(zoomState.sc));
81 this.log.debug('Loaded topo_zoom_prefs',
82 zoomState.tx, zoomState.ty, zoomState.sc);
83
84 }
85
86 /**
87 * Updates the cache of zoom preferences locally and onwards to the PrefsService
88 */
89 updateZoomState(x: number, y: number, scale: number): void {
90 this.ps.setPrefs(TOPO_ZOOM_PREFS, <TopoZoomPrefs>{
91 tx: x,
92 ty: y,
93 sc: scale
94 });
95 }
Sean Condon0c577f62018-11-18 22:40:05 +000096
Sean Condon91481822019-01-01 13:56:14 +000097 /**
98 * If the input object is changed then re-establish the zoom
99 */
Sean Condon0d064ec2019-02-04 21:53:53 +0000100 ngOnChanges(changes: SimpleChanges): void {
101 if (changes['zoomableOf']) {
102 const svg = d3.select(changes['zoomableOf'].currentValue);
103 svg.call(this.zoom);
104 this.log.debug('Applying zoomable behaviour on', this.zoomableOf, this._element.nativeElement);
105 }
Sean Condon0c577f62018-11-18 22:40:05 +0000106 }
107
Sean Condon91481822019-01-01 13:56:14 +0000108 /**
109 * Reset the zoom when the R key is pressed when in Topology view
Sean Condon0d064ec2019-02-04 21:53:53 +0000110 *
111 * Animated to run over 750ms
Sean Condon91481822019-01-01 13:56:14 +0000112 */
113 resetZoom(): void {
Sean Condon0d064ec2019-02-04 21:53:53 +0000114 const svg = d3.select(this.zoomableOf);
115 svg.transition().duration(750).call(this.zoom.transform, d3.zoomIdentity);
116 this.updateZoomState(0, 0, 1.0);
Sean Condon91481822019-01-01 13:56:14 +0000117 this.log.debug('Pan to 0,0 and zoom to 1.0');
118 }
119
Sean Condon0c577f62018-11-18 22:40:05 +0000120}