blob: 863d18ff7f0bc1f455664d8a1a29dcf047465a40 [file] [log] [blame]
Priyanka H Mfa5b77a2018-07-27 12:43:44 +05301/*
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 */
16import {Injectable} from '@angular/core';
17import {FnService} from '../util/fn.service';
Sean Condon5ca00262018-09-06 17:55:25 +010018import {LogService} from '../log.service';
Priyanka H Mfa5b77a2018-07-27 12:43:44 +053019import {ThemeService} from '../util/theme.service';
20import {WebSocketService} from '../remote/websocket.service';
21import * as d3 from 'd3';
22
23let fs;
24
25const defaultSettings = {
26 edge: 'right',
27 width: 200,
28 margin: 20,
29 hideMargin: 20,
30 xtnTime: 750,
31 fade: true,
32};
33
34let panels,
35 panelLayer;
36
37function init() {
38 panelLayer = d3.select('div#floatpanels');
39 panelLayer.text('');
40 panels = {};
41}
42
43// helpers for panel
44function noop() {
45}
46
47function margin(p: any) {
48 return p.settings.margin;
49}
50
51function hideMargin(p: any) {
52 return p.settings.hideMargin;
53}
54
55function noPx(p: any, what: any) {
56 return Number(p.el.style(what).replace(/px$/, ''));
57}
58
59function widthVal(p: any) {
60 return noPx(p, 'width');
61}
62
63function heightVal(p: any) {
64 return noPx(p, 'height');
65}
66
67function pxShow(p: any) {
68 return margin(p) + 'px';
69}
70
71function pxHide(p: any) {
72 return (-hideMargin(p) - widthVal(p) - (noPx(p, 'padding') * 2)) + 'px';
73}
74
75function makePanel(id: any, settings: any) {
76 const p = {
77 id: id,
78 settings: settings,
79 on: false,
80 el: null,
81 },
82 api = {
83 show: showPanel,
84 hide: hidePanel,
85 toggle: togglePanel,
86 empty: emptyPanel,
87 append: appendPanel,
88 width: panelWidth,
89 height: panelHeight,
90 bbox: panelBBox,
91 isVisible: panelIsVisible,
92 classed: classed,
93 el: panelEl,
94 };
95
96 p.el = panelLayer.append('div')
97 .attr('id', id)
98 .attr('class', 'floatpanel')
99 .style('opacity', 0);
100
101 // has to be called after el is set
102 p.el.style(p.settings.edge, pxHide(p));
103 panelWidth(p.settings.width);
104 if (p.settings.height) {
105 panelHeight(p.settings.height);
106 }
107
108 panels[id] = p;
109
110 function showPanel(cb: any) {
111 const endCb = fs.isF(cb) || noop;
112 p.on = true;
113 p.el.transition().duration(p.settings.xtnTime)
114 .style(p.settings.edge, pxShow(p))
115 .style('opacity', 1);
116 }
117
118 function hidePanel(cb: any) {
119 const endCb = fs.isF(cb) || noop,
120 endOpacity = p.settings.fade ? 0 : 1;
121 p.on = false;
122 p.el.transition().duration(p.settings.xtnTime)
123 .style(p.settings.edge, pxHide(p))
124 .style('opacity', endOpacity);
125 }
126
127 function togglePanel(cb: any) {
128 if (p.on) {
129 hidePanel(cb);
130 } else {
131 showPanel(cb);
132 }
133 return p.on;
134 }
135
136 function emptyPanel() {
137 return p.el.text('');
138 }
139
140 function appendPanel(what: any) {
141 return p.el.append(what);
142 }
143
144 function panelWidth(w: any) {
145 if (w === undefined) {
146 return widthVal(p);
147 }
148 p.el.style('width', w + 'px');
149 }
150
151 function panelHeight(h: any) {
152 if (h === undefined) {
153 return heightVal(p);
154 }
155 p.el.style('height', h + 'px');
156 }
157
158 function panelBBox() {
159 return p.el.node().getBoundingClientRect();
160 }
161
162 function panelIsVisible() {
163 return p.on;
164 }
165
166 function classed(cls: any, bool: any) {
167 return p.el.classed(cls, bool);
168 }
169
170 function panelEl() {
171 return p.el;
172 }
173
174 return api;
175}
176
177function removePanel(id: any) {
178 panelLayer.select('#' + id).remove();
179 delete panels[id];
180}
181
182@Injectable({
183 providedIn: 'root',
184})
Priyanka H Mfa5b77a2018-07-27 12:43:44 +0530185export class PanelService {
186 constructor(private funcs: FnService,
187 private log: LogService,
188 private ts: ThemeService,
189 private wss: WebSocketService) {
190 fs = this.funcs;
191 init();
192 }
193
194 createPanel(id: any, opts: any) {
Sean Condon98b6ddb2019-12-24 08:07:40 +0000195 const settings = (<any>Object).assign({}, defaultSettings, opts);
Priyanka H Mfa5b77a2018-07-27 12:43:44 +0530196 if (!id) {
197 this.log.warn('createPanel: no ID given');
198 return null;
199 }
200 if (panels[id]) {
201 this.log.warn('Panel with ID "' + id + '" already exists');
202 return null;
203 }
204 if (fs.debugOn('widget')) {
205 this.log.debug('creating panel:', id, settings);
206 }
207 return makePanel(id, settings);
208 }
209
210 destroyPanel(id: any) {
211 if (panels[id]) {
212 if (fs.debugOn('widget')) {
213 this.log.debug('destroying panel:', id);
214 }
215 removePanel(id);
216 } else {
217 if (fs.debugOn('widget')) {
218 this.log.debug('no panel to destroy:', id);
219 }
220 }
221 }
222}