@vcmap/ui 5.0.0-rc.16 → 5.0.0-rc.18
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/build/buildHelpers.js +7 -1
- package/config/base.config.json +3 -45
- package/config/www.config.json +756 -132
- package/dist/assets/{cesium.430460.js → cesium.2f992f.js} +0 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.5089ba.js → core.cb0408.js} +1700 -1718
- package/dist/assets/core.js +1 -1
- package/dist/assets/{index.854f8e2b.js → index.bccdf969.js} +1 -1
- package/dist/assets/{ol.9be53a.js → ol.5e3fd0.js} +0 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui.08c48f.css +1 -0
- package/dist/assets/{ui.49010a.js → ui.08c48f.js} +6254 -5906
- package/dist/assets/ui.js +1 -1
- package/dist/assets/{vue.247c1c.js → vue.228ead.js} +0 -0
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.735e58.css → vuetify.0b5039.css} +0 -0
- package/dist/assets/{vuetify.735e58.js → vuetify.0b5039.js} +5 -2
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +14 -3
- package/package.json +2 -2
- package/plugins/@vcmap/pluginExample/index.js +2 -1
- package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +7 -0
- package/plugins/buttonExamples/ButtonExamples.vue +18 -0
- package/plugins/categoryTest/Categories.vue +27 -13
- package/plugins/categoryTest/Category.vue +7 -1
- package/plugins/categoryTest/index.js +1 -1
- package/plugins/package.json +1 -1
- package/plugins/test/allIconsComponent.vue +3 -3
- package/plugins/test/index.js +9 -5
- package/plugins/test/testList.vue +4 -1
- package/plugins/test/toolbox-data.js +168 -111
- package/plugins/test/vcsContent.vue +1 -1
- package/plugins/test/windowManagerExample.vue +9 -7
- package/src/actions/actionHelper.js +13 -10
- package/src/application/VcsApp.vue +25 -26
- package/src/application/VcsNavbar.vue +1 -1
- package/src/components/buttons/VcsButton.vue +14 -3
- package/src/components/form-inputs-controls/VcsCheckbox.vue +1 -0
- package/src/components/form-inputs-controls/VcsFormSection.vue +14 -6
- package/src/components/lists/VcsActionList.vue +2 -0
- package/src/components/lists/VcsList.vue +4 -2
- package/src/contentTree/contentTreeCollection.js +9 -0
- package/src/contentTree/layerContentTreeItem.js +3 -3
- package/src/featureInfo/BalloonComponent.vue +5 -2
- package/src/featureInfo/balloonFeatureInfoView.js +2 -8
- package/src/featureInfo/balloonHelper.js +22 -5
- package/src/featureInfo/featureInfo.js +1 -2
- package/src/i18n/de.js +12 -3
- package/src/i18n/en.js +10 -1
- package/src/legend/legendHelper.js +6 -7
- package/src/legend/vcsLegend.vue +12 -3
- package/src/manager/categoryManager/CategoryComponent.vue +115 -0
- package/src/manager/categoryManager/CategoryComponentList.vue +57 -0
- package/src/manager/categoryManager/CategoryManager.vue +35 -0
- package/src/manager/categoryManager/categoryManager.js +251 -165
- package/src/manager/contextMenu/contextMenuManager.js +8 -2
- package/src/manager/toolbox/ToolboxManager.vue +1 -0
- package/src/manager/window/WindowComponent.vue +49 -75
- package/src/manager/window/WindowComponentHeader.vue +49 -7
- package/src/manager/window/WindowManager.vue +53 -30
- package/src/manager/window/windowHelper.js +341 -0
- package/src/manager/window/windowManager.js +162 -150
- package/src/notifier/notifier.js +4 -5
- package/src/vcsUiApp.js +7 -1
- package/dist/assets/ui.49010a.css +0 -1
- package/src/manager/categoryManager/ComponentsManager.vue +0 -30
@@ -8,10 +8,10 @@ import { vcsAppSymbol } from '../../pluginHelper.js';
|
|
8
8
|
/**
|
9
9
|
* @readonly
|
10
10
|
* @enum {string}
|
11
|
-
* @property {string} STATIC
|
12
|
-
* @property {string} DYNAMIC_LEFT
|
13
|
-
* @property {string} DYNAMIC_RIGHT
|
14
|
-
* @property {string} DETACHED
|
11
|
+
* @property {string} STATIC - Static windows cannot be moved and will be positioned top-left.
|
12
|
+
* @property {string} DYNAMIC_LEFT - Positioned top-left, if no static window is present. Can be moved by user interaction.
|
13
|
+
* @property {string} DYNAMIC_RIGHT - Positioned top-right. Can be moved by user interaction.
|
14
|
+
* @property {string} DETACHED - Positioned at initial provided position. Can be moved by user interaction.
|
15
15
|
*/
|
16
16
|
export const WindowSlot = {
|
17
17
|
STATIC: 'static',
|
@@ -22,38 +22,47 @@ export const WindowSlot = {
|
|
22
22
|
|
23
23
|
|
24
24
|
/**
|
25
|
-
* @typedef WindowPositionOptions
|
25
|
+
* @typedef {Object} WindowPositionOptions
|
26
26
|
* @property {string|number|undefined} left Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
27
27
|
* @property {string|number|undefined} top Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
28
28
|
* @property {string|number|undefined} right Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
29
29
|
* @property {string|number|undefined} bottom Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
30
|
-
* @property {string|number|undefined} width Can be a css position string (e.g. '320px') number values are treated as `px` values
|
31
|
-
* @property {string|number|undefined} height Can be
|
30
|
+
* @property {string|number|undefined} width Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
31
|
+
* @property {string|number|undefined} height Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
32
|
+
* @property {string|number|undefined} maxHeight Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
33
|
+
* @property {string|number|undefined} maxWidth Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
34
|
+
* @property {string|number|undefined} minHeight Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
35
|
+
* @property {string|number|undefined} minWidth Can be a css position string (e.g. '320px' or '50%') number values are treated as `px` values
|
32
36
|
*/
|
33
37
|
|
34
38
|
/**
|
35
|
-
* @typedef WindowPosition
|
36
|
-
* @property {string} left -
|
37
|
-
* @property {string} top -
|
38
|
-
* @property {string} right -
|
39
|
-
* @property {string} bottom -
|
40
|
-
* @property {string} width
|
41
|
-
* @property {string} height
|
39
|
+
* @typedef {Object} WindowPosition
|
40
|
+
* @property {string} left - The left CSS property participates in specifying the horizontal position of a window.
|
41
|
+
* @property {string} top - The top CSS property participates in specifying the vertical position of a window.
|
42
|
+
* @property {string} right - The right CSS property participates in specifying the horizontal position of a window.
|
43
|
+
* @property {string} bottom - The bottom CSS property participates in specifying the vertical position of a window.
|
44
|
+
* @property {string} width - The width CSS property sets an element's width.
|
45
|
+
* @property {string} height - The height CSS property sets an element's height.
|
46
|
+
* @property {string} [maxHeight] - It prevents the used value of the height property from becoming larger than the value specified for max-height. (max is target height, will be automatically updated)
|
47
|
+
* @property {string} [maxWidth] - It prevents the used value of the width property from becoming larger than the value specified by max-width. (max is target width, will be automatically updated)
|
48
|
+
* @property {string} [minHeight] - It prevents the used value of the height property from becoming smaller than the value specified for min-height.
|
49
|
+
* @property {string} [minWidth] - It prevents the used value of the width property from becoming smaller than the value specified for min-width.
|
42
50
|
*/
|
43
51
|
|
44
52
|
/**
|
45
53
|
* @readonly
|
46
|
-
* @enum {
|
47
|
-
* @property {
|
48
|
-
* @property {
|
49
|
-
* @property {
|
50
|
-
* @property {
|
54
|
+
* @enum {WindowPosition}
|
55
|
+
* @property {WindowPosition} TOP_LEFT position of the DYNAMIC_LEFT or STATIC Slot
|
56
|
+
* @property {WindowPosition} TOP_LEFT2 position of the DYNAMIC_LEFT Slot if a STATIC is present
|
57
|
+
* @property {WindowPosition} TOP_RIGHT position of the DYNAMIC_RIGHT Slot
|
58
|
+
* @property {WindowPosition} DETACHED default position of DETACHED Windows if no position is given
|
51
59
|
* @private
|
52
60
|
*/
|
53
61
|
export const WindowPositions = {
|
54
62
|
TOP_LEFT: {
|
55
63
|
left: '0px',
|
56
64
|
top: '0px',
|
65
|
+
maxWidth: '320px',
|
57
66
|
},
|
58
67
|
TOP_LEFT2: {
|
59
68
|
left: '320px',
|
@@ -62,6 +71,7 @@ export const WindowPositions = {
|
|
62
71
|
TOP_RIGHT: {
|
63
72
|
right: '0px',
|
64
73
|
top: '0px',
|
74
|
+
maxHeight: '70%',
|
65
75
|
},
|
66
76
|
DETACHED: {
|
67
77
|
left: '200px',
|
@@ -69,13 +79,33 @@ export const WindowPositions = {
|
|
69
79
|
},
|
70
80
|
};
|
71
81
|
|
82
|
+
/**
|
83
|
+
* Return true, if all values of pos1 match with the corresponding values of pos2
|
84
|
+
* @param {WindowPosition} pos1
|
85
|
+
* @param {WindowPosition} pos2
|
86
|
+
* @returns {boolean}
|
87
|
+
*/
|
88
|
+
export function compareWindowPositions(pos1, pos2) {
|
89
|
+
return !(Object.keys(pos1).some(key => pos1[key] !== pos2[key]));
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Returns true, if the provided position is a slot position
|
94
|
+
* @param {WindowPosition} windowPosition
|
95
|
+
* @returns {boolean}
|
96
|
+
*/
|
97
|
+
export function isSlotPosition(windowPosition) {
|
98
|
+
return [WindowPositions.TOP_LEFT, WindowPositions.TOP_LEFT2, WindowPositions.TOP_RIGHT]
|
99
|
+
.some(s => compareWindowPositions(s, windowPosition));
|
100
|
+
}
|
101
|
+
|
72
102
|
/**
|
73
103
|
* @typedef WindowComponentOptions
|
74
104
|
* @property {string} [id] Optional ID, If not provided an uuid will be generated.
|
75
105
|
* @property {import("vue").Component} component Main Component which is shown below the header.
|
76
106
|
* @property {import("vue").Component} [headerComponent] Replaces the Header Component.
|
77
|
-
* @property {WindowPositionOptions} [position] Will be ignored if WindowSlot !== DETACHED, can be given otherwise or default will be used
|
78
107
|
* @property {WindowState} [state]
|
108
|
+
* @property {WindowPositionOptions} [position] Will be ignored if WindowSlot !== DETACHED, can be given otherwise or default will be used
|
79
109
|
* @property {WindowSlot} [slot] If WindowSlot is not detached the position will be ignored
|
80
110
|
* @property {Object} [props]
|
81
111
|
* @property {Object} [provides]
|
@@ -86,11 +116,14 @@ export const WindowPositions = {
|
|
86
116
|
* @property {string} id
|
87
117
|
* @property {string|vcsAppSymbol} owner Owner of the window, set by windowManager on add
|
88
118
|
* @property {boolean} [hideHeader] be used to not show the header.
|
119
|
+
* @property {boolean} [hidePin] be used to not show the pin button.
|
89
120
|
* @property {string} [headerTitle]
|
90
121
|
* @property {string} [headerIcon]
|
91
122
|
* @property {Array<VcsAction>} [headerActions]
|
92
123
|
* @property {number} [headerActionsOverflowCount]
|
93
|
-
* @property {
|
124
|
+
* @property {string} [infoUrl] An optional url referencing help or further information on the window's content.
|
125
|
+
* @property {boolean} [dockable] Auto derived from hidePin, current slot, current position and initial position.
|
126
|
+
* @property {Object<string, string>} [styles] Can be used to add additional styles to the root WindowComponent. Use Vue Style Bindings Object Syntax https://vuejs.org/v2/guide/class-and-style.html
|
94
127
|
* @property {Array<string>|Object<string,string>} [classes] Can be used to add additional classes to the root WindowComponent. Use Vue Class Bindings Syntax https://vuejs.org/v2/guide/class-and-style.html
|
95
128
|
*/
|
96
129
|
|
@@ -99,9 +132,11 @@ export const WindowPositions = {
|
|
99
132
|
* @property {string} id
|
100
133
|
* @property {import("vue").Component} component
|
101
134
|
* @property {import("vue").Component} [headerComponent]
|
102
|
-
* @property {WindowPosition} position
|
103
135
|
* @property {WindowState} state
|
104
|
-
* @property {
|
136
|
+
* @property {WindowPosition} position
|
137
|
+
* @property {WindowPositionOptions} initialPositionOptions
|
138
|
+
* @property {import("vue").Ref<WindowSlot>} slot
|
139
|
+
* @property {WindowSlot} initialSlot
|
105
140
|
* @property {Object} props
|
106
141
|
* @property {Object} provides
|
107
142
|
*/
|
@@ -110,7 +145,7 @@ export const WindowPositions = {
|
|
110
145
|
* @param {string|number|undefined} pos
|
111
146
|
* @returns {string|undefined}
|
112
147
|
*/
|
113
|
-
function
|
148
|
+
export function posToPixel(pos) {
|
114
149
|
if (typeof pos === 'number') {
|
115
150
|
return `${pos}px`;
|
116
151
|
}
|
@@ -118,17 +153,18 @@ function parsePosition(pos) {
|
|
118
153
|
}
|
119
154
|
|
120
155
|
/**
|
156
|
+
* Returns CSS position string properties
|
121
157
|
* @param {WindowPositionOptions} windowPositionOptions
|
122
158
|
* @param {WindowPosition=} windowPosition
|
123
159
|
* @returns {WindowPosition}
|
124
160
|
*/
|
125
161
|
export function windowPositionFromOptions(windowPositionOptions, windowPosition = {}) {
|
126
|
-
let left =
|
127
|
-
const right =
|
128
|
-
let top =
|
129
|
-
const bottom =
|
130
|
-
let width =
|
131
|
-
let height =
|
162
|
+
let left = posToPixel(windowPositionOptions.left) || 'unset';
|
163
|
+
const right = posToPixel(windowPositionOptions.right) || 'unset';
|
164
|
+
let top = posToPixel(windowPositionOptions.top) || 'unset';
|
165
|
+
const bottom = posToPixel(windowPositionOptions.bottom) || 'unset';
|
166
|
+
let width = posToPixel(windowPositionOptions.width) || 'auto';
|
167
|
+
let height = posToPixel(windowPositionOptions.height) || 'auto';
|
132
168
|
if (left !== 'unset' && right !== 'unset') {
|
133
169
|
width = 'auto'; // left + right takes precedence over configured width
|
134
170
|
} else if (width === 'auto') {
|
@@ -151,127 +187,37 @@ export function windowPositionFromOptions(windowPositionOptions, windowPosition
|
|
151
187
|
width,
|
152
188
|
height,
|
153
189
|
};
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
/**
|
158
|
-
* @enum {number}
|
159
|
-
* @property {number} TOP_LEFT
|
160
|
-
* @property {number} TOP_RIGHT
|
161
|
-
* @property {number} BOTTOM_LEFT
|
162
|
-
* @property {number} BOTTOM_RIGHT
|
163
|
-
*/
|
164
|
-
export const WindowAlignment = {
|
165
|
-
TOP_LEFT: 1,
|
166
|
-
TOP_RIGHT: 2,
|
167
|
-
BOTTOM_LEFT: 3,
|
168
|
-
BOTTOM_RIGHT: 4,
|
169
|
-
};
|
170
|
-
|
171
|
-
/**
|
172
|
-
* @returns {HTMLElement|null}
|
173
|
-
*/
|
174
|
-
function getActiveMapElement() {
|
175
|
-
const mapElements = document.getElementsByClassName('mapElement');
|
176
|
-
for (let i = 0; i < mapElements.length; i++) {
|
177
|
-
const element = mapElements.item(i);
|
178
|
-
if (element.style.display !== 'none') {
|
179
|
-
return element;
|
180
|
-
}
|
190
|
+
if (windowPositionOptions.maxWidth) {
|
191
|
+
result.maxWidth = posToPixel(windowPositionOptions.maxWidth);
|
181
192
|
}
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
/**
|
186
|
-
* WindowPositionOptions from client position relative to a HTMLElement
|
187
|
-
* @param {number} x - client pixel position
|
188
|
-
* @param {number} y - client pixel position
|
189
|
-
* @param {HTMLElement} [element='mapElement'] - the element. if none is provided, the currently active mapElement will be taken
|
190
|
-
* @param {WindowAlignment} [alignment=WindowAlignment.TOP_LEFT]
|
191
|
-
* @returns {WindowPositionOptions}
|
192
|
-
*/
|
193
|
-
export function getWindowPositionOptions(x, y, element, alignment = WindowAlignment.TOP_LEFT) {
|
194
|
-
const mapElement = element ?? getActiveMapElement();
|
195
|
-
if (!mapElement) {
|
196
|
-
return { left: x, top: y };
|
193
|
+
if (windowPositionOptions.maxHeight) {
|
194
|
+
result.maxHeight = posToPixel(windowPositionOptions.maxHeight);
|
197
195
|
}
|
198
|
-
|
199
|
-
|
200
|
-
if (alignment === WindowAlignment.TOP_LEFT) {
|
201
|
-
return { left: x - left, top: y - top };
|
202
|
-
} else if (alignment === WindowAlignment.TOP_RIGHT) {
|
203
|
-
return { right: (left + width) - x, top: y - top };
|
204
|
-
} else if (alignment === WindowAlignment.BOTTOM_LEFT) {
|
205
|
-
return { left: x - left, bottom: (height + top) - y };
|
196
|
+
if (windowPositionOptions.minHeight) {
|
197
|
+
result.minHeight = posToPixel(windowPositionOptions.minHeight);
|
206
198
|
}
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
/**
|
211
|
-
* Get window position options based on a pixel in the map
|
212
|
-
* @param {import("@vcmap/cesium").Cartesian2} windowPosition - the window position, as retrieved from an InteractionEvent
|
213
|
-
* @param {WindowAlignment} [alignment]
|
214
|
-
* @returns {WindowPositionOptions}
|
215
|
-
*/
|
216
|
-
export function getWindowPositionOptionsFromMapEvent(windowPosition, alignment) {
|
217
|
-
const mapElement = getActiveMapElement();
|
218
|
-
if (!mapElement) {
|
219
|
-
return { left: windowPosition.x, top: windowPosition.y };
|
199
|
+
if (windowPositionOptions.minWidth) {
|
200
|
+
result.minWidth = posToPixel(windowPositionOptions.minWidth);
|
220
201
|
}
|
221
202
|
|
222
|
-
|
223
|
-
return getWindowPositionOptions(windowPosition.x + left, windowPosition.y + top, mapElement, alignment);
|
224
|
-
}
|
225
|
-
|
226
|
-
|
227
|
-
/**
|
228
|
-
* Fits a window aligned top left so it fits into the parent. this will change the alignment to be bottom or right depending
|
229
|
-
* on if the window would not fit into the parent.
|
230
|
-
* @param {number} x - client pixel position
|
231
|
-
* @param {number} y - client pixel position
|
232
|
-
* @param {number} width - window width to fit
|
233
|
-
* @param {number} height - window height to fit
|
234
|
-
* @param {HTMLElement} [element='mapElement'] - the element. if none is provided, the currently active mapElement will be taken
|
235
|
-
* @returns {WindowPositionOptions}
|
236
|
-
*/
|
237
|
-
export function getFittedWindowPositionOptions(x, y, width, height, element) {
|
238
|
-
const mapElement = element ?? getActiveMapElement();
|
239
|
-
if (!mapElement) {
|
240
|
-
return { left: x, top: y };
|
241
|
-
}
|
242
|
-
|
243
|
-
const { width: parentWidth, height: parentHeight } = mapElement.getBoundingClientRect();
|
244
|
-
const bottom = y + height > parentHeight;
|
245
|
-
const right = x + width > parentWidth;
|
246
|
-
let alignment = WindowAlignment.TOP_LEFT;
|
247
|
-
if (bottom) {
|
248
|
-
if (right) {
|
249
|
-
alignment = WindowAlignment.BOTTOM_RIGHT;
|
250
|
-
} else {
|
251
|
-
alignment = WindowAlignment.BOTTOM_LEFT;
|
252
|
-
}
|
253
|
-
} else if (right) {
|
254
|
-
alignment = WindowAlignment.TOP_RIGHT;
|
255
|
-
}
|
256
|
-
return getWindowPositionOptions(x, y, mapElement, alignment);
|
203
|
+
return Object.assign(windowPosition, result);
|
257
204
|
}
|
258
205
|
|
259
206
|
/**
|
260
|
-
*
|
261
|
-
*
|
262
|
-
* @param {
|
263
|
-
* @param {number} width
|
264
|
-
* @param {number} height
|
265
|
-
* @returns {WindowPositionOptions}
|
207
|
+
* Sets a position on a component. Updates dockable state.
|
208
|
+
* @param {WindowComponent} windowComponent
|
209
|
+
* @param {WindowComponentOptions} windowPositionOptions
|
266
210
|
*/
|
267
|
-
|
268
|
-
const
|
269
|
-
|
270
|
-
|
211
|
+
function setWindowPosition(windowComponent, windowPositionOptions) {
|
212
|
+
const windowPosition = windowPositionFromOptions(windowPositionOptions, windowComponent.position);
|
213
|
+
// not one of the default Positions, so we also have to DETACH the windowState.
|
214
|
+
if (!isSlotPosition(windowPosition)) {
|
215
|
+
windowComponent.slot.value = WindowSlot.DETACHED;
|
271
216
|
}
|
272
|
-
|
273
|
-
const
|
274
|
-
|
217
|
+
// check dockable state
|
218
|
+
const initialWindowPosition = windowPositionFromOptions(windowComponent.initialPositionOptions);
|
219
|
+
windowComponent.state.dockable = windowComponent.slot.value === WindowSlot.DETACHED &&
|
220
|
+
!compareWindowPositions(windowPosition, initialWindowPosition);
|
275
221
|
}
|
276
222
|
|
277
223
|
/**
|
@@ -300,6 +246,11 @@ class WindowManager {
|
|
300
246
|
* @private
|
301
247
|
*/
|
302
248
|
this._windowComponents = new Map();
|
249
|
+
/**
|
250
|
+
* @type {Map<string, WindowPosition>}
|
251
|
+
* @private
|
252
|
+
*/
|
253
|
+
this._windowPositionsCache = new Map();
|
303
254
|
}
|
304
255
|
|
305
256
|
/**
|
@@ -327,6 +278,7 @@ class WindowManager {
|
|
327
278
|
check(id, String);
|
328
279
|
const windowComponent = this._windowComponents.get(id);
|
329
280
|
if (windowComponent) {
|
281
|
+
this._cachePosition(windowComponent);
|
330
282
|
const index = this.componentIds.indexOf(id);
|
331
283
|
this.componentIds.splice(index, 1);
|
332
284
|
this._windowComponents.delete(id);
|
@@ -342,14 +294,7 @@ class WindowManager {
|
|
342
294
|
setWindowPositionOptions(id, windowPositionOptions) {
|
343
295
|
const windowComponent = this._windowComponents.get(id);
|
344
296
|
if (windowComponent) {
|
345
|
-
|
346
|
-
windowPositionOptions === WindowPositions.TOP_LEFT2 ||
|
347
|
-
windowPositionOptions === WindowPositions.TOP_RIGHT;
|
348
|
-
// not one of the default Positions, so we also have to DETACH the windowState.
|
349
|
-
if (!isSlotPosition) {
|
350
|
-
windowComponent.slot.value = WindowSlot.DETACHED;
|
351
|
-
}
|
352
|
-
windowPositionFromOptions(windowPositionOptions, windowComponent.position);
|
297
|
+
setWindowPosition(windowComponent, windowPositionOptions);
|
353
298
|
}
|
354
299
|
}
|
355
300
|
|
@@ -418,6 +363,42 @@ class WindowManager {
|
|
418
363
|
}
|
419
364
|
}
|
420
365
|
|
366
|
+
/**
|
367
|
+
* @param {string} id
|
368
|
+
* @returns {WindowPosition|undefined}
|
369
|
+
*/
|
370
|
+
getCachedPosition(id) {
|
371
|
+
return this._windowPositionsCache.get(id);
|
372
|
+
}
|
373
|
+
|
374
|
+
/**
|
375
|
+
* Caches the position, if it differs from the initial position
|
376
|
+
* @param {WindowComponent} windowComponent
|
377
|
+
* @private
|
378
|
+
*/
|
379
|
+
_cachePosition(windowComponent) {
|
380
|
+
const initialWindowPosition = windowPositionFromOptions(windowComponent.initialPositionOptions);
|
381
|
+
if (!compareWindowPositions(initialWindowPosition, windowComponent.position)) {
|
382
|
+
this._windowPositionsCache.set(windowComponent.id, { ...windowComponent.position });
|
383
|
+
}
|
384
|
+
}
|
385
|
+
|
386
|
+
/**
|
387
|
+
* Returns true, if cached position was assigned.
|
388
|
+
* @param {WindowComponent} windowComponent
|
389
|
+
* @returns {boolean}
|
390
|
+
* @private
|
391
|
+
*/
|
392
|
+
_assignCachedPosition(windowComponent) {
|
393
|
+
if (this._windowPositionsCache.has(windowComponent.id)) {
|
394
|
+
const windowPosition = this.getCachedPosition(windowComponent.id);
|
395
|
+
setWindowPosition(windowComponent, windowPosition);
|
396
|
+
this._windowPositionsCache.delete(windowComponent.id);
|
397
|
+
return true;
|
398
|
+
}
|
399
|
+
return false;
|
400
|
+
}
|
401
|
+
|
421
402
|
/**
|
422
403
|
* adds a windowComponent to the WindowManager and renders the Window at the provided position/slot.
|
423
404
|
* The reactive WindowState Object can be used to watch Changes on position/WindowSlot.
|
@@ -452,10 +433,13 @@ class WindowManager {
|
|
452
433
|
id,
|
453
434
|
owner,
|
454
435
|
hideHeader: !!windowComponentOptions?.state?.hideHeader,
|
436
|
+
hidePin: !!windowComponentOptions?.state?.hidePin,
|
455
437
|
headerTitle: windowComponentOptions?.state?.headerTitle,
|
456
438
|
headerIcon: windowComponentOptions?.state?.headerIcon,
|
457
439
|
headerActions: windowComponentOptions?.state?.headerActions,
|
458
440
|
headerActionsOverflow: windowComponentOptions?.state?.headerActionsOverflow,
|
441
|
+
dockable: false,
|
442
|
+
infoUrl: windowComponentOptions?.state?.infoUrl,
|
459
443
|
classes,
|
460
444
|
styles,
|
461
445
|
});
|
@@ -464,6 +448,7 @@ class WindowManager {
|
|
464
448
|
const provides = windowComponentOptions.provides || {};
|
465
449
|
|
466
450
|
const position = reactive(windowPosition);
|
451
|
+
const initialPosition = { ...windowPositionOptions };
|
467
452
|
/**
|
468
453
|
* @type {WindowComponent}
|
469
454
|
*/
|
@@ -483,9 +468,15 @@ class WindowManager {
|
|
483
468
|
get slot() {
|
484
469
|
return slotRef;
|
485
470
|
},
|
471
|
+
get initialSlot() {
|
472
|
+
return slot;
|
473
|
+
},
|
486
474
|
get position() {
|
487
475
|
return position;
|
488
476
|
},
|
477
|
+
get initialPositionOptions() {
|
478
|
+
return initialPosition;
|
479
|
+
},
|
489
480
|
get props() {
|
490
481
|
return props;
|
491
482
|
},
|
@@ -493,7 +484,10 @@ class WindowManager {
|
|
493
484
|
return provides;
|
494
485
|
},
|
495
486
|
};
|
496
|
-
this.
|
487
|
+
const cached = this._assignCachedPosition(windowComponent);
|
488
|
+
if (!cached) {
|
489
|
+
this._removeWindowAtSlot(slot);
|
490
|
+
}
|
497
491
|
this._windowComponents.set(id, windowComponent);
|
498
492
|
this.componentIds.push(id);
|
499
493
|
this._handleSlotsChanged(slot);
|
@@ -515,6 +509,24 @@ class WindowManager {
|
|
515
509
|
}
|
516
510
|
}
|
517
511
|
|
512
|
+
/**
|
513
|
+
* Docks a window by resetting detached to its initial slot.
|
514
|
+
* Updates position according to its initial slot or initial position.
|
515
|
+
* Clears any cached position for this window.
|
516
|
+
* @param {string} id
|
517
|
+
*/
|
518
|
+
pinWindow(id) {
|
519
|
+
const component = this.get(id);
|
520
|
+
if (!component?.state?.dockable) {
|
521
|
+
return;
|
522
|
+
}
|
523
|
+
this._removeWindowAtSlot(component.initialSlot);
|
524
|
+
component.slot.value = component.initialSlot;
|
525
|
+
const dockedPosition = this._getPositionOptionsForSlot(component.initialSlot, component.initialPositionOptions);
|
526
|
+
this.setWindowPositionOptions(id, dockedPosition);
|
527
|
+
this._windowPositionsCache.delete(id);
|
528
|
+
}
|
529
|
+
|
518
530
|
/**
|
519
531
|
* removes all windowComponents of a specific owner (plugin) and fires removed Events
|
520
532
|
* @param {string|vcsAppSymbol} owner
|
package/src/notifier/notifier.js
CHANGED
@@ -95,7 +95,8 @@ class Notifier {
|
|
95
95
|
*/
|
96
96
|
add(notification) {
|
97
97
|
const note = createNotification(notification, this);
|
98
|
-
|
98
|
+
// use spread since push won't trigger updates
|
99
|
+
this._notifications.value = [...this._notifications.value, note];
|
99
100
|
return note;
|
100
101
|
}
|
101
102
|
|
@@ -103,10 +104,8 @@ class Notifier {
|
|
103
104
|
* @param {Notification} notification
|
104
105
|
*/
|
105
106
|
remove(notification) {
|
106
|
-
|
107
|
-
|
108
|
-
this._notifications.value.splice(index, 1);
|
109
|
-
}
|
107
|
+
// reassign to trigger update
|
108
|
+
this._notifications.value = this._notifications.value.filter(n => n !== notification);
|
110
109
|
}
|
111
110
|
|
112
111
|
/**
|
package/src/vcsUiApp.js
CHANGED
@@ -8,7 +8,7 @@ import {
|
|
8
8
|
defaultDynamicContextId,
|
9
9
|
ObliqueMap,
|
10
10
|
Viewpoint,
|
11
|
-
volatileContextId,
|
11
|
+
volatileContextId, VcsEvent,
|
12
12
|
} from '@vcmap/core';
|
13
13
|
import { getLogger as getLoggerByName } from '@vcsuite/logger';
|
14
14
|
import {
|
@@ -235,6 +235,12 @@ class VcsUiApp extends VcsApp {
|
|
235
235
|
* @private
|
236
236
|
*/
|
237
237
|
this._cachedAppState = getStateFromURL(new URL(window.location.href));
|
238
|
+
/**
|
239
|
+
* An event triggered when the VcsApp was mounted and a target was set for the maps.
|
240
|
+
* Provides the id of the target html element.
|
241
|
+
* @type {import("@vcmap/core").VcsEvent<string>}
|
242
|
+
*/
|
243
|
+
this.mounted = new VcsEvent();
|
238
244
|
}
|
239
245
|
|
240
246
|
/**
|