@flexem/fc-gui 3.0.0-alpha.15 → 3.0.0-alpha.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +429 -1
- package/assets/img/black_first_page.png +0 -0
- package/assets/img/black_last_page.png +0 -0
- package/assets/img/black_next_page.png +0 -0
- package/assets/img/black_previous_page.png +0 -0
- package/bundles/@flexem/fc-gui.umd.js +24059 -19951
- package/bundles/@flexem/fc-gui.umd.js.map +1 -1
- package/bundles/@flexem/fc-gui.umd.min.js +5 -5
- package/bundles/@flexem/fc-gui.umd.min.js.map +1 -1
- package/communication/variable/variable-communicator.d.ts +4 -0
- package/communication/variable/variable-value.d.ts +4 -1
- package/communication/variable/variable-value.js +4 -1
- package/communication/variable/variable-value.metadata.json +1 -1
- package/config/alarm/alarm.store.d.ts +6 -0
- package/config/alarm/alarm.store.js +0 -0
- package/config/alarm/alarm.store.metadata.json +1 -0
- package/config/alarm/get-alarms-args.d.ts +12 -0
- package/config/alarm/get-alarms-args.js +13 -0
- package/config/alarm/get-alarms-args.metadata.json +1 -0
- package/config/alarm/index.d.ts +2 -0
- package/config/alarm/index.js +1 -0
- package/config/alarm/index.metadata.json +1 -0
- package/config/config-store.d.ts +2 -0
- package/config/index.d.ts +1 -0
- package/config/index.js +1 -0
- package/config/index.metadata.json +1 -1
- package/elements/air-quality/air-quality-element.d.ts +31 -0
- package/elements/air-quality/air-quality-element.js +194 -0
- package/elements/air-quality/air-quality-element.metadata.json +1 -0
- package/elements/alarm/alarm-element.d.ts +69 -0
- package/elements/alarm/alarm-element.js +497 -0
- package/elements/alarm/alarm-element.metadata.json +1 -0
- package/elements/bar-graph-element.d.ts +10 -2
- package/elements/bar-graph-element.js +135 -5
- package/elements/bar-graph-element.metadata.json +1 -1
- package/elements/base/readable-element.d.ts +6 -1
- package/elements/base/readable-element.js +65 -2
- package/elements/base/readable-element.metadata.json +1 -1
- package/elements/base/state-control-element.d.ts +3 -1
- package/elements/base/state-control-element.js +3 -0
- package/elements/datetime-display/datetime-display-element.d.ts +1 -0
- package/elements/datetime-display/datetime-display-element.js +10 -2
- package/elements/datetime-display/datetime-display-element.metadata.json +1 -1
- package/elements/datetime-display/time-zone-select-json.d.ts +8 -0
- package/elements/datetime-display/time-zone-select-json.js +558 -0
- package/elements/historical-curve/historical-curve.element.d.ts +33 -3
- package/elements/historical-curve/historical-curve.element.js +368 -26
- package/elements/historical-curve/historical-curve.element.metadata.json +1 -1
- package/elements/main-element.d.ts +1 -0
- package/elements/main-element.js +59 -9
- package/elements/main-element.metadata.json +1 -1
- package/elements/meter-element.d.ts +7 -1
- package/elements/meter-element.js +76 -7
- package/elements/meter-element.metadata.json +1 -1
- package/elements/numerical-display/numerical-display-element.d.ts +16 -3
- package/elements/numerical-display/numerical-display-element.js +83 -11
- package/elements/numerical-display/numerical-display-element.metadata.json +1 -1
- package/elements/per-view-variable-communicator.d.ts +3 -0
- package/elements/per-view-variable-communicator.js +15 -1
- package/elements/per-view-variable-communicator.metadata.json +1 -1
- package/elements/ring-graph/ring-graph-element.d.ts +13 -1
- package/elements/ring-graph/ring-graph-element.js +164 -3
- package/elements/ring-graph/ring-graph-element.metadata.json +1 -1
- package/elements/scroll-alarm/scroll-alarm-element.d.ts +74 -0
- package/elements/scroll-alarm/scroll-alarm-element.js +761 -0
- package/elements/scroll-alarm/scroll-alarm-element.metadata.json +1 -0
- package/elements/shared/graph/graph-state-element.d.ts +1 -0
- package/elements/shared/graph/graph-state-element.js +30 -4
- package/elements/shared/graph/graph-state-element.metadata.json +1 -1
- package/elements/shared/text/text-element.d.ts +9 -0
- package/elements/shared/text/text-element.js +34 -3
- package/elements/shared/text/text-element.metadata.json +1 -1
- package/elements/shared/text/text-state-element.d.ts +28 -2
- package/elements/shared/text/text-state-element.js +188 -65
- package/elements/shared/text/text-state-element.metadata.json +1 -1
- package/elements/static-elements/hyperlink-element.d.ts +24 -2
- package/elements/static-elements/hyperlink-element.js +124 -3
- package/elements/static-elements/hyperlink-element.metadata.json +1 -1
- package/elements/static-elements/text-element.d.ts +24 -2
- package/elements/static-elements/text-element.js +120 -3
- package/elements/static-elements/text-element.metadata.json +1 -1
- package/elements/switch-indicator-light/bit-indicator-light-operator.d.ts +1 -0
- package/elements/switch-indicator-light/bit-indicator-light-operator.js +5 -2
- package/elements/switch-indicator-light/bit-indicator-light-operator.metadata.json +1 -1
- package/elements/switch-indicator-light/switch-indicator-light-element.d.ts +11 -2
- package/elements/switch-indicator-light/switch-indicator-light-element.js +55 -11
- package/elements/switch-indicator-light/switch-indicator-light-element.metadata.json +1 -1
- package/elements/switch-indicator-light/word-indicator-light-operator.d.ts +1 -0
- package/elements/switch-indicator-light/word-indicator-light-operator.js +5 -2
- package/elements/switch-indicator-light/word-indicator-light-operator.metadata.json +1 -1
- package/elements/video/video-element.d.ts +10 -0
- package/elements/video/video-element.js +119 -21
- package/elements/video/video-element.metadata.json +1 -1
- package/elements/view-operation/view-operation.element.d.ts +24 -2
- package/elements/view-operation/view-operation.element.js +128 -4
- package/elements/view-operation/view-operation.element.metadata.json +1 -1
- package/elements/weather/weater-element.js +0 -1
- package/gui/gui-context.d.ts +12 -2
- package/gui/gui-host.d.ts +1 -1
- package/gui/gui-view.d.ts +4 -1
- package/gui/gui-view.js +51 -7
- package/gui/gui-view.metadata.json +1 -1
- package/gui/gui.component.d.ts +3 -0
- package/gui/gui.component.js +15 -2
- package/gui/gui.component.metadata.json +1 -1
- package/localization/localization.service.d.ts +7 -0
- package/localization/localization.service.js +10 -3
- package/localization/localization.service.metadata.json +1 -1
- package/localization/localization.service.zh_CN.js +8 -1
- package/localization/localization.service.zh_CN.metadata.json +1 -1
- package/modal/write-value/write-value-modal-args.d.ts +5 -1
- package/modal/write-value/write-value-modal-args.js +3 -1
- package/modal/write-value/write-value-modal-args.metadata.json +1 -1
- package/modal/write-value/write-value-modal.component.d.ts +13 -7
- package/modal/write-value/write-value-modal.component.html +10 -5
- package/modal/write-value/write-value-modal.component.js +87 -15
- package/modal/write-value/write-value-modal.component.metadata.json +1 -1
- package/model/air-quality/air-quality-info.d.ts +23 -0
- package/model/air-quality/air-quality-info.js +4 -0
- package/model/air-quality/air-quality-info.metadata.json +1 -0
- package/model/air-quality/air-quality.model.d.ts +7 -0
- package/model/air-quality/air-quality.model.js +0 -0
- package/model/air-quality/air-quality.model.metadata.json +1 -0
- package/model/alarm/alarm.model.d.ts +13 -0
- package/model/alarm/alarm.model.js +0 -0
- package/model/alarm/alarm.model.metadata.json +1 -0
- package/model/bar-graph/bar-graph.d.ts +4 -0
- package/model/base/font-setting-model.d.ts +12 -1
- package/model/base/font-setting-model.metadata.json +1 -1
- package/model/base/readable-model.d.ts +4 -0
- package/model/datetime-display/datetime-display.d.ts +1 -0
- package/model/historical-curve/historical-curve-axis-settings.d.ts +11 -0
- package/model/historical-curve/historical-curve-axis-settings.js +5 -0
- package/model/historical-curve/historical-curve-axis-settings.metadata.json +1 -1
- package/model/historical-curve/historical-curve-chanel.model.d.ts +8 -0
- package/model/meter/meter.d.ts +4 -0
- package/model/ring-graph/ring-graph.model.d.ts +8 -0
- package/model/scroll-alarm/scroll-alarm.model.d.ts +21 -0
- package/model/scroll-alarm/scroll-alarm.model.js +0 -0
- package/model/scroll-alarm/scroll-alarm.model.metadata.json +1 -0
- package/model/shared/text/text.d.ts +3 -0
- package/model/switch-indicator-light/switch-indicator-light.d.ts +2 -0
- package/model/view-operation/view-operation-element.model.d.ts +7 -1
- package/package.json +1 -1
- package/public_api.js +1 -0
- package/remote/communication/variable/remote-variable-communicator.d.ts +27 -0
- package/remote/communication/variable/remote-variable-communicator.js +148 -3
- package/remote/communication/variable/remote-variable-communicator.metadata.json +1 -1
- package/remote/communication/variable/remote-variable-protocol.d.ts +5 -0
- package/service/index.d.ts +4 -0
- package/service/index.js +1 -0
- package/service/index.metadata.json +1 -1
- package/service/language.service.d.ts +37 -0
- package/service/language.service.js +0 -0
- package/service/language.service.metadata.json +1 -0
- package/service/released-variable/index.d.ts +1 -0
- package/service/released-variable/index.js +0 -0
- package/service/released-variable/index.metadata.json +1 -0
- package/service/released-variable/released-variable.service.d.ts +4 -0
- package/service/released-variable/released-variable.service.js +0 -0
- package/service/released-variable/released-variable.service.metadata.json +1 -0
- package/service/system-text-library.service.d.ts +76 -0
- package/service/system-text-library.service.js +28 -0
- package/service/system-text-library.service.metadata.json +1 -0
- package/service/text-library.service.d.ts +49 -0
- package/service/text-library.service.js +0 -0
- package/service/text-library.service.metadata.json +1 -0
- package/service/weather.service.d.ts +1 -0
- package/shared/gui-consts.d.ts +3 -0
- package/shared/gui-consts.js +3 -0
- package/shared/gui-consts.metadata.json +1 -1
- package/utils/data-type/fbox-data-type.service.js +40 -0
|
@@ -16,6 +16,12 @@ export declare class VideoElement extends ConditionalDisplayElement {
|
|
|
16
16
|
private videoId;
|
|
17
17
|
private isShow;
|
|
18
18
|
private videoPlayer;
|
|
19
|
+
private refreshTimer;
|
|
20
|
+
private isFullscreen;
|
|
21
|
+
private videoUrl;
|
|
22
|
+
private visibilityChangeHandler;
|
|
23
|
+
private timeUpdateWatchdog;
|
|
24
|
+
private lastTimeUpdate;
|
|
19
25
|
constructor(element: HTMLElement, injector: Injector, permissionChecker: PermissionChecker, variableCommunicator: VariableCommunicator, variableStore: VariableStore, videoService: VideoService, guiSize: Size, svgRootClass: string, signalRAppId: string);
|
|
20
26
|
dispose(): void;
|
|
21
27
|
hide(): void;
|
|
@@ -24,4 +30,8 @@ export declare class VideoElement extends ConditionalDisplayElement {
|
|
|
24
30
|
private initVideo;
|
|
25
31
|
private addVideoAddressToolTip;
|
|
26
32
|
private setAndroidVideo;
|
|
33
|
+
private initVisibilityHandler;
|
|
34
|
+
private startTimeUpdateWatchdog;
|
|
35
|
+
private clearTimeUpdateWatchdog;
|
|
36
|
+
private setIosVideo;
|
|
27
37
|
}
|
|
@@ -11,8 +11,11 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
11
11
|
this.guiSize = guiSize;
|
|
12
12
|
this.svgRootClass = svgRootClass;
|
|
13
13
|
this.videoId = '';
|
|
14
|
+
this.isFullscreen = false;
|
|
15
|
+
this.lastTimeUpdate = 0;
|
|
14
16
|
this.isMobileMode = DisplayMode.Mobile === injector.get(GlobalSettings).displayMode;
|
|
15
17
|
this.localization = injector.get(LOCALIZATION);
|
|
18
|
+
this.initVisibilityHandler();
|
|
16
19
|
this.init();
|
|
17
20
|
}
|
|
18
21
|
dispose() {
|
|
@@ -22,6 +25,10 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
22
25
|
$('div.' + this.svgRootClass + ' video').each(function () {
|
|
23
26
|
$(this).remove();
|
|
24
27
|
});
|
|
28
|
+
if (this.visibilityChangeHandler) {
|
|
29
|
+
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
30
|
+
}
|
|
31
|
+
this.clearTimeUpdateWatchdog();
|
|
25
32
|
}
|
|
26
33
|
hide() {
|
|
27
34
|
super.hide();
|
|
@@ -50,12 +57,13 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
50
57
|
.attr('width', this.model.size.width)
|
|
51
58
|
.attr('height', this.model.size.height);
|
|
52
59
|
this.videoService.getVideoUrl(this.model.videoTag).then(result => {
|
|
53
|
-
this.
|
|
60
|
+
this.videoUrl = result.url;
|
|
61
|
+
this.initVideo(result.url, this.videoId);
|
|
54
62
|
}).catch(() => {
|
|
55
63
|
throw new Error('Failure of the videoService');
|
|
56
64
|
});
|
|
57
65
|
}
|
|
58
|
-
initVideo(videoUrl,
|
|
66
|
+
initVideo(videoUrl, videoId) {
|
|
59
67
|
const patt = /https:.+.m3u8/;
|
|
60
68
|
if (videoUrl.indexOf('http:') !== -1) {
|
|
61
69
|
videoUrl = videoUrl.replace('http:', 'https:');
|
|
@@ -68,6 +76,8 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
68
76
|
this.addVideoAddressToolTip(videoToolTip);
|
|
69
77
|
return;
|
|
70
78
|
}
|
|
79
|
+
const isAndroid = !!navigator.userAgent.match(/(Android)/i);
|
|
80
|
+
const isIos = !!navigator.userAgent.match(/(Mac)/i);
|
|
71
81
|
const currentRect = this.$element.find('rect#rect' + videoId).first();
|
|
72
82
|
if (!currentRect.length) {
|
|
73
83
|
return;
|
|
@@ -77,17 +87,19 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
77
87
|
const chartHeight = clientRect.height;
|
|
78
88
|
const left = this.model.location.x / this.guiSize.width * $('.' + this.svgRootClass).find('.svg-content').width();
|
|
79
89
|
const top = this.model.location.y / this.guiSize.height * $('.' + this.svgRootClass).find('.svg-content').height();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
const scareX = this.model.location.x / this.guiSize.width;
|
|
91
|
+
const scareY = this.model.location.y / this.guiSize.height;
|
|
92
|
+
if (isIos) {
|
|
93
|
+
videoUrl = videoUrl + '#t=1';
|
|
94
|
+
}
|
|
95
|
+
const preload = isIos ? ' preload=\'metadata\'' : '';
|
|
96
|
+
let videoHtml = `<video scareX="${scareX}"
|
|
97
|
+
scareY="${scareY}" id="${videoId}" ${preload} src="${videoUrl}" width="${chartWidth}" height="${chartHeight}"
|
|
98
|
+
style="position: absolute;top:${top}px;left:${left}px;object-fit:fill;z-index:0;"
|
|
99
|
+
playsInline webkit-playsinline `;
|
|
85
100
|
if (this.isMobileMode) {
|
|
86
101
|
if (isAndroid) {
|
|
87
|
-
|
|
88
|
-
videoHtml += ' controls ';
|
|
89
|
-
}
|
|
90
|
-
videoHtml += ' autoplay muted></video>';
|
|
102
|
+
videoHtml += ' muted></video>';
|
|
91
103
|
}
|
|
92
104
|
else {
|
|
93
105
|
videoHtml += ' controls muted></video>';
|
|
@@ -100,10 +112,32 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
100
112
|
if (this.isShow === false) {
|
|
101
113
|
$('#' + this.videoId).hide();
|
|
102
114
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
setTimeout(() => {
|
|
116
|
+
if (isAndroid) {
|
|
117
|
+
this.setAndroidVideo(videoId);
|
|
118
|
+
}
|
|
119
|
+
else if (isIos) {
|
|
120
|
+
this.setIosVideo(this.videoUrl, videoId);
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
this.videoPlayer = new EZUIPlayer(videoId);
|
|
124
|
+
if (isAndroid) {
|
|
125
|
+
// 确保在 EZUIPlayer 初始化后才调用 play 方法
|
|
126
|
+
this.videoPlayer.on('canplay', () => {
|
|
127
|
+
this.videoPlayer.play();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
this.startTimeUpdateWatchdog(videoId);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
console.log(err);
|
|
134
|
+
}
|
|
135
|
+
}, 1000);
|
|
136
|
+
const style = document.createElement('style');
|
|
137
|
+
style.innerHTML = `#${videoId}::-webkit-media-controls-enclosure {
|
|
138
|
+
display: none;
|
|
139
|
+
}`;
|
|
140
|
+
document.head.append();
|
|
107
141
|
}
|
|
108
142
|
addVideoAddressToolTip(videoToolTip) {
|
|
109
143
|
const size = this.model.size;
|
|
@@ -126,35 +160,99 @@ export class VideoElement extends ConditionalDisplayElement {
|
|
|
126
160
|
this.$element.append(textElement.Element);
|
|
127
161
|
}
|
|
128
162
|
setAndroidVideo(videoId) {
|
|
129
|
-
let isFullscreen = false;
|
|
130
163
|
const videoElement = $('#' + videoId);
|
|
131
164
|
let preHeight = videoElement.height();
|
|
132
165
|
let preWidth = videoElement.width();
|
|
133
166
|
let preTop = videoElement.css('top');
|
|
134
167
|
let preLeft = videoElement.css('left');
|
|
168
|
+
const { StatusBar } = window;
|
|
135
169
|
videoElement.on('click', () => {
|
|
136
|
-
if (!isFullscreen) {
|
|
170
|
+
if (!this.isFullscreen) {
|
|
171
|
+
if (StatusBar) {
|
|
172
|
+
StatusBar.hide();
|
|
173
|
+
}
|
|
137
174
|
preHeight = videoElement.height();
|
|
138
175
|
preWidth = videoElement.width();
|
|
139
176
|
preTop = videoElement.css('top');
|
|
140
177
|
preLeft = videoElement.css('left');
|
|
141
|
-
const width = document.
|
|
142
|
-
const height =
|
|
178
|
+
const width = document.documentElement.clientWidth;
|
|
179
|
+
const height = document.documentElement.clientHeight;
|
|
180
|
+
videoElement.css('object-fit', 'contain');
|
|
181
|
+
videoElement.css('background', '#000000');
|
|
143
182
|
videoElement.css('width', width + 'px');
|
|
144
183
|
videoElement.css('height', height + 'px');
|
|
145
184
|
videoElement.css('left', '0px');
|
|
146
185
|
videoElement.css('top', '0px');
|
|
147
186
|
videoElement.css('z-index', '99');
|
|
148
|
-
|
|
187
|
+
videoElement.css('position', 'fixed');
|
|
188
|
+
this.isFullscreen = true;
|
|
189
|
+
try {
|
|
190
|
+
screen.orientation.lock(screen.orientation.type);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
console.error(error);
|
|
194
|
+
}
|
|
149
195
|
}
|
|
150
196
|
else {
|
|
197
|
+
videoElement.css('object-fit', 'fill');
|
|
151
198
|
videoElement.css('width', preWidth + 'px');
|
|
152
199
|
videoElement.css('height', preHeight + 'px');
|
|
153
200
|
videoElement.css('left', preLeft);
|
|
154
201
|
videoElement.css('top', preTop);
|
|
155
202
|
videoElement.css('z-index', '0');
|
|
156
|
-
|
|
203
|
+
videoElement.css('position', 'absolute');
|
|
204
|
+
this.isFullscreen = false;
|
|
205
|
+
try {
|
|
206
|
+
if (screen.orientation.type.includes('portrait')) {
|
|
207
|
+
StatusBar.show();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error(error);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
initVisibilityHandler() {
|
|
217
|
+
this.visibilityChangeHandler = () => {
|
|
218
|
+
if (!document.hidden && this.videoUrl && this.videoId) {
|
|
219
|
+
this.initVideo(this.videoUrl, this.videoId);
|
|
157
220
|
}
|
|
221
|
+
};
|
|
222
|
+
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
223
|
+
}
|
|
224
|
+
startTimeUpdateWatchdog(videoId) {
|
|
225
|
+
this.clearTimeUpdateWatchdog();
|
|
226
|
+
this.lastTimeUpdate = Date.now();
|
|
227
|
+
const videoEl = document.getElementById(videoId);
|
|
228
|
+
if (videoEl && videoEl.tagName === 'VIDEO') {
|
|
229
|
+
videoEl.addEventListener('timeupdate', () => {
|
|
230
|
+
this.lastTimeUpdate = Date.now();
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
this.timeUpdateWatchdog = setInterval(() => {
|
|
234
|
+
if (document.hidden)
|
|
235
|
+
return;
|
|
236
|
+
if (Date.now() - this.lastTimeUpdate > 30000) {
|
|
237
|
+
this.initVideo(this.videoUrl, this.videoId);
|
|
238
|
+
}
|
|
239
|
+
}, 30000);
|
|
240
|
+
}
|
|
241
|
+
clearTimeUpdateWatchdog() {
|
|
242
|
+
if (this.timeUpdateWatchdog) {
|
|
243
|
+
clearInterval(this.timeUpdateWatchdog);
|
|
244
|
+
this.timeUpdateWatchdog = null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
setIosVideo(videoUrl, videoId) {
|
|
248
|
+
const video = $('#' + this.videoId);
|
|
249
|
+
video.on('webkitendfullscreen', () => {
|
|
250
|
+
video.remove();
|
|
251
|
+
clearTimeout(this.refreshTimer);
|
|
252
|
+
this.refreshTimer = null;
|
|
253
|
+
this.refreshTimer = setTimeout(() => {
|
|
254
|
+
this.initVideo(videoUrl, videoId);
|
|
255
|
+
}, 500);
|
|
158
256
|
});
|
|
159
257
|
}
|
|
160
258
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"VideoElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":15,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"VideoElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-display-element","name":"ConditionalDisplayElement","line":15,"character":34},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":30,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":31,"character":18},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":32,"character":27},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":33,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":34,"character":23},{"__symbolic":"reference","module":"../../service","name":"VideoService","line":35,"character":39},{"__symbolic":"reference","module":"../../model","name":"Size","line":36,"character":34},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"}]}],"dispose":[{"__symbolic":"method"}],"hide":[{"__symbolic":"method"}],"show":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"initVideo":[{"__symbolic":"method"}],"addVideoAddressToolTip":[{"__symbolic":"method"}],"setAndroidVideo":[{"__symbolic":"method"}],"initVisibilityHandler":[{"__symbolic":"method"}],"startTimeUpdateWatchdog":[{"__symbolic":"method"}],"clearTimeUpdateWatchdog":[{"__symbolic":"method"}],"setIosVideo":[{"__symbolic":"method"}]}}}}]
|
|
@@ -3,11 +3,12 @@ import { BsModalService } from 'ngx-bootstrap/modal';
|
|
|
3
3
|
import { Localization } from '../../localization';
|
|
4
4
|
import { GraphStore, VariableStore } from '../../config';
|
|
5
5
|
import { ViewOperationElementModel } from '../../model';
|
|
6
|
-
import { PermissionChecker, OperationRecordService } from '../../service';
|
|
6
|
+
import { PermissionChecker, OperationRecordService, TextLibraryService, LanguageService } from '../../service';
|
|
7
7
|
import { VariableCommunicator } from '../../communication';
|
|
8
8
|
import { ConditionalEnableElement } from '../base/conditional-enable-element';
|
|
9
9
|
import { PopupViewService } from '../../view/popup-view.service';
|
|
10
10
|
import { SecurityChecker } from '../../security';
|
|
11
|
+
import { GuiContext } from '../../gui/gui-context';
|
|
11
12
|
export declare class ViewOperationElement extends ConditionalEnableElement {
|
|
12
13
|
private readonly modalService;
|
|
13
14
|
private readonly graphStore;
|
|
@@ -16,13 +17,18 @@ export declare class ViewOperationElement extends ConditionalEnableElement {
|
|
|
16
17
|
private readonly popupViewService;
|
|
17
18
|
private readonly hostContainerId;
|
|
18
19
|
private readonly el;
|
|
20
|
+
private readonly textLibraryService?;
|
|
21
|
+
private readonly languageService?;
|
|
22
|
+
private readonly guiContext?;
|
|
19
23
|
protected model: ViewOperationElementModel;
|
|
20
24
|
private readonly logger;
|
|
21
25
|
private readonly viewService;
|
|
22
26
|
private graphStateElement?;
|
|
27
|
+
private textElementModal?;
|
|
28
|
+
private languageChangeSubscription?;
|
|
23
29
|
private touchedScreenX;
|
|
24
30
|
private touchedScreenY;
|
|
25
|
-
constructor(element: HTMLElement, injector: Injector, modalService: BsModalService, variableCommunicator: VariableCommunicator, variableStore: VariableStore, graphStore: GraphStore, permissionChecker: PermissionChecker, operationRecordService: OperationRecordService, securityChecker: SecurityChecker, localization: Localization, popupViewService: PopupViewService, hostContainerId: string, el: ElementRef, signalRAppId: string);
|
|
31
|
+
constructor(element: HTMLElement, injector: Injector, modalService: BsModalService, variableCommunicator: VariableCommunicator, variableStore: VariableStore, graphStore: GraphStore, permissionChecker: PermissionChecker, operationRecordService: OperationRecordService, securityChecker: SecurityChecker, localization: Localization, popupViewService: PopupViewService, hostContainerId: string, el: ElementRef, signalRAppId: string, textLibraryService?: TextLibraryService, languageService?: LanguageService, guiContext?: GuiContext);
|
|
26
32
|
private initElement;
|
|
27
33
|
private switchToState;
|
|
28
34
|
private initGraph;
|
|
@@ -33,4 +39,20 @@ export declare class ViewOperationElement extends ConditionalEnableElement {
|
|
|
33
39
|
private closeView;
|
|
34
40
|
private moveView;
|
|
35
41
|
private recordViewOperation;
|
|
42
|
+
/**
|
|
43
|
+
* 订阅语种变化事件
|
|
44
|
+
*/
|
|
45
|
+
private subscribeLanguageChange;
|
|
46
|
+
/**
|
|
47
|
+
* 更新文本内容(支持文本库和语种切换)
|
|
48
|
+
*/
|
|
49
|
+
private updateTextContent;
|
|
50
|
+
/**
|
|
51
|
+
* 获取显示文本
|
|
52
|
+
*/
|
|
53
|
+
private getDisplayText;
|
|
54
|
+
/**
|
|
55
|
+
* 释放资源
|
|
56
|
+
*/
|
|
57
|
+
dispose(): void;
|
|
36
58
|
}
|
|
@@ -2,6 +2,7 @@ import { LOGGER_SERVICE_TOKEN } from '../../logger';
|
|
|
2
2
|
import * as d3 from 'd3-selection';
|
|
3
3
|
import { drag } from 'd3-drag';
|
|
4
4
|
import { ViewOperationType } from '../../model';
|
|
5
|
+
import { TextElementModal } from '../shared/text/text-element';
|
|
5
6
|
import { ConditionalEnableElement } from '../base/conditional-enable-element';
|
|
6
7
|
import { GraphStateElement } from '../shared/graph/graph-state-element';
|
|
7
8
|
import { AlertModalComponent } from '../../modal/alert/alert-modal.component';
|
|
@@ -9,7 +10,7 @@ import { ConfirmOperationModalComponent } from '../../modal/confirm-operation/co
|
|
|
9
10
|
import { VerifyPasswordModalComponent } from '../../modal/verify-password/verify-password-modal.component';
|
|
10
11
|
import { ViewService } from '../../view/view.service';
|
|
11
12
|
export class ViewOperationElement extends ConditionalEnableElement {
|
|
12
|
-
constructor(element, injector, modalService, variableCommunicator, variableStore, graphStore, permissionChecker, operationRecordService, securityChecker, localization, popupViewService, hostContainerId, el, signalRAppId) {
|
|
13
|
+
constructor(element, injector, modalService, variableCommunicator, variableStore, graphStore, permissionChecker, operationRecordService, securityChecker, localization, popupViewService, hostContainerId, el, signalRAppId, textLibraryService, languageService, guiContext) {
|
|
13
14
|
super(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId);
|
|
14
15
|
this.modalService = modalService;
|
|
15
16
|
this.graphStore = graphStore;
|
|
@@ -18,20 +19,27 @@ export class ViewOperationElement extends ConditionalEnableElement {
|
|
|
18
19
|
this.popupViewService = popupViewService;
|
|
19
20
|
this.hostContainerId = hostContainerId;
|
|
20
21
|
this.el = el;
|
|
22
|
+
this.textLibraryService = textLibraryService;
|
|
23
|
+
this.languageService = languageService;
|
|
24
|
+
this.guiContext = guiContext;
|
|
21
25
|
this.touchedScreenX = 0;
|
|
22
26
|
this.touchedScreenY = 0;
|
|
23
27
|
this.logger = injector.get(LOGGER_SERVICE_TOKEN);
|
|
24
28
|
this.viewService = injector.get(ViewService);
|
|
25
29
|
this.initElement();
|
|
30
|
+
this.subscribeLanguageChange();
|
|
26
31
|
}
|
|
27
32
|
initElement() {
|
|
28
33
|
const width = this.model.size.width;
|
|
29
34
|
const height = this.model.size.height;
|
|
35
|
+
// 在 initGraph 之前移除模板原有的 SVG <text>(改用 foreignObject 渲染,支持换行居中)
|
|
36
|
+
// 必须在 initGraph 前执行,否则会误删图形状态内部后续添加的文字节点
|
|
37
|
+
this.$element.find('text').remove();
|
|
30
38
|
this.initGraph(width, height);
|
|
31
39
|
this.rootElement.append('rect').attr('id', 'StateFrame').attr('width', width).attr('height', height).attr('fill', 'transparent');
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
const font = Object.assign(Object.assign({}, this.model.label.font), { fontFamily: this.model.label.font.fontFamily || 'msyh' });
|
|
41
|
+
this.textElementModal = new TextElementModal(this.getDisplayText(), font, width, height);
|
|
42
|
+
this.$element.append(this.textElementModal.Element);
|
|
35
43
|
this.switchToState(0);
|
|
36
44
|
this.rootElement.on('mousedown', () => {
|
|
37
45
|
if (!this.isInitialized) {
|
|
@@ -170,6 +178,9 @@ export class ViewOperationElement extends ConditionalEnableElement {
|
|
|
170
178
|
const viewIndex = this.model.viewIndex;
|
|
171
179
|
if (null != viewIndex) {
|
|
172
180
|
this.popupViewService.popView(viewIndex, this.hostContainerId, this.el).subscribe(() => this.recordViewOperation(), error => this.logger.error(`ToggleView(${viewIndex}) failed. ${error}`));
|
|
181
|
+
$(`#${this.hostContainerId} video`)
|
|
182
|
+
.addClass('video-hidden')
|
|
183
|
+
.css('visibility', 'hidden');
|
|
173
184
|
}
|
|
174
185
|
else {
|
|
175
186
|
this.logger.error('[GUI]Toggle View:invalid view index');
|
|
@@ -177,6 +188,11 @@ export class ViewOperationElement extends ConditionalEnableElement {
|
|
|
177
188
|
}
|
|
178
189
|
closeView() {
|
|
179
190
|
this.popupViewService.closeView();
|
|
191
|
+
if ($(`#${this.hostContainerId} > svg > svg`).length === 0) {
|
|
192
|
+
$(`#${this.hostContainerId} .video-hidden`)
|
|
193
|
+
.removeClass('video-hidden')
|
|
194
|
+
.css('visibility', 'visible');
|
|
195
|
+
}
|
|
180
196
|
this.recordViewOperation();
|
|
181
197
|
}
|
|
182
198
|
moveView(movementX, movementY) {
|
|
@@ -191,4 +207,112 @@ export class ViewOperationElement extends ConditionalEnableElement {
|
|
|
191
207
|
this.operationRecordService.record({ operationDescription: this.model.operationDescription });
|
|
192
208
|
}
|
|
193
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* 订阅语种变化事件
|
|
212
|
+
*/
|
|
213
|
+
subscribeLanguageChange() {
|
|
214
|
+
if (this.guiContext && this.guiContext.languageChanged$) {
|
|
215
|
+
this.languageChangeSubscription = this.guiContext.languageChanged$.subscribe(() => {
|
|
216
|
+
this.updateTextContent();
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* 更新文本内容(支持文本库和语种切换)
|
|
222
|
+
*/
|
|
223
|
+
updateTextContent() {
|
|
224
|
+
if (this.textElementModal) {
|
|
225
|
+
this.textElementModal.updateText(this.getDisplayText());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 获取显示文本
|
|
230
|
+
*/
|
|
231
|
+
getDisplayText() {
|
|
232
|
+
var _a, _b, _c, _d, _e, _f;
|
|
233
|
+
// 检查是否使用文本库
|
|
234
|
+
if (this.model.textLibrary && this.model.textLibrary.labelType === 'textLibrary') {
|
|
235
|
+
const textLibraryId = this.model.textLibrary.selectedTextLibraryItem;
|
|
236
|
+
const textItem = this.model.textLibrary.selectedTextItem;
|
|
237
|
+
if (textLibraryId && textItem && this.textLibraryService) {
|
|
238
|
+
// 获取文本库数据
|
|
239
|
+
const textLibraryData = this.textLibraryService.getTextLibraryById(typeof textLibraryId === 'string' ? parseInt(textLibraryId, 10) : textLibraryId);
|
|
240
|
+
if (textLibraryData && textLibraryData.data) {
|
|
241
|
+
// 查找对应的文本条目
|
|
242
|
+
const textEntry = textLibraryData.data.find(entry => entry.key === textItem.toString());
|
|
243
|
+
if (textEntry) {
|
|
244
|
+
// 获取当前语种ID
|
|
245
|
+
const currentLanguageId = (_c = (_b = (_a = this.guiContext) === null || _a === void 0 ? void 0 : _a.getCurrentLanguageId) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : null;
|
|
246
|
+
// 确定要使用的语种代码(culture)
|
|
247
|
+
let targetLanguage;
|
|
248
|
+
const defaultLanguage = ((_d = this.languageService) === null || _d === void 0 ? void 0 : _d.getDefaultLanguage()) || 'zh-CN';
|
|
249
|
+
if (currentLanguageId === null || currentLanguageId === undefined) {
|
|
250
|
+
// 设备未设置当前语种,使用默认语种
|
|
251
|
+
targetLanguage = defaultLanguage;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// 设备已设置当前语种,获取对应的语种代码
|
|
255
|
+
const currentLanguage = (_f = (_e = this.guiContext) === null || _e === void 0 ? void 0 : _e.getLanguageCultureById) === null || _f === void 0 ? void 0 : _f.call(_e, currentLanguageId);
|
|
256
|
+
if (currentLanguage) {
|
|
257
|
+
targetLanguage = currentLanguage;
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// 无法获取语种代码,使用默认语种
|
|
261
|
+
targetLanguage = defaultLanguage;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// 返回对应语种的文本
|
|
265
|
+
if (textEntry.cultures && textEntry.cultures[targetLanguage]) {
|
|
266
|
+
return textEntry.cultures[targetLanguage];
|
|
267
|
+
}
|
|
268
|
+
// 如果没有对应语种,返回空字符串
|
|
269
|
+
return '';
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// 文本库配置但未找到数据,返回空字符串
|
|
274
|
+
return '';
|
|
275
|
+
}
|
|
276
|
+
// 处理自定义文本(支持多语种)
|
|
277
|
+
if (this.model.label) {
|
|
278
|
+
// 获取目标语种(公共逻辑)
|
|
279
|
+
const getTargetLanguage = () => {
|
|
280
|
+
var _a, _b, _c, _d, _e, _f;
|
|
281
|
+
const currentLanguageId = (_c = (_b = (_a = this.guiContext) === null || _a === void 0 ? void 0 : _a.getCurrentLanguageId) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : null;
|
|
282
|
+
const defaultLanguage = ((_d = this.languageService) === null || _d === void 0 ? void 0 : _d.getDefaultLanguage()) || 'zh-CN';
|
|
283
|
+
if (currentLanguageId === null || currentLanguageId === undefined) {
|
|
284
|
+
return defaultLanguage;
|
|
285
|
+
}
|
|
286
|
+
return ((_f = (_e = this.guiContext) === null || _e === void 0 ? void 0 : _e.getLanguageCultureById) === null || _f === void 0 ? void 0 : _f.call(_e, currentLanguageId)) || defaultLanguage;
|
|
287
|
+
};
|
|
288
|
+
// 新格式:cultures 在 label 顶层
|
|
289
|
+
if (this.model.label.cultures && typeof this.model.label.cultures === 'object') {
|
|
290
|
+
return this.model.label.cultures[getTargetLanguage()] || '';
|
|
291
|
+
}
|
|
292
|
+
if (this.model.label.content) {
|
|
293
|
+
// 中间格式(兼容):content 为 { cultures: {...} }
|
|
294
|
+
if (typeof this.model.label.content === 'object' && this.model.label.content.cultures) {
|
|
295
|
+
return this.model.label.content.cultures[getTargetLanguage()] || '';
|
|
296
|
+
}
|
|
297
|
+
// 旧格式:字符串
|
|
298
|
+
if (typeof this.model.label.content === 'string') {
|
|
299
|
+
return this.model.label.content;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return '';
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* 释放资源
|
|
307
|
+
*/
|
|
308
|
+
dispose() {
|
|
309
|
+
// 取消语种变化订阅
|
|
310
|
+
if (this.languageChangeSubscription) {
|
|
311
|
+
this.languageChangeSubscription.unsubscribe();
|
|
312
|
+
this.languageChangeSubscription = undefined;
|
|
313
|
+
}
|
|
314
|
+
if (this.$element) {
|
|
315
|
+
this.$element.remove();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
194
318
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"__symbolic":"module","version":4,"metadata":{"ViewOperationElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":
|
|
1
|
+
[{"__symbolic":"module","version":4,"metadata":{"ViewOperationElement":{"__symbolic":"class","extends":{"__symbolic":"reference","module":"../base/conditional-enable-element","name":"ConditionalEnableElement","line":23,"character":42},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":36,"character":25,"context":{"typeName":"HTMLElement"}},{"__symbolic":"reference","module":"@angular/core","name":"Injector","line":36,"character":48},{"__symbolic":"reference","module":"ngx-bootstrap/modal","name":"BsModalService","line":37,"character":39},{"__symbolic":"reference","module":"../../communication","name":"VariableCommunicator","line":38,"character":30},{"__symbolic":"reference","module":"../../config","name":"VariableStore","line":39,"character":23},{"__symbolic":"reference","module":"../../config","name":"GraphStore","line":40,"character":37},{"__symbolic":"reference","module":"../../service","name":"PermissionChecker","line":41,"character":27},{"__symbolic":"reference","module":"../../service","name":"OperationRecordService","line":42,"character":49},{"__symbolic":"reference","module":"../../security","name":"SecurityChecker","line":43,"character":42},{"__symbolic":"reference","module":"../../localization","name":"Localization","line":44,"character":22},{"__symbolic":"reference","module":"../../view/popup-view.service","name":"PopupViewService","line":45,"character":43},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"@angular/core","name":"ElementRef","line":47,"character":29},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","module":"../../service","name":"TextLibraryService","line":49,"character":46},{"__symbolic":"reference","module":"../../service","name":"LanguageService","line":50,"character":43},{"__symbolic":"reference","module":"../../gui/gui-context","name":"GuiContext","line":51,"character":38}]}],"initElement":[{"__symbolic":"method"}],"switchToState":[{"__symbolic":"method"}],"initGraph":[{"__symbolic":"method"}],"checkElementPassword":[{"__symbolic":"method"}],"executeViewOperation":[{"__symbolic":"method"}],"toggleView":[{"__symbolic":"method"}],"popView":[{"__symbolic":"method"}],"closeView":[{"__symbolic":"method"}],"moveView":[{"__symbolic":"method"}],"recordViewOperation":[{"__symbolic":"method"}],"subscribeLanguageChange":[{"__symbolic":"method"}],"updateTextContent":[{"__symbolic":"method"}],"getDisplayText":[{"__symbolic":"method"}],"dispose":[{"__symbolic":"method"}]}}}}]
|
|
@@ -45,7 +45,6 @@ export class WeatherElement extends ConditionalDisplayElement {
|
|
|
45
45
|
}
|
|
46
46
|
handleGettingAddress() {
|
|
47
47
|
this.handleUnusualCommon(this.localization.weatherNotAvailable);
|
|
48
|
-
setTimeout(() => this.initWeatherInfo(), 1000 * 60);
|
|
49
48
|
}
|
|
50
49
|
handleNoAddress() {
|
|
51
50
|
this.handleUnusualCommon(this.localization.weatherNotAddress);
|
package/gui/gui-context.d.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import { ConfigStore } from '../config';
|
|
2
2
|
import { VariableCommunicator } from '../communication';
|
|
3
3
|
import { SecurityChecker } from '../security';
|
|
4
|
-
import { VideoService, WeatherService, PermissionChecker, OperationRecordService } from '../service';
|
|
4
|
+
import { VideoService, WeatherService, PermissionChecker, OperationRecordService, ReleasedVariableService, TextLibraryService, LanguageService, SystemTextLibraryService } from '../service';
|
|
5
|
+
import { Subject } from 'rxjs';
|
|
5
6
|
export interface GuiContext {
|
|
6
7
|
readonly configStore: ConfigStore;
|
|
7
8
|
readonly variableCommunicator: VariableCommunicator;
|
|
8
9
|
readonly permissionChecker: PermissionChecker;
|
|
9
10
|
readonly operationRecordService: OperationRecordService;
|
|
11
|
+
readonly releasedVariableService: ReleasedVariableService;
|
|
10
12
|
readonly securityChecker: SecurityChecker;
|
|
11
13
|
readonly videoService: VideoService;
|
|
12
14
|
readonly weatherService: WeatherService;
|
|
15
|
+
readonly textLibraryService?: TextLibraryService;
|
|
16
|
+
readonly languageService?: LanguageService;
|
|
17
|
+
readonly systemTextLibraryService?: SystemTextLibraryService;
|
|
13
18
|
readonly configureViewId?: number;
|
|
14
19
|
readonly configureViewCode?: string;
|
|
15
|
-
|
|
20
|
+
readonly languageChanged$?: Subject<number | null>;
|
|
21
|
+
getCurrentLanguageId?(): number | null;
|
|
22
|
+
getDefaultLanguageId?(): number;
|
|
23
|
+
getLanguageCultureById?(languageId: number | null): string | null;
|
|
24
|
+
updateCurrentLanguageId?(languageId: number | null): Promise<void>;
|
|
25
|
+
dispose(): void;
|
|
16
26
|
}
|
package/gui/gui-host.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare class GuiHost implements Disposable {
|
|
|
13
13
|
readonly el: ElementRef;
|
|
14
14
|
private isLoaded;
|
|
15
15
|
private currentView;
|
|
16
|
-
|
|
16
|
+
currentViewIndex: number;
|
|
17
17
|
private containerEl;
|
|
18
18
|
private currentViewSize;
|
|
19
19
|
private currentViewReiszeMode;
|
package/gui/gui-view.d.ts
CHANGED
|
@@ -21,7 +21,10 @@ export declare class GuiView implements PopupViewService {
|
|
|
21
21
|
private mainElement;
|
|
22
22
|
private muskElement;
|
|
23
23
|
private openVariableStatesSubscription;
|
|
24
|
-
private
|
|
24
|
+
private requestVirtualDeviceState;
|
|
25
|
+
private virtualDeviceStatesChanged;
|
|
26
|
+
private openVariablesSubscriptions;
|
|
27
|
+
private openedVariableNamesForValues;
|
|
25
28
|
private openedVariableNames;
|
|
26
29
|
private perViewVariableCommunicator;
|
|
27
30
|
private svgRootClass;
|