qwc2 2025.11.18 → 2025.11.26

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.
Files changed (94) hide show
  1. package/actions/windows.js +3 -1
  2. package/components/AppMenu.js +141 -204
  3. package/components/AttributeTableWidget.js +5 -1
  4. package/components/FeatureAttributesWindow.js +1 -2
  5. package/components/FullscreenSwitcher.js +3 -0
  6. package/components/Icon.js +6 -0
  7. package/components/ImportLayer.js +3 -9
  8. package/components/LayerInfoWindow.js +1 -2
  9. package/components/MapButton.js +2 -0
  10. package/components/NumericInputWindow.js +1 -2
  11. package/components/PickFeature.js +1 -1
  12. package/components/PluginsContainer.js +48 -6
  13. package/components/ResizeableWindow.js +18 -9
  14. package/components/SearchBox.js +117 -124
  15. package/components/ServiceInfoWindow.js +1 -2
  16. package/components/ThemeLayersListWindow.js +22 -11
  17. package/components/ThemeList.js +7 -2
  18. package/components/WindowManager.js +14 -2
  19. package/components/map/layers/VectorLayer.js +4 -2
  20. package/components/map3d/HeightProfile3D.js +0 -1
  21. package/components/map3d/Map3D.js +36 -35
  22. package/components/map3d/View3DSwitcher.js +2 -1
  23. package/components/map3d/drawtool/NumericInput3D.js +1 -2
  24. package/components/map3d/layers/GeoTIFFLayer3D.js +2 -1
  25. package/components/map3d/layers/VectorLayer3D.js +12 -2
  26. package/components/map3d/layers/WFSLayer3D.js +17 -1
  27. package/components/style/App.css +4 -0
  28. package/components/style/AppMenu.css +33 -48
  29. package/components/style/DefaultColorScheme.css +1 -0
  30. package/components/style/PickFeature.css +0 -6
  31. package/components/style/ResizeableWindow.css +0 -4
  32. package/components/style/SearchBox.css +0 -21
  33. package/components/style/WindowManager.css +6 -0
  34. package/components/widgets/ColorButton.js +7 -2
  35. package/components/widgets/ComboBox.js +18 -16
  36. package/components/widgets/EditableSelect.js +5 -10
  37. package/components/widgets/LayerCatalogWidget.js +66 -16
  38. package/components/widgets/MenuButton.js +16 -15
  39. package/components/widgets/PopupMenu.js +153 -13
  40. package/components/widgets/ToggleSwitch.js +5 -2
  41. package/components/widgets/style/ComboBox.css +7 -20
  42. package/components/widgets/style/EditableSelect.css +0 -2
  43. package/components/widgets/style/MenuButton.css +1 -17
  44. package/components/widgets/style/PopupMenu.css +20 -0
  45. package/package.json +2 -2
  46. package/plugins/AttributeTable.js +0 -1
  47. package/plugins/BackgroundSwitcher.js +104 -8
  48. package/plugins/Cyclomedia.js +1 -2
  49. package/plugins/FeatureForm.js +3 -6
  50. package/plugins/GeometryDigitizer.js +1 -2
  51. package/plugins/HeightProfile.js +2 -5
  52. package/plugins/Identify.js +2 -5
  53. package/plugins/LayerCatalog.js +2 -13
  54. package/plugins/LayerTree.js +22 -13
  55. package/plugins/MapLegend.js +1 -2
  56. package/plugins/ObjectList.js +0 -1
  57. package/plugins/Panoramax.js +1 -2
  58. package/plugins/Print.js +1 -2
  59. package/plugins/Routing.js +1 -2
  60. package/plugins/TimeManager.js +2 -5
  61. package/plugins/ValueTool.js +1 -2
  62. package/plugins/View3D.js +0 -1
  63. package/plugins/map/MeasurementSupport.js +2 -2
  64. package/plugins/map3d/Identify3D.js +1 -2
  65. package/plugins/map3d/Measure3D.js +21 -12
  66. package/plugins/style/BackgroundSwitcher.css +2 -1
  67. package/plugins/style/LayerTree.css +3 -18
  68. package/reducers/windows.js +2 -1
  69. package/static/translations/bg-BG.json +1 -0
  70. package/static/translations/ca-ES.json +29 -28
  71. package/static/translations/cs-CZ.json +1 -0
  72. package/static/translations/de-CH.json +1 -0
  73. package/static/translations/de-DE.json +1 -0
  74. package/static/translations/en-US.json +1 -0
  75. package/static/translations/es-ES.json +34 -33
  76. package/static/translations/fi-FI.json +1 -0
  77. package/static/translations/fr-FR.json +2 -1
  78. package/static/translations/hu-HU.json +1 -0
  79. package/static/translations/it-IT.json +1 -0
  80. package/static/translations/ja-JP.json +1 -0
  81. package/static/translations/nl-NL.json +1 -0
  82. package/static/translations/no-NO.json +1 -0
  83. package/static/translations/pl-PL.json +1 -0
  84. package/static/translations/pt-BR.json +1 -0
  85. package/static/translations/pt-PT.json +1 -0
  86. package/static/translations/ro-RO.json +1 -0
  87. package/static/translations/ru-RU.json +1 -0
  88. package/static/translations/sv-SE.json +1 -0
  89. package/static/translations/tr-TR.json +1 -0
  90. package/static/translations/tsconfig.json +1 -0
  91. package/static/translations/uk-UA.json +1 -0
  92. package/utils/MapUtils.js +6 -0
  93. package/utils/MiscUtils.js +12 -0
  94. package/utils/ThemeUtils.js +2 -1
@@ -35,7 +35,7 @@ import PropTypes from 'prop-types';
35
35
  import { LayerRole, addLayer } from '../actions/layers';
36
36
  import { setCurrentTask } from '../actions/task';
37
37
  import { setThemeLayersList } from '../actions/theme';
38
- import { showNotification, closeWindow } from '../actions/windows';
38
+ import { showNotification, closeWindow, NotificationType } from '../actions/windows';
39
39
  import LayerUtils from '../utils/LayerUtils';
40
40
  import LocaleUtils from '../utils/LocaleUtils';
41
41
  import ThemeUtils from '../utils/ThemeUtils';
@@ -62,22 +62,33 @@ var ThemeLayersListWindow = /*#__PURE__*/function (_React$Component) {
62
62
  });
63
63
  _defineProperty(_this, "addLayers", function (sublayers) {
64
64
  _this.props.closeWindow("existinglayers");
65
- var existingLayer = _this.props.layers.find(function (l) {
66
- return l.type === 'wms' && l.url === _this.props.theme.url;
67
- });
68
- if (existingLayer) {
69
- var existingSublayers = [].concat(_toConsumableArray(LayerUtils.getSublayerNames(existingLayer)), [existingLayer.name]);
65
+ var existingSublayers = _this.props.layers.reduce(function (res, layer) {
66
+ if (layer.type === 'wms' && layer.url === _this.props.theme.url) {
67
+ return [].concat(_toConsumableArray(res), _toConsumableArray(LayerUtils.getSublayerNames(layer)), [layer.name]);
68
+ }
69
+ return res;
70
+ }, []);
71
+ if (!isEmpty(existingSublayers)) {
70
72
  var filteredSublayers = [];
71
73
  sublayers = sublayers.filter(function (sublayer) {
72
74
  if (existingSublayers.includes(sublayer.name)) {
73
- filteredSublayers.push(sublayer.title);
75
+ filteredSublayers.push(sublayer);
74
76
  return false;
75
77
  }
76
78
  return true;
77
79
  });
78
80
  if (!isEmpty(filteredSublayers)) {
79
- var text = LocaleUtils.tr("themelayerslist.existinglayers") + ": " + filteredSublayers.join(",");
80
- _this.props.showNotification("existinglayers", text);
81
+ var text = LocaleUtils.tr("themelayerslist.existinglayers") + ": " + filteredSublayers.map(function (l) {
82
+ return l.title;
83
+ }).join(", ");
84
+ var actions = [{
85
+ name: LocaleUtils.tr("themelayerslist.addanyway"),
86
+ onClick: function onClick() {
87
+ _this.props.addLayer(ThemeUtils.createThemeLayer(_this.props.theme, _this.props.themes, LayerRole.USERLAYER, filteredSublayers));
88
+ return true;
89
+ }
90
+ }];
91
+ _this.props.showNotification("existinglayers", text, NotificationType.INFO, false, actions);
81
92
  }
82
93
  }
83
94
  if (!isEmpty(sublayers)) {
@@ -108,6 +119,7 @@ var ThemeLayersListWindow = /*#__PURE__*/function (_React$Component) {
108
119
  }
109
120
  });
110
121
  _defineProperty(_this, "onClose", function () {
122
+ _this.props.closeWindow("existinglayers");
111
123
  _this.props.setThemeLayersList(null);
112
124
  });
113
125
  return _this;
@@ -180,8 +192,7 @@ var ThemeLayersListWindow = /*#__PURE__*/function (_React$Component) {
180
192
  onClose: this.onClose,
181
193
  title: LocaleUtils.tr("themelayerslist.addlayerstotheme")
182
194
  }, /*#__PURE__*/React.createElement("div", {
183
- className: "theme-list-window-body",
184
- role: "body"
195
+ className: "theme-list-window-body"
185
196
  }, /*#__PURE__*/React.createElement("h4", {
186
197
  className: "theme-list-window-title"
187
198
  }, this.props.theme.title), /*#__PURE__*/React.createElement("div", {
@@ -39,6 +39,7 @@ import { setCurrentTask } from '../actions/task';
39
39
  import { setCurrentTheme, setThemeLayersList } from '../actions/theme';
40
40
  import ConfigUtils from '../utils/ConfigUtils';
41
41
  import LocaleUtils from '../utils/LocaleUtils';
42
+ import MiscUtils from '../utils/MiscUtils';
42
43
  import ThemeUtils from '../utils/ThemeUtils';
43
44
  import Icon from './Icon';
44
45
  import './style/ThemeList.css';
@@ -96,7 +97,9 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
96
97
  expandedGroups: _objectSpread(_objectSpread({}, state.expandedGroups), {}, _defineProperty({}, subdir.id, !expanded))
97
98
  };
98
99
  });
99
- }
100
+ },
101
+ onKeyDown: MiscUtils.checkKeyActivate,
102
+ tabIndex: "0"
100
103
  }, _this.props.collapsibleGroups ? /*#__PURE__*/React.createElement(Icon, {
101
104
  icon: expanded ? "collapse" : "expand"
102
105
  }) : null, " ", subdir.titleMsgId ? LocaleUtils.tr(subdir.titleMsgId) : subdir.title), expanded ? _this.renderThemeGroup(subdir, filter) : null);
@@ -171,7 +174,9 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
171
174
  target: link.target
172
175
  }, link.title);
173
176
  })) : null) : null, /*#__PURE__*/React.createElement("div", {
174
- className: "theme-item-body"
177
+ className: "theme-item-body",
178
+ onKeyDown: MiscUtils.checkKeyActivate,
179
+ tabIndex: 0
175
180
  }, item.description ? /*#__PURE__*/React.createElement("div", {
176
181
  className: "theme-item-description",
177
182
  dangerouslySetInnerHTML: {
@@ -32,6 +32,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
32
32
 
33
33
  import React from 'react';
34
34
  import { connect } from 'react-redux';
35
+ import isEmpty from 'lodash.isempty';
35
36
  import PropTypes from 'prop-types';
36
37
  import { closeWindow, closeAllWindows, NotificationType } from '../actions/windows';
37
38
  import LocaleUtils from '../utils/LocaleUtils';
@@ -78,7 +79,6 @@ var WindowManager = /*#__PURE__*/function (_React$Component) {
78
79
  }, /*#__PURE__*/React.createElement("iframe", {
79
80
  className: "windows-iframe-dialog-body",
80
81
  name: key,
81
- role: "body",
82
82
  src: data.url
83
83
  }));
84
84
  });
@@ -92,7 +92,19 @@ var WindowManager = /*#__PURE__*/function (_React$Component) {
92
92
  return /*#__PURE__*/React.createElement("div", {
93
93
  className: className,
94
94
  key: key
95
- }, /*#__PURE__*/React.createElement("div", null, data.text), /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Icon, {
95
+ }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", null, data.text), !isEmpty(data.actions) ? /*#__PURE__*/React.createElement("div", {
96
+ className: "windows-notification-actions"
97
+ }, data.actions.map(function (action, idx) {
98
+ return /*#__PURE__*/React.createElement("button", {
99
+ className: "button",
100
+ key: "action" + idx,
101
+ onClick: function onClick() {
102
+ var res = action.onClick();
103
+ if (res) _this.closeWindow(key);
104
+ },
105
+ type: "button"
106
+ }, action.name);
107
+ })) : null), /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Icon, {
96
108
  icon: "remove",
97
109
  onClick: function onClick() {
98
110
  return _this.closeWindow(key);
@@ -23,6 +23,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23
23
  import ol from 'openlayers';
24
24
  import FeatureStyles from '../../../utils/FeatureStyles';
25
25
  export function createFeatures(options, mapCrs) {
26
+ var segmentize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
26
27
  var format = new ol.format.GeoJSON();
27
28
  return (options.features || []).reduce(function (collection, featureObj) {
28
29
  var _ref, _featureObj$crs;
@@ -41,7 +42,7 @@ export function createFeatures(options, mapCrs) {
41
42
  var featureStyleOptions = _objectSpread(_objectSpread({}, options.styleOptions), featureObj.styleOptions);
42
43
  feature.set('styleName', featureStyleName);
43
44
  feature.set('styleOptions', featureStyleOptions);
44
- if (featureObj.circleParams) {
45
+ if (featureObj.circleParams && !segmentize) {
45
46
  feature.set('circleParams', featureObj.circleParams);
46
47
  feature.setGeometry(new ol.geom.Circle(featureObj.circleParams.center, featureObj.circleParams.radius));
47
48
  }
@@ -58,6 +59,7 @@ export function createFeatures(options, mapCrs) {
58
59
  }, []);
59
60
  }
60
61
  export function updateFeatures(source, newOptions, oldOptions, mapCrs) {
62
+ var segmentize = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
61
63
  var format = new ol.format.GeoJSON();
62
64
  var oldFeaturesMap = (oldOptions.features || []).reduce(function (res, f) {
63
65
  res[f.id] = f;
@@ -118,7 +120,7 @@ export function updateFeatures(source, newOptions, oldOptions, mapCrs) {
118
120
  var _feature$getGeometry2;
119
121
  (_feature$getGeometry2 = _feature.getGeometry()) === null || _feature$getGeometry2 === void 0 || _feature$getGeometry2.transform(featureCrs, mapCrs);
120
122
  }
121
- if (featureObj.circleParams) {
123
+ if (featureObj.circleParams && !segmentize) {
122
124
  _feature.setGeometry(new ol.geom.Circle(featureObj.circleParams.center, featureObj.circleParams.radius));
123
125
  }
124
126
  var featureStyleName = featureObj.styleName || newOptions.styleName;
@@ -257,7 +257,6 @@ var HeightProfile = /*#__PURE__*/function (_React$Component) {
257
257
  return /*#__PURE__*/React.createElement("div", {
258
258
  className: "height-profile-chart-container",
259
259
  onMouseLeave: _this3.hideMarker,
260
- role: "body",
261
260
  style: {
262
261
  position: 'relative'
263
262
  }
@@ -37,10 +37,12 @@ import React, { Suspense } from 'react';
37
37
  import ReactDOM from 'react-dom';
38
38
  import { connect } from 'react-redux';
39
39
  import Instance from '@giro3d/giro3d/core/Instance.js';
40
- import Coordinates from '@giro3d/giro3d/core/geographic/Coordinates';
40
+ import Coordinates, { crsIsGeographic } from '@giro3d/giro3d/core/geographic/Coordinates';
41
+ import Ellipsoid from '@giro3d/giro3d/core/geographic/Ellipsoid';
41
42
  import Extent from '@giro3d/giro3d/core/geographic/Extent.js';
43
+ import CoordinateSystem from '@giro3d/giro3d/core/geographic/coordinate-system/CoordinateSystem';
42
44
  import ElevationLayer from '@giro3d/giro3d/core/layer/ElevationLayer.js';
43
- import FeatureCollection from "@giro3d/giro3d/entities/FeatureCollection.js";
45
+ import DrapedFeatureCollection from '@giro3d/giro3d/entities/DrapedFeatureCollection';
44
46
  import Map from '@giro3d/giro3d/entities/Map.js';
45
47
  import Tiles3D from "@giro3d/giro3d/entities/Tiles3D.js";
46
48
  import Inspector from "@giro3d/giro3d/gui/Inspector.js";
@@ -212,7 +214,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
212
214
  colorLayers[layer.id] = _objectSpread(_objectSpread({}, layer), {}, {
213
215
  visibility: (_prevOptions$visibili = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.visibility) !== null && _prevOptions$visibili !== void 0 ? _prevOptions$visibili : false,
214
216
  opacity: (_prevOptions$opacity = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity) !== null && _prevOptions$opacity !== void 0 ? _prevOptions$opacity : 255,
215
- extrusionHeight: (_prevOptions$extrusio = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== null && _prevOptions$extrusio !== void 0 ? _prevOptions$extrusio : ['vector', 'wfs'].includes(layer.type) ? 0 : undefined,
217
+ extrusionHeight: (_prevOptions$extrusio = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== null && _prevOptions$extrusio !== void 0 ? _prevOptions$extrusio : layerCreator.createFeatureSource ? 0 : undefined,
216
218
  fields: (_prevOptions$fields = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.fields) !== null && _prevOptions$fields !== void 0 ? _prevOptions$fields : undefined,
217
219
  sublayers: _preserveSublayerOptions(layer, prevOptions)
218
220
  });
@@ -250,9 +252,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
250
252
  mapLayer.visible = options.visibility;
251
253
  mapLayer.opacity = options.opacity / 255;
252
254
  layerBelow = mapLayer;
253
- if (options.extrusionHeight !== 0) {
254
- _this2.createUpdateExtrudedLayer(mapLayer, options, options.features !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.features));
255
- } else if ((prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== 0) {
255
+ if (options.extrusionHeight !== undefined && options.extrusionHeight !== 0) {
256
+ _this2.createUpdateExtrudedLayer(layerCreator, mapLayer, options, options.features !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.features));
257
+ } else if ((prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== undefined && (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== 0) {
256
258
  _this2.removeExtrudedLayer(options.id);
257
259
  }
258
260
  });
@@ -262,7 +264,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
262
264
  layerId = _ref4[0],
263
265
  options = _ref4[1];
264
266
  if (!(layerId in colorLayers)) {
265
- if (options.extrusionHeight !== 0) {
267
+ if (options.extrusionHeight !== undefined && options.extrusionHeight !== 0) {
266
268
  _this2.removeExtrudedLayer(options.id);
267
269
  }
268
270
  _this2.removeLayer(layerId);
@@ -270,11 +272,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
270
272
  });
271
273
  _this2.instance.notifyChange(_this2.map);
272
274
  });
273
- _defineProperty(_this2, "createUpdateExtrudedLayer", function (mapLayer, options) {
275
+ _defineProperty(_this2, "createUpdateExtrudedLayer", function (layerCreator, mapLayer, options) {
274
276
  var _options$features, _options$features$red;
275
- var forceCreate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
276
- var bounds = options.bbox.bounds;
277
- var extent = new Extent(options.bbox.crs, bounds[0], bounds[2], bounds[1], bounds[3]);
277
+ var forceCreate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
278
278
  var objId = options.id + ":extruded";
279
279
  var makeColor = function makeColor(c) {
280
280
  if (Array.isArray(c)) {
@@ -292,20 +292,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
292
292
  _this2.instance.remove(obj);
293
293
  }
294
294
  var layercolor = makeColor((_options$color = options.color) !== null && _options$color !== void 0 ? _options$color : "#FF0000");
295
- obj = new FeatureCollection({
296
- source: mapLayer.source.source,
297
- extent: extent,
298
- minLevel: 1,
299
- maxLevel: 1,
300
- ignoreZ: true,
301
- elevation: function elevation(feature) {
302
- var _this2$getTerrainHeig;
303
- var coordinates = feature.getGeometry().getCoordinates();
304
- while (Array.isArray(coordinates[0])) {
305
- coordinates = coordinates[0];
306
- }
307
- return (_this2$getTerrainHeig = _this2.getTerrainHeightFromMap(coordinates)) !== null && _this2$getTerrainHeig !== void 0 ? _this2$getTerrainHeig : 0;
308
- },
295
+ obj = new DrapedFeatureCollection({
296
+ source: layerCreator.createFeatureSource(mapLayer, options, _this2.state.sceneContext.mapCrs),
297
+ drapingMode: 'per-feature',
309
298
  extrusionOffset: function extrusionOffset(feature) {
310
299
  if (typeof obj.userData.extrusionHeight === "string") {
311
300
  return parseFloat(feature.getProperties()[obj.userData.extrusionHeight]) || 0;
@@ -325,7 +314,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
325
314
  });
326
315
  obj.castShadow = true;
327
316
  obj.receiveShadow = true;
328
- _this2.instance.add(obj);
317
+ _this2.instance.add(obj).then(function () {
318
+ obj.attach(_this2.map);
319
+ });
329
320
  _this2.objectMap[objId] = obj;
330
321
  }
331
322
  obj.userData.extrusionHeight = options.extrusionHeight;
@@ -339,7 +330,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
339
330
  }, {});
340
331
  obj.opacity = mapLayer.opacity;
341
332
  obj.visible = mapLayer.visible;
342
- obj.updateStyles();
333
+ if (obj.visible) {
334
+ obj.updateStyles();
335
+ }
343
336
  });
344
337
  _defineProperty(_this2, "removeExtrudedLayer", function (layerId) {
345
338
  var objId = layerId + ":extruded";
@@ -602,23 +595,25 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
602
595
  return;
603
596
  }
604
597
  var projection = _this2.props.theme.mapCrs;
598
+ var crs = CoordinateSystem.fromSrid(projection);
605
599
 
606
600
  // Setup instance
607
601
  _this2.instance = new Instance({
608
602
  target: _this2.container,
609
- crs: projection,
603
+ crs: crs,
610
604
  renderer: {
611
605
  clearColor: 0x000000,
612
606
  preserveDrawingBuffer: true
613
607
  }
614
608
  });
615
609
  _this2.sceneObjectGroup = new Group();
610
+ _this2.sceneObjectGroup.name = "sceneObjects";
616
611
  _this2.instance.add(_this2.sceneObjectGroup);
617
612
 
618
613
  // Setup map
619
614
  var initialBbox = (_this2$props$theme$ma = (_this2$props$theme$ma2 = _this2.props.theme.map3d) === null || _this2$props$theme$ma2 === void 0 ? void 0 : _this2$props$theme$ma2.extent) !== null && _this2$props$theme$ma !== void 0 ? _this2$props$theme$ma : _this2.props.theme.initialBbox;
620
615
  var bounds = CoordinatesUtils.reprojectBbox(initialBbox.bounds, initialBbox.crs, projection);
621
- var extent = new Extent(projection, bounds[0], bounds[2], bounds[1], bounds[3]);
616
+ var extent = new Extent(crs, bounds[0], bounds[2], bounds[1], bounds[3]);
622
617
  _this2.map = new Map({
623
618
  extent: extent,
624
619
  backgroundColor: "white"
@@ -627,7 +622,12 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
627
622
 
628
623
  // Setup camera
629
624
  var center = extent.center();
630
- _this2.instance.view.camera.position.set(center.x, center.y, 0.5 * (extent.east - extent.west));
625
+ if (crsIsGeographic(center.crs)) {
626
+ var position = Ellipsoid.WGS84.toCartesian(center.latitude, center.longitude, center.altitude);
627
+ _this2.instance.view.camera.position.set(position.x, position.y, 0.5 * (extent.east - extent.west));
628
+ } else {
629
+ _this2.instance.view.camera.position.set(center.x, center.y, 0.5 * (extent.east - extent.west));
630
+ }
631
631
 
632
632
  // Skybox
633
633
  var cubeTextureLoader = new CubeTextureLoader();
@@ -637,7 +637,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
637
637
 
638
638
  // Setup elevation
639
639
  var demUrl = MiscUtils.resolveAssetsPath((_this2$props$theme$ma3 = (_this2$props$theme$ma4 = _this2.props.theme.map3d) === null || _this2$props$theme$ma4 === void 0 || (_this2$props$theme$ma4 = _this2$props$theme$ma4.dtm) === null || _this2$props$theme$ma4 === void 0 ? void 0 : _this2$props$theme$ma4.url) !== null && _this2$props$theme$ma3 !== void 0 ? _this2$props$theme$ma3 : "");
640
- var demCrs = ((_this2$props$theme$ma5 = _this2.props.theme.map3d) === null || _this2$props$theme$ma5 === void 0 || (_this2$props$theme$ma5 = _this2$props$theme$ma5.dtm) === null || _this2$props$theme$ma5 === void 0 ? void 0 : _this2$props$theme$ma5.crs) || "EPSG:3857";
640
+ var demCrs = CoordinateSystem.fromSrid(((_this2$props$theme$ma5 = _this2.props.theme.map3d) === null || _this2$props$theme$ma5 === void 0 || (_this2$props$theme$ma5 = _this2$props$theme$ma5.dtm) === null || _this2$props$theme$ma5 === void 0 ? void 0 : _this2$props$theme$ma5.crs) || "EPSG:3857");
641
641
  if (demUrl) {
642
642
  var _this2$props$theme$ma6, _this2$props$theme$ma7;
643
643
  var demSource = new GeoTIFFSource({
@@ -740,8 +740,8 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
740
740
 
741
741
  // Add other objects
742
742
  (((_this2$props$theme$ma10 = _this2.props.theme.map3d) === null || _this2$props$theme$ma10 === void 0 ? void 0 : _this2$props$theme$ma10.objects3d) || []).forEach(function (entry) {
743
- var _entry$visibility2;
744
- importGltf(MiscUtils.resolveAssetsPath(entry.url), entry.name, _this2.state.sceneContext, {
743
+ var _entry$title2, _entry$visibility2;
744
+ importGltf(MiscUtils.resolveAssetsPath(entry.url), (_entry$title2 = entry.title) !== null && _entry$title2 !== void 0 ? _entry$title2 : entry.name, _this2.state.sceneContext, {
745
745
  visibility: (_entry$visibility2 = entry.visibility) !== null && _entry$visibility2 !== void 0 ? _entry$visibility2 : true
746
746
  });
747
747
  });
@@ -911,7 +911,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
911
911
  scenePos = [scenePos];
912
912
  }
913
913
  var dtmPos = scenePos.map(function (p) {
914
- return CoordinatesUtils.reproject(p, _this2.state.sceneContext.mapCrs, _this2.state.sceneContext.dtmCrs);
914
+ return CoordinatesUtils.reproject(p, _this2.state.sceneContext.mapCrs, _this2.state.sceneContext.dtmCrs.name);
915
915
  });
916
916
  var dtmExt = [Infinity, Infinity, -Infinity, -Infinity];
917
917
  dtmPos.forEach(function (p) {
@@ -968,7 +968,8 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
968
968
  });
969
969
  _defineProperty(_this2, "getTerrainHeightFromMap", function (scenePos) {
970
970
  var _elevationResult$samp;
971
- var coordinates = new Coordinates(_this2.state.sceneContext.mapCrs, scenePos[0], scenePos[1], 0);
971
+ var crs = CoordinateSystem.fromSrid(_this2.state.sceneContext.mapCrs);
972
+ var coordinates = new Coordinates(crs, scenePos[0], scenePos[1], 0);
972
973
  var elevationResult = _this2.state.sceneContext.map.getElevation({
973
974
  coordinates: coordinates
974
975
  });
@@ -63,7 +63,8 @@ var View3DSwitcher = /*#__PURE__*/function (_React$Component) {
63
63
  },
64
64
  position: _this.props.position
65
65
  }, /*#__PURE__*/React.createElement("div", {
66
- className: "view3d-switcher-buttons" + (_this.state.expanded ? " view3d-switcher-buttons-expanded" : "")
66
+ className: "view3d-switcher-buttons" + (_this.state.expanded ? " view3d-switcher-buttons-expanded" : ""),
67
+ inert: _this.state.expanded ? undefined : "true"
67
68
  }, buttons.map(function (button) {
68
69
  return /*#__PURE__*/React.createElement("button", {
69
70
  className: "map-button" + (button.mode === _this.props.view3dMode ? " map-button-active" : ""),
@@ -212,8 +212,7 @@ var NumericInput3D = /*#__PURE__*/function (_React$Component) {
212
212
  scrollable: true,
213
213
  title: LocaleUtils.tr("draw3d.numericinput")
214
214
  }, /*#__PURE__*/React.createElement("div", {
215
- className: "draw3d-numeric-input-body",
216
- role: "body"
215
+ className: "draw3d-numeric-input-body"
217
216
  }, /*#__PURE__*/React.createElement("table", null, /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("draw3d.position")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(NumberInput, {
218
217
  decimals: 0,
219
218
  disabled: disabled,
@@ -6,6 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
 
9
+ import CoordinateSystem from '@giro3d/giro3d/core/geographic/coordinate-system/CoordinateSystem';
9
10
  import ColorLayer from '@giro3d/giro3d/core/layer/ColorLayer';
10
11
  import GeoTIFFSource from "@giro3d/giro3d/sources/GeoTIFFSource.js";
11
12
  export default {
@@ -14,7 +15,7 @@ export default {
14
15
  name: options.name,
15
16
  source: new GeoTIFFSource({
16
17
  url: options.url,
17
- crs: projection
18
+ crs: CoordinateSystem.fromSrid(projection)
18
19
  })
19
20
  });
20
21
  }
@@ -12,7 +12,9 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
12
12
  * LICENSE file in the root directory of this source tree.
13
13
  */
14
14
 
15
+ import CoordinateSystem from '@giro3d/giro3d/core/geographic/coordinate-system/CoordinateSystem';
15
16
  import ColorLayer from '@giro3d/giro3d/core/layer/ColorLayer';
17
+ import StaticFeatureSource from '@giro3d/giro3d/sources/StaticFeatureSource';
16
18
  import VectorSource from "@giro3d/giro3d/sources/VectorSource.js";
17
19
  import ol from 'openlayers';
18
20
  import FeatureStyles from '../../../utils/FeatureStyles';
@@ -22,7 +24,8 @@ export default {
22
24
  return new ColorLayer({
23
25
  name: options.name,
24
26
  source: new VectorSource({
25
- data: createFeatures(options, projection),
27
+ dataProjection: CoordinateSystem.fromSrid(projection),
28
+ data: createFeatures(options, projection, true),
26
29
  format: new ol.format.GeoJSON(),
27
30
  style: options.styleFunction || function (feature) {
28
31
  var styleName = options.styleName || 'default';
@@ -39,7 +42,7 @@ export default {
39
42
  layer.source.setStyle(newOptions.styleFunction);
40
43
  }
41
44
  if (newOptions.features !== oldOptions.features) {
42
- updateFeatures(layer.source, newOptions, oldOptions, projection);
45
+ updateFeatures(layer.source, newOptions, oldOptions, projection, true);
43
46
  } else if ((oldOptions.rev || 0) !== (newOptions.rev || 0)) {
44
47
  layer.source.update();
45
48
  }
@@ -54,5 +57,12 @@ export default {
54
57
  });
55
58
  resolve(_toConsumableArray(fields.values()));
56
59
  });
60
+ },
61
+ createFeatureSource: function createFeatureSource(layer, options, projection) {
62
+ var crs = CoordinateSystem.fromSrid(projection);
63
+ return new StaticFeatureSource({
64
+ coordinateSystem: crs,
65
+ features: layer.source.source.getFeatures()
66
+ });
57
67
  }
58
68
  };
@@ -22,7 +22,10 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
22
22
  * LICENSE file in the root directory of this source tree.
23
23
  */
24
24
 
25
+ import Extent from '@giro3d/giro3d/core/geographic/Extent';
26
+ import CoordinateSystem from '@giro3d/giro3d/core/geographic/coordinate-system/CoordinateSystem';
25
27
  import ColorLayer from '@giro3d/giro3d/core/layer/ColorLayer';
28
+ import StreamableFeatureSource, { wfsBuilder, tiledLoadingStrategy } from '@giro3d/giro3d/sources/StreamableFeatureSource';
26
29
  import VectorSource from "@giro3d/giro3d/sources/VectorSource.js";
27
30
  import axios from 'axios';
28
31
  import { tile } from "ol/loadingstrategy.js";
@@ -55,7 +58,7 @@ export default {
55
58
  return new ColorLayer({
56
59
  name: options.name,
57
60
  source: new VectorSource({
58
- dataProjection: options.projection,
61
+ dataProjection: CoordinateSystem.fromSrid(projection),
59
62
  data: {
60
63
  url: url.format(urlParts),
61
64
  format: olOpts.format
@@ -110,5 +113,18 @@ export default {
110
113
  reject([]);
111
114
  });
112
115
  });
116
+ },
117
+ createFeatureSource: function createFeatureSource(layer, options, projection) {
118
+ var bounds = CoordinatesUtils.reprojectBbox(options.bbox.bounds, options.bbox.crs, projection);
119
+ var crs = CoordinateSystem.fromSrid(projection);
120
+ var maxextent = new Extent(crs, bounds[0], bounds[2], bounds[1], bounds[3]);
121
+ return new StreamableFeatureSource({
122
+ queryBuilder: wfsBuilder(options.url, options.name),
123
+ sourceCoordinateSystem: crs,
124
+ extent: maxextent,
125
+ loadingStrategy: tiledLoadingStrategy({
126
+ tileSize: 5000
127
+ })
128
+ });
113
129
  }
114
130
  };
@@ -111,6 +111,10 @@ button.button {
111
111
  outline: none;
112
112
  }
113
113
 
114
+ button.button:focus {
115
+ outline: var(--focus-outline);
116
+ }
117
+
114
118
  button.button:disabled {
115
119
  background-color: var(--button-bg-color-disabled);
116
120
  color: var(--button-text-color-disabled);
@@ -44,7 +44,6 @@ div.AppMenu .appmenu-icon > span.icon {
44
44
  transition: color 0.25s, border-color 0.25s, background-color 0.25s;
45
45
  }
46
46
 
47
-
48
47
  div.AppMenu.appmenu-visible .appmenu-icon > span.icon {
49
48
  color: var(--app-submenu-text-color-hover);
50
49
  border-color: var(--app-submenu-text-color-hover);
@@ -80,14 +79,15 @@ div.AppMenu.appmenu-compact div.appmenu-menu-container {
80
79
  top: 3.5em;
81
80
  }
82
81
 
83
- div.AppMenu.appmenu-compact div.appmenu-menu-container:hover {
82
+ div.AppMenu.appmenu-compact div.appmenu-menu-container:hover,
83
+ div.AppMenu.appmenu-compact div.appmenu-menu-container:focus-within {
84
84
  right: 0;
85
85
  }
86
86
 
87
- div.AppMenu ul.appmenu-menu {
88
- text-align: left;
89
- padding: 0;
87
+ div.AppMenu div.appmenu-menu {
90
88
  background-color: var(--app-menu-bg-color);
89
+ text-align: left;
90
+ font-size: small;
91
91
  }
92
92
 
93
93
  div.AppMenu.appmenu-visible div.appmenu-menu-container {
@@ -95,72 +95,57 @@ div.AppMenu.appmenu-visible div.appmenu-menu-container {
95
95
  opacity: 1;
96
96
  }
97
97
 
98
- div.AppMenu ul.appmenu-menu li {
98
+ div.appmenu-menu-item {
99
+ display: flex;
100
+ align-items: center;
99
101
  color: var(--app-menu-text-color);
100
- list-style-type: none;
101
- margin: 0;
102
- font-size: small;
103
102
  font-weight: bold;
104
103
  }
105
104
 
106
- div.AppMenu ul.appmenu-menu li:not(:last-child) {
105
+ div.appmenu-menu-item:not(:last-child) {
107
106
  border-bottom: 1px solid var(--app-menu-text-color);
108
107
  }
109
108
 
110
- div.AppMenu ul.appmenu-menu > li.appmenu-leaf-active,
111
- div.AppMenu ul.appmenu-menu > li.appmenu-submenu-active,
112
- div.AppMenu ul.appmenu-menu > li.appmenu-submenu-expanded {
113
- background-color: var(--app-menu-bg-color-hover);
114
- color: var(--app-menu-text-color-hover);
115
- }
116
-
117
- div.AppMenu ul.appmenu-menu li > .icon {
118
- vertical-align: middle;
109
+ div.appmenu-menu-item > .icon {
119
110
  width: 2em;
120
111
  margin: 0.5em 1em 0.5em 1em;
121
112
  }
122
113
 
123
- div.AppMenu ul.appmenu-menu li.appmenu-submenu > ul {
124
- background-color: var(--app-submenu-bg-color);
125
- padding: 0;
126
- display: none;
127
- }
128
-
129
- div.AppMenu ul.appmenu-menu li.appmenu-submenu-expanded > ul {
130
- display: block;
114
+ div.appmenu-menu-item-label {
115
+ margin: 0.25em 0;
131
116
  }
132
117
 
133
- div.AppMenu ul.appmenu-menu li.appmenu-submenu > ul > li {
134
- color: var(--app-submenu-text-color);
118
+ div.appmenu-menu-item-comment {
119
+ font-weight: normal;
120
+ font-size: 90%;
135
121
  }
136
122
 
137
- div.AppMenu ul.appmenu-menu li.appmenu-submenu > ul > li.appmenu-leaf-active,
138
- div.AppMenu ul.appmenu-menu li.appmenu-submenu > ul > li.appmenu-submenu-active,
139
- div.AppMenu ul.appmenu-menu li.appmenu-submenu > ul > li.appmenu-submenu-expanded {
140
- background-color: var(--app-submenu-bg-color-hover);
141
- color: var(--app-submenu-text-color-hover);
123
+ div.appmenu-submenu-active,
124
+ div.appmenu-submenu-expanded {
125
+ background-color: var(--app-menu-bg-color-hover);
126
+ color: var(--app-menu-text-color-hover);
142
127
  }
143
128
 
144
- div.AppMenu ul.appmenu-menu li.appmenu-leaf {
145
- display: flex;
146
- align-items: center;
129
+ div.appmenu-menu-item-nested {
130
+ background-color: var(--app-submenu-bg-color);
131
+ color: var(--app-submenu-text-color);
147
132
  }
148
133
 
149
- div.AppMenu ul.appmenu-menu li.appmenu-leaf > span.icon {
150
- flex: 0 0 auto;
134
+ div.appmenu-menu-item:focus-within {
135
+ background-color: var(--app-menu-bg-color-hover);
136
+ color: var(--app-menu-text-color-hover);
137
+ outline: none;
151
138
  }
152
139
 
153
- div.AppMenu ul.appmenu-menu li.appmenu-leaf > span.appmenu-leaf-label {
154
- flex: 1 1 auto;
155
- margin: 0.25em 0;
140
+ div.appmenu-menu-item-nested:focus-within {
141
+ background-color: var(--app-submenu-bg-color-hover);
142
+ color: var(--app-submenu-text-color-hover);
156
143
  }
157
144
 
158
- div.AppMenu ul.appmenu-menu li.appmenu-leaf div.appmenu-leaf-comment {
159
- font-weight: normal;
160
- font-size: 90%;
145
+ div.appmenu-menu-item-filter {
146
+ padding-right: 0.5em;
161
147
  }
162
148
 
163
- div.appmenu-filter {
164
- width: 100%;
165
- margin-right: 0.5em;
149
+ div.appmenu-menu-item-filter > div.input-container {
150
+ flex: 1 1 auto;
166
151
  }
@@ -40,6 +40,7 @@
40
40
  /* List */
41
41
  --list-bg-color: white;
42
42
  --list-section-bg-color: #ccc;
43
+ --list-section-bg-color-hover: #bbb;
43
44
  --list-section-text-color: #595959;
44
45
  --list-item-bg-color-even: #f0f0f0;
45
46
  --list-item-bg-color-hover: #dcdcdc;
@@ -1,9 +1,3 @@
1
- div.PickFeatureMenu {
2
- border: 1px solid var(--border-color);
3
- background-color: var(--list-bg-color);
4
- box-shadow: 0px 2px 4px rgba(136, 136, 136, 0.5);
5
- }
6
-
7
1
  div.PickFeatureMenu > div {
8
2
  padding: 0.25em 0.5em;
9
3
  }