@eclipse-scout/core 22.0.1 → 22.0.11

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 (156) hide show
  1. package/dist/eclipse-scout-core-e5e8740e3649f5b9f279.min.js +2 -0
  2. package/dist/eclipse-scout-core-e5e8740e3649f5b9f279.min.js.map +1 -0
  3. package/dist/eclipse-scout-core-theme-74b63e0d57bed407a729.min.css +1 -0
  4. package/dist/eclipse-scout-core-theme-dark-b82aea152f416e38ce7f.min.css +1 -0
  5. package/dist/eclipse-scout-core-theme-dark.css +517 -361
  6. package/dist/eclipse-scout-core-theme-dark.css.map +1 -1
  7. package/dist/eclipse-scout-core-theme.css +300 -144
  8. package/dist/eclipse-scout-core-theme.css.map +1 -1
  9. package/dist/eclipse-scout-core.js +1150 -766
  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/ErrorHandler.js +66 -28
  16. package/src/{table/TableHeaderMenuButtonKeyStroke.js → action/ActionExecKeyStroke.js} +4 -5
  17. package/src/action/Button.less +1 -0
  18. package/src/box/Box.less +10 -6
  19. package/src/breadcrumbbar/BreadcrumbItem.less +3 -6
  20. package/src/calendar/Calendar.js +40 -58
  21. package/src/calendar/Calendar.less +10 -10
  22. package/src/calendar/CalendarLayout.js +3 -1
  23. package/src/checkbox/CheckBox.less +3 -1
  24. package/src/datepicker/DatePicker.less +1 -0
  25. package/src/datepicker/DatePickerTouchPopup.js +8 -0
  26. package/src/desktop/DisableBrowserF5ReloadKeyStroke.js +1 -0
  27. package/src/desktop/bench/DesktopTabSelectKeyStroke.js +2 -1
  28. package/src/desktop/desktoptab/DesktopTab.less +5 -2
  29. package/src/desktop/desktoptab/DesktopTabArea.less +7 -3
  30. package/src/desktop/desktoptab/DisableBrowserTabSwitchingKeyStroke.js +1 -0
  31. package/src/desktop/navigation/DesktopNavigation.less +4 -0
  32. package/src/desktop/navigation/EnlargeNavigationKeyStroke.js +1 -0
  33. package/src/desktop/navigation/ShrinkNavigationKeyStroke.js +1 -0
  34. package/src/desktop/notification/DesktopNotification.js +11 -4
  35. package/src/desktop/notification/DesktopNotification.less +5 -3
  36. package/src/desktop/outline/Outline.less +4 -4
  37. package/src/desktop/viewbutton/ViewButton.less +13 -9
  38. package/src/desktop/viewbutton/ViewMenuPopupEnterKeyStroke.js +2 -1
  39. package/src/desktop/viewbutton/ViewMenuTab.less +3 -2
  40. package/src/filechooser/FileChooser.js +1 -1
  41. package/src/filechooser/FileChooser.less +16 -11
  42. package/src/focus/FocusContext.js +11 -8
  43. package/src/focus/FocusManager.js +24 -5
  44. package/src/form/Form.less +1 -0
  45. package/src/form/fields/LookupBox.js +5 -2
  46. package/src/form/fields/LookupBox.less +28 -2
  47. package/src/form/fields/TextFieldIcon.less +2 -2
  48. package/src/form/fields/ValueField.js +11 -2
  49. package/src/form/fields/breadcrumbbarfield/BreadcrumbBarField.less +20 -0
  50. package/src/form/fields/button/ButtonKeyStroke.js +0 -3
  51. package/src/form/fields/datefield/DateField.js +31 -47
  52. package/src/form/fields/filechooserfield/FileChooserFieldBrowseKeyStroke.js +1 -3
  53. package/src/form/fields/filechooserfield/FileChooserFieldDeleteKeyStroke.js +1 -3
  54. package/src/form/fields/groupbox/GroupBox.js +14 -9
  55. package/src/form/fields/groupbox/GroupBox.less +1 -0
  56. package/src/form/fields/htmlfield/HtmlField.less +0 -1
  57. package/src/form/fields/listbox/ListBox.js +13 -7
  58. package/src/form/fields/lookupfield/lookupField.js +6 -5
  59. package/src/form/fields/smartfield/ProposalField.js +2 -1
  60. package/src/form/fields/smartfield/ProposalTreeNode.js +4 -8
  61. package/src/form/fields/smartfield/SmartField.js +4 -20
  62. package/src/form/fields/smartfield/SmartField.less +24 -11
  63. package/src/form/fields/splitbox/SplitBoxCollapseKeyStroke.js +1 -0
  64. package/src/form/fields/splitbox/SplitBoxFirstCollapseKeyStroke.js +1 -0
  65. package/src/form/fields/splitbox/SplitBoxSecondCollapseKeyStroke.js +1 -0
  66. package/src/form/fields/tabbox/TabAreaLayout.js +63 -66
  67. package/src/form/fields/tabbox/TabAreaLeftKeyStroke.js +2 -0
  68. package/src/form/fields/tabbox/TabAreaRightKeyStroke.js +2 -0
  69. package/src/form/fields/tabbox/TabBox.js +8 -7
  70. package/src/form/fields/tabbox/TabBox.less +2 -1
  71. package/src/form/fields/tabbox/TabBoxHeader.js +4 -0
  72. package/src/form/fields/tabbox/TabBoxHeaderLayout.js +5 -5
  73. package/src/form/fields/tabbox/TabItem.js +4 -0
  74. package/src/form/fields/treebox/TreeBox.js +6 -5
  75. package/src/glasspane/GlassPane.js +3 -3
  76. package/src/group/Group.less +1 -1
  77. package/src/index.js +1 -1
  78. package/src/index.less +1 -0
  79. package/src/jquery/jquery-scout.js +17 -4
  80. package/src/keystroke/CloseKeyStroke.js +1 -0
  81. package/src/keystroke/ContextMenuKeyStroke.js +1 -0
  82. package/src/keystroke/FocusFilterFieldKeyStroke.js +1 -0
  83. package/src/keystroke/KeyStroke.js +11 -3
  84. package/src/keystroke/TabItemKeyStroke.js +8 -5
  85. package/src/logging/logging.js +16 -8
  86. package/src/login/LoginBox.js +3 -2
  87. package/src/login/LoginBox.less +18 -1
  88. package/src/menu/ContextMenuPopup.less +9 -2
  89. package/src/menu/Menu.less +1 -0
  90. package/src/menu/MenuExecKeyStroke.js +3 -17
  91. package/src/menu/MenuNavigationKeyStroke.js +1 -0
  92. package/src/menu/menubar/MenuBarLeftKeyStroke.js +2 -0
  93. package/src/menu/menubar/MenuBarRightKeyStroke.js +2 -0
  94. package/src/messagebox/MessageBox.less +17 -17
  95. package/src/modeselector/Mode.less +15 -37
  96. package/src/modeselector/ModeSelector.js +1 -1
  97. package/src/modeselector/ModeSelector.less +2 -1
  98. package/src/planner/Planner.js +2 -0
  99. package/src/planner/PlannerHeader.less +2 -1
  100. package/src/popup/Popup.js +24 -8
  101. package/src/popup/PopupLayout.js +2 -8
  102. package/src/scrollbar/Scrollbar.less +8 -1
  103. package/src/scrollbar/scrollbars.js +26 -4
  104. package/src/session/Session.js +8 -5
  105. package/src/style/colors-dark.less +17 -10
  106. package/src/style/colors.less +11 -3
  107. package/src/style/fonts.less +10 -1
  108. package/src/style/mixins.less +16 -12
  109. package/src/style/sizes-dark.less +4 -1
  110. package/src/style/sizes.less +17 -9
  111. package/src/table/Table.js +62 -48
  112. package/src/table/Table.less +50 -20
  113. package/src/table/TableAdapter.js +9 -12
  114. package/src/table/TableHeader.js +10 -8
  115. package/src/table/TableHeader.less +1 -0
  116. package/src/table/TableHeaderMenu.js +3 -1
  117. package/src/table/TableHeaderMenu.less +7 -2
  118. package/src/table/TableHeaderMenuButton.js +2 -2
  119. package/src/table/TableLayout.js +6 -0
  120. package/src/table/columns/BooleanColumn.js +2 -2
  121. package/src/table/columns/Column.js +10 -7
  122. package/src/table/editor/CellEditorPopup.js +29 -15
  123. package/src/table/keystrokes/AbstractTableNavigationKeyStroke.js +1 -0
  124. package/src/table/keystrokes/TableCopyKeyStroke.js +1 -0
  125. package/src/table/keystrokes/TableNavigationCollapseKeyStroke.js +2 -2
  126. package/src/table/keystrokes/TableNavigationEndKeyStroke.js +2 -2
  127. package/src/table/keystrokes/TableNavigationExpandKeyStroke.js +2 -2
  128. package/src/table/keystrokes/TableNavigationHomeKeyStroke.js +2 -2
  129. package/src/table/keystrokes/TableNavigationPageDownKeyStroke.js +2 -2
  130. package/src/table/keystrokes/TableNavigationPageUpKeyStroke.js +2 -2
  131. package/src/table/keystrokes/TableNavigationUpKeyStroke.js +2 -2
  132. package/src/table/keystrokes/TableRefreshKeyStroke.js +2 -2
  133. package/src/table/keystrokes/TableSelectAllKeyStroke.js +3 -2
  134. package/src/table/keystrokes/TableStartCellEditKeyStroke.js +2 -2
  135. package/src/testing/index.js +1 -0
  136. package/src/testing/lookup/AbortableMicrotaskStaticLookupCall.js +50 -0
  137. package/src/tile/TileGrid.js +10 -12
  138. package/src/tile/TileGridLayout.js +2 -2
  139. package/src/tile/accordion/TileAccordion.js +16 -1
  140. package/src/tile/fields/FormFieldTile.less +18 -11
  141. package/src/tile/fields/tablefield/TileTableField.less +19 -2
  142. package/src/tile/keystrokes/TileGridSelectKeyStroke.js +3 -2
  143. package/src/timepicker/TimePickerTouchPopup.js +8 -0
  144. package/src/tree/CompactTree.less +1 -1
  145. package/src/tree/Tree.js +4 -4
  146. package/src/tree/Tree.less +13 -5
  147. package/src/tree/keystrokes/AbstractTreeNavigationKeyStroke.js +1 -0
  148. package/src/tree/keystrokes/TreeCollapseAllKeyStroke.js +2 -2
  149. package/src/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js +2 -2
  150. package/src/tree/keystrokes/TreeNavigationDownKeyStroke.js +2 -2
  151. package/src/tree/keystrokes/TreeNavigationEndKeyStroke.js +2 -2
  152. package/src/tree/keystrokes/TreeNavigationUpKeyStroke.js +2 -2
  153. package/src/util/Device.js +4 -4
  154. package/src/util/arrays.js +44 -2
  155. package/src/util/objects.js +4 -1
  156. package/src/widget/Widget.js +17 -7
@@ -23,6 +23,7 @@ export default class Table extends Widget {
23
23
  this.contextColumn = null;
24
24
  this.checkable = false;
25
25
  this.checkableStyle = Table.CheckableStyle.CHECKBOX;
26
+ this.cellEditorPopup = null;
26
27
  this.compact = false;
27
28
  this.compactHandler = scout.create('TableCompactHandler', {table: this});
28
29
  this.compactColumn = null;
@@ -100,6 +101,7 @@ export default class Table extends Widget {
100
101
  this._popupOpenHandler = this._onDesktopPopupOpen.bind(this);
101
102
  this._rerenderViewPortAfterAttach = false;
102
103
  this._renderViewPortAfterAttach = false;
104
+ this._postAttachActions = [];
103
105
  this._desktopPropertyChangeHandler = this._onDesktopPropertyChange.bind(this);
104
106
  this._addWidgetProperties(['tableControls', 'menus', 'keyStrokes', 'staticMenus', 'tileTableHeader', 'tableTileGridMediator']);
105
107
 
@@ -475,7 +477,6 @@ export default class Table extends Widget {
475
477
  }
476
478
 
477
479
  _removeData() {
478
- this._destroyCellEditorPopup();
479
480
  this._removeAggregateRows();
480
481
  this._uninstallImageListeners();
481
482
  this._uninstallCellTooltipSupport();
@@ -554,7 +555,7 @@ export default class Table extends Widget {
554
555
  return; // row was removed while loading the image
555
556
  }
556
557
  let oldRowHeight = row.height;
557
- row.height = $row.outerHeight(true);
558
+ row.height = this._measureRowHeight($row);
558
559
  if (oldRowHeight !== row.height) {
559
560
  this.invalidateLayoutTree();
560
561
  }
@@ -633,11 +634,11 @@ export default class Table extends Widget {
633
634
  // Don't start cell editor or trigger click if row control was clicked (expansion itself is handled by the mouse down handler)
634
635
  return;
635
636
  }
637
+ let row = $row.data('row'); // read row before the $row potentially could be replaced by the column specific logic on mouse up
636
638
  if (mouseButton === 1) {
637
639
  column.onMouseUp(event, $row);
638
640
  $appLink = this._find$AppLink(event);
639
641
  }
640
- let row = $row.data('row');
641
642
  if ($appLink) {
642
643
  this._triggerAppLinkAction(column, row, $appLink.data('ref'), $appLink);
643
644
  } else {
@@ -1527,12 +1528,12 @@ export default class Table extends Widget {
1527
1528
 
1528
1529
  _updateRowHeight() {
1529
1530
  let $emptyRow = this.$data.appendDiv('table-row');
1530
- let $emptyAggrRow = this.$data.appendDiv('table-aggregate-row');
1531
+ let $emptyAggrRow = this._build$AggregateRow().appendTo(this.$data);
1531
1532
 
1532
1533
  $emptyRow.appendDiv('table-cell').html(' ');
1533
- $emptyAggrRow.appendDiv('table-cell').html(' ');
1534
- this.rowHeight = $emptyRow.outerHeight(true);
1535
- this.aggregateRowHeight = $emptyAggrRow.outerHeight(true);
1534
+ $emptyAggrRow.appendDiv('table-cell table-aggregate-cell').appendSpan('text').html(' ');
1535
+ this.rowHeight = this._measureRowHeight($emptyRow);
1536
+ this.aggregateRowHeight = this._measureRowHeight($emptyAggrRow);
1536
1537
  $emptyRow.remove();
1537
1538
  $emptyAggrRow.remove();
1538
1539
  }
@@ -1545,14 +1546,14 @@ export default class Table extends Widget {
1545
1546
  if (!row.$row) {
1546
1547
  row.height = null;
1547
1548
  } else {
1548
- row.height = row.$row.outerHeight(true);
1549
+ row.height = this._measureRowHeight(row.$row);
1549
1550
  }
1550
1551
  });
1551
1552
  this._aggregateRows.forEach(aggregateRow => {
1552
1553
  if (!aggregateRow.$row) {
1553
1554
  aggregateRow.height = null;
1554
1555
  } else {
1555
- aggregateRow.height = aggregateRow.$row.outerHeight(true);
1556
+ aggregateRow.height = this._measureRowHeight(aggregateRow.$row);
1556
1557
  }
1557
1558
  });
1558
1559
  }
@@ -1866,7 +1867,7 @@ export default class Table extends Widget {
1866
1867
  }
1867
1868
 
1868
1869
  this._destroyTooltipsForRow(row);
1869
- this._removeCellEditorForRow(row);
1870
+ this._destroyCellEditorForRow(row);
1870
1871
 
1871
1872
  // Do not remove rows which are removed using an animation
1872
1873
  if (!$row.hasClass('hiding')) {
@@ -1936,7 +1937,7 @@ export default class Table extends Widget {
1936
1937
  * is expected to be linked with the corresponding '$row' (row.$row and $row.data('row')).
1937
1938
  */
1938
1939
  _installRow(row) {
1939
- row.height = row.$row.outerHeight(true);
1940
+ row.height = this._measureRowHeight(row.$row);
1940
1941
 
1941
1942
  if (row.hasError) {
1942
1943
  this._showCellErrorForRow(row);
@@ -2068,8 +2069,24 @@ export default class Table extends Widget {
2068
2069
  }
2069
2070
 
2070
2071
  /**
2071
- * This functions starts the cell editor for the given row and column. Prepare must wait until
2072
- * a pending completeCellEdit operation is resolved.
2072
+ * Starts cell editing for the cell at the given column and row, but only if editing is allowed.
2073
+ * @see prepareCellEdit
2074
+ */
2075
+ focusCell(column, row) {
2076
+ let cell = this.cell(column, row);
2077
+ if (this.enabledComputed && row.enabled && cell.editable) {
2078
+ this.prepareCellEdit(column, row);
2079
+ }
2080
+ }
2081
+
2082
+ /**
2083
+ * Creates a cell editor for the cell at the given column and row, ensures the row is selected and passes the editor
2084
+ * to {@link #startCellEdit} which starts the editing by rendering the editor in a {@link CellEditorPopup}.<br>
2085
+ * If the completion of a previous cell edit is still in progress, the preparation is delayed until the completion is finished.
2086
+ *
2087
+ * @param {boolean} [openFieldPopupOnCellEdit] true to instruct the editor to open its control popup when the editor is rendered.
2088
+ * This only has an effect if the editor has a popup (e.g. SmartField or DateField).
2089
+ * @returns Promise the promise will be resolved when the preparation has been finished.
2073
2090
  */
2074
2091
  prepareCellEdit(column, row, openFieldPopupOnCellEdit) {
2075
2092
  let promise = $.resolvedPromise();
@@ -2080,10 +2097,10 @@ export default class Table extends Widget {
2080
2097
  }
2081
2098
 
2082
2099
  /**
2083
- * @param openFieldPopupOnCellEdit when this parameter is set to true, the CellEditorPopup sets an
2100
+ * @param {boolean} [openFieldPopupOnCellEdit] when this parameter is set to true, the CellEditorPopup sets an
2084
2101
  * additional property 'cellEditor' on the editor-field. The field instance may use this property
2085
2102
  * to decide whether or not it should open a popup immediately after it is rendered. This is used
2086
- * for Smart- and DateFields.
2103
+ * for Smart- and DateFields. Default is false.
2087
2104
  */
2088
2105
  prepareCellEditInternal(column, row, openFieldPopupOnCellEdit) {
2089
2106
  let event = new Event({
@@ -2380,14 +2397,14 @@ export default class Table extends Widget {
2380
2397
  return;
2381
2398
  }
2382
2399
 
2383
- let $aggregateRow = this._buildAggregateRowDiv(aggregateRow);
2400
+ let $aggregateRow = this._build$AggregateRow(aggregateRow);
2384
2401
  $aggregateRow[insertFunc](refRow.$row).width(this.rowWidth);
2385
2402
 
2386
2403
  this.visibleColumns()
2387
2404
  .map(column => $(column.buildCellForAggregateRow(aggregateRow)).appendTo($aggregateRow))
2388
2405
  .forEach($c => this._resizeAggregateCell($c));
2389
2406
 
2390
- aggregateRow.height = $aggregateRow.outerHeight(true);
2407
+ aggregateRow.height = this._measureRowHeight($aggregateRow);
2391
2408
  aggregateRow.$row = $aggregateRow;
2392
2409
  if (animate) {
2393
2410
  this._showRow(aggregateRow);
@@ -2395,7 +2412,7 @@ export default class Table extends Widget {
2395
2412
  }, this);
2396
2413
  }
2397
2414
 
2398
- _buildAggregateRowDiv(aggregateRow) {
2415
+ _build$AggregateRow(aggregateRow) {
2399
2416
  let onTop = this.groupingStyle === Table.GroupingStyle.TOP;
2400
2417
  let $aggregateRow = this.$container
2401
2418
  .makeDiv('table-aggregate-row')
@@ -2966,7 +2983,7 @@ export default class Table extends Widget {
2966
2983
  oldRow.$row.replaceWith($updatedRow);
2967
2984
  Table.linkRowToDiv(row, $updatedRow);
2968
2985
  this._destroyTooltipsForRow(row);
2969
- this._removeCellEditorForRow(row);
2986
+ this._destroyCellEditorForRow(row);
2970
2987
  this._installRow(row);
2971
2988
  if (oldRow.$row.hasClass('showing') && oldRow.$row.outerHeight() < row.$row.outerHeight() / 3) {
2972
2989
  // If the row was being shown by an animation, start the animation again for the new row, otherwise row would immediately appear without animation.
@@ -3036,17 +3053,25 @@ export default class Table extends Widget {
3036
3053
  }
3037
3054
  }
3038
3055
 
3039
- _removeCellEditorForRow(row) {
3056
+ _destroyCellEditorForRow(row) {
3040
3057
  if (this.cellEditorPopup && this.cellEditorPopup.rendered && this.cellEditorPopup.row.id === row.id) {
3041
- this.cellEditorPopup.remove();
3058
+ this.cellEditorPopup.destroy();
3042
3059
  }
3043
3060
  }
3044
3061
 
3045
3062
  startCellEdit(column, row, field) {
3046
- if (!this._isDataRendered() || !this.isAttachedAndRendered()) {
3063
+ if (field.destroyed) {
3064
+ // May happen if the action was postponed and the field destroyed in the meantime using endCellEdit.
3065
+ return;
3066
+ }
3067
+ if (!this._isDataRendered()) {
3047
3068
  this._postRenderActions.push(this.startCellEdit.bind(this, column, row, field));
3048
3069
  return;
3049
3070
  }
3071
+ if (!this.$container.isAttached()) {
3072
+ this._postAttachActions.push(this.startCellEdit.bind(this, column, row, field));
3073
+ return;
3074
+ }
3050
3075
 
3051
3076
  this.trigger('startCellEdit', {
3052
3077
  column: column,
@@ -3066,11 +3091,6 @@ export default class Table extends Widget {
3066
3091
  * value is updated by an updateRow event instead.
3067
3092
  */
3068
3093
  endCellEdit(field, saveEditorValue) {
3069
- if (!this._isDataRendered() || !this.isAttachedAndRendered()) {
3070
- this._postRenderActions.push(this.endCellEdit.bind(this, field, saveEditorValue));
3071
- return;
3072
- }
3073
-
3074
3094
  if (!this.cellEditorPopup) {
3075
3095
  // the cellEditorPopup could already be removed by scrolling (out of view range) or be removed by update rows
3076
3096
  field.destroy();
@@ -4656,7 +4676,9 @@ export default class Table extends Widget {
4656
4676
  this.$container.toggleClass('checkable', scout.isOneOf(this.checkableStyle, Table.CheckableStyle.TABLE_ROW, Table.CheckableStyle.CHECKBOX_TABLE_ROW));
4657
4677
  this.$container.toggleClass('table-row-check', this.checkableStyle === Table.CheckableStyle.TABLE_ROW);
4658
4678
  if (this._isDataRendered()) {
4679
+ this._updateRowWidth();
4659
4680
  this._redraw();
4681
+ this.invalidateLayoutTree();
4660
4682
  }
4661
4683
  }
4662
4684
 
@@ -4831,7 +4853,7 @@ export default class Table extends Widget {
4831
4853
  this.$data.setEnabled(enabled);
4832
4854
  }
4833
4855
 
4834
- this.$container.setTabbable(enabled);
4856
+ this.$container.setTabbableOrFocusable(enabled);
4835
4857
  }
4836
4858
 
4837
4859
  /**
@@ -4974,8 +4996,11 @@ export default class Table extends Widget {
4974
4996
  }
4975
4997
 
4976
4998
  _heightForRow(row) {
4977
- let height = 0,
4999
+ let height = 0;
5000
+ let aggregateRow = row.aggregateRowBefore;
5001
+ if (this.groupingStyle === Table.GroupingStyle.BOTTOM) {
4978
5002
  aggregateRow = row.aggregateRowAfter;
5003
+ }
4979
5004
 
4980
5005
  if (row.height) {
4981
5006
  height = row.height;
@@ -4995,6 +5020,10 @@ export default class Table extends Widget {
4995
5020
  return height;
4996
5021
  }
4997
5022
 
5023
+ _measureRowHeight($row) {
5024
+ return graphics.size($row, {includeMargin: true, exact: true}).height;
5025
+ }
5026
+
4998
5027
  /**
4999
5028
  * Returns a range of size this.viewRangeSize. Start of range is rowIndex - viewRangeSize / 4.
5000
5029
  * -> 1/4 of the rows are before the viewport 2/4 in the viewport 1/4 after the viewport,
@@ -5302,18 +5331,6 @@ export default class Table extends Widget {
5302
5331
  }
5303
5332
  }
5304
5333
 
5305
- focusCell(column, row) {
5306
- if (!this._isDataRendered() || !this.isAttachedAndRendered()) {
5307
- this._postRenderActions.push(this.focusCell.bind(this, column, row));
5308
- return;
5309
- }
5310
-
5311
- let cell = this.cell(column, row);
5312
- if (this.enabledComputed && row.enabled && cell.editable) {
5313
- this.prepareCellEdit(column, row, false);
5314
- }
5315
- }
5316
-
5317
5334
  _attach() {
5318
5335
  this.$parent.append(this.$container);
5319
5336
  super._attach();
@@ -5337,6 +5354,9 @@ export default class Table extends Widget {
5337
5354
  super._renderOnAttach();
5338
5355
  this._rerenderViewportAfterAttach();
5339
5356
  this._renderViewportAfterAttach();
5357
+ let actions = this._postAttachActions;
5358
+ this._postAttachActions = [];
5359
+ actions.forEach(action => action());
5340
5360
  }
5341
5361
 
5342
5362
  _rerenderViewportAfterAttach() {
@@ -5365,11 +5385,6 @@ export default class Table extends Widget {
5365
5385
  super._detach();
5366
5386
  }
5367
5387
 
5368
- _onDetach() {
5369
- super._onDetach();
5370
- this._destroyCellEditorPopup();
5371
- }
5372
-
5373
5388
  /**
5374
5389
  * @param {function} [callback] function to be called right after the popup is destroyed
5375
5390
  */
@@ -5396,7 +5411,6 @@ export default class Table extends Widget {
5396
5411
  if (promise.state() === 'resolved') {
5397
5412
  // Do it immediately if promise has already been resolved.
5398
5413
  // This makes sure updateRow does not immediately reopen the editor after closing.
5399
- // At least for Scout JS, for Scout Classic it prevents flickering (endCellEdit comes after updateRows, but updateRows does not know whether the editor is closing so it will reopen it)
5400
5414
  destroyEditor();
5401
5415
  } else {
5402
5416
  promise.then(destroyEditor);
@@ -5435,7 +5449,7 @@ export default class Table extends Widget {
5435
5449
  // same as on Tree.prototype._onDesktopPopupOpen
5436
5450
  _onDesktopPopupOpen(event) {
5437
5451
  let popup = event.popup;
5438
- if (!this.enabledComputed) {
5452
+ if (!this.isFocusable(false)) {
5439
5453
  return;
5440
5454
  }
5441
5455
  // Set table style to focused if a context menu or a menu bar popup opens, so that it looks as it still has the focus
@@ -49,25 +49,48 @@
49
49
  /* Used for scout.Table.CheckableStyle.TABLE_ROW */
50
50
 
51
51
  &.table-row-check {
52
+ & > .table-data {
53
+ & > .table-row {
54
+ &.selected {
55
+ /* Don't draw selection */
56
+ background-color: transparent;
52
57
 
53
- & > .table-data > .table-row {
58
+ &::after {
59
+ display: none;
60
+ }
61
+ }
54
62
 
55
- &.selected {
56
- /* Don't draw selection */
63
+ &:hover {
64
+ background-color: @hover-background-color;
65
+ }
66
+ }
67
+
68
+ & > .table-row.disabled,
69
+ &.disabled > .table-row {
57
70
  background-color: transparent;
71
+ }
58
72
 
59
- &::after {
60
- display: none;
73
+ & > .table-row {
74
+ &.checked,
75
+ &.checked.selected {
76
+ /* Mark checked rows with a background color */
77
+ background-color: @table-row-checked-background-color;
78
+
79
+ & > .table-cell {
80
+ color: @table-row-checked-color;
81
+ }
82
+
83
+ &:hover {
84
+ background-color: @selected-hover-background-color;
85
+ }
61
86
  }
62
87
  }
63
88
 
64
- &.checked,
65
- &.checked.selected {
66
- /* Mark checked rows with a background color */
67
- background-color: @table-row-checked-background-color;
68
-
69
- & > .table-cell {
70
- color: @table-row-checked-color;
89
+ & > .table-row.disabled,
90
+ &.disabled > .table-row {
91
+ &.checked,
92
+ &.checked.selected {
93
+ background-color: @selected-disabled-background-color;
71
94
  }
72
95
  }
73
96
  }
@@ -419,6 +442,9 @@
419
442
  .table-cell-icon {
420
443
  .font-icon& {
421
444
  color: @icon-color;
445
+ font-size: @table-cell-font-icon-size;
446
+ line-height: @table-cell-font-icon-line-height;
447
+ vertical-align: top;
422
448
 
423
449
  .disabled & {
424
450
  color: @disabled-color;
@@ -443,15 +469,12 @@
443
469
  overflow: hidden;
444
470
  padding-left: var(--table-row-margin-x);
445
471
  padding-right: var(--table-row-margin-x);
472
+ font-size: @table-aggregate-row-font-size;
446
473
 
447
474
  & > .table-cell {
448
475
  padding: var(--table-row-padding-y) @table-cell-padding-right 0 @table-cell-padding-left;
449
476
  border-bottom: 0;
450
477
  height: 100%;
451
-
452
- & > .font-icon {
453
- margin-top: 1px;
454
- }
455
478
  }
456
479
  }
457
480
 
@@ -463,7 +486,7 @@
463
486
  margin-top: -1px; // top border should cover bottom border of the previous row
464
487
  padding-left: var(--table-row-margin-x);
465
488
  padding-right: var(--table-row-margin-x);
466
- font-size: 12px;
489
+ font-size: @table-aggregate-row-font-size;
467
490
 
468
491
  & > .table-cell {
469
492
  border-bottom: 0;
@@ -495,10 +518,17 @@
495
518
  display: inline-block;
496
519
  color: @text-color;
497
520
  vertical-align: middle;
521
+ line-height: @table-aggregate-cell-font-icon-line-height;
498
522
  }
499
523
 
500
- &.sum > .table-cell-icon, &.avg > .table-cell-icon {
501
- font-size: @font-size-extra-small;
524
+ &.sum > .table-cell-icon,
525
+ &.avg > .table-cell-icon {
526
+ font-size: @table-aggregate-sum-avg-font-icon-size;
527
+ }
528
+
529
+ &.min > .table-cell-icon,
530
+ &.max > .table-cell-icon {
531
+ font-size: @table-aggregate-min-max-font-icon-size;
502
532
  }
503
533
 
504
534
  /* if aggregation is based on selected rows */
@@ -622,4 +652,4 @@
622
652
 
623
653
  .organize-columns-behind-scrollbar-column.table-cell.last {
624
654
  padding: 0;
625
- }
655
+ }
@@ -187,26 +187,20 @@ export default class TableAdapter extends ModelAdapter {
187
187
 
188
188
  _onWidgetCompleteCellEdit(event) {
189
189
  event.preventDefault();
190
- this._sendCompleteCellEdit(event.field);
190
+ this._sendCompleteCellEdit();
191
191
  }
192
192
 
193
- _sendCompleteCellEdit(field) {
194
- let data = {
195
- fieldId: field.id
196
- };
197
- this._send('completeCellEdit', data);
193
+ _sendCompleteCellEdit() {
194
+ this._send('completeCellEdit');
198
195
  }
199
196
 
200
197
  _onWidgetCancelCellEdit(event) {
201
198
  event.preventDefault();
202
- this._sendCancelCellEdit(event.field);
199
+ this._sendCancelCellEdit();
203
200
  }
204
201
 
205
- _sendCancelCellEdit(field) {
206
- let data = {
207
- fieldId: field.id
208
- };
209
- this._send('cancelCellEdit', data);
202
+ _sendCancelCellEdit() {
203
+ this._send('cancelCellEdit');
210
204
  }
211
205
 
212
206
  _onWidgetRowsChecked(event) {
@@ -507,6 +501,9 @@ export default class TableAdapter extends ModelAdapter {
507
501
 
508
502
  _onEndCellEdit(fieldId) {
509
503
  let field = this.session.getModelAdapter(fieldId);
504
+ if (!field) {
505
+ throw new Error('Field adapter could not be resolved. Id: ' + fieldId);
506
+ }
510
507
  this.widget.endCellEdit(field.widget);
511
508
  }
512
509
 
@@ -8,7 +8,7 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
- import {arrays, Column, ColumnUserFilter, Device, graphics, GroupBoxMenuItemsOrder, inspector, MenuBar, MenuDestinations, scout, scrollbars, strings, styles, Table, tooltips, Widget} from '../index';
11
+ import {arrays, Column, ColumnUserFilter, Device, graphics, GroupBoxMenuItemsOrder, inspector, MenuBar, MenuDestinations, objects, scout, scrollbars, strings, styles, Table, tooltips, Widget} from '../index';
12
12
  import $ from 'jquery';
13
13
 
14
14
  export default class TableHeader extends Widget {
@@ -459,21 +459,23 @@ export default class TableHeader extends Widget {
459
459
  let filtered = this.table.getFilter(column.id);
460
460
  if (column.sortActive || column.grouped || filtered) {
461
461
  if (column.minWidth < Column.DEFAULT_MIN_WIDTH) {
462
- column.prefMinWidth = column.minWidth;
462
+ column.__minWidthWithoutState = column.minWidth;
463
+ column.__widthWithoutState = column.width;
463
464
  column.minWidth = Column.DEFAULT_MIN_WIDTH;
464
465
  }
465
466
  if (column.width < column.minWidth) {
466
467
  this.table.resizeColumn(column, column.minWidth);
467
468
  }
468
469
  } else {
469
- // Reset to preferred min width if no state is visible
470
- if (column.prefMinWidth !== null) {
471
- column.minWidth = column.prefMinWidth;
472
- column.prefMinWidth = null;
473
- // Resize to old min width, assuming user has not manually changed the size because column is still as width as default_min_width
470
+ // Reset to previous min width if no state is visible
471
+ if (!objects.isNullOrUndefined(column.__minWidthWithoutState)) {
472
+ column.minWidth = column.__minWidthWithoutState;
473
+ // Resize to previous min width, assuming user has not manually changed the size because column is still as width as default_min_width
474
474
  if (column.width === Column.DEFAULT_MIN_WIDTH) {
475
- this.table.resizeColumn(column, column.minWidth);
475
+ this.table.resizeColumn(column, column.__widthWithoutState);
476
476
  }
477
+ column.__minWidthWithoutState = null;
478
+ column.__widthWithoutState = null;
477
479
  }
478
480
  }
479
481
  }
@@ -180,6 +180,7 @@
180
180
 
181
181
  .table-header-item-text {
182
182
  #scout.overflow-ellipsis-nowrap();
183
+ margin-top: @text-margin-top;
183
184
  }
184
185
 
185
186
  .table-header-item-state {
@@ -241,7 +241,9 @@ export default class TableHeaderMenu extends Popup {
241
241
  if (this.filterTable) {
242
242
  this.filterTable.off('rowsChecked', this._filterTableRowsCheckedHandler);
243
243
  }
244
- this.tableHeader.$container.off('scroll', this._tableHeaderScrollHandler);
244
+ if (this.tableHeader.rendered) {
245
+ this.tableHeader.$container.off('scroll', this._tableHeaderScrollHandler);
246
+ }
245
247
  this.$headerItem.select(false);
246
248
  this.table.off('columnMoved', this._onColumnMovedHandler);
247
249
  this.table.off('filterAdded', this._tableFilterHandler);
@@ -33,6 +33,11 @@
33
33
  display: inline-block;
34
34
  vertical-align: top;
35
35
  padding: @table-header-menu-padding;
36
+
37
+ & > .table-header-menu-group > .table-header-menu-group-text {
38
+ // Increase size a little to ensure every text is fully visible, at least for german and english (currently necessary for additional sorting group)
39
+ width: calc(100% + 12px);
40
+ }
36
41
  }
37
42
 
38
43
  .table-header-menu-filters {
@@ -252,11 +257,11 @@
252
257
 
253
258
  & > .table-data {
254
259
  margin-top: 0;
255
- padding: 3px 4px;
260
+ padding: 3px;
256
261
 
257
262
  & > .table-row {
258
263
  border-radius: @border-radius;
259
- margin-bottom: 1px;
264
+ margin-bottom: 2px;
260
265
 
261
266
  &.last {
262
267
  margin-bottom: 0;
@@ -8,7 +8,7 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
- import {Action, TableHeaderMenuButtonKeyStroke} from '../index';
11
+ import {Action, ActionExecKeyStroke} from '../index';
12
12
 
13
13
  export default class TableHeaderMenuButton extends Action {
14
14
 
@@ -24,7 +24,7 @@ export default class TableHeaderMenuButton extends Action {
24
24
  _initKeyStrokeContext() {
25
25
  super._initKeyStrokeContext();
26
26
 
27
- this.keyStrokeContext.registerKeyStroke([new TableHeaderMenuButtonKeyStroke(this)]);
27
+ this.keyStrokeContext.registerKeyStroke([new ActionExecKeyStroke(this)]);
28
28
  }
29
29
 
30
30
  _render() {
@@ -104,6 +104,12 @@ export default class TableLayout extends AbstractLayout {
104
104
  // Always render viewport (not only when viewRangeSize changes), because view range depends on scroll position and data height
105
105
  this.table._renderViewport();
106
106
 
107
+ // Render scroll top again to make sure the data is really at the correct position after rendering viewport.
108
+ // Somehow table.$data[0].scrollTop changes during _renderViewport sometimes (e.g. when there are aggregate rows)
109
+ if (!htmlContainer.layouted) {
110
+ this.table._renderScrollTop();
111
+ }
112
+
107
113
  // Make sure tooltips and editor popup are at correct position after layouting (e.g after window resizing)
108
114
  this.table.tooltips.forEach(tooltip => {
109
115
  if (tooltip.rendered) {
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010-2020 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
@@ -21,7 +21,7 @@ export default class BooleanColumn extends Column {
21
21
  this.comparator = comparators.NUMERIC;
22
22
  this.filterType = 'ColumnUserFilter';
23
23
  this.horizontalAlignment = 0;
24
- this.minWidth = Column.NARROW_MIN_WIDTH;
24
+ this.minWidth = Column.SMALL_MIN_WIDTH;
25
25
  this.triStateEnabled = false;
26
26
  this.textBased = false;
27
27
  }
@@ -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
@@ -43,7 +43,6 @@ export default class Column {
43
43
  this.type = 'text';
44
44
  this.width = 60;
45
45
  this.initialWidth = undefined; // the width the column initially has
46
- this.prefMinWidth = null;
47
46
  this.minWidth = Column.DEFAULT_MIN_WIDTH; // the minimal width the column can have
48
47
  this.showSeparator = true;
49
48
  this.table = null;
@@ -71,7 +70,8 @@ export default class Column {
71
70
  }
72
71
 
73
72
  static DEFAULT_MIN_WIDTH = 60;
74
- static NARROW_MIN_WIDTH = 32; // for columns without text (icon, check box)
73
+ static SMALL_MIN_WIDTH = 38;
74
+ static NARROW_MIN_WIDTH = 34;
75
75
 
76
76
  init(model) {
77
77
  this.session = model.session;
@@ -394,16 +394,19 @@ export default class Column {
394
394
  cell.field = field;
395
395
  // Override field alignment with the cell's alignment
396
396
  cell.field.gridData.horizontalAlignment = cell.horizontalAlignment;
397
+ popup = this._createEditorPopup(row, cell);
398
+ popup.$anchor = $cell;
399
+ popup.open(this.table.$data);
400
+ return popup;
401
+ }
397
402
 
398
- popup = scout.create('CellEditorPopup', {
403
+ _createEditorPopup(row, cell) {
404
+ return scout.create('CellEditorPopup', {
399
405
  parent: this.table,
400
406
  column: this,
401
407
  row: row,
402
408
  cell: cell
403
409
  });
404
- popup.$anchor = $cell;
405
- popup.open(this.table.$data);
406
- return popup;
407
410
  }
408
411
 
409
412
  /**