First part of migrating Topo2 to GUI2
Change-Id: I316dd34cba161688e01dfb7b340bff5f2c3c57d4
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/zoom.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/zoom.service.ts
new file mode 100644
index 0000000..fdf08f9
--- /dev/null
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/zoom.service.ts
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable } from '@angular/core';
+import * as d3 from 'd3';
+import { LogService } from '../log.service';
+
+export interface ZoomOpts {
+ svg: any; // D3 selection of <svg> element
+ zoomLayer: any; // D3 selection of <g> element
+ zoomMin: number; // Min zoom level - usually 0.25
+ zoomMax: number; // Max zoom level - usually 10
+ zoomEnabled(ev: any): boolean; // Function that takes event and returns boolean
+ zoomCallback(translate: number[], scale: number): void; // Function that is called on zoom
+}
+
+export interface Zoomer {
+ panZoom(translate: number[], scale: number, transition?: number): void;
+ reset(): void;
+ translate(): number[];
+ scale(): number;
+ scaleExtent(): number[];
+}
+
+export const CZ: string = 'ZoomService.createZoomer(): ';
+export const D3S: string = ' (D3 selection) property defined';
+
+/**
+ * ONOS GUI -- Topology Zoom Service Module.
+ */
+@Injectable({
+ providedIn: 'root',
+})
+export class ZoomService {
+ defaultSettings: ZoomOpts;
+
+ zoom: any;
+ public zoomer: Zoomer;
+ settings: ZoomOpts;
+
+ constructor(
+ protected log: LogService,
+ ) {
+ this.defaultSettings = <ZoomOpts>{
+ zoomMin: 0.05,
+ zoomMax: 50,
+ zoomEnabled: (ev) => true,
+ zoomCallback: (t, s) => { return; }
+ };
+
+ this.log.debug('ZoomService constructed');
+ }
+
+ createZoomer(opts: ZoomOpts): Zoomer {
+ this.settings = Object.assign(this.defaultSettings, opts);
+
+ if (!this.settings.svg) {
+ this.log.error(CZ + 'No "svg" (svg tag)' + D3S);
+ throw new Error(CZ + 'No "svg" (svg tag)' + D3S);
+ }
+ if (!this.settings.zoomLayer) {
+ this.log.error(CZ + 'No "zoomLayer" (g tag)' + D3S);
+ throw new Error(CZ + 'No "zoomLayer" (g tag)' + D3S);
+ }
+
+ this.zoom = d3.zoom()
+ .scaleExtent([this.settings.zoomMin, this.settings.zoomMax])
+ .extent([[0, 0], [1000, 1000]])
+ .on('zoom', () => this.zoomed);
+
+
+ this.zoomer = <Zoomer>{
+ panZoom: (translate: number[], scale: number, transition?: number) => {
+ this.settings.svg.call(this.zoom.translateBy, translate[0], translate[1]);
+ this.settings.svg.call(this.zoom.scaleTo, scale);
+ this.adjustZoomLayer(translate, scale, transition);
+ },
+
+ reset: () => {
+ this.settings.svg.call(this.zoom.translateTo, 500, 500);
+ this.settings.svg.call(this.zoom.scaleTo, 1);
+ this.adjustZoomLayer([0, 0], 1, 0);
+ },
+
+ translate: () => {
+ const trans = d3.zoomTransform(this.settings.svg.node());
+ return [trans.x, trans.y];
+ },
+
+ scale: () => {
+ const trans = d3.zoomTransform(this.settings.svg.node());
+ return trans.k;
+ },
+
+ scaleExtent: () => {
+ return this.zoom.scaleExtent();
+ },
+ };
+
+ // apply the zoom behavior to the SVG element
+/*
+ if (this.settings.svg ) {
+ this.settings.svg.call(this.zoom);
+ }
+*/
+ // Remove zoom on double click (prevents a
+ // false zoom navigating regions)
+ this.settings.svg.on('dblclick.zoom', null);
+
+ return this.zoomer;
+ }
+
+ /**
+ * zoom events from mouse gestures...
+ */
+ zoomed() {
+ const ev = d3.event.sourceEvent;
+ if (this.settings.zoomEnabled(ev)) {
+ this.adjustZoomLayer(d3.event.translate, d3.event.scale);
+ }
+ }
+
+ /**
+ * Adjust the zoom layer
+ */
+ adjustZoomLayer(translate: number[], scale: number, transition?: any): void {
+
+ this.settings.zoomLayer.transition()
+ .duration(transition || 0)
+ .attr('transform',
+ 'translate(' + translate + ') scale(' + scale + ')');
+
+ this.settings.zoomCallback(translate, scale);
+ }
+
+}