@sapui5/sap.suite.ui.commons 1.136.11 → 1.136.13
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 +1 -1
- package/src/sap/suite/ui/commons/.library +1 -1
- package/src/sap/suite/ui/commons/AriaProperties.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilder.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderExpression.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderFunction.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderGroup.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderItem.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderValidationResult.js +1 -1
- package/src/sap/suite/ui/commons/CalculationBuilderVariable.js +1 -1
- package/src/sap/suite/ui/commons/CloudFilePicker.js +1 -1
- package/src/sap/suite/ui/commons/MicroProcessFlow.js +1 -1
- package/src/sap/suite/ui/commons/MicroProcessFlowItem.js +1 -1
- package/src/sap/suite/ui/commons/TimelineRenderManager.js +8 -4
- package/src/sap/suite/ui/commons/flexibility/changeHandler/PropertyChangeMapper.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/CropCustomShapeHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/CropEllipseHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/CropRectangleHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/CustomSizeItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/FilterHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/FlipHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/HistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/ImageEditor.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/ImageEditorContainer.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/ImageEditorResponsiveContainer.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/ResizeHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/imageeditor/RotateHistoryItem.js +1 -1
- package/src/sap/suite/ui/commons/library.js +100 -3
- package/src/sap/suite/ui/commons/messagebundle.properties +73 -12
- package/src/sap/suite/ui/commons/messagebundle_ar.properties +1 -1
- package/src/sap/suite/ui/commons/messagebundle_en_US_saprigi.properties +39 -5
- package/src/sap/suite/ui/commons/messagebundle_fr_CA.properties +1 -1
- package/src/sap/suite/ui/commons/messagebundle_hu.properties +1 -1
- package/src/sap/suite/ui/commons/messagebundle_id.properties +2 -2
- package/src/sap/suite/ui/commons/messagebundle_it.properties +1 -1
- package/src/sap/suite/ui/commons/messagebundle_pt.properties +1 -1
- package/src/sap/suite/ui/commons/messagebundle_ru.properties +1 -1
- package/src/sap/suite/ui/commons/networkgraph/ElementBase.js +19 -1
- package/src/sap/suite/ui/commons/networkgraph/Graph.js +590 -48
- package/src/sap/suite/ui/commons/networkgraph/GraphMap.js +25 -3
- package/src/sap/suite/ui/commons/networkgraph/GraphRenderer.js +19 -8
- package/src/sap/suite/ui/commons/networkgraph/KeyboardNavigator.js +367 -12
- package/src/sap/suite/ui/commons/networkgraph/Line.js +814 -22
- package/src/sap/suite/ui/commons/networkgraph/Node.js +573 -79
- package/src/sap/suite/ui/commons/networkgraph/Tooltip.js +4 -0
- package/src/sap/suite/ui/commons/networkgraph/Utils.js +249 -10
- package/src/sap/suite/ui/commons/networkgraph/layout/NoopLayout.js +77 -7
- package/src/sap/suite/ui/commons/networkgraph/util/ConnectionPathUtils.js +1174 -0
- package/src/sap/suite/ui/commons/networkgraph/util/CreateConnectionPopover.js +374 -0
- package/src/sap/suite/ui/commons/networkgraph/util/DependencyLayoutHelper.js +1017 -0
- package/src/sap/suite/ui/commons/networkgraph/util/DragDropManager.js +721 -0
- package/src/sap/suite/ui/commons/networkgraph/util/PortManager.js +582 -0
- package/src/sap/suite/ui/commons/statusindicator/Circle.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/CustomShape.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/DiscreteThreshold.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/FillingOption.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/LibraryShape.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/Path.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/PropertyThreshold.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/Rectangle.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/Shape.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/ShapeGroup.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/SimpleShape.js +1 -1
- package/src/sap/suite/ui/commons/statusindicator/StatusIndicator.js +1 -1
- package/src/sap/suite/ui/commons/taccount/TAccount.js +1 -1
- package/src/sap/suite/ui/commons/taccount/TAccountGroup.js +1 -1
- package/src/sap/suite/ui/commons/taccount/TAccountItem.js +1 -1
- package/src/sap/suite/ui/commons/taccount/TAccountItemProperty.js +1 -1
- package/src/sap/suite/ui/commons/taccount/TAccountPanel.js +1 -1
- package/src/sap/suite/ui/commons/themes/base/NetworkGraph.less +26 -13
- package/src/sap/suite/ui/commons/themes/base/NetworkGroup.less +4 -0
- package/src/sap/suite/ui/commons/themes/base/NetworkLine.less +58 -13
- package/src/sap/suite/ui/commons/themes/base/NetworkNode.less +251 -47
- package/src/sap/suite/ui/commons/themes/base/SemanticColorMixins.less +55 -0
|
@@ -364,12 +364,28 @@ sap.ui.define([
|
|
|
364
364
|
}
|
|
365
365
|
};
|
|
366
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Returns the horizontal scroll position in graph coordinates, accounting for RTL.
|
|
369
|
+
*/
|
|
370
|
+
GraphMap.prototype._getScrollLeftForMap = function (oGraph) {
|
|
371
|
+
const fScrollLeft = oGraph.$scroller[0].scrollLeft;
|
|
372
|
+
|
|
373
|
+
if (oGraph._bIsRtl) {
|
|
374
|
+
const iGraphWidth = oGraph.$svg.width() / oGraph._fZoomLevel;
|
|
375
|
+
const iViewportWidth = oGraph.$scroller.width() / oGraph._fZoomLevel;
|
|
376
|
+
const iScrollPosAbs = Math.abs(fScrollLeft) / oGraph._fZoomLevel;
|
|
377
|
+
return iGraphWidth - iScrollPosAbs - iViewportWidth;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return fScrollLeft / oGraph._fZoomLevel;
|
|
381
|
+
};
|
|
382
|
+
|
|
367
383
|
GraphMap.prototype._resize = function () {
|
|
368
384
|
var oGraph = this.getGraph(),
|
|
369
385
|
$scroller = oGraph.$scroller,
|
|
370
386
|
$mapNavigator = this.$("mapNavigator");
|
|
371
387
|
|
|
372
|
-
$mapNavigator.attr("x", Math.max(NAVIGATORLINESIZE / 2,
|
|
388
|
+
$mapNavigator.attr("x", Math.max(NAVIGATORLINESIZE / 2, this._getScrollLeftForMap(oGraph)));
|
|
373
389
|
$mapNavigator.attr("y", Math.max(NAVIGATORLINESIZE / 2, $scroller[0].scrollTop / oGraph._fZoomLevel));
|
|
374
390
|
|
|
375
391
|
$mapNavigator.attr("width", $scroller.width() / oGraph._fZoomLevel);
|
|
@@ -400,7 +416,7 @@ sap.ui.define([
|
|
|
400
416
|
$mapNavigator = this.$("mapNavigator");
|
|
401
417
|
|
|
402
418
|
if (oGraph && $scroller[0]) {
|
|
403
|
-
$mapNavigator.attr("x", Math.max(NAVIGATORLINESIZE / 2,
|
|
419
|
+
$mapNavigator.attr("x", Math.max(NAVIGATORLINESIZE / 2, this._getScrollLeftForMap(oGraph)));
|
|
404
420
|
$mapNavigator.attr("y", Math.max(NAVIGATORLINESIZE / 2, $scroller[0].scrollTop / oGraph._fZoomLevel));
|
|
405
421
|
|
|
406
422
|
this._correctMapNavigator();
|
|
@@ -421,7 +437,13 @@ sap.ui.define([
|
|
|
421
437
|
fRealStartX = $border.offset().left,
|
|
422
438
|
fRealStartY = $border.offset().top;
|
|
423
439
|
|
|
424
|
-
|
|
440
|
+
const fTargetScrollLeft = (oScrollData.pageX - fRealStartX) * iRatio - ($scroller.width() / 2);
|
|
441
|
+
if (oGraph._bIsRtl) {
|
|
442
|
+
const iScrollRange = oScroller.scrollWidth - oScroller.clientWidth;
|
|
443
|
+
oScroller.scrollLeft = -(iScrollRange - fTargetScrollLeft);
|
|
444
|
+
} else {
|
|
445
|
+
oScroller.scrollLeft = fTargetScrollLeft;
|
|
446
|
+
}
|
|
425
447
|
oScroller.scrollTop = (oScrollData.pageY - fRealStartY) * iRatio - ($scroller.height() / 2);
|
|
426
448
|
};
|
|
427
449
|
|
|
@@ -65,6 +65,14 @@ sap.ui.define([
|
|
|
65
65
|
}
|
|
66
66
|
oRM.openEnd();
|
|
67
67
|
|
|
68
|
+
if (oNetworkGraph.getLoading()) {
|
|
69
|
+
this._renderLoading(oRM, oNetworkGraph);
|
|
70
|
+
oRM.close("div");
|
|
71
|
+
oRM.close("div");
|
|
72
|
+
oRM.close("div");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
68
76
|
if (oNetworkGraph.getNoData()) {
|
|
69
77
|
this._renderNoData(oRM, oNetworkGraph);
|
|
70
78
|
oRM.close("div");
|
|
@@ -165,16 +173,19 @@ sap.ui.define([
|
|
|
165
173
|
oRM.class("sapSuiteUiCommonsNetworkGraphNoDataWrapper");
|
|
166
174
|
oRM.attr("tabindex", "0");
|
|
167
175
|
oRM.openEnd();
|
|
168
|
-
oNetworkGraph.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
176
|
+
oRM.renderControl(oNetworkGraph._getIllustratedMessage());
|
|
177
|
+
oRM.close("div");
|
|
178
|
+
},
|
|
179
|
+
_renderLoading: function (oRM, oNetworkGraph) {
|
|
173
180
|
oRM.openStart("div");
|
|
174
|
-
oRM.class("
|
|
181
|
+
oRM.class("sapSuiteUiCommonsNetworkGraphLoadingWrapper");
|
|
182
|
+
oRM.attr("tabindex", "0");
|
|
175
183
|
oRM.openEnd();
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
|
|
185
|
+
// Render the busy indicator
|
|
186
|
+
var oBusyIndicator = oNetworkGraph._getBusyIndicator();
|
|
187
|
+
oRM.renderControl(oBusyIndicator);
|
|
188
|
+
|
|
178
189
|
oRM.close("div");
|
|
179
190
|
}
|
|
180
191
|
};
|
|
@@ -18,6 +18,8 @@ sap.ui.define([
|
|
|
18
18
|
], function (jQuery, BaseObject, Group, Node, Line, KeyCodes, containsOrEquals, Log, CoreLib) {
|
|
19
19
|
"use strict";
|
|
20
20
|
|
|
21
|
+
const oResourceBundle = CoreLib.getResourceBundleFor("sap.suite.ui.commons");
|
|
22
|
+
|
|
21
23
|
var mDirections = {
|
|
22
24
|
LEFT: "left",
|
|
23
25
|
RIGHT: "right",
|
|
@@ -73,6 +75,13 @@ sap.ui.define([
|
|
|
73
75
|
this._oFocusPosition = null;
|
|
74
76
|
this._oWrapperDom = null;
|
|
75
77
|
this.isFromFullscreen = null;
|
|
78
|
+
this._oAltNode = null;
|
|
79
|
+
this._oAltConnectors = null;
|
|
80
|
+
this._oAltAnnouncement = null;
|
|
81
|
+
this._oAssociatedControl = null;
|
|
82
|
+
this._oAssociatedContainer = null;
|
|
83
|
+
this._oAssociatedDelegate = null;
|
|
84
|
+
this._bCtrlAltDown = false;
|
|
76
85
|
}
|
|
77
86
|
});
|
|
78
87
|
|
|
@@ -123,6 +132,14 @@ sap.ui.define([
|
|
|
123
132
|
this._iColumns = aRow.length;
|
|
124
133
|
}
|
|
125
134
|
}, this);
|
|
135
|
+
|
|
136
|
+
const oControl = this._oGraph.getAssociatedControl();
|
|
137
|
+
if (oControl !== this._oAssociatedControl) {
|
|
138
|
+
this._updateAssociatedDelegate(oControl);
|
|
139
|
+
}
|
|
140
|
+
this._oAltNode = null;
|
|
141
|
+
this._oAltConnectors = null;
|
|
142
|
+
this._oAltAnnouncement = null;
|
|
126
143
|
};
|
|
127
144
|
|
|
128
145
|
KeyboardNavigator.prototype.setWrapperDom = function (oDom) {
|
|
@@ -186,13 +203,15 @@ sap.ui.define([
|
|
|
186
203
|
};
|
|
187
204
|
|
|
188
205
|
KeyboardNavigator.prototype.onkeyup = function(oEvent) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
206
|
+
if (oEvent.keyCode === KeyCodes.SPACE){
|
|
207
|
+
this._handleEnter();
|
|
208
|
+
if (this._oGraph.getFocusDomRef() === document.activeElement) {
|
|
192
209
|
oEvent.stopPropagation();
|
|
193
210
|
oEvent.preventDefault();
|
|
194
|
-
}
|
|
195
211
|
}
|
|
212
|
+
} else if (oEvent.keyCode === KeyCodes.DELETE || oEvent.keyCode === KeyCodes.BACKSPACE) {
|
|
213
|
+
this._handleDelete(oEvent);
|
|
214
|
+
}
|
|
196
215
|
};
|
|
197
216
|
|
|
198
217
|
KeyboardNavigator.prototype.onsapenter = function (oEvent) {
|
|
@@ -226,6 +245,12 @@ sap.ui.define([
|
|
|
226
245
|
KeyboardNavigator.prototype.onkeydown = function (oEvent) {
|
|
227
246
|
var oItem, oBtn,
|
|
228
247
|
oFocus = this.getFocus();
|
|
248
|
+
|
|
249
|
+
// On Windows, Ctrl+Alt = AltGr — browsers strip ctrlKey/altKey from the character keydown.
|
|
250
|
+
if (oEvent.keyCode === KeyCodes.ALT && oEvent.ctrlKey) {
|
|
251
|
+
this._bCtrlAltDown = true;
|
|
252
|
+
}
|
|
253
|
+
|
|
229
254
|
if (!oFocus) {
|
|
230
255
|
return;
|
|
231
256
|
}
|
|
@@ -253,11 +278,7 @@ sap.ui.define([
|
|
|
253
278
|
}
|
|
254
279
|
oEvent.stopPropagation();
|
|
255
280
|
} else if (oEvent.keyCode === KeyCodes.F6) {
|
|
256
|
-
|
|
257
|
-
oFocus.button = null;
|
|
258
|
-
this._oGraph.setFocus(oFocus);
|
|
259
|
-
}
|
|
260
|
-
this._handleArrow(oEvent, oEvent.shiftKey ? mDirections.LEFT : mDirections.RIGHT);
|
|
281
|
+
this._handleF6(oEvent);
|
|
261
282
|
} else if (oEvent.keyCode === KeyCodes.F7 && !oEvent.shiftKey) {
|
|
262
283
|
if (oItem && oBtn) {
|
|
263
284
|
oFocus.button = null;
|
|
@@ -269,6 +290,24 @@ sap.ui.define([
|
|
|
269
290
|
this._onCtrlPlus(oEvent);
|
|
270
291
|
} else if (oEvent.ctrlKey && (oEvent.keyCode === KeyCodes.SLASH || oEvent.keyCode === KeyCodes.NUMPAD_MINUS)) {
|
|
271
292
|
this._onCtrlMinus(oEvent);
|
|
293
|
+
} else if (this._bCtrlAltDown && oEvent.keyCode === KeyCodes.P) {
|
|
294
|
+
this._bCtrlAltDown = false;
|
|
295
|
+
const oAssociatedControl = this._oGraph.getAssociatedControl();
|
|
296
|
+
if (oAssociatedControl) {
|
|
297
|
+
oAssociatedControl.focus();
|
|
298
|
+
oItem._setFocus(false);
|
|
299
|
+
}
|
|
300
|
+
oEvent.preventDefault();
|
|
301
|
+
oEvent.stopPropagation();
|
|
302
|
+
} else if (oEvent.altKey && !oEvent.ctrlKey && !oEvent.shiftKey && oItem instanceof Node) {
|
|
303
|
+
if (oEvent.keyCode === KeyCodes.PLUS || oEvent.keyCode === KeyCodes.NUMPAD_PLUS) {
|
|
304
|
+
this._handleAltAnnounce(oEvent, oItem);
|
|
305
|
+
} else {
|
|
306
|
+
const iDigitIndex = this._getAltDigitIndex(oEvent.keyCode);
|
|
307
|
+
if (iDigitIndex >= 0) {
|
|
308
|
+
this._handleAltConnectorNavigation(oEvent, oItem, iDigitIndex);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
272
311
|
}
|
|
273
312
|
};
|
|
274
313
|
|
|
@@ -276,6 +315,59 @@ sap.ui.define([
|
|
|
276
315
|
/* Private methods */
|
|
277
316
|
/* =========================================================== */
|
|
278
317
|
|
|
318
|
+
KeyboardNavigator.prototype._getAltDigitIndex = function (iKeyCode) {
|
|
319
|
+
if (iKeyCode >= KeyCodes.DIGIT_1 && iKeyCode <= KeyCodes.DIGIT_9) {
|
|
320
|
+
return iKeyCode - KeyCodes.DIGIT_1;
|
|
321
|
+
}
|
|
322
|
+
if (iKeyCode >= KeyCodes.NUMPAD_1 && iKeyCode <= KeyCodes.NUMPAD_9) {
|
|
323
|
+
return iKeyCode - KeyCodes.NUMPAD_1;
|
|
324
|
+
}
|
|
325
|
+
return -1;
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Handles F6 / Shift+F6 — skip to next/previous visible group regardless of what is focused.
|
|
330
|
+
* @private
|
|
331
|
+
*/
|
|
332
|
+
KeyboardNavigator.prototype._handleF6 = function (oEvent) {
|
|
333
|
+
const bBackward = oEvent.shiftKey,
|
|
334
|
+
oFocus = this.getFocus(),
|
|
335
|
+
oItem = oFocus ? oFocus.item : null,
|
|
336
|
+
bIsRtl = this._oGraph._bIsRtl,
|
|
337
|
+
aGroups = this._oGraph.getGroups().filter(function (oGroup) {
|
|
338
|
+
return !oGroup.isHidden() && oGroup.getVisible();
|
|
339
|
+
}).sort(function (oA, oB) {
|
|
340
|
+
// Top-to-bottom, then by reading direction (RTL: descending x, LTR: ascending x)
|
|
341
|
+
const iDeltaY = oA.getY() - oB.getY();
|
|
342
|
+
if (iDeltaY !== 0) { return iDeltaY; }
|
|
343
|
+
const iDeltaX = oA.getX() - oB.getX();
|
|
344
|
+
return bIsRtl ? -iDeltaX : iDeltaX;
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
if (aGroups.length === 0) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let iCurrentIndex = -1;
|
|
352
|
+
if (oItem instanceof Group) {
|
|
353
|
+
iCurrentIndex = aGroups.indexOf(oItem);
|
|
354
|
+
} else if (oItem instanceof Node && oItem._oGroup) {
|
|
355
|
+
iCurrentIndex = aGroups.indexOf(oItem._oGroup);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const iTargetIndex = bBackward
|
|
359
|
+
? (iCurrentIndex > 0 ? iCurrentIndex - 1 : aGroups.length - 1)
|
|
360
|
+
: (iCurrentIndex < aGroups.length - 1 ? iCurrentIndex + 1 : 0);
|
|
361
|
+
|
|
362
|
+
// Ensure setFocus lands on the group header, not the menu button
|
|
363
|
+
if (this._oGraph._oFocus) {
|
|
364
|
+
this._oGraph._oFocus.groupInFocused = false;
|
|
365
|
+
}
|
|
366
|
+
this._oGraph.setFocus({ item: aGroups[iTargetIndex], button: null });
|
|
367
|
+
oEvent.preventDefault();
|
|
368
|
+
oEvent.stopPropagation();
|
|
369
|
+
};
|
|
370
|
+
|
|
279
371
|
KeyboardNavigator.prototype._handleEnter = function () {
|
|
280
372
|
var oItem, oBtn,
|
|
281
373
|
oFocus = this.getFocus();
|
|
@@ -324,9 +416,71 @@ sap.ui.define([
|
|
|
324
416
|
}
|
|
325
417
|
};
|
|
326
418
|
|
|
419
|
+
KeyboardNavigator.prototype._handleDelete = function (oEvent) {
|
|
420
|
+
// Only handle delete when DnD is enabled
|
|
421
|
+
if (!this._oGraph._isDnDEnabled()) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
var oFocus = this.getFocus();
|
|
426
|
+
if (!oFocus) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
var oItem = oFocus.item;
|
|
431
|
+
|
|
432
|
+
// Only allow delete for Node and Line, not Group
|
|
433
|
+
if (oItem instanceof Node || oItem instanceof Line) {
|
|
434
|
+
oItem.setSelected(false);
|
|
435
|
+
|
|
436
|
+
// Clear focus before delete to prevent stale reference issues
|
|
437
|
+
if (this._oGraph._oFocus && this._oGraph._oFocus.item === oItem) {
|
|
438
|
+
this._oGraph._oFocus = null;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Fire the itemDeleted event on the graph
|
|
442
|
+
var bExecuteDefault = this._oGraph.fireEvent("itemDeleted", {
|
|
443
|
+
item: oItem
|
|
444
|
+
}, true);
|
|
445
|
+
|
|
446
|
+
if (bExecuteDefault) {
|
|
447
|
+
oEvent.stopPropagation();
|
|
448
|
+
oEvent.preventDefault();
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Restore focus after a small timeout (to let any rerender settle)
|
|
452
|
+
setTimeout(function () {
|
|
453
|
+
this._oGraph.setFocus(oFocus)
|
|
454
|
+
}.bind(this), 0);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Fires the nodeAdded event and shifts focus to the newly added node after re-render.
|
|
460
|
+
* Only active when DnD is enabled.
|
|
461
|
+
* @private
|
|
462
|
+
*/
|
|
463
|
+
KeyboardNavigator.prototype._handleAddNode = function (oEvent) {
|
|
464
|
+
if (!this._oGraph._isDnDEnabled()) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
this._oGraph.fireEvent("nodeAdded", {}, false);
|
|
468
|
+
const fnFocus = () => {
|
|
469
|
+
this._oGraph.detachGraphReady(fnFocus);
|
|
470
|
+
const aNodes = this._oGraph.getNodes();
|
|
471
|
+
if (aNodes.length) {
|
|
472
|
+
this._oGraph.setFocus({ item: aNodes.at(-1), button: null });
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
this._oGraph.attachGraphReady(fnFocus);
|
|
476
|
+
oEvent.preventDefault();
|
|
477
|
+
oEvent.stopPropagation();
|
|
478
|
+
};
|
|
479
|
+
|
|
327
480
|
KeyboardNavigator.prototype._handleTab = function (oEvent, sDirection) {
|
|
328
|
-
|
|
329
|
-
|
|
481
|
+
const oFocus = this.getFocus(),
|
|
482
|
+
bBackward = sDirection === mDirections.LEFT;
|
|
483
|
+
this._oWrapperDom.setAttribute("aria-live", "assertive");
|
|
330
484
|
this._oGraph._setAriaLabelForWrapper(oResourceBundle.getText("NETWORK_GRAPH_ACCESSIBILITY_LABEL"));
|
|
331
485
|
if (this._ignoreEvent(oEvent)) {
|
|
332
486
|
this._oWrapperDom.setAttribute("aria-live","off");
|
|
@@ -348,7 +502,118 @@ sap.ui.define([
|
|
|
348
502
|
return;
|
|
349
503
|
}
|
|
350
504
|
|
|
351
|
-
|
|
505
|
+
if (oFocus?.item instanceof Node) {
|
|
506
|
+
const bMoved = this._navigateFromNode(oFocus.item, bBackward);
|
|
507
|
+
if (!bMoved && bBackward) {
|
|
508
|
+
const oGroup = oFocus.item._oGroup;
|
|
509
|
+
if (oGroup) {
|
|
510
|
+
this._oGraph.setFocus({ item: oGroup, button: Group.BUTTONS.COLLAPSE });
|
|
511
|
+
oEvent.preventDefault();
|
|
512
|
+
oEvent.stopPropagation();
|
|
513
|
+
} else {
|
|
514
|
+
this._moveItemFocus(oEvent, mDirections.LEFT);
|
|
515
|
+
}
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
} else if (oFocus?.item instanceof Line) {
|
|
519
|
+
this._navigateFromConnector(oFocus.item, bBackward);
|
|
520
|
+
} else {
|
|
521
|
+
this._moveItemFocus(oEvent, sDirection);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
oEvent.preventDefault();
|
|
526
|
+
oEvent.stopPropagation();
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Navigate from a node to its first connector.
|
|
531
|
+
* @returns {boolean} True if focus moved to a connector, false otherwise
|
|
532
|
+
* @private
|
|
533
|
+
*/
|
|
534
|
+
KeyboardNavigator.prototype._navigateFromNode = function (oNode, bBackward) {
|
|
535
|
+
const aLines = bBackward ? oNode.getParentLines() : oNode.getChildLines();
|
|
536
|
+
const aVisibleLines = this._getVisibleLines(aLines, bBackward);
|
|
537
|
+
|
|
538
|
+
if (aVisibleLines.length > 0) {
|
|
539
|
+
this._oGraph.setFocus({
|
|
540
|
+
item: aVisibleLines[0],
|
|
541
|
+
button: null
|
|
542
|
+
});
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
return false;
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Navigate from a connector to its connected node
|
|
550
|
+
* @param {Line} oLine - The connector to navigate from
|
|
551
|
+
* @param {boolean} bBackward - True for source node, false for target node
|
|
552
|
+
* @private
|
|
553
|
+
*/
|
|
554
|
+
KeyboardNavigator.prototype._navigateFromConnector = function (oLine, bBackward) {
|
|
555
|
+
const oNode = bBackward ? oLine.getFromNode() : oLine.getToNode();
|
|
556
|
+
|
|
557
|
+
if (oNode && !oNode.isHidden()) {
|
|
558
|
+
this._oGraph.setFocus({
|
|
559
|
+
item: oNode,
|
|
560
|
+
button: null
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Returns visible lines sorted top-to-bottom.
|
|
567
|
+
* @param {Array} aLines - Array of lines to filter and sort
|
|
568
|
+
* @param {boolean} bSortBySource - If true, sort by source node Y position; otherwise by target node
|
|
569
|
+
* @private
|
|
570
|
+
*/
|
|
571
|
+
KeyboardNavigator.prototype._getVisibleLines = function (aLines, bSortBySource) {
|
|
572
|
+
if (!aLines || aLines.length === 0) {
|
|
573
|
+
return [];
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const aVisibleLines = aLines.filter(function (oLine) {
|
|
577
|
+
return !oLine.isHidden() && !oLine._isIgnored() && oLine.getVisible();
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const fnGetSortY = (oLine) => {
|
|
581
|
+
const oNode = bSortBySource ? oLine.getFromNode() : oLine.getToNode();
|
|
582
|
+
if (oNode && !oNode.isHidden()) {
|
|
583
|
+
return oNode.getY();
|
|
584
|
+
}
|
|
585
|
+
const aCoords = oLine.getCoordinates();
|
|
586
|
+
return (aCoords && aCoords.length > 0) ? aCoords[0].getY() : 0;
|
|
587
|
+
};
|
|
588
|
+
return aVisibleLines.sort((oLine1, oLine2) => fnGetSortY(oLine1) - fnGetSortY(oLine2));
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
KeyboardNavigator.prototype._handleAltAnnounce = function (oEvent, oNode) {
|
|
592
|
+
if (this._oAltNode !== oNode) {
|
|
593
|
+
this._oAltNode = oNode;
|
|
594
|
+
this._oAltConnectors = oNode._getAltNavigationConnectors();
|
|
595
|
+
const { aIncomingConnectors, aOutgoingConnectors, aConnectors } = this._oAltConnectors;
|
|
596
|
+
this._oAltAnnouncement = (aIncomingConnectors.length >= 2 || aOutgoingConnectors.length >= 2)
|
|
597
|
+
? oNode._getAltConnectorsAnnouncement(aConnectors)
|
|
598
|
+
: null;
|
|
599
|
+
}
|
|
600
|
+
if (!this._oAltAnnouncement) { return; }
|
|
601
|
+
this._oGraph._setAccessibilityTitle(this._oAltAnnouncement);
|
|
602
|
+
oEvent.preventDefault();
|
|
603
|
+
oEvent.stopPropagation();
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
KeyboardNavigator.prototype._handleAltConnectorNavigation = function (oEvent, oNode, iIndex) {
|
|
607
|
+
if (this._oAltNode !== oNode || !this._oAltConnectors) {
|
|
608
|
+
this._oAltNode = oNode;
|
|
609
|
+
this._oAltConnectors = oNode._getAltNavigationConnectors();
|
|
610
|
+
}
|
|
611
|
+
const { aConnectors } = this._oAltConnectors;
|
|
612
|
+
if (iIndex < aConnectors.length) {
|
|
613
|
+
this._oGraph.setFocus({ item: aConnectors[iIndex].line, button: null });
|
|
614
|
+
oEvent.preventDefault();
|
|
615
|
+
oEvent.stopPropagation();
|
|
616
|
+
}
|
|
352
617
|
};
|
|
353
618
|
|
|
354
619
|
KeyboardNavigator.prototype._handleTabOverLinesWithButtons = function (oEvent, sDirection) {
|
|
@@ -576,9 +841,60 @@ sap.ui.define([
|
|
|
576
841
|
return;
|
|
577
842
|
}
|
|
578
843
|
|
|
844
|
+
const oFocus = this.getFocus();
|
|
845
|
+
const oItem = oFocus.item;
|
|
846
|
+
if (oItem instanceof Line) {
|
|
847
|
+
if (sDirection === mDirections.UP || sDirection === mDirections.DOWN) {
|
|
848
|
+
this._navigateBetweenConnectors(oEvent, sDirection);
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// For all other cases, use default behavior
|
|
579
854
|
this._moveItemFocus(oEvent, sDirection, true);
|
|
580
855
|
};
|
|
581
856
|
|
|
857
|
+
/**
|
|
858
|
+
* Navigate between multiple connectors from the same source node
|
|
859
|
+
* @private
|
|
860
|
+
*/
|
|
861
|
+
KeyboardNavigator.prototype._navigateBetweenConnectors = function (oEvent, sDirection) {
|
|
862
|
+
const oFocus = this.getFocus(),
|
|
863
|
+
oLine = oFocus.item;
|
|
864
|
+
|
|
865
|
+
if (!(oLine instanceof Line)) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// ↑/↓ navigates among the outgoing connectors of this line's source node,
|
|
870
|
+
// giving a consistent vertical ordering regardless of which connector is focused.
|
|
871
|
+
const oSourceNode = oLine.getFromNode();
|
|
872
|
+
if (!oSourceNode) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const aVisibleLines = this._getVisibleLines(oSourceNode.getChildLines());
|
|
877
|
+
if (aVisibleLines.length <= 1) {
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const iCurrentIndex = aVisibleLines.indexOf(oLine);
|
|
882
|
+
if (iCurrentIndex === -1) {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
const iTargetIndex = sDirection === mDirections.DOWN ? iCurrentIndex + 1 : iCurrentIndex - 1;
|
|
887
|
+
if (iTargetIndex >= 0 && iTargetIndex < aVisibleLines.length) {
|
|
888
|
+
this._oGraph.setFocus({
|
|
889
|
+
item: aVisibleLines[iTargetIndex],
|
|
890
|
+
button: null
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
oEvent.preventDefault();
|
|
895
|
+
oEvent.stopPropagation();
|
|
896
|
+
};
|
|
897
|
+
|
|
582
898
|
KeyboardNavigator.prototype._moveItemFocus = function (oEvent, sDirection, bStopOnLast) {
|
|
583
899
|
var oFocus,
|
|
584
900
|
bBackTab = (sDirection === mDirections.LEFT && oEvent.key === "Tab"),
|
|
@@ -767,6 +1083,45 @@ sap.ui.define([
|
|
|
767
1083
|
oEvent.stopPropagation();
|
|
768
1084
|
};
|
|
769
1085
|
|
|
1086
|
+
KeyboardNavigator.prototype._updateAssociatedDelegate = function (oControl) {
|
|
1087
|
+
if (this._oAssociatedContainer) {
|
|
1088
|
+
this._oAssociatedContainer.removeEventDelegate(this._oAssociatedDelegate);
|
|
1089
|
+
this._oAssociatedContainer = null;
|
|
1090
|
+
this._oAssociatedDelegate = null;
|
|
1091
|
+
}
|
|
1092
|
+
const oContainer = oControl && oControl.getParent();
|
|
1093
|
+
if (oContainer) {
|
|
1094
|
+
this._oAssociatedDelegate = {
|
|
1095
|
+
onkeydown: (oEvent) => {
|
|
1096
|
+
if (oEvent.keyCode === KeyCodes.ALT && oEvent.ctrlKey) {
|
|
1097
|
+
this._bCtrlAltDown = true;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
if (oEvent.shiftKey && oEvent.keyCode === KeyCodes.F10) {
|
|
1101
|
+
this._oGraph._restoreFocusToGraph();
|
|
1102
|
+
oEvent.preventDefault();
|
|
1103
|
+
oEvent.stopPropagation();
|
|
1104
|
+
} else if (oEvent.keyCode === KeyCodes.INSERT || (this._bCtrlAltDown && oEvent.keyCode === KeyCodes.N)) {
|
|
1105
|
+
this._bCtrlAltDown = false;
|
|
1106
|
+
this._handleAddNode(oEvent);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
this._oAssociatedContainer = oContainer;
|
|
1111
|
+
oContainer.addEventDelegate(this._oAssociatedDelegate);
|
|
1112
|
+
}
|
|
1113
|
+
this._oAssociatedControl = oControl;
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
KeyboardNavigator.prototype.destroy = function () {
|
|
1117
|
+
if (this._oAssociatedContainer) {
|
|
1118
|
+
this._oAssociatedContainer.removeEventDelegate(this._oAssociatedDelegate);
|
|
1119
|
+
this._oAssociatedContainer = null;
|
|
1120
|
+
this._oAssociatedDelegate = null;
|
|
1121
|
+
}
|
|
1122
|
+
BaseObject.prototype.destroy.apply(this, arguments);
|
|
1123
|
+
};
|
|
1124
|
+
|
|
770
1125
|
KeyboardNavigator.prototype._ignoreEvent = function (oEvent) {
|
|
771
1126
|
return !containsOrEquals(this._oWrapperDom, oEvent.target);
|
|
772
1127
|
};
|