@eclipse-scout/core 22.0.0-beta.5 → 22.0.2

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 (101) hide show
  1. package/dist/eclipse-scout-core-c98fb5230e71dcec75ce.min.js +2 -0
  2. package/dist/eclipse-scout-core-c98fb5230e71dcec75ce.min.js.map +1 -0
  3. package/dist/eclipse-scout-core-theme-6b2fef56e9e49231a49c.min.css +1 -0
  4. package/dist/eclipse-scout-core-theme-dark-d2bb274dd42f132bfca0.min.css +1 -0
  5. package/dist/eclipse-scout-core-theme-dark.css +511 -399
  6. package/dist/eclipse-scout-core-theme-dark.css.map +1 -1
  7. package/dist/eclipse-scout-core-theme.css +247 -135
  8. package/dist/eclipse-scout-core-theme.css.map +1 -1
  9. package/dist/eclipse-scout-core.js +865 -646
  10. package/dist/eclipse-scout-core.js.map +1 -1
  11. package/dist/file-list +7 -0
  12. package/dist/locales.json +47126 -0
  13. package/dist/texts.json +1153 -0
  14. package/package.json +2 -2
  15. package/src/App.js +17 -10
  16. package/src/action/Button.less +1 -0
  17. package/src/box/Box.less +2 -2
  18. package/src/breadcrumbbar/BreadcrumbBarLayout.js +2 -2
  19. package/src/calendar/Calendar.js +40 -58
  20. package/src/calendar/Calendar.less +10 -10
  21. package/src/calendar/CalendarLayout.js +3 -1
  22. package/src/datepicker/DatePicker.less +1 -0
  23. package/src/desktop/desktoptab/DesktopTab.less +19 -2
  24. package/src/desktop/desktoptab/DesktopTabArea.less +7 -3
  25. package/src/desktop/desktoptab/DesktopTabAreaLayout.js +1 -1
  26. package/src/desktop/navigation/DesktopNavigation.less +4 -0
  27. package/src/desktop/notification/DesktopNotification.js +11 -4
  28. package/src/desktop/notification/DesktopNotification.less +5 -3
  29. package/src/desktop/outline/Outline.js +0 -30
  30. package/src/desktop/outline/Outline.less +4 -4
  31. package/src/desktop/viewbutton/ViewButton.less +18 -9
  32. package/src/desktop/viewbutton/ViewButtonBox.js +2 -2
  33. package/src/desktop/viewbutton/ViewMenuTab.less +3 -2
  34. package/src/filechooser/FileChooser.less +1 -1
  35. package/src/form/Form.less +1 -0
  36. package/src/form/fields/LookupBox.js +2 -1
  37. package/src/form/fields/breadcrumbbarfield/BreadcrumbBarField.less +14 -0
  38. package/src/form/fields/groupbox/GroupBox.js +13 -9
  39. package/src/form/fields/groupbox/GroupBox.less +4 -1
  40. package/src/form/fields/htmlfield/HtmlField.less +0 -1
  41. package/src/form/fields/listbox/ListBox.js +8 -3
  42. package/src/form/fields/tabbox/TabAreaLayout.js +63 -66
  43. package/src/form/fields/tabbox/TabBox.js +4 -7
  44. package/src/form/fields/tabbox/TabBox.less +2 -1
  45. package/src/form/fields/tabbox/TabBoxHeaderLayout.js +5 -5
  46. package/src/glasspane/GlassPane.js +3 -3
  47. package/src/group/Group.less +1 -1
  48. package/src/index.js +2 -1
  49. package/src/index.less +1 -0
  50. package/src/jquery/jquery-scout.js +5 -4
  51. package/src/login/LoginBox.less +9 -7
  52. package/src/menu/ContextMenuPopup.less +9 -2
  53. package/src/menu/Menu.less +1 -0
  54. package/src/messagebox/MessageBox.less +3 -3
  55. package/src/modeselector/Mode.less +15 -37
  56. package/src/modeselector/ModeSelector.js +1 -1
  57. package/src/modeselector/ModeSelector.less +2 -1
  58. package/src/planner/PlannerHeader.less +2 -1
  59. package/src/popup/Popup.js +24 -8
  60. package/src/popup/PopupLayout.js +2 -8
  61. package/src/scrollbar/Scrollbar.less +8 -1
  62. package/src/scrollbar/scrollbars.js +26 -4
  63. package/src/session/Session.js +4 -1
  64. package/src/style/colors-dark.less +25 -11
  65. package/src/style/colors.less +17 -3
  66. package/src/style/fonts.less +5 -0
  67. package/src/style/mixins.less +21 -14
  68. package/src/style/sizes-dark.less +4 -1
  69. package/src/style/sizes.less +7 -7
  70. package/src/table/Table.js +45 -33
  71. package/src/table/Table.less +49 -16
  72. package/src/table/TableHeader.js +10 -8
  73. package/src/table/TableHeader.less +1 -0
  74. package/src/table/TableHeaderMenu.js +3 -1
  75. package/src/table/TableHeaderMenu.less +7 -2
  76. package/src/table/columns/BooleanColumn.js +2 -2
  77. package/src/table/columns/Column.js +3 -3
  78. package/src/table/columns/ColumnOptimalWidthMeasurer.js +1 -1
  79. package/src/table/editor/CellEditorPopup.js +8 -1
  80. package/src/tagbar/TagBarOverflowPopupLayout.js +1 -1
  81. package/src/tile/TileGrid.js +1 -1
  82. package/src/tile/TileGridLayout.js +2 -2
  83. package/src/tile/accordion/TileAccordion.js +16 -1
  84. package/src/tile/fields/FormFieldTile.less +18 -11
  85. package/src/tile/fields/button/ButtonTile.js +1 -1
  86. package/src/tile/fields/htmlfield/TileHtmlField.js +28 -0
  87. package/src/tooltip/Tooltip.less +7 -5
  88. package/src/tree/CompactTree.less +1 -1
  89. package/src/tree/LazyNodeFilter.js +26 -15
  90. package/src/tree/Tree.js +114 -143
  91. package/src/tree/Tree.less +3 -5
  92. package/src/tree/TreeLayout.js +1 -1
  93. package/src/tree/TreeNode.js +2 -2
  94. package/src/util/Device.js +6 -2
  95. package/src/util/arrays.js +24 -2
  96. package/src/util/dragAndDrop.js +5 -4
  97. package/src/util/events.js +1 -1
  98. package/src/util/objects.js +4 -1
  99. package/src/widget/FilterSupport.js +7 -5
  100. package/src/widget/FilterSupport.less +38 -9
  101. package/src/widget/Widget.js +24 -7
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
+ * All rights reserved. This program and the accompanying materials
4
+ * are made available under the terms of the Eclipse Public License v1.0
5
+ * which accompanies this distribution, and is available at
6
+ * http://www.eclipse.org/legal/epl-v10.html
7
+ *
8
+ * Contributors:
9
+ * BSI Business Systems Integration AG - initial API and implementation
10
+ */
11
+ import {HtmlField} from '../../../index';
12
+
13
+ export default class TileHtmlField extends HtmlField {
14
+
15
+ constructor() {
16
+ super();
17
+ }
18
+
19
+ _render() {
20
+ super._render();
21
+
22
+ this.$container.addClass('scrollbar-y-outside');
23
+ }
24
+
25
+ _installScrollbars(options) {
26
+ return super._installScrollbars($.extend(true, {}, options, {scrollShadow: 'gradient'}));
27
+ }
28
+ }
@@ -17,11 +17,6 @@
17
17
  #scout.drop-shadow(@y: 4px, @blur: 6px, @alpha: 5%);
18
18
  max-width: 300px;
19
19
  white-space: normal;
20
-
21
- &.has-menus {
22
- padding-top: 6px;
23
- padding-bottom: 6px;
24
- }
25
20
  }
26
21
 
27
22
  .tooltip-content {
@@ -37,6 +32,7 @@
37
32
  font-weight: @font-weight-bold;
38
33
  padding-left: @context-menu-item-padding-left;
39
34
  padding-right: @context-menu-item-padding-right;
35
+ padding-top: @tooltip-padding-y + 6px;
40
36
  }
41
37
 
42
38
  & .small {
@@ -53,6 +49,12 @@
53
49
 
54
50
  .tooltip-menus {
55
51
  position: relative;
52
+ background-color: inherit; // Necessary if arrow has a border
53
+ padding-bottom: 6px;
54
+
55
+ .no-text > & {
56
+ padding-top: 6px;
57
+ }
56
58
 
57
59
  & > .menu-item {
58
60
  display: flex;
@@ -19,7 +19,7 @@
19
19
 
20
20
  & > .tree-data > .nodes > .section > .section-node.selected {
21
21
  text-decoration: underline;
22
- color: @active-color;
22
+ color: @focus-color;
23
23
  }
24
24
  }
25
25
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2014-2017 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
@@ -8,27 +8,38 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
+
11
12
  export default class LazyNodeFilter {
12
13
 
13
- constructor(tree) { //
14
+ constructor(tree) {
14
15
  this.tree = tree;
15
16
  }
16
17
 
17
18
  accept(node) {
18
- if (!node.expanded && node.parentNode && node.parentNode.expandedLazy && node.parentNode.lazyExpandingEnabled && this.tree.lazyExpandingEnabled) {
19
- // if this node is not expanded and parent is lazyExpanding.
20
- for (let i = 0; i < this.tree.selectedNodes.length; i++) {
21
- let selectedNode = this.tree.selectedNodes[i];
22
- // not initialized selected nodes
23
- if (typeof selectedNode === 'string') {
24
- break;
25
- }
26
- if (selectedNode === node || selectedNode.isDescendantOf(node)) {
27
- return true;
28
- }
19
+ if (node.expanded) {
20
+ return true;
21
+ }
22
+ // not expanded: remove lazy expand marker (forget lazy expanded children)
23
+ node.childNodes.forEach(child => {
24
+ child._lazyNodeFilterAccepted = false;
25
+ });
26
+
27
+ if (!node.parentNode || !node.parentNode.expandedLazy || !node.parentNode.lazyExpandingEnabled || !this.tree.lazyExpandingEnabled) {
28
+ // no lazy expanding supported
29
+ return true;
30
+ }
31
+
32
+ // if this node is not expanded and parent is lazyExpanding.
33
+ for (let i = 0; i < this.tree.selectedNodes.length; i++) {
34
+ let selectedNode = this.tree.selectedNodes[i];
35
+ if (typeof selectedNode === 'string') {
36
+ break;
37
+ }
38
+ if (selectedNode === node) {
39
+ node._lazyNodeFilterAccepted = true;
40
+ return true;
29
41
  }
30
- return false;
31
42
  }
32
- return true;
43
+ return !!node._lazyNodeFilterAccepted;
33
44
  }
34
45
  }
package/src/tree/Tree.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
@@ -128,10 +128,8 @@ export default class Tree extends Widget {
128
128
  this.initialTraversing = true;
129
129
  this._setCheckable(this.checkable);
130
130
  this._ensureTreeNodes(this.nodes);
131
- this.visitNodes(this._initTreeNode.bind(this));
132
- this.visitNodes(this._updateFlatListAndSelectionPath.bind(this));
131
+ this._initNodes(this.nodes);
133
132
  this.initialTraversing = false;
134
- this.selectedNodes = this._nodesByIds(this.selectedNodes);
135
133
  this.menuBar = scout.create('MenuBar', {
136
134
  parent: this,
137
135
  position: MenuBar.Position.BOTTOM,
@@ -145,6 +143,22 @@ export default class Tree extends Widget {
145
143
  this._setMenus(this.menus);
146
144
  }
147
145
 
146
+ /**
147
+ * Initialize nodes, applies filters and updates flat list
148
+ */
149
+ _initNodes(nodes, parentNode) {
150
+ if (!nodes) {
151
+ nodes = this.nodes;
152
+ }
153
+ Tree.visitNodes(this._initTreeNode.bind(this), nodes, parentNode);
154
+ if (typeof this.selectedNodes[0] === 'string') {
155
+ this.selectedNodes = this._nodesByIds(this.selectedNodes);
156
+ }
157
+ this._updateSelectionPath();
158
+ nodes.forEach(node => this.applyFiltersForNode(node));
159
+ Tree.visitNodes((node, parentNode) => this._addToVisibleFlatList(node, false), nodes, parentNode);
160
+ }
161
+
148
162
  /**
149
163
  * Iterates through the given array and converts node-models to instances of TreeNode (or a subclass).
150
164
  * If the array element is already a TreeNode the function leaves the element untouched. This function also
@@ -226,44 +240,25 @@ export default class Tree extends Widget {
226
240
  }
227
241
 
228
242
  isSelectedNode(node) {
229
- if (this.initialTraversing) {
230
- return this.selectedNodes.indexOf(node.id) > -1;
231
- }
232
243
  return this.selectedNodes.indexOf(node) > -1;
233
244
  }
234
245
 
235
- _updateFlatListAndSelectionPath(node, parentNode) {
236
- // if this node is selected all parent nodes have to be added to selectionPath
237
- if (this.isSelectedNode(node) && (node.parentNode && !this.visibleNodesMap[node.parentNode.id] || node.level === 0)) {
238
- let p = node;
239
- while (p) {
240
- this._inSelectionPathList[p.id] = true;
241
- p.filterDirty = true;
242
-
243
- if (p !== node) {
244
- // ensure node is expanded
245
- node.expanded = true;
246
- // if parent was filtered before, try refilter after adding to selection path.
247
- if (p.level === 0) {
248
- this.applyFiltersForNode(p);
249
-
250
- // add visible nodes to visible nodes array when they are initialized
251
- this._addToVisibleFlatList(p, false);
252
-
253
- // process children
254
- this._addChildrenToFlatList(p, this.visibleNodesFlat.length - 1, false, null, true);
255
- }
256
- }
257
- p = p.parentNode;
258
- }
259
- } else if (node.parentNode && this.isSelectedNode(node.parentNode)) {
260
- this._inSelectionPathList[node.id] = true;
246
+ _updateSelectionPath() {
247
+ let selectedNode = this.selectedNodes[0];
248
+ if (!selectedNode) {
249
+ return;
261
250
  }
251
+ this._inSelectionPathList[selectedNode.id] = true;
262
252
 
263
- this.applyFiltersForNode(node);
253
+ selectedNode.childNodes.forEach(child => {
254
+ this._inSelectionPathList[child.id] = true;
255
+ });
264
256
 
265
- // add visible nodes to visible nodes array when they are initialized
266
- this._addToVisibleFlatList(node, false);
257
+ let parentNode = selectedNode.parentNode;
258
+ while (parentNode) {
259
+ this._inSelectionPathList[parentNode.id] = true;
260
+ parentNode = parentNode.parentNode;
261
+ }
267
262
  }
268
263
 
269
264
  _initTreeNode(node, parentNode) {
@@ -303,6 +298,7 @@ export default class Tree extends Widget {
303
298
  this._removeFromFlatList(node, false); // ensure node is not longer in visible nodes list.
304
299
  node.destroy();
305
300
 
301
+ // noinspection JSUnresolvedVariable
306
302
  if (this._onNodeDeleted) { // Necessary for subclasses
307
303
  this._onNodeDeleted(node);
308
304
  }
@@ -366,8 +362,8 @@ export default class Tree extends Widget {
366
362
  }
367
363
 
368
364
  _remove() {
369
- // remove listener
370
365
  this.session.desktop.off('popupOpen', this._popupOpenHandler);
366
+ this.filterSupport.remove();
371
367
 
372
368
  // stop all animations
373
369
  if (this._$animationWrapper) {
@@ -381,9 +377,8 @@ export default class Tree extends Widget {
381
377
  this.$fillBefore = null;
382
378
  this.$fillAfter = null;
383
379
  this.$data = null;
384
- // reset rendered view range because now range is rendered
380
+ // reset rendered view range because no range is rendered
385
381
  this.viewRangeRendered = new Range(0, 0);
386
- this.filterSupport.remove();
387
382
  super._remove();
388
383
  }
389
384
 
@@ -1422,8 +1417,7 @@ export default class Tree extends Widget {
1422
1417
  node.expanded = expanded;
1423
1418
  node.expandedLazy = lazy;
1424
1419
 
1425
- let filterStateChanged = this.applyFiltersForNode(node, false, renderAnimated);
1426
- if (filterStateChanged && renderExpansionOpts.expansionChanged) {
1420
+ if (renderExpansionOpts.expansionChanged) {
1427
1421
  if (node.parentNode) {
1428
1422
  // ensure node is visible under the parent node if there is a parent.
1429
1423
  this._rebuildParent(node.parentNode, opts);
@@ -1433,9 +1427,7 @@ export default class Tree extends Widget {
1433
1427
  this._removeFromFlatList(node, false);
1434
1428
  }
1435
1429
  } else if (renderExpansionOpts.expandLazyChanged) {
1436
- node.childNodes.forEach(child => {
1437
- this.applyFiltersForNode(child, false, renderAnimated);
1438
- });
1430
+ this.applyFiltersForNode(node, false, renderAnimated);
1439
1431
  }
1440
1432
 
1441
1433
  if (this.groupedNodes[node.id]) {
@@ -1443,8 +1435,7 @@ export default class Tree extends Widget {
1443
1435
  }
1444
1436
 
1445
1437
  if (node.expanded) {
1446
- node.ensureLoadChildren().done(
1447
- this._addChildrenToFlatList.bind(this, node, null, renderAnimated, null, true));
1438
+ node.ensureLoadChildren().done(this._addChildrenToFlatList.bind(this, node, null, renderAnimated, null, true /* required that ctrl+shift+add expands all rows of a table-page */));
1448
1439
  } else {
1449
1440
  this._removeChildrenFromFlatList(node, renderAnimated);
1450
1441
  }
@@ -1477,7 +1468,7 @@ export default class Tree extends Widget {
1477
1468
  return;
1478
1469
  }
1479
1470
  if (node.expanded || node.expandedLazy) {
1480
- this._addChildrenToFlatList(node, null, false, null, true);
1471
+ this._addChildrenToFlatList(node, null, true, null, true /* required so that double clicking a table-page-row expands the clicked child row */);
1481
1472
  } else {
1482
1473
  this._removeChildrenFromFlatList(node, false);
1483
1474
  }
@@ -1580,7 +1571,6 @@ export default class Tree extends Widget {
1580
1571
  }
1581
1572
 
1582
1573
  _removeFromFlatList(node, animatedRemove) {
1583
- let removedNodes = [];
1584
1574
  if (this.visibleNodesMap[node.id]) {
1585
1575
  let index = this.visibleNodesFlat.indexOf(node);
1586
1576
  this._removeChildrenFromFlatList(node, false);
@@ -1591,12 +1581,10 @@ export default class Tree extends Widget {
1591
1581
  this.nodeWidthDirty = true;
1592
1582
  }
1593
1583
  }
1594
- removedNodes = arrays.ensure(this.visibleNodesFlat.splice(index, 1));
1584
+ this.visibleNodesFlat.splice(index, 1);
1595
1585
  delete this.visibleNodesMap[node.id];
1596
1586
  this.hideNode(node, animatedRemove);
1597
1587
  }
1598
- removedNodes.push(node);
1599
- return removedNodes;
1600
1588
  }
1601
1589
 
1602
1590
  /**
@@ -1605,8 +1593,8 @@ export default class Tree extends Widget {
1605
1593
  _addToVisibleFlatList(node, renderingAnimated) {
1606
1594
  // if node already is in visible list don't do anything. If no parentNode is available this node is on toplevel, if a parent is available
1607
1595
  // it has to be in visible list and also be expanded
1608
- if (!this.visibleNodesMap[node.id] && node.isFilterAccepted() && (!node.parentNode ||
1609
- node.parentNode.expanded && this.visibleNodesMap[node.parentNode.id])) {
1596
+ if (!this.visibleNodesMap[node.id] && node.filterAccepted
1597
+ && (!node.parentNode || node.parentNode.expanded && this.visibleNodesMap[node.parentNode.id])) {
1610
1598
  if (this.initialTraversing) {
1611
1599
  // for faster index calculation
1612
1600
  this._addToVisibleFlatListNoCheck(node, this.visibleNodesFlat.length, renderingAnimated);
@@ -1653,11 +1641,10 @@ export default class Tree extends Widget {
1653
1641
  let insertIndex, isAlreadyAdded = this.visibleNodesMap[node.id];
1654
1642
  if (isAlreadyAdded) {
1655
1643
  this.insertBatchInVisibleNodes(insertBatch, this._showNodes(insertBatch), animatedRendering);
1656
- this.checkAndHandleBatchAnimationWrapper(parentNode, animatedRendering, insertBatch);
1644
+ // Animate rendering is always false because it would generate a bunch of animation wrappers which stay forever without really starting an animation...
1645
+ this.checkAndHandleBatchAnimationWrapper(parentNode, false, insertBatch);
1657
1646
  insertBatch = this.newInsertBatch(insertBatch.nextBatchInsertIndex());
1658
1647
  insertBatch = this._addChildrenToFlatListIfExpanded(1, node, insertIndex, animatedRendering, insertBatch, forceFilter);
1659
- // do not animate following
1660
- animatedRendering = false;
1661
1648
  } else {
1662
1649
  insertBatch.insertNodes.push(node);
1663
1650
  this.visibleNodesMap[node.id] = true;
@@ -2201,9 +2188,7 @@ export default class Tree extends Widget {
2201
2188
  parentNode.childNodes.push(entry);
2202
2189
  });
2203
2190
  }
2204
- // initialize node and add to visible list if node is visible
2205
- Tree.visitNodes(this._initTreeNode.bind(this), nodes, parentNode);
2206
- Tree.visitNodes(this._updateFlatListAndSelectionPath.bind(this), nodes, parentNode);
2191
+ this._initNodes(nodes, parentNode);
2207
2192
  if (this.groupedNodes[parentNode.id]) {
2208
2193
  this._updateItemPath(false, parentNode);
2209
2194
  }
@@ -2226,9 +2211,7 @@ export default class Tree extends Widget {
2226
2211
  } else {
2227
2212
  arrays.pushAll(this.nodes, nodes);
2228
2213
  }
2229
- // initialize node and add to visible list if node is visible
2230
- Tree.visitNodes(this._initTreeNode.bind(this), nodes, parentNode);
2231
- Tree.visitNodes(this._updateFlatListAndSelectionPath.bind(this), nodes, parentNode);
2214
+ this._initNodes(nodes, parentNode);
2232
2215
  }
2233
2216
  if (this.rendered) {
2234
2217
  this.viewRangeDirty = true;
@@ -2352,9 +2335,7 @@ export default class Tree extends Widget {
2352
2335
  }, this);
2353
2336
 
2354
2337
  // update child node indices
2355
- parentNodesToReindex.forEach(function(p) {
2356
- this._updateChildNodeIndex(p.childNodes);
2357
- }, this);
2338
+ parentNodesToReindex.forEach(p => this._updateChildNodeIndex(p.childNodes));
2358
2339
  this._updateChildNodeIndex(topLevelNodesToReindex);
2359
2340
 
2360
2341
  this.deselectNodes(deletedNodes, {collectChildren: true});
@@ -2748,10 +2729,8 @@ export default class Tree extends Widget {
2748
2729
  // Filter nodes
2749
2730
  this.nodes.forEach(node => {
2750
2731
  let result = this.applyFiltersForNode(node, false, this.filterAnimated);
2751
- arrays.removeAll(newlyHidden, result.newlyShown);
2752
- arrays.removeAll(newlyShown, result.newlyHidden);
2753
- result.newlyHidden.forEach(hidden => arrays.pushSet(newlyHidden, hidden));
2754
- result.newlyShown.forEach(shown => arrays.pushSet(newlyShown, shown));
2732
+ newlyHidden.push(...result.newlyHidden);
2733
+ newlyShown.push(...result.newlyShown);
2755
2734
  });
2756
2735
  return {
2757
2736
  newlyHidden: newlyHidden,
@@ -2764,28 +2743,30 @@ export default class Tree extends Widget {
2764
2743
  return;
2765
2744
  }
2766
2745
  if (opts.textFilterText) {
2767
- result.newlyShown.forEach(node => this._expandAllParentNodes(node));
2746
+ this._nodesByIds(Object.keys(this.nodesMap))
2747
+ .filter(it => it.filterAccepted)
2748
+ .forEach(node => this._expandAllParentNodes(node));
2768
2749
  }
2769
2750
  result.newlyShown.forEach(node => this._addToVisibleFlatList(node, this.filterAnimated));
2770
- this._nodesFiltered(arrays.flatMap(result.newlyHidden, node => this._removeFromFlatList(node, this.filterAnimated)));
2751
+ result.newlyHidden.forEach(node => this._removeFromFlatList(node, this.filterAnimated));
2771
2752
  this.filteredElementsDirty = false;
2772
2753
  }
2773
2754
 
2774
2755
  filterVisibleNodes(animated) {
2775
2756
  // Filter nodes
2776
2757
  let newlyHidden = [];
2777
- for (let i = 0; i < this.visibleNodesFlat.length; i++) {
2758
+ // iterate from end to beginning (child nodes first) so that the state of the children has already been updated
2759
+ for (let i = this.visibleNodesFlat.length - 1; i >= 0; i--) {
2778
2760
  let node = this.visibleNodesFlat[i];
2779
- let result = this.applyFiltersForNode(node, false, animated);
2761
+ let result = this._applyFiltersForNodeRec(node, true, animated);
2780
2762
  if (result.newlyHidden.length) {
2781
2763
  if (!node.isFilterAccepted()) {
2782
- i--;
2783
- arrays.pushAll(newlyHidden, this._removeFromFlatList(node, animated));
2764
+ newlyHidden.push(...result.newlyHidden);
2784
2765
  }
2785
2766
  this.viewRangeDirty = true;
2786
2767
  }
2787
2768
  }
2788
-
2769
+ newlyHidden.forEach(h => this._removeFromFlatList(h, animated));
2789
2770
  this._nodesFiltered(newlyHidden);
2790
2771
  }
2791
2772
 
@@ -2795,88 +2776,78 @@ export default class Tree extends Widget {
2795
2776
  }
2796
2777
 
2797
2778
  applyFiltersForNode(node, applyNewHiddenShownNodes = true, animated = false) {
2798
- let newlyHidden = [],
2799
- newlyShown = [];
2800
- animated = animated && this.filterAnimated;
2801
- node.filterDirty = true;
2802
- let changed = this._applyFiltersForNode(node);
2803
- if (changed) {
2804
- let parents = [];
2805
- let parent = node.parentNode;
2779
+ let result = this._applyFiltersForNodeRec(node, true, animated);
2806
2780
 
2807
- // collect all parents that need to be updated
2808
- // show: if node.filterAccepted === true, all parents with parent.filterAccepted === false need to be updated
2809
- // hide: if node.filterAccepted === false, all parents with parent.filterAccepted === true need to be updated...
2810
- // ...EXCEPT there are other childNodes of parent with childNode.filterAccepted === true OR the parent is directly accepted by all filters
2811
- while (parent && parent.filterAccepted !== node.filterAccepted && (node.filterAccepted || (parent.childNodes.filter(child => parents.indexOf(child) === -1).every(child => !child.filterAccepted) && !this.filterSupport.elementAcceptedByFilters(parent)))) {
2812
- arrays.insert(parents, parent, 0);
2813
- parent = parent.parentNode;
2814
- }
2781
+ // the result so far only includes the node and all its children.
2782
+ // always include the parent nodes as well so that the filter has an effect
2783
+ let parent = node.parentNode;
2784
+ while (parent) {
2785
+ let parentResult = this._applyFiltersForNodeRec(parent, false, animated);
2786
+ result.newlyHidden.unshift(...parentResult.newlyHidden);
2787
+ result.newlyShown.unshift(...parentResult.newlyShown);
2788
+ parent = parent.parentNode;
2789
+ }
2790
+ this._nodesFiltered(result.newlyHidden);
2815
2791
 
2816
- let removeFrom = node.filterAccepted ? newlyHidden : newlyShown,
2817
- pushTo = node.filterAccepted ? newlyShown : newlyHidden;
2792
+ if (applyNewHiddenShownNodes) {
2793
+ result.newlyShown.forEach(node => this._addToVisibleFlatList(node, animated));
2794
+ result.newlyHidden.forEach(node => this._removeFromFlatList(node, animated));
2795
+ }
2796
+ return result;
2797
+ }
2818
2798
 
2819
- parents.forEach(p => {
2820
- p.setFilterAccepted(node.filterAccepted);
2821
- arrays.remove(removeFrom, p);
2822
- arrays.pushSet(pushTo, p);
2823
- });
2824
- arrays.pushSet(pushTo, node);
2799
+ _applyFiltersForNodeRec(node, recursive, animated = false) {
2800
+ let newlyHidden = [], newlyShown = [];
2801
+ animated = animated && this.filterAnimated;
2825
2802
 
2826
- if (this.rendered) {
2827
- this.viewRangeDirty = true;
2828
- }
2829
- } else {
2830
- // this else branch is required when the filter-state of a node has not changed
2831
- // for instance Node "Telefon mit Sabrina" is visible for filter "tel" and also
2832
- // for filter "abr". However, it is possible that the node is _not_ attached, when
2833
- // we switch from one filter to another, because the node was not in the view-range
2834
- // with the previous filter. That's why we must make sure, the node is attached to
2835
- // the DOM, even though the filter state hasn't changed. Otherwise we'd have a
2836
- // problem when we insert nodes in this._insertNodeInDOMAtPlace.
2837
- if (!node.attached) {
2838
- this.showNode(node, animated);
2839
- if (node.attached) {
2840
- // If sibling nodes are hiding at the same time, the nodes to be shown should be added after these nodes to make the animation look correctly -> move them
2841
- node.$node.insertAfter(node.$node.nextAll('.hiding:last'));
2842
- }
2803
+ let changed = this._applyFiltersForNode(node);
2804
+ let hasChildrenWithFilterAccepted = false;
2805
+ if (node.level < 32 /* see org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.expandAllRec */) {
2806
+ if (recursive) {
2807
+ node.childNodes.forEach(childNode => {
2808
+ let result = this._applyFiltersForNodeRec(childNode, true, animated);
2809
+ newlyHidden.push(...result.newlyHidden);
2810
+ newlyShown.push(...result.newlyShown);
2811
+ hasChildrenWithFilterAccepted = hasChildrenWithFilterAccepted || childNode.filterAccepted;
2812
+ });
2813
+ } else if (!node.filterAccepted) {
2814
+ // Check children only if filterAccepted is false because only then hasChildrenWithFilterAccepted is used (see below).
2815
+ // This has great impact on performance when there are many nodes
2816
+ hasChildrenWithFilterAccepted = node.childNodes.some(childNode => childNode.filterAccepted);
2843
2817
  }
2844
2818
  }
2845
2819
 
2846
- if (node.level < 32) {
2847
- node.childNodes.forEach(childNode => {
2848
- let result = this.applyFiltersForNode(childNode, false, animated);
2849
- arrays.removeAll(newlyHidden, result.newlyShown);
2850
- arrays.removeAll(newlyShown, result.newlyHidden);
2851
- result.newlyHidden.forEach(hidden => arrays.pushSet(newlyHidden, hidden));
2852
- result.newlyShown.forEach(shown => arrays.pushSet(newlyShown, shown));
2853
- });
2820
+ // set filter accepted on this node if it has children with filter accepted (so that the children are visible)
2821
+ if (!node.filterAccepted && hasChildrenWithFilterAccepted) {
2822
+ node.setFilterAccepted(true);
2823
+ changed = !changed;
2854
2824
  }
2855
2825
 
2856
- if (applyNewHiddenShownNodes) {
2857
- newlyShown.forEach(node => this._addToVisibleFlatList(node, animated));
2858
- this._nodesFiltered(arrays.flatMap(newlyHidden, node => this._removeFromFlatList(node, animated)));
2826
+ // remember changed node
2827
+ if (changed) {
2828
+ let pushTo = node.filterAccepted ? newlyShown : newlyHidden;
2829
+ pushTo.unshift(node);
2830
+
2831
+ if (this.rendered) {
2832
+ this.viewRangeDirty = true;
2833
+ }
2859
2834
  }
2860
2835
 
2861
- return {
2862
- newlyHidden: newlyHidden,
2863
- newlyShown: newlyShown
2864
- };
2836
+ return {newlyHidden: newlyHidden, newlyShown: newlyShown};
2865
2837
  }
2866
2838
 
2867
2839
  /**
2868
2840
  * @returns {Boolean} true if node state has changed, false if not
2869
2841
  */
2870
2842
  _applyFiltersForNode(node) {
2871
- let changed = this.filterSupport.applyFiltersForElement(node) || node.filterDirty;
2872
- if (changed) {
2843
+ let changed = this.filterSupport.applyFiltersForElement(node);
2844
+ if (changed || node.filterDirty) {
2873
2845
  node.filterDirty = false;
2874
2846
  node.childNodes.forEach(childNode => {
2875
2847
  childNode.filterDirty = true;
2876
2848
  });
2877
- return true;
2878
2849
  }
2879
- return false;
2850
+ return changed;
2880
2851
  }
2881
2852
 
2882
2853
  /**
@@ -2912,7 +2883,7 @@ export default class Tree extends Widget {
2912
2883
  }
2913
2884
  nodes = nodes.filter(function(node) {
2914
2885
  let index = indexHint === undefined ? this.visibleNodesFlat.indexOf(node) : indexHint;
2915
- if (index === -1 || !(this.viewRangeRendered.from + this.viewRangeSize >= index && this.viewRangeRendered.from <= index && this.viewRangeRendered.size() > 0) || node.attached) {
2886
+ if (index === -1 || !(this.viewRangeRendered.from + this.viewRangeSize >= index && this.viewRangeRendered.from <= index && this.viewRangeSize > 0) || node.attached) {
2916
2887
  // node is not visible
2917
2888
  return false;
2918
2889
  }
@@ -3073,6 +3044,10 @@ export default class Tree extends Widget {
3073
3044
  that.runningAnimationsFinishFunc();
3074
3045
  $node.removeClass('hiding');
3075
3046
  if (!$node.hasClass('showing')) {
3047
+ // JQuery sets display to none which we don't need because node will be detached.
3048
+ // If node is added using another method than slideDown (used by show node), it would be invisible.
3049
+ // Example: parent is collapsed while nodes are hiding -> remove filter, expand parent -> invisible nodes
3050
+ $node.css('display', '');
3076
3051
  $node.detach();
3077
3052
  node.attached = false;
3078
3053
  }
@@ -3086,15 +3061,11 @@ export default class Tree extends Widget {
3086
3061
  }
3087
3062
 
3088
3063
  _nodesToIds(nodes) {
3089
- return nodes.map(node => {
3090
- return node.id;
3091
- });
3064
+ return nodes.map(node => node.id);
3092
3065
  }
3093
3066
 
3094
3067
  _nodesByIds(ids) {
3095
- return ids.map(id => {
3096
- return this.nodesMap[id];
3097
- });
3068
+ return ids.map(id => this.nodesMap[id]);
3098
3069
  }
3099
3070
 
3100
3071
  _nodeById(id) {
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
@@ -28,7 +28,7 @@
28
28
  }
29
29
 
30
30
  & > .filter-field {
31
- --filter-field-max-bottom: calc(~'50% - ' (@filter-field-height + var(--menubar-height)) / 2);
31
+ --filter-field-max-bottom: calc(~'50% - ' (var(--filter-field-height) + var(--menubar-height)) / 2);
32
32
  bottom: calc(min(var(--filter-field-bottom), var(--filter-field-max-bottom)) + var(--menubar-height));
33
33
 
34
34
  &:not(.focused).empty {
@@ -216,18 +216,16 @@
216
216
 
217
217
  .tree-node.lazy > & {
218
218
  font-family: @font-default-family;
219
- font-size: @font-size-normal;
220
219
  content: '+';
221
220
  /* Move to left because '+' sign is not as wide as 'arrow-down' */
222
221
  margin-left: -2px;
223
222
  }
224
223
 
225
224
  .tree-node.expanded > & {
226
- /* This "imprecise" angle is a workround for firefox to prevent shifting the div a little when the animation finishes. */
225
+ /* This "imprecise" angle is a workaround for firefox to prevent shifting the div a little when the animation finishes. */
227
226
  /* See https://bugzilla.mozilla.org/show_bug.cgi?id=739176 */
228
227
  #scout.transform(rotate(89.99deg));
229
228
  }
230
-
231
229
  }
232
230
 
233
231
  &:hover {
@@ -34,7 +34,7 @@ export default class TreeLayout extends AbstractLayout {
34
34
  })
35
35
  .subtract(htmlContainer.insets());
36
36
 
37
- if (this.tree.toggleBreadcrumbStyleEnabled) {
37
+ if (this.tree.toggleBreadcrumbStyleEnabled && this._sizeChanged(htmlContainer)) {
38
38
  this.tree.setBreadcrumbStyleActive(Math.floor(containerSize.width) <= this.tree.breadcrumbTogglingThreshold);
39
39
  }
40
40
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
@@ -147,7 +147,7 @@ export default class TreeNode {
147
147
 
148
148
  isFilterAccepted(forceFilter) {
149
149
  if (this.filterDirty || forceFilter) {
150
- this.getTree().applyFiltersForNode(this, false);
150
+ this.getTree().applyFiltersForNode(this);
151
151
  }
152
152
  return this.filterAccepted;
153
153
  }