@sapui5/sap.ui.vbm 1.139.0 → 1.141.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.ui.vbm",
3
- "version": "1.139.0",
3
+ "version": "1.141.0",
4
4
  "description": "SAPUI5 Library sap.ui.vbm",
5
5
  "homepage": "https://sap.github.io/ui5-tooling/pages/SAPUI5/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -3,7 +3,7 @@
3
3
  <name>sap.ui.vbm</name>
4
4
  <vendor>SAP SE</vendor>
5
5
  <copyright>SAP UI development toolkit for HTML5 (SAPUI5) (c) Copyright 2009-2012 SAP AG. All rights reserved</copyright>
6
- <version>1.139.0</version>
6
+ <version>1.141.0</version>
7
7
 
8
8
  <documentation>SAP UI library: sap.ui.vbm</documentation>
9
9
 
@@ -24,7 +24,7 @@ sap.ui.define([
24
24
  * @param {string} [sId] id for the new control, generated automatically if no id is given
25
25
  * @param {object} [mSettings] initial settings for the new object
26
26
  * @author SAP SE
27
- * @version 1.139.0
27
+ * @version 1.141.0
28
28
  * @extends sap.ui.core.Element
29
29
  * @constructor
30
30
  * @public
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  * @param {string} [sId] id for the new control, generated automatically if no id is given
48
48
  * @param {object} [mSettings] initial settings for the new object
49
49
  * @author SAP SE
50
- * @version 1.139.0
50
+ * @version 1.141.0
51
51
  * @extends sap.ui.core.Element
52
52
  * @constructor
53
53
  * @public
@@ -23,7 +23,7 @@ sap.ui.define([
23
23
  *
24
24
  * @public
25
25
  * @author SAP SE
26
- * @version 1.139.0
26
+ * @version 1.141.0
27
27
  * @extends sap.ui.core.Control
28
28
  * @alias sap.ui.vbm.Viewport
29
29
  */
@@ -22,7 +22,7 @@ sap.ui.define([
22
22
  *
23
23
  * @private
24
24
  * @author SAP SE
25
- * @version 1.139.0
25
+ * @version 1.141.0
26
26
  * @alias sap.ui.vbm.adapter3d.ColladaBounds
27
27
  */
28
28
  var ColladaBounds = BaseObject.extend("sap.ui.vbm.adapter3d.ColladaBounds", /** @lends sap.ui.vbm.adapter3d.ColladaBounds.prototype */ {
@@ -83,7 +83,7 @@ sap.ui.define([
83
83
  *
84
84
  * @private
85
85
  * @author SAP SE
86
- * @version 1.139.0
86
+ * @version 1.141.0
87
87
  * @alias sap.ui.vbm.adapter3d.DragDropHandler
88
88
  */
89
89
  var DragDropHandler = BaseObject.extend("sap.ui.vbm.adapter3d.DragDropHandler", /** @lends sap.ui.vbm.adapter3d.DragDropHandler.prototype */ {
@@ -29,7 +29,7 @@ sap.ui.define([
29
29
  *
30
30
  * @private
31
31
  * @author SAP SE
32
- * @version 1.139.0
32
+ * @version 1.141.0
33
33
  * @alias sap.ui.vbm.adapter3d.ModelHandler
34
34
  */
35
35
  var ModelHandler = BaseObject.extend("sap.ui.vbm.adapter3d.ModelHandler", /** @lends sap.ui.vbm.adapter3d.ModelHandler.prototype */ {
@@ -377,7 +377,7 @@ sap.ui.define([
377
377
  *
378
378
  * @private
379
379
  * @author SAP SE
380
- * @version 1.139.0
380
+ * @version 1.141.0
381
381
  * @alias sap.ui.vbm.adapter3d.ObjectFactory
382
382
  */
383
383
  var ObjectFactory = BaseObject.extend("sap.ui.vbm.adapter3d.ObjectFactory", /** @lends sap.ui.vbm.adapter3d.ObjectFactory.prototype */ {});
@@ -32,7 +32,7 @@ sap.ui.define([
32
32
  *
33
33
  * @private
34
34
  * @author SAP SE
35
- * @version 1.139.0
35
+ * @version 1.141.0
36
36
  * @alias sap.ui.vbm.adapter3d.PolygonHandler
37
37
  */
38
38
  var PolygonHandler = BaseObject.extend("sap.ui.vbm.adapter3d.PolygonHandler", /** @lends sap.ui.vbm.adapter3d.PolygonHandler.prototype */ {
@@ -7,7 +7,7 @@ sap.ui.define([
7
7
  var Vector2 = THREE.Vector2;
8
8
  var _frustum = new THREE.Frustum;
9
9
  var _center = new THREE.Vector3;
10
- var _tmpPoint = new THREE.Vector3;
10
+ //var _tmpPoint = new THREE.Vector3;
11
11
  var _vecNear = new THREE.Vector3;
12
12
  var _vecTopLeft = new THREE.Vector3;
13
13
  var _vecTopRight = new THREE.Vector3;
@@ -39,7 +39,7 @@ sap.ui.define([
39
39
  *
40
40
  * @private
41
41
  * @author SAP SE
42
- * @version 1.139.0
42
+ * @version 1.141.0
43
43
  * @alias sap.ui.vbm.adapter3d.RectangleTracker
44
44
  */
45
45
  var RectangleTracker = BaseObject.extend("sap.ui.vbm.adapter3d.RectangleTracker", /** @lends sap.ui.vbm.adapter3d.RectangleTracker.prototype */ {
@@ -148,6 +148,9 @@ sap.ui.define([
148
148
  };
149
149
 
150
150
  RectangleTracker.prototype._onPointerDown = function (event) {
151
+ if (event.button !== 0) {
152
+ return; // Don't start selection if it's not the left button
153
+ }
151
154
  this._updateController(true);
152
155
  this.onSelectStart(event);
153
156
  var that = this;
@@ -420,6 +423,14 @@ sap.ui.define([
420
423
  this.startPoint = startPoint || this.startPoint;
421
424
  this.endPoint = endPoint || this.endPoint;
422
425
  this.collection = [];
426
+ const dx = Math.abs(endPoint.x - startPoint.x);
427
+ const dy = Math.abs(endPoint.y - startPoint.y);
428
+
429
+ // if less than 2-3 pixels movement => treat as click, skip updateFrustum
430
+ if (dx < 0.002 && dy < 0.002) {
431
+ // 👉 handle as simple click (use raycaster for single object select)
432
+ return;
433
+ }
423
434
  this.updateFrustum(this.startPoint, this.endPoint);
424
435
  this.searchChildInFrustum(_frustum, this._scene);
425
436
  this._scene.remove(this._planeMesh);
@@ -447,52 +458,46 @@ sap.ui.define([
447
458
 
448
459
  if (this._camera.isPerspectiveCamera) {
449
460
 
450
- _tmpPoint = startPoint;
451
- _tmpPoint.x = Math.min(startPoint.x, endPoint.x);
452
- _tmpPoint.y = Math.max(startPoint.y, endPoint.y);
453
- endPoint.x = Math.max(startPoint.x, endPoint.x);
454
- endPoint.y = Math.min(startPoint.y, endPoint.y);
461
+ // Normalize rectangle regardless of drag direction
462
+ var minX = Math.min(startPoint.x, endPoint.x);
463
+ var maxX = Math.max(startPoint.x, endPoint.x);
464
+ var minY = Math.min(startPoint.y, endPoint.y);
465
+ var maxY = Math.max(startPoint.y, endPoint.y);
455
466
 
467
+ // Define corners in NDC (normalized device coordinates)
468
+ _vecTopLeft.set(minX, maxY, 0);
469
+ _vecTopRight.set(maxX, maxY, 0);
470
+ _vecDownRight.set(maxX, minY, 0);
471
+ _vecDownLeft.set(minX, minY, 0);
472
+
473
+ // Camera position
456
474
  _vecNear.setFromMatrixPosition(this._camera.matrixWorld);
457
- _vecTopLeft.copy(_tmpPoint);
458
- _vecTopRight.set(endPoint.x, _tmpPoint.y, 0);
459
- _vecDownRight.copy(endPoint);
460
- _vecDownLeft.set(_tmpPoint.x, endPoint.y, 0);
461
475
 
462
476
  _vecTopLeft.unproject(this._camera);
463
477
  _vecTopRight.unproject(this._camera);
464
478
  _vecDownRight.unproject(this._camera);
465
479
  _vecDownLeft.unproject(this._camera);
466
480
 
467
- _vectemp1.copy(_vecTopLeft).sub(_vecNear);
468
- _vectemp2.copy(_vecTopRight).sub(_vecNear);
469
- _vectemp3.copy(_vecDownRight).sub(_vecNear);
470
- _vectemp1.normalize();
471
- _vectemp2.normalize();
472
- _vectemp3.normalize();
473
-
474
-
475
- _vectemp1.multiplyScalar(this.deep);
476
- _vectemp2.multiplyScalar(this.deep);
477
- _vectemp3.multiplyScalar(this.deep);
478
- _vectemp4.multiplyScalar(this.deep);
479
- _vectemp1.sub(_vecNear);
480
- _vectemp2.sub(_vecNear);
481
- _vectemp3.sub(_vecNear);
481
+ // Far points (deep into the scene)
482
+ _vectemp1.copy(_vecTopLeft).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
483
+ _vectemp2.copy(_vecTopRight).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
484
+ _vectemp3.copy(_vecDownRight).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
485
+ _vectemp4.copy(_vecDownLeft).sub(_vecNear).normalize().multiplyScalar(this.deep).add(_vecNear);
482
486
 
483
487
  var planes = _frustum.planes;
484
488
 
485
- planes[0].setFromCoplanarPoints(_vecNear, _vecTopLeft, _vecTopRight);
486
- planes[1].setFromCoplanarPoints(_vecNear, _vecTopRight, _vecDownRight);
487
- planes[2].setFromCoplanarPoints(_vecDownRight, _vecDownLeft, _vecNear);
488
- planes[3].setFromCoplanarPoints(_vecDownLeft, _vecTopLeft, _vecNear);
489
- planes[4].setFromCoplanarPoints(_vecTopRight, _vecDownRight, _vecDownLeft);
490
- planes[5].setFromCoplanarPoints(_vectemp3, _vectemp2, _vectemp1);
489
+ // Build planes around the selection frustum
490
+ planes[0].setFromCoplanarPoints(_vecNear, _vecTopLeft, _vecTopRight); // top
491
+ planes[1].setFromCoplanarPoints(_vecNear, _vecTopRight, _vecDownRight); // right
492
+ planes[2].setFromCoplanarPoints(_vecNear, _vecDownRight, _vecDownLeft); // bottom
493
+ planes[3].setFromCoplanarPoints(_vecNear, _vecDownLeft, _vecTopLeft); // left
494
+ planes[4].setFromCoplanarPoints(_vecTopRight, _vecDownRight, _vecDownLeft); // near plane
495
+ planes[5].setFromCoplanarPoints(_vectemp3, _vectemp2, _vectemp1); // far plane
491
496
  planes[5].normal.multiplyScalar(-1);
492
497
  }
493
498
 
494
-
495
- }
499
+ return _frustum; // ✅ return the frustum so selecting() can use it
500
+ };
496
501
 
497
502
  RectangleTracker.prototype.searchChildInFrustum = function (frustum, object) {
498
503
  var count = 0;
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  *
48
48
  * @private
49
49
  * @author SAP SE
50
- * @version 1.139.0
50
+ * @version 1.141.0
51
51
  * @alias sap.ui.vbm.adapter3d.SceneBuilder
52
52
  */
53
53
  var SceneBuilder = BaseObject.extend("sap.ui.vbm.adapter3d.SceneBuilder", /** @lends sap.ui.vbm.adapter3d.SceneBuilder.prototype */ {
@@ -56,7 +56,7 @@ sap.ui.define([
56
56
  *
57
57
  * @private
58
58
  * @author SAP SE
59
- * @version 1.139.0
59
+ * @version 1.141.0
60
60
  * @alias sap.ui.vbm.adapter3d.VBIJSONParser
61
61
  */
62
62
  var VBIJSONParser = BaseObject.extend("sap.ui.vbm.adapter3d.VBIJSONParser", /** @lends sap.ui.vbm.adapter3d.VBIJSONParser.prototype */ {
@@ -20,7 +20,7 @@ sap.ui.define([
20
20
  * @namespace
21
21
  * @alias sap.ui.vbm
22
22
  * @author SAP SE
23
- * @version 1.139.0
23
+ * @version 1.141.0
24
24
  * @public
25
25
  */
26
26
 
@@ -46,7 +46,7 @@ sap.ui.define([
46
46
  "sap.ui.vbm.ClusterBase", "sap.ui.vbm.ClusterTree", "sap.ui.vbm.ClusterGrid", "sap.ui.vbm.ClusterDistance", "sap.ui.vbm.Heatmap",
47
47
  "sap.ui.vbm.HeatPoint", "sap.ui.vbm.ClusterContainer", "sap.ui.vbm.Adapter", "sap.ui.vbm.Adapter3D"
48
48
  ],
49
- version: "1.139.0"
49
+ version: "1.141.0"
50
50
  });
51
51
 
52
52
  sap.ui.loader.config({
@@ -39,7 +39,7 @@ sap.ui.define([
39
39
  let fixedBounds;
40
40
  var containerID;
41
41
  let previousCenter = null;
42
- let previousZoom = null;
42
+ let previousZoom = null;
43
43
 
44
44
 
45
45
 
@@ -59,11 +59,11 @@ sap.ui.define([
59
59
  }
60
60
 
61
61
  VBI.MapRenderer.renderMap = () => {
62
-
62
+
63
63
  if (this.map) {
64
64
  previousCenter = this.map.getCenter();
65
65
  previousZoom = this.map.getZoom();
66
- this.map.remove();
66
+ this.map.remove();
67
67
  }
68
68
 
69
69
  let geoJSON = VBI.VBITransformer.getTransformedJSON();
@@ -76,6 +76,7 @@ sap.ui.define([
76
76
  document.head.appendChild(styleSheet);
77
77
 
78
78
  const map = VectorUtils.createMap(geoJSON, map_container);
79
+ map.doubleClickZoom.disable();
79
80
 
80
81
  if (previousCenter && previousZoom !== null) {
81
82
  map.jumpTo({
@@ -104,13 +105,13 @@ sap.ui.define([
104
105
  map.on('load', () => {
105
106
 
106
107
  map.getCanvas().style.cursor = 'default';
107
- map.on('mouseup', function () {
108
- map.getCanvas().style.cursor = 'default';
109
- });
110
- map.getCanvas().addEventListener('mousemove', function () {
111
- map.getCanvas().style.cursor = 'default';
112
- });
113
-
108
+ map.on('mouseup', function () {
109
+ map.getCanvas().style.cursor = 'default';
110
+ });
111
+ map.getCanvas().addEventListener('mousemove', function () {
112
+ map.getCanvas().style.cursor = 'default';
113
+ });
114
+
114
115
  if (VBI.mapFlags.isLegendExists) {
115
116
  // Legend control
116
117
  VBI.VBITransformer._createLegend(map_container);
@@ -162,9 +163,15 @@ sap.ui.define([
162
163
  let markerCoordinates = marker.geometry.coordinates;
163
164
  if (marker.geometry.type === 'Point') {
164
165
  // create a DOM element for the marker (parent div)
165
- const el = VectorUtils.createSpotElement(marker);
166
+ let createdSpot = VectorUtils.createSpotElement(marker, spotid);
167
+ const el = createdSpot.spotEl;
168
+ spotid = createdSpot.spotId;
169
+ if (marker.properties.Label) {
170
+ const child_e1 = VectorUtils.createMarkerLabel(marker.properties.Label, marker.properties.LabelBGColor);
171
+ el.appendChild(child_e1);
172
+ }
166
173
  if (marker.properties.Icon) {
167
- const iconColor = marker.properties.contentColor? marker.properties.contentColor : "#000000";
174
+ const iconColor = marker.properties.contentColor ? marker.properties.contentColor : "#000000";
168
175
  // Create child element for the SAP icon (icon overlay)
169
176
  const child_el = VectorUtils.createIconElement(marker.properties.Icon, iconColor);
170
177
  child_el.id = '__mapspot' + spotid++;
@@ -175,7 +182,7 @@ sap.ui.define([
175
182
  let spot = new maplibregl.Marker({
176
183
  element: el,
177
184
  draggable: true,
178
- offset: [0, -20]
185
+ anchor: 'bottom'
179
186
  }).setLngLat(marker.geometry.coordinates)
180
187
  .on('dragend', onDragEnd)
181
188
  .addTo(map);
@@ -477,6 +484,10 @@ sap.ui.define([
477
484
  PayloadGenerator.objectClick('Spot', event, marker, clickCoordinates);
478
485
  };
479
486
 
487
+ el.addEventListener('dblclick', (e) => {
488
+ triggerPayloadSpot(e, 'DOUBLE_CLICK');
489
+ });
490
+
480
491
  el.addEventListener('click', (e) => {
481
492
  //Trigger payload
482
493
  triggerPayloadSpot(e, 'DETAIL_REQUEST');
@@ -504,6 +515,22 @@ sap.ui.define([
504
515
  predefinedMarkers.push(markerCoordinates);
505
516
  }
506
517
  } else if (marker.geometry.type == "LineString") {
518
+
519
+ if (marker.properties.Label) {
520
+ const midpoint = getMidpoint(marker.geometry.coordinates);
521
+
522
+ const routeLabelEl = VectorUtils.createRouteLabel(
523
+ marker.properties.Label,
524
+ marker.properties.LabelBGColor
525
+ );
526
+
527
+ new maplibregl.Marker({
528
+ element: routeLabelEl,
529
+ anchor: 'left',
530
+ })
531
+ .setLngLat(midpoint)
532
+ .addTo(map);
533
+ }
507
534
  const coords = marker.geometry.coordinates;
508
535
  const startCoord = coords[0]; // First coordinate
509
536
  const endCoord = coords[coords.length - 1]; // Last coordinate
@@ -559,10 +586,10 @@ sap.ui.define([
559
586
  }
560
587
 
561
588
  });
562
- if(VBI.mapFlags.automations){
589
+ if (VBI.mapFlags.automations) {
563
590
  let automations = new SAPAutomationManager(map, maplibregl.LngLatBounds);
564
591
  automations.load(VBI.mapFlags.automations);
565
- }
592
+ }
566
593
  map.addLayer({
567
594
  'id': 'geojson-source-point',
568
595
  'type': 'circle',
@@ -602,6 +629,18 @@ sap.ui.define([
602
629
  },
603
630
  'filter': ['==', '$type', 'LineString']
604
631
  });
632
+
633
+ function getMidpoint(coords) {
634
+ if (coords.length < 2) return coords[0];
635
+
636
+ const start = coords[0];
637
+ const end = coords[coords.length - 1];
638
+ const midLng = (start[0] + end[0]) / 2;
639
+ const midLat = (start[1] + end[1]) / 2;
640
+
641
+ return [midLng, midLat];
642
+ }
643
+
605
644
  // Create a new FeatureCollection for the points
606
645
  const pointGeoJSON = {
607
646
  'type': 'FeatureCollection',
@@ -650,8 +689,8 @@ sap.ui.define([
650
689
  }
651
690
  });
652
691
  });
653
-
654
692
  });
693
+
655
694
  // Change mouse cursor when hovering over the line
656
695
  map.on('mouseenter', 'geojson-source-route', function (event) {
657
696
  if (!that.Apressed && !that.Rpressed) {
@@ -715,14 +754,12 @@ sap.ui.define([
715
754
  }
716
755
  popupLink.remove();
717
756
  });
757
+
718
758
  map.on('click', 'geojson-source-route', function (e) {
719
759
  //Trigger payload
720
760
  triggerPayloadRoute(e, 'DETAIL_REQUEST');
721
761
  });
722
- // map.getContainer().addEventListener('contextmenu', 'geojson-source-route', function (e) {
723
- // //Trigger payload
724
- // triggerPayloadRoute(e, 'DETAIL_REQUEST');
725
- // });
762
+
726
763
  function triggerPayloadRoute(e, event) {
727
764
  // Get the mouse coordinates within the map container
728
765
  const offsetX = e.offsetX;
@@ -740,7 +777,7 @@ sap.ui.define([
740
777
  function triggerPayloaddnd() {
741
778
  PayloadGenerator.objectDrop(action, dropItems);
742
779
  }
743
-
780
+
744
781
  map.on('mousedown', 'geojson-source-route', (e) => {
745
782
  dragInstance = map.queryRenderedFeatures(e.point, {
746
783
  layers: ['geojson-source-route']
@@ -771,7 +808,7 @@ sap.ui.define([
771
808
  map.on('mousemove', onMove);
772
809
  map.on('mouseup', onUp);
773
810
 
774
-
811
+
775
812
  if (!that.Apressed && !that.Rpressed) {
776
813
  map.getCanvas().style.cursor = 'pointer';
777
814
  }
@@ -826,10 +863,10 @@ sap.ui.define([
826
863
  }
827
864
 
828
865
  // Reset cursor and remove event listeners
829
- map.getCanvas().style.cursor = 'default';
866
+ map.getCanvas().style.cursor = 'default';
830
867
  setTimeout(() => {
831
- map.getCanvas().style.cursor = 'default';
832
- }, 100);
868
+ map.getCanvas().style.cursor = 'default';
869
+ }, 100);
833
870
  map.off('mousemove', onMove);
834
871
  map.off('mouseup', onUp);
835
872
  lineDrag = false;
@@ -856,12 +893,12 @@ sap.ui.define([
856
893
  map.getCanvas().style.cursor = validDrop ? 'copy' : 'not-allowed';
857
894
  }
858
895
  else {
859
-
896
+
860
897
  map.getCanvas().style.cursor = 'default';
861
898
  }
862
899
  }
863
900
  }
864
-
901
+
865
902
  mapCanvas.oncontextmenu = (e) => {
866
903
  e.preventDefault();
867
904
  // Get the mouse coordinates within the map container
@@ -892,7 +929,7 @@ sap.ui.define([
892
929
  PayloadGenerator.onMapContextMenu(coords, currentZoom, currentCenter, screenX, screenY);
893
930
  }
894
931
  };
895
-
932
+
896
933
  var that = this;
897
934
  map.on('idle', () => {
898
935
  const container = map.getContainer();
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.139.0
15
+ * @version 1.141.0
16
16
  * @alias sap.ui.vbm.vector.PayloadGenerator
17
17
  */
18
18
  var adapter = {};
@@ -12,7 +12,7 @@ sap.ui.define([
12
12
  *
13
13
  * @private
14
14
  * @author SAP SE
15
- * @version 1.139.0
15
+ * @version 1.141.0
16
16
  * @alias sap.ui.vbm.vector.RectangularSelection
17
17
  */
18
18
 
@@ -223,12 +223,10 @@ sap.ui.define([
223
223
  "Image": currSpot.I ? currSpot.I : "",
224
224
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
225
225
  "Key": currSpot.K ? currSpot.K : "",
226
- "Scale": currSpot.S ? currSpot.S : "",
226
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
227
227
  "DisplayRole": currSpot.R ? currSpot.R : "",
228
228
  "DragData": currSpot.DD ? currSpot.DD : "",
229
229
  "Alignment": currSpot.AL ? currSpot.AL : "",
230
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
231
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
232
230
  "menu": menus,
233
231
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
234
232
  };
@@ -273,15 +271,12 @@ sap.ui.define([
273
271
  "Image": currSpot.I ? currSpot.I : "",
274
272
  "base64": resources.find(resource => resource.name === currSpot.I)?.value || defaultbase64,
275
273
  "Key": currSpot.K ? currSpot.K : "",
276
- "Scale": currSpot.S ? currSpot.S : "",
274
+ "Scale": currSpot.S ? currSpot.S : "1;1;1",
277
275
  "DisplayRole": currSpot.R ? currSpot.R : "",
278
276
  "DragData": currSpot.DD ? currSpot.DD : "",
279
277
  "Alignment": currSpot.AL ? currSpot.AL : "",
280
- "height": resources.find(resource => resource.name === currSpot.I) ? '45px' : '30px',
281
- "width": resources.find(resource => resource.name === currSpot.I) ? '45px' : '24px',
282
278
  "type": "{00100000-2012-0004-B001-64592B8DB964}"
283
-
284
- };
279
+ };
285
280
 
286
281
  let coord_array = currSpot.A.split(";");
287
282
 
@@ -320,7 +315,6 @@ sap.ui.define([
320
315
  let routeProperties = {
321
316
  "GeoPosition": currRoute.A ? currRoute.A : "",
322
317
  "ToolTip": currRoute.B ? currRoute.B : "",
323
- "Label": currRoute.L ? currRoute.L : "",
324
318
  "LabelBGColor": currRoute.LC ? currRoute.LC : "",
325
319
  "LabelAlignment": currRoute.LA ? currRoute.LA : "",
326
320
  "Color": currRoute.C ? VectorUtils.argbToRgba(currRoute.C) : "",
@@ -337,12 +331,31 @@ sap.ui.define([
337
331
  "DotWidth": currRoute.DW ? currRoute.DW : "",
338
332
  "DotColor": currRoute.DC ? currRoute.DC : "",
339
333
  "LineDash": currRoute.LD ? currRoute.LD : "",
334
+ "LineColor": currRoute.F ? currRoute.F : "",
340
335
  "DirectionIndicator": currRoute.DI ? currRoute.DI : "",
341
336
  "DragData": currRoute.DD ? currRoute.DD : "",
342
337
  "type": "{00100000-2012-0004-B001-C46BD7336A1A}"
343
338
  };
339
+ let labeledRoutes = new Set();
340
+ if (currRoute.L) {
341
+ routeProperties["Label"] = currRoute.L;
342
+ // ✅ Only label the first route with this Label
343
+ if (!labeledRoutes.has(currRoute.L)) {
344
+ routeProperties["ShowLabel"] = true;
345
+ labeledRoutes.add(currRoute.L);
346
+ }
347
+ }
348
+ const colorStr = currRoute.F;
349
+ routeProperties["lineLabelTextColor"] = '#000000'; // Default color
350
+
351
+ if (colorStr) {
352
+ const [r, g, b, a] = VectorUtils.parseRGBAString(colorStr);
353
+ routeProperties["lineLabelTextColor"] = VectorUtils.getContrastTextColor(r, g, b);
354
+ const { hexColor, opacity } = VectorUtils.rgbaToHexAndOpacity(colorStr);
355
+ routeProperties["labelHaloColor"] = hexColor;
356
+ routeProperties["opacity"] = opacity;
357
+ }
344
358
 
345
- //itearate through the route points and add the coordinates to the GeoJSON
346
359
  let coord_array = currRoute.H.split(";");
347
360
  let coord_collection = [];
348
361
 
@@ -350,6 +363,7 @@ sap.ui.define([
350
363
  coord_collection.push([Number(coord_array[i]), Number(coord_array[i + 1])])
351
364
  }
352
365
 
366
+
353
367
  let geometry = {
354
368
  "coordinates": coord_collection,
355
369
  "type": "LineString"
@@ -360,7 +374,7 @@ sap.ui.define([
360
374
  "properties": routeProperties,
361
375
  "geometry": geometry,
362
376
  // "id" : currRoute['VB:ix'],
363
- "id": route_id++,
377
+ "id": route_id++
364
378
  };
365
379
  let indexNum = featureCollection.findIndex(item => item.properties.Key === route_data.properties.Key)
366
380
  if (indexNum !== -1) {
@@ -378,7 +392,6 @@ sap.ui.define([
378
392
  let routeProperties = {
379
393
  "GeoPosition": currRoute.A ? currRoute.A : "",
380
394
  "ToolTip": currRoute.B ? currRoute.B : "",
381
- "Label": currRoute.L ? currRoute.L : "",
382
395
  "LabelBGColor": currRoute.LC ? currRoute.LC : "",
383
396
  "LabelAlignment": currRoute.LA ? currRoute.LA : "",
384
397
  "Color": currRoute.C ? VectorUtils.argbToRgba(currRoute.C) : "",
@@ -395,11 +408,32 @@ sap.ui.define([
395
408
  "DotWidth": currRoute.DW ? currRoute.DW : "",
396
409
  "DotColor": currRoute.DC ? currRoute.DC : "",
397
410
  "LineDash": currRoute.LD ? currRoute.LD : "",
411
+ "LineColor": currRoute.F ? currRoute.F : "",
398
412
  "DirectionIndicator": currRoute.DI ? currRoute.DI : "",
399
413
  "DragData": currRoute.DD ? currRoute.DD : "",
400
414
  "type": "{00100000-2012-0004-B001-C46BD7336A1A}"
415
+
401
416
 
402
417
  };
418
+ let labeledRoutes = new Set();
419
+ if (currRoute.L) {
420
+ routeProperties["Label"] = currRoute.L;
421
+ // ✅ Only label the first route with this Label
422
+ if (!labeledRoutes.has(currRoute.L)) {
423
+ routeProperties["ShowLabel"] = true;
424
+ labeledRoutes.add(currRoute.L);
425
+ }
426
+ }
427
+ const colorStr = currRoute.F;
428
+ routeProperties["lineLabelTextColor"] = '#000000'; // Default color
429
+
430
+ if (colorStr) {
431
+ const [r, g, b, a] = VectorUtils.parseRGBAString(colorStr);
432
+ routeProperties["lineLabelTextColor"] = VectorUtils.getContrastTextColor(r, g, b);
433
+ const { hexColor, opacity } = VectorUtils.rgbaToHexAndOpacity(colorStr);
434
+ routeProperties["labelHaloColor"] = hexColor;
435
+ routeProperties["opacity"] = opacity;
436
+ }
403
437
 
404
438
  //itearate through the route points and add the coordinates to the GeoJSON
405
439
  let coord_array = currRoute.H.split(";");
@@ -775,6 +809,13 @@ sap.ui.define([
775
809
  }
776
810
  }
777
811
 
812
+ if (obj.SAPVB.Data.Set && (typeof obj.SAPVB.Data.Set === 'object') && !(jQuery.isEmptyObject(obj.SAPVB.Data.Set))) {
813
+ if (!Array.isArray(obj.SAPVB.Data.Set) && !(obj.SAPVB.Data.Set.name) && !(obj.SAPVB.Data.Set.type)) {
814
+ //Full Update - Replace complete Data Section
815
+ featureCollection.splice(0, featureCollection.length);
816
+ }
817
+ }
818
+
778
819
  }
779
820
 
780
821
  // Get the datatypes
@@ -34,18 +34,28 @@ sap.ui.define([
34
34
  });
35
35
  };
36
36
 
37
- VectorUtils.createSpotElement = (marker) => {
38
- // create a DOM element for the marker (parent div)
37
+ VectorUtils.createSpotElement = (marker, spotid) => {
39
38
  const el = document.createElement('div');
40
-
41
- // Set background image for the marker
42
- var base64decoded = "data:image/png;base64," + marker.properties.base64;
39
+ const base64decoded = "data:image/png;base64," + (marker.properties.base64 || "");
40
+ el.id = '__mapmarker' + spotid++;
43
41
  el.style.backgroundImage = `url(${base64decoded})`;
44
- el.style.width = marker.properties.width;
45
- el.style.height = marker.properties.height;
46
- el.style.backgroundSize = 'cover'; // Ensure image fits
47
- return el;
42
+ el.style.backgroundSize = 'cover';
43
+ el.style.pointerEvents = 'none';
44
+ el.style.display = 'inline-block';
45
+ el.style.transform = 'translate(-50%, -100%)';
46
+
47
+ // load the image to get natural size
48
+ const img = new Image();
49
+ img.src = base64decoded;
50
+ img.onload = () => {
51
+ const scaleParts = (marker.properties.Scale || "1;1;1").split(';').map(Number);
52
+ const [sx, sy] = scaleParts.some(isNaN) ? [1, 1] : [scaleParts[0], scaleParts[1]];
53
+ el.style.width = `${img.naturalWidth * sx}px`;
54
+ el.style.height = `${img.naturalHeight * sy}px`;
55
+ };
56
+ return {spotEl:el, spotId:spotid};
48
57
  };
58
+
49
59
  VectorUtils.isAccepted = (drag, drop) => {
50
60
  var validDrop = drag.some(item => drop.includes(item));
51
61
  return validDrop;
@@ -65,10 +75,10 @@ sap.ui.define([
65
75
  return child_el;
66
76
  }
67
77
  //Function to set the canvas id
68
- VectorUtils._setcanvasid = () => {
69
- var mapCanvas = '__mapcanvas';
78
+ VectorUtils._setcanvasid = () => {
79
+ var mapCanvas = '__mapcanvas';
70
80
  return mapCanvas;
71
- }
81
+ }
72
82
 
73
83
  VectorUtils.createDropdownMenu = (menuData) => {
74
84
  const dropdown = document.createElement('div');
@@ -232,6 +242,107 @@ sap.ui.define([
232
242
 
233
243
  return windowContainer;
234
244
  };
245
+
246
+ VectorUtils.createMarkerLabel = (label, labelcolor) => {
247
+ var r, g, b, a;
248
+ const obj = document.createElement('div');
249
+ obj.className = 'marker-label';
250
+ obj.textContent = label;
251
+ obj.style.color = labelcolor;
252
+ obj.style.position = 'absolute';
253
+ obj.style.top = '100%';
254
+ if (!labelcolor) {
255
+ [r, g, b, a] = [211, 211, 211, 1];
256
+ } else {
257
+ [r, g, b, a] = VectorUtils.parseRGBAString(labelcolor);
258
+ }
259
+ obj.style.backgroundColor = `rgba(${r}, ${g}, ${b}, ${a})`;
260
+ obj.style.border = `2px solid rgba(${r}, ${g}, ${b}, ${a})`;
261
+ const textColor = VectorUtils.getContrastTextColor(r, g, b);
262
+ obj.style.color = textColor;
263
+ obj.style.fontFamily = 'Arial, sans-serif';
264
+ obj.style.fontSize = '14px';
265
+ obj.style.padding = '2px 6px';
266
+ obj.style.borderRadius = '4px';
267
+ obj.style.whiteSpace = 'pre-wrap';
268
+ obj.style.boxSizing = 'border-box';
269
+ obj.style.textAlign = 'center';
270
+
271
+ return obj;
272
+ }
273
+
274
+ VectorUtils.createRouteLabel = (label, labelcolor) => {
275
+ let r, g, b, a;
276
+ const obj = document.createElement('div');
277
+ obj.className = 'route-label';
278
+ obj.textContent = label;
279
+
280
+ if (!labelcolor) {
281
+ [r, g, b, a] = [211, 211, 211, 1];
282
+ } else {
283
+ [r, g, b, a] = VectorUtils.parseRGBAString(labelcolor);
284
+ }
285
+
286
+ const textColor = VectorUtils.getContrastTextColor(r, g, b);
287
+
288
+ obj.style.backgroundColor = `rgba(${r}, ${g}, ${b}, ${a})`;
289
+ obj.style.border = `2px solid rgba(${r}, ${g}, ${b}, ${a})`;
290
+ obj.style.color = textColor;
291
+ obj.style.fontFamily = 'Arial, sans-serif';
292
+ obj.style.fontSize = '14px';
293
+ obj.style.padding = '2px 6px';
294
+ obj.style.borderRadius = '4px';
295
+ obj.style.whiteSpace = 'pre-wrap';
296
+ obj.style.boxSizing = 'border-box';
297
+ obj.style.textAlign = 'center';
298
+
299
+ return obj;
300
+ };
301
+
302
+ VectorUtils.rgbaToHexAndOpacity = (rgbaString) => {
303
+ const rgbaRegex = /rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d*\.?\d+)\s*\)/i;
304
+ const match = rgbaString.match(rgbaRegex);
305
+
306
+ if (!match) {
307
+ throw new Error("Invalid RGBA format");
308
+ }
309
+
310
+ const r = parseInt(match[1], 10);
311
+ const g = parseInt(match[2], 10);
312
+ const b = parseInt(match[3], 10);
313
+ const a = parseFloat(match[4]);
314
+
315
+ const toHex = (value) => value.toString(16).padStart(2, '0');
316
+
317
+ const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
318
+
319
+ return {
320
+ hexColor: hex,
321
+ opacity: a
322
+ };
323
+ }
324
+
325
+
326
+ VectorUtils.parseRGBAString = (rgbaStr) => {
327
+ const match = rgbaStr.match(/rgba?\s*\(\s*(\d+),\s*(\d+),\s*(\d+),\s*(\d+)\s*\)/i);
328
+
329
+ if (!match) return null;
330
+
331
+ const r = parseInt(match[1]);
332
+ const g = parseInt(match[2]);
333
+ const b = parseInt(match[3]);
334
+ const a = parseInt(match[4]) / 255;
335
+
336
+ return [r, g, b, parseFloat(a.toFixed(3))];
337
+ }
338
+
339
+ VectorUtils.getContrastTextColor = (r, g, b) => {
340
+ if (r === 0 && g === 0 && b === 0) {
341
+ return '#000000';
342
+ }
343
+ const brightness = 0.299 * r + 0.587 * g + 0.114 * b;
344
+ return brightness < 128 ? '#FFFFFF' : '#000000';
345
+ }
235
346
  VectorUtils.createSubCaption = (item) => {
236
347
  const obj = document.createElement('div');
237
348
  obj.setAttribute("role", sap.ui.core.AccessibleRole.Secondary);