@sapui5/sap.suite.ui.commons 1.136.12 → 1.136.15

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 (117) hide show
  1. package/package.json +1 -1
  2. package/src/sap/suite/ui/commons/.library +1 -1
  3. package/src/sap/suite/ui/commons/AriaProperties.js +1 -1
  4. package/src/sap/suite/ui/commons/CalculationBuilder.js +1 -1
  5. package/src/sap/suite/ui/commons/CalculationBuilderExpression.js +1 -1
  6. package/src/sap/suite/ui/commons/CalculationBuilderFunction.js +1 -1
  7. package/src/sap/suite/ui/commons/CalculationBuilderGroup.js +1 -1
  8. package/src/sap/suite/ui/commons/CalculationBuilderItem.js +1 -1
  9. package/src/sap/suite/ui/commons/CalculationBuilderValidationResult.js +1 -1
  10. package/src/sap/suite/ui/commons/CalculationBuilderVariable.js +1 -1
  11. package/src/sap/suite/ui/commons/CloudFilePicker.js +1 -1
  12. package/src/sap/suite/ui/commons/MicroProcessFlow.js +1 -1
  13. package/src/sap/suite/ui/commons/MicroProcessFlowItem.js +1 -1
  14. package/src/sap/suite/ui/commons/TimelineRenderManager.js +8 -4
  15. package/src/sap/suite/ui/commons/flexibility/changeHandler/PropertyChangeMapper.js +1 -1
  16. package/src/sap/suite/ui/commons/imageeditor/CropCustomShapeHistoryItem.js +1 -1
  17. package/src/sap/suite/ui/commons/imageeditor/CropEllipseHistoryItem.js +1 -1
  18. package/src/sap/suite/ui/commons/imageeditor/CropRectangleHistoryItem.js +1 -1
  19. package/src/sap/suite/ui/commons/imageeditor/CustomSizeItem.js +1 -1
  20. package/src/sap/suite/ui/commons/imageeditor/FilterHistoryItem.js +1 -1
  21. package/src/sap/suite/ui/commons/imageeditor/FlipHistoryItem.js +1 -1
  22. package/src/sap/suite/ui/commons/imageeditor/HistoryItem.js +1 -1
  23. package/src/sap/suite/ui/commons/imageeditor/ImageEditor.js +1 -1
  24. package/src/sap/suite/ui/commons/imageeditor/ImageEditorContainer.js +1 -1
  25. package/src/sap/suite/ui/commons/imageeditor/ImageEditorResponsiveContainer.js +1 -1
  26. package/src/sap/suite/ui/commons/imageeditor/ResizeHistoryItem.js +1 -1
  27. package/src/sap/suite/ui/commons/imageeditor/RotateHistoryItem.js +1 -1
  28. package/src/sap/suite/ui/commons/library.js +100 -3
  29. package/src/sap/suite/ui/commons/messagebundle.properties +73 -12
  30. package/src/sap/suite/ui/commons/messagebundle_ar.properties +39 -5
  31. package/src/sap/suite/ui/commons/messagebundle_bg.properties +39 -5
  32. package/src/sap/suite/ui/commons/messagebundle_ca.properties +39 -5
  33. package/src/sap/suite/ui/commons/messagebundle_cnr.properties +39 -5
  34. package/src/sap/suite/ui/commons/messagebundle_cs.properties +38 -4
  35. package/src/sap/suite/ui/commons/messagebundle_cy.properties +39 -5
  36. package/src/sap/suite/ui/commons/messagebundle_da.properties +38 -4
  37. package/src/sap/suite/ui/commons/messagebundle_de.properties +39 -5
  38. package/src/sap/suite/ui/commons/messagebundle_el.properties +39 -5
  39. package/src/sap/suite/ui/commons/messagebundle_en.properties +39 -5
  40. package/src/sap/suite/ui/commons/messagebundle_en_GB.properties +39 -5
  41. package/src/sap/suite/ui/commons/messagebundle_en_US_sappsd.properties +99 -28
  42. package/src/sap/suite/ui/commons/messagebundle_en_US_saprigi.properties +39 -5
  43. package/src/sap/suite/ui/commons/messagebundle_en_US_saptrc.properties +600 -537
  44. package/src/sap/suite/ui/commons/messagebundle_es.properties +39 -5
  45. package/src/sap/suite/ui/commons/messagebundle_es_MX.properties +38 -4
  46. package/src/sap/suite/ui/commons/messagebundle_et.properties +38 -4
  47. package/src/sap/suite/ui/commons/messagebundle_fi.properties +38 -4
  48. package/src/sap/suite/ui/commons/messagebundle_fr.properties +39 -5
  49. package/src/sap/suite/ui/commons/messagebundle_fr_CA.properties +40 -6
  50. package/src/sap/suite/ui/commons/messagebundle_hi.properties +39 -5
  51. package/src/sap/suite/ui/commons/messagebundle_hr.properties +39 -5
  52. package/src/sap/suite/ui/commons/messagebundle_hu.properties +39 -5
  53. package/src/sap/suite/ui/commons/messagebundle_id.properties +39 -5
  54. package/src/sap/suite/ui/commons/messagebundle_it.properties +44 -10
  55. package/src/sap/suite/ui/commons/messagebundle_iw.properties +39 -5
  56. package/src/sap/suite/ui/commons/messagebundle_ja.properties +39 -5
  57. package/src/sap/suite/ui/commons/messagebundle_kk.properties +38 -4
  58. package/src/sap/suite/ui/commons/messagebundle_ko.properties +38 -4
  59. package/src/sap/suite/ui/commons/messagebundle_lt.properties +39 -5
  60. package/src/sap/suite/ui/commons/messagebundle_lv.properties +39 -5
  61. package/src/sap/suite/ui/commons/messagebundle_mk.properties +39 -5
  62. package/src/sap/suite/ui/commons/messagebundle_ms.properties +39 -5
  63. package/src/sap/suite/ui/commons/messagebundle_nl.properties +38 -4
  64. package/src/sap/suite/ui/commons/messagebundle_no.properties +39 -5
  65. package/src/sap/suite/ui/commons/messagebundle_pl.properties +39 -5
  66. package/src/sap/suite/ui/commons/messagebundle_pt.properties +39 -5
  67. package/src/sap/suite/ui/commons/messagebundle_pt_PT.properties +39 -5
  68. package/src/sap/suite/ui/commons/messagebundle_ro.properties +39 -5
  69. package/src/sap/suite/ui/commons/messagebundle_ru.properties +39 -5
  70. package/src/sap/suite/ui/commons/messagebundle_sh.properties +39 -5
  71. package/src/sap/suite/ui/commons/messagebundle_sk.properties +39 -5
  72. package/src/sap/suite/ui/commons/messagebundle_sl.properties +38 -4
  73. package/src/sap/suite/ui/commons/messagebundle_sr.properties +39 -5
  74. package/src/sap/suite/ui/commons/messagebundle_sv.properties +38 -4
  75. package/src/sap/suite/ui/commons/messagebundle_th.properties +39 -5
  76. package/src/sap/suite/ui/commons/messagebundle_tr.properties +39 -5
  77. package/src/sap/suite/ui/commons/messagebundle_uk.properties +38 -4
  78. package/src/sap/suite/ui/commons/messagebundle_vi.properties +39 -5
  79. package/src/sap/suite/ui/commons/messagebundle_zh_CN.properties +39 -5
  80. package/src/sap/suite/ui/commons/messagebundle_zh_TW.properties +39 -5
  81. package/src/sap/suite/ui/commons/networkgraph/ElementBase.js +19 -1
  82. package/src/sap/suite/ui/commons/networkgraph/Graph.js +562 -45
  83. package/src/sap/suite/ui/commons/networkgraph/GraphMap.js +25 -3
  84. package/src/sap/suite/ui/commons/networkgraph/GraphRenderer.js +19 -8
  85. package/src/sap/suite/ui/commons/networkgraph/KeyboardNavigator.js +367 -12
  86. package/src/sap/suite/ui/commons/networkgraph/Line.js +814 -22
  87. package/src/sap/suite/ui/commons/networkgraph/Node.js +573 -79
  88. package/src/sap/suite/ui/commons/networkgraph/Tooltip.js +4 -0
  89. package/src/sap/suite/ui/commons/networkgraph/Utils.js +249 -10
  90. package/src/sap/suite/ui/commons/networkgraph/layout/NoopLayout.js +77 -7
  91. package/src/sap/suite/ui/commons/networkgraph/util/ConnectionPathUtils.js +1420 -0
  92. package/src/sap/suite/ui/commons/networkgraph/util/CreateConnectionPopover.js +374 -0
  93. package/src/sap/suite/ui/commons/networkgraph/util/DependencyLayoutHelper.js +1032 -0
  94. package/src/sap/suite/ui/commons/networkgraph/util/DragDropManager.js +721 -0
  95. package/src/sap/suite/ui/commons/networkgraph/util/PortManager.js +582 -0
  96. package/src/sap/suite/ui/commons/statusindicator/Circle.js +1 -1
  97. package/src/sap/suite/ui/commons/statusindicator/CustomShape.js +1 -1
  98. package/src/sap/suite/ui/commons/statusindicator/DiscreteThreshold.js +1 -1
  99. package/src/sap/suite/ui/commons/statusindicator/FillingOption.js +1 -1
  100. package/src/sap/suite/ui/commons/statusindicator/LibraryShape.js +1 -1
  101. package/src/sap/suite/ui/commons/statusindicator/Path.js +1 -1
  102. package/src/sap/suite/ui/commons/statusindicator/PropertyThreshold.js +1 -1
  103. package/src/sap/suite/ui/commons/statusindicator/Rectangle.js +1 -1
  104. package/src/sap/suite/ui/commons/statusindicator/Shape.js +1 -1
  105. package/src/sap/suite/ui/commons/statusindicator/ShapeGroup.js +1 -1
  106. package/src/sap/suite/ui/commons/statusindicator/SimpleShape.js +1 -1
  107. package/src/sap/suite/ui/commons/statusindicator/StatusIndicator.js +1 -1
  108. package/src/sap/suite/ui/commons/taccount/TAccount.js +1 -1
  109. package/src/sap/suite/ui/commons/taccount/TAccountGroup.js +1 -1
  110. package/src/sap/suite/ui/commons/taccount/TAccountItem.js +1 -1
  111. package/src/sap/suite/ui/commons/taccount/TAccountItemProperty.js +1 -1
  112. package/src/sap/suite/ui/commons/taccount/TAccountPanel.js +1 -1
  113. package/src/sap/suite/ui/commons/themes/base/NetworkGraph.less +26 -13
  114. package/src/sap/suite/ui/commons/themes/base/NetworkGroup.less +4 -0
  115. package/src/sap/suite/ui/commons/themes/base/NetworkLine.less +58 -13
  116. package/src/sap/suite/ui/commons/themes/base/NetworkNode.less +251 -47
  117. package/src/sap/suite/ui/commons/themes/base/SemanticColorMixins.less +55 -0
@@ -31,7 +31,10 @@ sap.ui.define([
31
31
  "sap/ui/performance/Measurement",
32
32
  "sap/base/security/encodeXML",
33
33
  "sap/m/ToggleButton",
34
+ "sap/m/BusyIndicator",
34
35
  "sap/m/library",
36
+ "sap/m/IllustratedMessage",
37
+ "sap/m/IllustratedMessageType",
35
38
  "sap/suite/ui/commons/util/FullScreenUtil",
36
39
  "sap/ui/core/InvisibleMessage",
37
40
  "sap/ui/core/library",
@@ -42,7 +45,10 @@ sap.ui.define([
42
45
  "sap/ui/core/RenderManager",
43
46
  "sap/ui/core/Theming",
44
47
  'sap/ui/core/InvisibleText',
45
- "./GraphRenderer"
48
+ "./GraphRenderer",
49
+ "./util/DragDropManager",
50
+ "./util/PortManager",
51
+ "sap/ui/core/IconPool"
46
52
  ], function (
47
53
  library,
48
54
  jQuery,
@@ -69,7 +75,10 @@ sap.ui.define([
69
75
  Measurement,
70
76
  encodeXML,
71
77
  ToggleButton,
78
+ BusyIndicator,
72
79
  MobileLibrary,
80
+ IllustratedMessage,
81
+ IllustratedMessageType,
73
82
  FullScreenUtil,
74
83
  InvisibleMessage,
75
84
  coreLibrary,
@@ -80,7 +89,10 @@ sap.ui.define([
80
89
  RenderManager,
81
90
  Theming,
82
91
  InvisibleText,
83
- GraphRenderer
92
+ GraphRenderer,
93
+ DragDropManager,
94
+ PortManager,
95
+ IconPool
84
96
  ) {
85
97
  "use strict";
86
98
 
@@ -89,7 +101,8 @@ sap.ui.define([
89
101
  Orientation = library.networkgraph.Orientation,
90
102
  LayoutRenderType = library.networkgraph.LayoutRenderType,
91
103
  RenderType = library.networkgraph.RenderType,
92
- SemanticColorType = library.SemanticColorType;
104
+ SemanticColorType = library.SemanticColorType,
105
+ NodePorts = library.networkgraph.NodePorts;
93
106
 
94
107
  var AGG_NODES = "nodes",
95
108
  AGG_LINES = "lines",
@@ -136,6 +149,7 @@ sap.ui.define([
136
149
  var Graph = SvgBase.extend("sap.suite.ui.commons.networkgraph.Graph", {
137
150
  metadata: {
138
151
  library: "sap.suite.ui.commons",
152
+ dnd: { draggable: false, droppable: true },
139
153
  properties: {
140
154
  /**
141
155
  * The height of the graph. If this property is set to 'auto', the network graph will be resized to fit the height of its content, regardless of the height of the parent control.
@@ -205,15 +219,96 @@ sap.ui.define([
205
219
  noDataText: {
206
220
  type: "string", group: "Behavior", defaultValue: ""
207
221
  },
222
+ /**
223
+ * Set this property to <code>true</code> to display a loading indicator while the data loads.
224
+ * @public
225
+ * @since 1.136.19
226
+ */
227
+ loading: {
228
+ type: "boolean", group: "Behavior", defaultValue: false
229
+ },
230
+ /**
231
+ * Text that is displayed when the loading is set. <br> This property takes effect only when the <code>loading</code> property is set to <code>true</code>.
232
+ * @public
233
+ * @since 1.136.19
234
+ */
235
+ loadingText: {
236
+ type: "string", group: "Behavior", defaultValue: ""
237
+ },
208
238
  /**
209
239
  * Adds delay in wheel scrolling to make zooming smooth.
210
240
  * Only works when enableWheelZoom is set to true or 'ctrl' key is pressed while wheel scrolling.
211
241
  * Add delay in milliseconds.
212
242
  *
213
- * @private since 1.125
243
+ * @private
214
244
  */
215
245
  _smoothWheelZoom: {
216
246
  type: "int", group: "Behavior", defaultValue: 125, visibility: "hidden"
247
+ },
248
+ /**
249
+ * Enables the drag and drop of nodes. This property is ignored if the layout property is not set to noop.
250
+ * If set to <code>true</code>, nodes can be dragged and dropped within the graph.
251
+ * @public
252
+ * @since 1.136.19
253
+ */
254
+ enableDragAndDrop: {
255
+ type: "boolean", group: "Behavior", defaultValue: false
256
+ },
257
+ /**
258
+ * Specifies the ports that are to be displayed on nodes. Ports are used for creating connections between nodes.
259
+ * Ports are available only when the layout algorithm is set to "NoopLayout", and when the drag and drop is enabled. Otherwise, this property is ignored.
260
+ * @public
261
+ * @since 1.136.19
262
+ */
263
+ nodePorts: {
264
+ type: "sap.suite.ui.commons.networkgraph.NodePorts", group: "Behavior", defaultValue: NodePorts.None
265
+ },
266
+ /**
267
+ * This action button is used to create connections between nodes as an accessible alternative to node ports.
268
+ * The button is displayed on each node when the layout algorithm is set to "NoopLayout" and drag and drop is enabled.
269
+ * shows the 'Create Connection' action button on node.
270
+ * If set to <code>false</code>, the button remains hidden.
271
+ * Hide this button when you want to implement your own way of creating connections between nodes as an accessible alternative to node ports.
272
+ * @public
273
+ * @since 1.136.19
274
+ */
275
+ showCreateConnectionButton: {
276
+ type: "boolean", group: "Behavior", defaultValue: true
277
+ },
278
+ /**
279
+ * Mapping of connection types to their display text keys or custom text values.
280
+ * This allows customization of how connection types are displayed in the connection creation popover.
281
+ * The mapping should be an object where keys are connection type values (LeftToLeft, LeftToRight, RightToLeft, RightToRight)
282
+ * and values are custom text that follows the correct format (e.g., "Start to End", "Source to Target").
283
+ * If the format is invalid or not provided, default values are used
284
+ * @public
285
+ * @since 1.136.19
286
+ */
287
+ connectionTypeMapping: {
288
+ type: "object", group: "Behavior", defaultValue: {
289
+ "LeftToLeft": "Start to Start",
290
+ "LeftToRight": "Start to Finish",
291
+ "RightToLeft": "Finish to Start",
292
+ "RightToRight": "Finish to Finish"
293
+ }
294
+ },
295
+ /**
296
+ * Custom labels for element types displayed in the SearchField suggestions and Legend section headers.
297
+ * Supported keys: nodeLabel, nodeLabelPlural, lineLabel, lineLabelPlural, groupLabel, groupLabelPlural.
298
+ * Reverts to the default values for keys that are not set.
299
+ * @public
300
+ * @since 1.149
301
+ */
302
+ labels: {
303
+ type: "object", group: "Appearance", defaultValue: {}
304
+ },
305
+ /**
306
+ * Enables enhanced line routing for the network graph.
307
+ * When set to <code>true</code>, overlapping connections are visually separated.
308
+ * @public
309
+ */
310
+ enableEnhancedLineRouting: {
311
+ type: "boolean", group: "Behavior", defaultValue: false
217
312
  }
218
313
  },
219
314
  aggregations: {
@@ -264,7 +359,12 @@ sap.ui.define([
264
359
  /**
265
360
  * Controls or IDs that label this control. This association is used by screen reader software.
266
361
  */
267
- ariaLabelledBy: { type: "sap.ui.core.Control", multiple: true, singularName: "ariaLabelledBy" }
362
+ ariaLabelledBy: { type: "sap.ui.core.Control", multiple: true, singularName: "ariaLabelledBy" },
363
+ /**
364
+ * Control or ID of an auxiliary control associated with this graph.
365
+ * @since 1.136.19
366
+ */
367
+ associatedControl: { type: "sap.ui.core.Control", multiple: false, singularName: "associatedControl" }
268
368
  },
269
369
  events: {
270
370
  /**
@@ -327,7 +427,79 @@ sap.ui.define([
327
427
  term: { type: "string" },
328
428
  key: { type: "string" }
329
429
  }
330
- }
430
+ },
431
+ /**
432
+ * This event is fired when a user drops a node in the graph.
433
+ * This event is available only when the layout algorithm is set to "NoopLayout" and the <code>enableDragAndDrop</code> property is set to <code>true</code>.
434
+ * @public
435
+ * @since 1.136.19
436
+ */
437
+ nodeDropped: {
438
+ parameters: {
439
+ /**
440
+ * The node that was moved.
441
+ */
442
+ node: { type: "sap.suite.ui.commons.networkgraph.Node" },
443
+ /**
444
+ * The new x coordinate of the node.
445
+ */
446
+ newX: { type: "float" },
447
+ /**
448
+ * The new y coordinate of the node.
449
+ */
450
+ newY: { type: "float" }
451
+ }
452
+ },
453
+ /**
454
+ * This event is fired when a new connection is created between two nodes by using node ports.
455
+ * @public
456
+ * @since 1.136.19
457
+ */
458
+ connectionCreated: {
459
+ parameters: {
460
+ /**
461
+ * The key of the source node.
462
+ **/
463
+ from: { type: "string" },
464
+ /**
465
+ * The key of the target node.
466
+ **/
467
+ to: { type: "string" },
468
+ /**
469
+ * The connection type defining how the line connects the source and target nodes.
470
+ */
471
+ connectionType: {type: "sap.suite.ui.commons.networkgraph.ConnectionType"},
472
+ /**
473
+ * The source node control instance.
474
+ **/
475
+ fromNode: { type: "sap.suite.ui.commons.networkgraph.Node" },
476
+ /**
477
+ * The target node control instance.
478
+ **/
479
+ toNode: { type: "sap.suite.ui.commons.networkgraph.Node" }
480
+ }
481
+ },
482
+ /**
483
+ * This event is fired when a user presses the delete key on a focused node or line.
484
+ * This event is available only when the layout algorithm is set to "NoopLayout" and the <code>enableDragAndDrop</code> property is set to <code>true</code>.
485
+ * @public
486
+ * @since 1.136.19
487
+ */
488
+ itemDeleted: {
489
+ parameters: {
490
+ /**
491
+ * The item (node or line) that is to be deleted.
492
+ */
493
+ item: { type: "sap.suite.ui.commons.networkgraph.ElementBase" }
494
+ }
495
+ },
496
+ /**
497
+ * Fired when the user requests to add a node via INSERT or Ctrl+Alt+N.
498
+ * Only available when NoopLayout is used and enableDragAndDrop is <code>true</code>.
499
+ * @public
500
+ * @since 1.136.19
501
+ */
502
+ nodeAdded: {}
331
503
  }
332
504
  }
333
505
  });
@@ -388,6 +560,9 @@ sap.ui.define([
388
560
  // RTL mode - it's reset in 'onBeforeRendering' in case it changed runtime
389
561
  this._bIsRtl = Localization.getRTL();
390
562
 
563
+ // Private variable for multiple directed arrows feature
564
+ this._enableMultipleDirectedArrows = false;
565
+
391
566
  // element with focus
392
567
  this._oFocus = null;
393
568
 
@@ -406,8 +581,71 @@ sap.ui.define([
406
581
  // flag to check if the events has been added to the graph
407
582
  this._bEventsAdded = false;
408
583
 
584
+ // illustrated message instance for empty state
585
+ this._oIllustratedMessage = null;
586
+
409
587
  this._createToolbar();
410
588
 
589
+ /**
590
+ * Attach drag and drop events
591
+ */
592
+ if (this.getDragDropConfig().length === 0) {
593
+ try {
594
+ DragDropManager.injectDnD(this);
595
+ } catch (error) {
596
+ Log.warning("Graph injectDnD issue: ", error);
597
+ }
598
+ }
599
+ // Initialize PortManager with this graph instance
600
+ PortManager.setGraphInstance(this);
601
+ Core.ready(this._handleCoreInitialized.bind(this));
602
+
603
+ };
604
+
605
+ /**
606
+ * Handler for the core's init event. Attaches listener for localization changes.
607
+ * @private
608
+ */
609
+ Graph.prototype._handleCoreInitialized = function () {
610
+ Localization.attachChange(this._handleLocalizationChanged.bind(this));
611
+ };
612
+
613
+ /**
614
+ * Handler for localization changes. Sets a pending flag when RTL mode changes so that
615
+ * node dimensions are re-measured after RTL CSS files finish loading.
616
+ * UI5 automatically re-renders all UIAreas on RTL change; the flag prevents premature
617
+ * layout calculation in onAfterRendering before CSS dimensions are stable.
618
+ * @private
619
+ */
620
+ Graph.prototype._handleLocalizationChanged = function () {
621
+ const bNewRtl = Localization.getRTL();
622
+ if (this._bIsRtl !== bNewRtl) {
623
+ this._bIsRtl = bNewRtl;
624
+ this._bRtlMeasurementPending = true;
625
+
626
+ const fnOnApplied = function () {
627
+ Theming.detachApplied(fnOnApplied);
628
+ if (this._bRtlMeasurementPending) {
629
+ this._bRtlMeasurementPending = false;
630
+ this._measureAndLayout();
631
+ }
632
+ }.bind(this);
633
+ Theming.attachApplied(fnOnApplied);
634
+ }
635
+ };
636
+
637
+ Graph.prototype._measureAndLayout = function () {
638
+ var aNodes = this.getNodes();
639
+ aNodes.forEach(function (oNode) {
640
+ if (this._isUseNodeHtml()) {
641
+ oNode._setupDivDimensions();
642
+ } else {
643
+ oNode.calculateSizes();
644
+ oNode._setupWidthAndHeight();
645
+ }
646
+ }.bind(this));
647
+ this._bTriggerLayoutCalculation = true;
648
+ this._preprocessData();
411
649
  };
412
650
 
413
651
  Graph.prototype.onBeforeRendering = function () {
@@ -467,7 +705,6 @@ sap.ui.define([
467
705
  this.$().addClass("sapSuiteUiCommonsNetworkGraphFullScreen");
468
706
  }
469
707
 
470
-
471
708
  if (aNodes.length === 0 || this._bIsInvalid || this.getNoData()) {
472
709
  if (this._bIsInvalid) {
473
710
  oRm.openStart("span");
@@ -529,29 +766,18 @@ sap.ui.define([
529
766
  oRm.flush(this._$innerscroller[0], true, this._$innerscroller.children().length);
530
767
  }
531
768
 
532
- // make sure everything is rendered
533
- aNodes.forEach(function (oNode) {
534
- if (this._isUseNodeHtml()) {
535
- // call after rendering before layouter starts - can be handy when user custom renders
536
- oNode._setupDivDimensions();
537
- } else {
538
- oNode.calculateSizes();
539
- oNode._setupWidthAndHeight();
540
- }
541
- }.bind(this));
542
-
543
- this._preprocessData();
544
- Theming.detachApplied(fnProcess);
769
+ if (!this._bRtlMeasurementPending) {
770
+ this._measureAndLayout();
771
+ }
545
772
  }.bind(this);
546
773
 
547
- // In case theme is applied fnProcess will be called immediately,
548
- // else it will be called once theme is applied.
549
- Theming.attachApplied(fnProcess);
774
+ fnProcess();
550
775
  }
551
776
  this.oInvisibleMessage = InvisibleMessage.getInstance();
552
777
  oRm.destroy();
553
778
 
554
779
  };
780
+
555
781
  Graph.prototype.exit = function () {
556
782
  // if (this.oHashChanger) {
557
783
  // this.oHashChanger.destroy();
@@ -559,6 +785,20 @@ sap.ui.define([
559
785
  if (this._oFullScreenUtil) {
560
786
  this._oFullScreenUtil.cleanUpFullScreen(this);
561
787
  }
788
+
789
+ // Clean up busy indicator
790
+ if (this._oBusyIndicator) {
791
+ this._oBusyIndicator.destroy();
792
+ this._oBusyIndicator = null;
793
+ }
794
+
795
+ // Clean up illustrated message
796
+ if (this._oIllustratedMessage) {
797
+ this._oIllustratedMessage.destroy();
798
+ this._oIllustratedMessage = null;
799
+ }
800
+
801
+ DragDropManager.removeDnD(this);
562
802
  };
563
803
  /* =========================================================== */
564
804
  /* Pseudo events and event triggers */
@@ -589,6 +829,7 @@ sap.ui.define([
589
829
  /**
590
830
  * Returns <code>true</code> if the graph is in full screen mode.
591
831
  * @public
832
+ * @returns {boolean} Returns whether the graph is in full screen mode.
592
833
  */
593
834
  Graph.prototype.isFullScreen = function () {
594
835
  return this._bIsFullScreen;
@@ -723,6 +964,33 @@ sap.ui.define([
723
964
  return this._mNodes[sKey];
724
965
  };
725
966
 
967
+ /**
968
+ * Re-rendering a node and all connected lines to update the positions of both the node and the lines.
969
+ * Note: This method should be used only when the layout algorithm is set to NoopLayout and enableDragAndDrop is set to true.
970
+ *
971
+ * @param {sap.suite.ui.commons.networkgraph.Node|string} vNode Node instance or node key
972
+ * @param {number} iX New X coordinate
973
+ * @param {number} iY New Y coordinate
974
+ * @returns {sap.suite.ui.commons.networkgraph.Graph} Reference to this for method chaining
975
+ * @public
976
+ * @since 1.136.19
977
+ */
978
+ Graph.prototype.updateNodePosition = function (vNode, iX, iY) {
979
+ if (!this._isDnDEnabled()) {
980
+ return this;
981
+ }
982
+
983
+ var oNode = typeof vNode === "string" ? this.getNodeByKey(vNode) : vNode;
984
+
985
+ if (!oNode) {
986
+ Log.warning("Node not found", "updateNodePosition", "sap.suite.ui.commons.networkgraph.Graph");
987
+ return this;
988
+ }
989
+
990
+ this.invalidate();
991
+ return this;
992
+ };
993
+
726
994
  /**
727
995
  * Sets a custom label for the legend.
728
996
  * @param {object} mArguments Parameters for this method
@@ -759,6 +1027,13 @@ sap.ui.define([
759
1027
  this._createLegend();
760
1028
  };
761
1029
 
1030
+ Graph.prototype.setLabels = function (oValue) {
1031
+ this.setProperty("labels", oValue, true);
1032
+ this._createSearchSuggestItems();
1033
+ this._createLegend();
1034
+ return this;
1035
+ };
1036
+
762
1037
 
763
1038
  /**
764
1039
  * Zooms in or out of the graph.
@@ -797,7 +1072,7 @@ sap.ui.define([
797
1072
  /**
798
1073
  * Returns current zoom level.
799
1074
  *
800
- * @return {number}
1075
+ * @return {number} Current zoom level
801
1076
  * @public
802
1077
  */
803
1078
  Graph.prototype.getCurrentZoomLevel = function () {
@@ -817,6 +1092,31 @@ sap.ui.define([
817
1092
  this._oZoomLevelInvisibleText.setText(oResourceBundle.getText("NETWORK_GRAPH_ZOOM_LEVEL") + ": " + this._getZoomText());
818
1093
  };
819
1094
 
1095
+ /**
1096
+ * Restores keyboard focus to the last focused item in the graph, or falls back to the graph wrapper.
1097
+ * @private
1098
+ */
1099
+ Graph.prototype._restoreFocusToGraph = function () {
1100
+ if (this._oFocus) {
1101
+ const oFocusToRestore = this._oFocus;
1102
+ // Force setFocus to re-apply even if the item hasn't changed.
1103
+ this._oFocus = null;
1104
+ this.setFocus(oFocusToRestore);
1105
+ } else {
1106
+ this.getFocusDomRef().focus();
1107
+ }
1108
+ };
1109
+
1110
+ /**
1111
+ * Gets the associated control linked to this graph instance using the 'associatedControl' association.
1112
+ * This can be any UI5 control that is related to the graph.
1113
+ * @returns {sap.ui.core.Control|null} The associated control instance or null if not set.
1114
+ * @public
1115
+ */
1116
+ Graph.prototype.getAssociatedControl = function () {
1117
+ var sId = this.getAssociation("associatedControl");
1118
+ return sId ? Element.getElementById(sId) : null;
1119
+ };
820
1120
 
821
1121
  /* =========================================================== */
822
1122
  /* Private methods */
@@ -843,6 +1143,24 @@ sap.ui.define([
843
1143
  };
844
1144
  };
845
1145
 
1146
+ /**
1147
+ * Returns a busy indicator instance for loading states.
1148
+ * @returns {sap.m.BusyIndicator} BusyIndicator instance
1149
+ * @private
1150
+ */
1151
+ Graph.prototype._getBusyIndicator = function () {
1152
+ var sText = this.getLoadingText() || oResourceBundle.getText("NETWORK_GRAPH_OPENING_CANVAS");
1153
+
1154
+ if (!this._oBusyIndicator) {
1155
+ this._oBusyIndicator = new BusyIndicator({ text: sText });
1156
+ this.addDependent(this._oBusyIndicator);
1157
+ } else {
1158
+ this._oBusyIndicator.setText(sText);
1159
+ }
1160
+
1161
+ return this._oBusyIndicator;
1162
+ };
1163
+
846
1164
  Graph.prototype._createTooltip = function () {
847
1165
  var oTooltip = new Tooltip(this.getId() + "-tooltip");
848
1166
  this.addDependent(oTooltip);
@@ -858,6 +1176,7 @@ sap.ui.define([
858
1176
  return;
859
1177
  }
860
1178
 
1179
+ this._oFocus = null;
861
1180
  this.setFocus(oFocus);
862
1181
 
863
1182
  if (oFocus.button == "menu") {
@@ -870,13 +1189,92 @@ sap.ui.define([
870
1189
  return oTooltip;
871
1190
  };
872
1191
 
1192
+ /**
1193
+ * Gets or creates an IllustratedMessage instance for displaying empty state.
1194
+ * This method reuses the same instance to avoid memory leaks.
1195
+ * The illustrated message content depends on whether drag-and-drop is enabled:
1196
+ * - When drag-and-drop is enabled: Shows "AddDimensions" illustration with plan-building message
1197
+ * - When drag-and-drop is disabled: Shows "NoChartData" illustration with custom or default no-data text
1198
+ *
1199
+ * @returns {sap.m.IllustratedMessage} The illustrated message instance for empty state
1200
+ * @private
1201
+ */
1202
+ Graph.prototype._getIllustratedMessage = function () {
1203
+ // Helper function to get configuration based on current state
1204
+ var fnConfigureIllustratedMessage = function () {
1205
+ var sText = this.getNoDataText(),
1206
+ sTextInline = sText || oResourceBundle.getText("NETWORK_GRAPH_NO_DATA");
1207
+
1208
+ if (this._isDnDEnabled()) {
1209
+ return {
1210
+ illustrationType: IllustratedMessageType.AddDimensions,
1211
+ title: oResourceBundle.getText("NETWORK_GRAPH_DND_EMPTY_TITLE"),
1212
+ description: oResourceBundle.getText("NETWORK_GRAPH_DND_EMPTY_DESCRIPTION"),
1213
+ enableDefaultTitleAndDescription: false
1214
+ };
1215
+ } else {
1216
+ return {
1217
+ illustrationType: IllustratedMessageType.NoChartData,
1218
+ title: sTextInline,
1219
+ enableDefaultTitleAndDescription: false
1220
+ };
1221
+ }
1222
+ }.bind(this);
1223
+
1224
+ if (!this._oIllustratedMessage) {
1225
+ var oConfig = fnConfigureIllustratedMessage();
1226
+ this._oIllustratedMessage = new IllustratedMessage(oConfig);
1227
+ this.addDependent(this._oIllustratedMessage);
1228
+ } else {
1229
+ var oConfig = fnConfigureIllustratedMessage();
1230
+ this._oIllustratedMessage.setIllustrationType(oConfig.illustrationType);
1231
+ this._oIllustratedMessage.setTitle(oConfig.title);
1232
+ this._oIllustratedMessage.setDescription(oConfig.description);
1233
+ }
1234
+
1235
+ return this._oIllustratedMessage;
1236
+ };
1237
+
873
1238
  /**
874
1239
  * @private
1240
+ * Defocuses the currently focused element.
875
1241
  */
876
1242
  Graph.prototype.defocus = function () {
877
1243
  this.$().find("." + this.FOCUS_CLASS).removeClass(this.FOCUS_CLASS);
878
1244
  };
879
1245
 
1246
+ /**
1247
+ * Sets whether drag and drop is enabled.
1248
+ * @param {boolean} bEnabled Whether drag and drop should be enabled
1249
+ * @private
1250
+ */
1251
+ Graph.prototype.setEnableDragAndDrop = function (bEnabled) {
1252
+ this.setProperty("enableDragAndDrop", bEnabled, true);
1253
+
1254
+ // Update zoom button visibility
1255
+ if (this._zoomIn && this._zoomOut && this._zoomToFitButton) {
1256
+ var bZoomVisible = !this._isDnDEnabled();
1257
+ this._zoomIn.setVisible(bZoomVisible);
1258
+ this._zoomOut.setVisible(bZoomVisible);
1259
+ this._zoomToFitButton.setVisible(bZoomVisible);
1260
+ }
1261
+
1262
+ // remove the node ports when drag and drop is disabled
1263
+ if (!bEnabled) {
1264
+ PortManager.removeAllPorts();
1265
+ }
1266
+
1267
+ return this;
1268
+ };
1269
+
1270
+ /**
1271
+ * @private
1272
+ * @returns {boolean} Returns whether drag and drop is enabled.
1273
+ */
1274
+ Graph.prototype.getEnableDragAndDrop = function () {
1275
+ return this.getProperty("enableDragAndDrop");
1276
+ };
1277
+
880
1278
  /**
881
1279
  * Sets focus of the graph. Since one element at max can be focused at one time, handling of this belongs to the graph itself.
882
1280
  * @param {object} oFocus Element (and optionally button) to focus
@@ -900,12 +1298,12 @@ sap.ui.define([
900
1298
  this._oFocus.item.isA("sap.suite.ui.commons.networkgraph.Node")))) {
901
1299
  this._updateAccessibility(oFocus);
902
1300
  }
903
- this._updateAccessibility(oFocus);
904
- return;
1301
+ this._updateAccessibility(oFocus);
1302
+ return;
905
1303
  }
906
1304
 
907
1305
  this.defocus();
908
- if (this.getFocusDomRef()) {
1306
+ if (this.getFocusDomRef() && !(oFocus && oFocus.button && oFocus.button.id && oFocus.button.id.indexOf("actionOverflow") !== -1)) {
909
1307
  this.getFocusDomRef().focus();
910
1308
  }
911
1309
 
@@ -945,7 +1343,7 @@ sap.ui.define([
945
1343
  this._setAccessibilityTitle(oResourceBundle.getText("NETWORK_GRAPH_ACCESSIBILITY_CONTENT"));
946
1344
  }.bind(this),
947
1345
  fnBuildTitleForButton = function (sLabel) {
948
- var sTitleLabel = sLabel + " " + oResourceBundle.getText("NETWORK_GRAPH_ACCESSIBILITY_ACTION_BUTTON") ;
1346
+ var sTitleLabel = sLabel + " " + oResourceBundle.getText("NETWORK_GRAPH_ACCESSIBILITY_ACTION_BUTTON");
949
1347
  if (sLabel === "Expand/Collapse") {
950
1348
  if (oFocus.item.getCollapsed()) {
951
1349
  sTitleLabel = sTitleLabel + " " + oResourceBundle.getText("NETWORK_GRAPH_COLLAPSED");
@@ -1049,6 +1447,14 @@ sap.ui.define([
1049
1447
  return this.getNodes().concat(this.getGroups());
1050
1448
  };
1051
1449
 
1450
+ Graph.prototype._isNoopLayout = function () {
1451
+ return this._getLayoutAlgorithm().isA("sap.suite.ui.commons.networkgraph.layout.NoopLayout");
1452
+ };
1453
+
1454
+ Graph.prototype._isDnDEnabled = function() {
1455
+ return this._isNoopLayout() && this.getEnableDragAndDrop();
1456
+ };
1457
+
1052
1458
  Graph.prototype._render = function () {
1053
1459
  this._beforeRender();
1054
1460
 
@@ -1077,8 +1483,9 @@ sap.ui.define([
1077
1483
  this.$background.width(iSvgWidth * this._fZoomLevel);
1078
1484
  this.$background.height(iSvgHeight * this._fZoomLevel);
1079
1485
 
1486
+ var sScale = "";
1080
1487
  if (this._isUseNodeHtml()) {
1081
- var sScale = "scale(" + this._fZoomLevel + ")";
1488
+ sScale = "scale(" + this._fZoomLevel + ")";
1082
1489
  this.$("divnodes").css("transform", sScale);
1083
1490
  }
1084
1491
 
@@ -1125,6 +1532,10 @@ sap.ui.define([
1125
1532
 
1126
1533
  if (!this._isSwimLane() && !this._isTwoColumnsLayout()) {
1127
1534
  this.$("innerscroller").addClass(" sapSuiteUiCommonsNetworkGraphInnerScrollerCenter ");
1535
+ if (this._isDnDEnabled()) {
1536
+ // If NoopLayout is used, users must set certain styles to ensure precise coordinates setting.
1537
+ this.$("innerscroller").addClass("sapSuiteUiCommonsNetworkGraphInnerScrollerNoMargin");
1538
+ }
1128
1539
  }
1129
1540
  };
1130
1541
 
@@ -1348,6 +1759,8 @@ sap.ui.define([
1348
1759
  oRm.openStart("g", this.getId() + "-svgbody");
1349
1760
  oRm.openEnd();
1350
1761
  fnRenderItems("lines", aLines, "sapSuiteUiCommonsNetworkLines");
1762
+ // Render line texts after all lines are rendered to handle overlaps
1763
+ this._renderAllLineTexts(aLines, oRm);
1351
1764
  if (!this._isUseNodeHtml()) {
1352
1765
  fnRenderItems("nodes", aNodes, "sapSuiteUiCommonsNetworkNodes");
1353
1766
  }
@@ -1372,6 +1785,45 @@ sap.ui.define([
1372
1785
 
1373
1786
  };
1374
1787
 
1788
+ /**
1789
+ * Renders text labels for all lines in a dedicated SVG group container.
1790
+ *
1791
+ * This method creates a batch rendering context for line labels, enabling
1792
+ * potential overlap handling and positioning optimizations. Labels are only
1793
+ * rendered for lines that meet all of the following conditions:
1794
+ * - The line has a labelName property value set
1795
+ * - The graph is using NoopLayout
1796
+ * - The line's arrowPosition is set to "Both"
1797
+ *
1798
+ * @param {sap.suite.ui.commons.networkgraph.Line[]} aLines Array of line objects to render text labels for
1799
+ * @param {sap.ui.core.RenderManager} oRm The RenderManager instance used for SVG rendering
1800
+ * @private
1801
+ */
1802
+ Graph.prototype._renderAllLineTexts = function (aLines, oRm) {
1803
+ // Early return if line labels are disabled or NoopLayout is not active
1804
+ if (!this._isNoopLayout()) {
1805
+ return;
1806
+ }
1807
+
1808
+ // Create a dedicated SVG group container for all line text labels
1809
+ // This enables batch processing and potential overlap handling
1810
+ oRm.openStart("g");
1811
+ oRm.attr("id", this.getId() + "-line-texts");
1812
+ oRm.class("sapSuiteUiCommonsNetworkLineTexts");
1813
+ oRm.openEnd();
1814
+
1815
+ // Iterate through all lines and render their text labels within the group
1816
+ // Only process lines that are valid, not ignored by layout, and visible
1817
+ aLines.forEach(function (oLine) {
1818
+ if (oLine && !oLine._isIgnored() && oLine.getVisible()) {
1819
+ oLine._renderLineText(oRm);
1820
+ }
1821
+ });
1822
+
1823
+ // Close the SVG group container
1824
+ oRm.close("g");
1825
+ };
1826
+
1375
1827
  Graph.prototype._isProperKey = function (sKey) {
1376
1828
  return sKey || (sKey === "0");
1377
1829
  };
@@ -1452,7 +1904,11 @@ sap.ui.define([
1452
1904
  }
1453
1905
  }
1454
1906
 
1455
- this._isUseNodeHtml() ? oNode._resetDimensions() : oNode._setupWidthAndHeight();
1907
+ if (this._isUseNodeHtml()) {
1908
+ oNode._resetDimensions();
1909
+ } else {
1910
+ oNode._setupWidthAndHeight();
1911
+ }
1456
1912
  oNode._clearChildren();
1457
1913
  oNode._rendered = false;
1458
1914
 
@@ -1881,16 +2337,24 @@ sap.ui.define([
1881
2337
  }
1882
2338
  });
1883
2339
  this._toolbar.addContent(this._zoomOut);
1884
- }
2340
+ }
1885
2341
 
1886
2342
  // fit to viewport
1887
- this._toolbar.addContent(new OverflowToolbarButton({
2343
+ this._zoomToFitButton = new OverflowToolbarButton({
1888
2344
  type: ButtonType.Transparent,
1889
2345
  icon: "sap-icon://popup-window",
1890
2346
  tooltip: oResourceBundle.getText("NETWORK_GRAPH_ZOOMTOFIT"),
1891
2347
  text: oResourceBundle.getText("NETWORK_GRAPH_ZOOMTOFIT"),
1892
2348
  press: this._fitToScreen.bind(this)
1893
- }));
2349
+ });
2350
+ this._toolbar.addContent(this._zoomToFitButton);
2351
+
2352
+ // Hide zoom buttons if drag and drop is enabled
2353
+ if (this._isDnDEnabled()) {
2354
+ this._zoomIn.setVisible(false);
2355
+ this._zoomOut.setVisible(false);
2356
+ this._zoomToFitButton.setVisible(false);
2357
+ }
1894
2358
 
1895
2359
  // toggle full screen
1896
2360
  this._oFullScreenButton = new OverflowToolbarButton({
@@ -2172,7 +2636,9 @@ sap.ui.define([
2172
2636
 
2173
2637
  $wrapper.on("mouseleave", this._endDragging.bind(this));
2174
2638
  $wrapper.on("mouseup", this._mouseUp.bind(this));
2175
- if (this.getEnableZoom()) {
2639
+ if (this.getEnableZoom() && !this._isDnDEnabled()) {
2640
+ // Disabling zooming capability in edit mode.
2641
+ // TODO: consider scaling when dragging and dropping nodes and update ghost image dimenstion and coordinates prediction, to allow zooming.
2176
2642
  $wrapper.on("wheel", function (oEvent) {
2177
2643
  if (this._wheel({
2178
2644
  x: oEvent.originalEvent.clientX,
@@ -2230,6 +2696,7 @@ sap.ui.define([
2230
2696
  this._oZoomLevelInvisibleText.setText(oResourceBundle.getText("NETWORK_GRAPH_ZOOM_LEVEL") + ": " + this._getZoomText());
2231
2697
  return true;
2232
2698
  }
2699
+ return false;
2233
2700
  };
2234
2701
 
2235
2702
  Graph.prototype._endDragging = function () {
@@ -2262,6 +2729,11 @@ sap.ui.define([
2262
2729
  this._oPanning.dragging = true;
2263
2730
 
2264
2731
  this._tooltip.instantClose();
2732
+
2733
+ // Remove all ports when deselecting
2734
+ if (PortManager._currentTriggerNodeKey !== null) {
2735
+ PortManager.removeAllPorts();
2736
+ }
2265
2737
  };
2266
2738
 
2267
2739
  Graph.prototype._mouseUp = function () {
@@ -2410,6 +2882,11 @@ sap.ui.define([
2410
2882
  // indicates current count of suggestion items when they are rendered
2411
2883
  this._oSuggestionItemsModel.setSizeLimit(SUGGESTION_ITEMS_LIMIT);
2412
2884
 
2885
+ const oLabels = this.getLabels() || {};
2886
+ const sNodeLabel = oLabels.nodeLabel || oResourceBundle.getText("NETWORK_GRAPH_NODE");
2887
+ const sLineLabel = oLabels.lineLabel || oResourceBundle.getText("NETWORK_GRAPH_LINE");
2888
+ const sGroupLabel = oLabels.groupLabel || oResourceBundle.getText("NETWORK_GRAPH_GROUP");
2889
+
2413
2890
  aNodes.forEach(function (oNode) {
2414
2891
  var sTitle = Utils.trimText(oNode.getTitle(), TITLE_LENGTH);
2415
2892
  oData.items.push({
@@ -2417,7 +2894,7 @@ sap.ui.define([
2417
2894
  type: SUGGESTIONS.Node,
2418
2895
  icon: oNode.getIcon(),
2419
2896
  key: oNode.getKey(),
2420
- description: "(" + oResourceBundle.getText("NETWORK_GRAPH_NODE") + ")"
2897
+ description: "(" + sNodeLabel + ")"
2421
2898
  });
2422
2899
  });
2423
2900
 
@@ -2430,7 +2907,7 @@ sap.ui.define([
2430
2907
  text: oLine._createSuggestionHelpText(),
2431
2908
  type: SUGGESTIONS.Line,
2432
2909
  key: oLine._getLineId(),
2433
- description: "(" + oResourceBundle.getText("NETWORK_GRAPH_LINE") + ")"
2910
+ description: "(" + sLineLabel + ")"
2434
2911
  });
2435
2912
  }
2436
2913
  });
@@ -2442,7 +2919,7 @@ sap.ui.define([
2442
2919
  text: sTitle ? sTitle : oGroup.getKey(),
2443
2920
  key: oGroup.getKey(),
2444
2921
  type: SUGGESTIONS.Group,
2445
- description: "(" + oResourceBundle.getText("NETWORK_GRAPH_GROUP") + ")"
2922
+ description: "(" + sGroupLabel + ")"
2446
2923
  });
2447
2924
  }
2448
2925
  });
@@ -2486,7 +2963,13 @@ sap.ui.define([
2486
2963
  fHeight = oItem._iHeight;
2487
2964
  }
2488
2965
 
2489
- this.$scroller.get(0).scrollLeft = ((fX + (fWidth ? fWidth : 0) / 2) * this._fZoomLevel) - (this.$scroller.width() / 2);
2966
+ const fScrollLeft = ((fX + (fWidth ? fWidth : 0) / 2) * this._fZoomLevel) - (this.$scroller.width() / 2);
2967
+
2968
+ if (this._bIsRtl) {
2969
+ this.$scroller.get(0).scrollLeft = -fScrollLeft;
2970
+ } else {
2971
+ this.$scroller.get(0).scrollLeft = fScrollLeft;
2972
+ }
2490
2973
  this.$scroller.get(0).scrollTop = ((fY + (fHeight ? fHeight : 0) / 2) * this._fZoomLevel) - (this.$scroller.height() / 2);
2491
2974
  };
2492
2975
 
@@ -2507,6 +2990,14 @@ sap.ui.define([
2507
2990
  iRight = iLeft + this.$scroller.width() / this._fZoomLevel,
2508
2991
  iBottom = iTop + this.$scroller.height() / this._fZoomLevel;
2509
2992
 
2993
+ if (this._bIsRtl) {
2994
+ const iGraphWidth = this.$svg.width() / this._fZoomLevel;
2995
+ const iViewportWidth = this.$scroller.width() / this._fZoomLevel;
2996
+ const iScrollPosAbs = Math.abs(iLeft);
2997
+ iLeft = iGraphWidth - iScrollPosAbs - iViewportWidth;
2998
+ iRight = iLeft + iViewportWidth;
2999
+ }
3000
+
2510
3001
  if (!oItem._isOnScreen(iLeft, iRight, iTop, iBottom)) {
2511
3002
  if (oItem instanceof Node) {
2512
3003
  iCenterX = oItem.getX() + oItem._iWidth / 2;
@@ -2521,7 +3012,14 @@ sap.ui.define([
2521
3012
  }
2522
3013
 
2523
3014
  if (iCenterX < iLeft || iCenterX > iRight) {
2524
- oScroller.scrollLeft = iCenterX * this._fZoomLevel - this.$scroller.width() / 2;
3015
+ let iTargetScrollLeft = iCenterX * this._fZoomLevel - this.$scroller.width() / 2;
3016
+
3017
+ if (this._bIsRtl) {
3018
+ const iScrollRange = oScroller.scrollWidth - oScroller.clientWidth;
3019
+ iTargetScrollLeft = -(iScrollRange - iTargetScrollLeft);
3020
+ }
3021
+
3022
+ oScroller.scrollLeft = iTargetScrollLeft;
2525
3023
  }
2526
3024
  if (iCenterY < iTop || iCenterY > iBottom) {
2527
3025
  oScroller.scrollTop = iCenterY * this._fZoomLevel - this.$scroller.height() / 2;
@@ -2586,7 +3084,7 @@ sap.ui.define([
2586
3084
  if (fnHasStatus(oCollection)) {
2587
3085
  oRm.openStart("div").class(sClass).openEnd();
2588
3086
  oRm.openStart("label").class("sapSuiteUiCommonsNetworkGraphLegendTitle").openEnd();
2589
- oRm.text(oResourceBundle.getText(sTitle));
3087
+ oRm.text(sTitle);
2590
3088
  oRm.close("label");
2591
3089
  oRm.close("div");
2592
3090
  // get the status labels for sorting (some statuses can have custom labels)
@@ -2621,12 +3119,13 @@ sap.ui.define([
2621
3119
  return;
2622
3120
  }
2623
3121
 
3122
+ const oLabels = this.getLabels() || {};
2624
3123
  fnProcessElements(this.getNodes(), oNodeStatuses, "sapSuiteUiCommonsNetworkGraphLegendTitleNode",
2625
- "NETWORK_GRAPH_NODES", StatusType.Node);
3124
+ oLabels.nodeLabelPlural || oResourceBundle.getText("NETWORK_GRAPH_NODES"), StatusType.Node);
2626
3125
  fnProcessElements(this.getLines(), oLineStatuses, "sapSuiteUiCommonsNetworkGraphLegendTitleLine",
2627
- "NETWORK_GRAPH_LINES", StatusType.Line);
3126
+ oLabels.lineLabelPlural || oResourceBundle.getText("NETWORK_GRAPH_LINES"), StatusType.Line);
2628
3127
  fnProcessElements(this.getGroups(), oGroupStatuses, "sapSuiteUiCommonsNetworkGraphLegendTitleLine",
2629
- "NETWORK_GRAPH_GROUPS", StatusType.Group);
3128
+ oLabels.groupLabelPlural || oResourceBundle.getText("NETWORK_GRAPH_GROUPS"), StatusType.Group);
2630
3129
  oRm.flush($legend[0]);
2631
3130
  oRm.destroy();
2632
3131
  // $legend.html(sHtml);
@@ -2786,8 +3285,15 @@ sap.ui.define([
2786
3285
  };
2787
3286
 
2788
3287
  Graph.prototype._isTopBottom = function () {
2789
- return this.getOrientation() === Orientation.TopBottom ||
2790
- this.getOrientation() === Orientation.BottomTop;
3288
+ return this.getOrientation() === Orientation.TopBottom
3289
+ };
3290
+
3291
+ Graph.prototype._isBottomTop = function () {
3292
+ return this.getOrientation() === Orientation.BottomTop;
3293
+ };
3294
+
3295
+ Graph.prototype._isRightLeft = function () {
3296
+ return this.getOrientation() === Orientation.RightLeft;
2791
3297
  };
2792
3298
 
2793
3299
  /* =========================================================== */
@@ -2929,5 +3435,16 @@ sap.ui.define([
2929
3435
  }
2930
3436
  };
2931
3437
 
3438
+ /**
3439
+ * Checks if the current layout algorithm supports node ports functionality.
3440
+ * For now, only NoopLayout algorithms support node ports.
3441
+ *
3442
+ * @returns {boolean} True if the layout supports node ports, false otherwise
3443
+ * @private
3444
+ */
3445
+ Graph.prototype._supportsNodePorts = function () {
3446
+ return this.getNodePorts() !== "None" && this._isDnDEnabled();
3447
+ };
3448
+
2932
3449
  return Graph;
2933
3450
  });