You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GridConnector.java 23KB

Migrate 7.7.5 branch patches to v8. (#7969) * Prevent adding several scrollbar handlers (#19189). Change-Id: Ib0cc6c6835aab6d263f153362a328bcf2be7bc5c * Prevent adding several scrollbar handlers (#19189). * Keep expand ratio for last row/column when reducing grid layout size (#20297) Change-Id: Iff53a803596f4fc1eae8e4bfa307b9c1f4df961a * Fixed drag and drop failure when message dragged from email client (#20451) When dragging message form email client on Windows, item.webkitGetAsEntry() might return null creating NPE on the client side. Added additional checks for this situation. Change-Id: I569f7e6d0d7b137f24be53d1fbce384695ae8c73 * Change expected pre-release version number pattern in publish report Change-Id: Icdacecc490d2490ea9e262f5c5736c1dece2a89d * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/main/java/com/vaadin/tests/components/textfield/TextChangeEvents.java * Fixed touch scrolling issue in Surface and WP devices (#18737) Fixed by using pointerevents instead of touchevents when the browser is IE11, or Edge. Also added touch-action: none; css rules into escalator.css to prevent default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers, behaviour on those will stay the same as before the fix. No new unit tests since we do not have automatic touch testing possibilities yet. Please test manually with Surface: IE11 and Edge, use for example uitest: com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703 * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 # Conflicts: # client/src/main/java/com/vaadin/client/connectors/GridConnector.java # client/src/main/java/com/vaadin/client/widgets/Grid.java # server/src/main/java/com/vaadin/ui/Grid.java # shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java # themes/src/main/themes/VAADIN/themes/base/grid/grid.scss # uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java Change-Id: Ieca56121875198ed559a41c143b28926e2695433 * Fix NPE in case some items don't contain all properties of Grid. This could occur in when parent is a different entity than its children in hierarchical data. Change-Id: Icd53b5b5e5544a3680d0cd99702ab78224b2dc08 # Conflicts: # server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java # server/src/main/java/com/vaadin/ui/Grid.java * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/test/java/com/vaadin/tests/components/textfield/TextChangeEventsTest.java * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 * Removed V8 VTextField unused import, forgotten @RunLocally. * Don't rely on selenium "sendKeys" behavior. * Revert "Change expected pre-release version number pattern in publish report" This reverts commit 8df27b952dddb691aead6a633c5b3724c98bf343. * Migrate TextField/TextArea patch from 7.7 to master (modern components) Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50
7 years ago
Migrate 7.7.5 branch patches to v8. (#7969) * Prevent adding several scrollbar handlers (#19189). Change-Id: Ib0cc6c6835aab6d263f153362a328bcf2be7bc5c * Prevent adding several scrollbar handlers (#19189). * Keep expand ratio for last row/column when reducing grid layout size (#20297) Change-Id: Iff53a803596f4fc1eae8e4bfa307b9c1f4df961a * Fixed drag and drop failure when message dragged from email client (#20451) When dragging message form email client on Windows, item.webkitGetAsEntry() might return null creating NPE on the client side. Added additional checks for this situation. Change-Id: I569f7e6d0d7b137f24be53d1fbce384695ae8c73 * Change expected pre-release version number pattern in publish report Change-Id: Icdacecc490d2490ea9e262f5c5736c1dece2a89d * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/main/java/com/vaadin/tests/components/textfield/TextChangeEvents.java * Fixed touch scrolling issue in Surface and WP devices (#18737) Fixed by using pointerevents instead of touchevents when the browser is IE11, or Edge. Also added touch-action: none; css rules into escalator.css to prevent default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers, behaviour on those will stay the same as before the fix. No new unit tests since we do not have automatic touch testing possibilities yet. Please test manually with Surface: IE11 and Edge, use for example uitest: com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703 * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 # Conflicts: # client/src/main/java/com/vaadin/client/connectors/GridConnector.java # client/src/main/java/com/vaadin/client/widgets/Grid.java # server/src/main/java/com/vaadin/ui/Grid.java # shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java # themes/src/main/themes/VAADIN/themes/base/grid/grid.scss # uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java Change-Id: Ieca56121875198ed559a41c143b28926e2695433 * Fix NPE in case some items don't contain all properties of Grid. This could occur in when parent is a different entity than its children in hierarchical data. Change-Id: Icd53b5b5e5544a3680d0cd99702ab78224b2dc08 # Conflicts: # server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java # server/src/main/java/com/vaadin/ui/Grid.java * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/test/java/com/vaadin/tests/components/textfield/TextChangeEventsTest.java * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 * Removed V8 VTextField unused import, forgotten @RunLocally. * Don't rely on selenium "sendKeys" behavior. * Revert "Change expected pre-release version number pattern in publish report" This reverts commit 8df27b952dddb691aead6a633c5b3724c98bf343. * Migrate TextField/TextArea patch from 7.7 to master (modern components) Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50
7 years ago
Migrate 7.7.5 branch patches to v8. (#7969) * Prevent adding several scrollbar handlers (#19189). Change-Id: Ib0cc6c6835aab6d263f153362a328bcf2be7bc5c * Prevent adding several scrollbar handlers (#19189). * Keep expand ratio for last row/column when reducing grid layout size (#20297) Change-Id: Iff53a803596f4fc1eae8e4bfa307b9c1f4df961a * Fixed drag and drop failure when message dragged from email client (#20451) When dragging message form email client on Windows, item.webkitGetAsEntry() might return null creating NPE on the client side. Added additional checks for this situation. Change-Id: I569f7e6d0d7b137f24be53d1fbce384695ae8c73 * Change expected pre-release version number pattern in publish report Change-Id: Icdacecc490d2490ea9e262f5c5736c1dece2a89d * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/main/java/com/vaadin/tests/components/textfield/TextChangeEvents.java * Fixed touch scrolling issue in Surface and WP devices (#18737) Fixed by using pointerevents instead of touchevents when the browser is IE11, or Edge. Also added touch-action: none; css rules into escalator.css to prevent default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers, behaviour on those will stay the same as before the fix. No new unit tests since we do not have automatic touch testing possibilities yet. Please test manually with Surface: IE11 and Edge, use for example uitest: com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703 * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 # Conflicts: # client/src/main/java/com/vaadin/client/connectors/GridConnector.java # client/src/main/java/com/vaadin/client/widgets/Grid.java # server/src/main/java/com/vaadin/ui/Grid.java # shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java # themes/src/main/themes/VAADIN/themes/base/grid/grid.scss # uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java Change-Id: Ieca56121875198ed559a41c143b28926e2695433 * Fix NPE in case some items don't contain all properties of Grid. This could occur in when parent is a different entity than its children in hierarchical data. Change-Id: Icd53b5b5e5544a3680d0cd99702ab78224b2dc08 # Conflicts: # server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java # server/src/main/java/com/vaadin/ui/Grid.java * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/test/java/com/vaadin/tests/components/textfield/TextChangeEventsTest.java * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 * Removed V8 VTextField unused import, forgotten @RunLocally. * Don't rely on selenium "sendKeys" behavior. * Revert "Change expected pre-release version number pattern in publish report" This reverts commit 8df27b952dddb691aead6a633c5b3724c98bf343. * Migrate TextField/TextArea patch from 7.7 to master (modern components) Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50
7 years ago
Migrate 7.7.5 branch patches to v8. (#7969) * Prevent adding several scrollbar handlers (#19189). Change-Id: Ib0cc6c6835aab6d263f153362a328bcf2be7bc5c * Prevent adding several scrollbar handlers (#19189). * Keep expand ratio for last row/column when reducing grid layout size (#20297) Change-Id: Iff53a803596f4fc1eae8e4bfa307b9c1f4df961a * Fixed drag and drop failure when message dragged from email client (#20451) When dragging message form email client on Windows, item.webkitGetAsEntry() might return null creating NPE on the client side. Added additional checks for this situation. Change-Id: I569f7e6d0d7b137f24be53d1fbce384695ae8c73 * Change expected pre-release version number pattern in publish report Change-Id: Icdacecc490d2490ea9e262f5c5736c1dece2a89d * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/main/java/com/vaadin/tests/components/textfield/TextChangeEvents.java * Fixed touch scrolling issue in Surface and WP devices (#18737) Fixed by using pointerevents instead of touchevents when the browser is IE11, or Edge. Also added touch-action: none; css rules into escalator.css to prevent default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers, behaviour on those will stay the same as before the fix. No new unit tests since we do not have automatic touch testing possibilities yet. Please test manually with Surface: IE11 and Edge, use for example uitest: com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703 * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 # Conflicts: # client/src/main/java/com/vaadin/client/connectors/GridConnector.java # client/src/main/java/com/vaadin/client/widgets/Grid.java # server/src/main/java/com/vaadin/ui/Grid.java # shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java # themes/src/main/themes/VAADIN/themes/base/grid/grid.scss # uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java Change-Id: Ieca56121875198ed559a41c143b28926e2695433 * Fix NPE in case some items don't contain all properties of Grid. This could occur in when parent is a different entity than its children in hierarchical data. Change-Id: Icd53b5b5e5544a3680d0cd99702ab78224b2dc08 # Conflicts: # server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java # server/src/main/java/com/vaadin/ui/Grid.java * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/test/java/com/vaadin/tests/components/textfield/TextChangeEventsTest.java * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 * Removed V8 VTextField unused import, forgotten @RunLocally. * Don't rely on selenium "sendKeys" behavior. * Revert "Change expected pre-release version number pattern in publish report" This reverts commit 8df27b952dddb691aead6a633c5b3724c98bf343. * Migrate TextField/TextArea patch from 7.7 to master (modern components) Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50
7 years ago
Migrate 7.7.5 branch patches to v8. (#7969) * Prevent adding several scrollbar handlers (#19189). Change-Id: Ib0cc6c6835aab6d263f153362a328bcf2be7bc5c * Prevent adding several scrollbar handlers (#19189). * Keep expand ratio for last row/column when reducing grid layout size (#20297) Change-Id: Iff53a803596f4fc1eae8e4bfa307b9c1f4df961a * Fixed drag and drop failure when message dragged from email client (#20451) When dragging message form email client on Windows, item.webkitGetAsEntry() might return null creating NPE on the client side. Added additional checks for this situation. Change-Id: I569f7e6d0d7b137f24be53d1fbce384695ae8c73 * Change expected pre-release version number pattern in publish report Change-Id: Icdacecc490d2490ea9e262f5c5736c1dece2a89d * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/main/java/com/vaadin/tests/components/textfield/TextChangeEvents.java * Fixed touch scrolling issue in Surface and WP devices (#18737) Fixed by using pointerevents instead of touchevents when the browser is IE11, or Edge. Also added touch-action: none; css rules into escalator.css to prevent default touch behaviour on IE11 and Edge. Does not affect IE8 to IE10 browsers, behaviour on those will stay the same as before the fix. No new unit tests since we do not have automatic touch testing possibilities yet. Please test manually with Surface: IE11 and Edge, use for example uitest: com.vaadin.tests.components.grid.basics.GridBasicsomponents.grid.basics.GridBasics Change-Id: Iddbf1852e6ffafc855f749d6f4ebb235ed0f5703 * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 # Conflicts: # client/src/main/java/com/vaadin/client/connectors/GridConnector.java # client/src/main/java/com/vaadin/client/widgets/Grid.java # server/src/main/java/com/vaadin/ui/Grid.java # shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java # themes/src/main/themes/VAADIN/themes/base/grid/grid.scss # uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java Change-Id: Ieca56121875198ed559a41c143b28926e2695433 * Fix NPE in case some items don't contain all properties of Grid. This could occur in when parent is a different entity than its children in hierarchical data. Change-Id: Icd53b5b5e5544a3680d0cd99702ab78224b2dc08 # Conflicts: # server/src/main/java/com/vaadin/data/fieldgroup/FieldGroup.java # server/src/main/java/com/vaadin/ui/Grid.java * Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50 # Conflicts: # client/src/main/java/com/vaadin/client/ui/VTextField.java # uitest/src/test/java/com/vaadin/tests/components/textfield/TextChangeEventsTest.java * Add lazy/simple resize mode to Grid (#20108) Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4 * Removed V8 VTextField unused import, forgotten @RunLocally. * Don't rely on selenium "sendKeys" behavior. * Revert "Change expected pre-release version number pattern in publish report" This reverts commit 8df27b952dddb691aead6a633c5b3724c98bf343. * Migrate TextField/TextArea patch from 7.7 to master (modern components) Mark TextField/TextArea as busy when a text change event is pending (#20469) Change-Id: I404985ae0be1e7dc65171b610032f8649e700f50
7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.connectors.grid;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19. import java.util.Collections;
  20. import java.util.HashMap;
  21. import java.util.HashSet;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Objects;
  25. import java.util.Set;
  26. import java.util.stream.Collectors;
  27. import com.google.gwt.core.client.Scheduler;
  28. import com.google.gwt.dom.client.Element;
  29. import com.google.gwt.dom.client.EventTarget;
  30. import com.google.gwt.dom.client.NativeEvent;
  31. import com.google.gwt.event.shared.HandlerRegistration;
  32. import com.vaadin.client.ComponentConnector;
  33. import com.vaadin.client.ConnectorHierarchyChangeEvent;
  34. import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
  35. import com.vaadin.client.DeferredWorker;
  36. import com.vaadin.client.HasComponentsConnector;
  37. import com.vaadin.client.MouseEventDetailsBuilder;
  38. import com.vaadin.client.TooltipInfo;
  39. import com.vaadin.client.WidgetUtil;
  40. import com.vaadin.client.annotations.OnStateChange;
  41. import com.vaadin.client.connectors.AbstractListingConnector;
  42. import com.vaadin.client.connectors.grid.ColumnConnector.CustomColumn;
  43. import com.vaadin.client.data.DataSource;
  44. import com.vaadin.client.ui.SimpleManagedLayout;
  45. import com.vaadin.client.widget.escalator.RowContainer;
  46. import com.vaadin.client.widget.grid.CellReference;
  47. import com.vaadin.client.widget.grid.EventCellReference;
  48. import com.vaadin.client.widget.grid.events.BodyClickHandler;
  49. import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler;
  50. import com.vaadin.client.widget.grid.events.GridClickEvent;
  51. import com.vaadin.client.widget.grid.events.GridDoubleClickEvent;
  52. import com.vaadin.client.widget.grid.sort.SortEvent;
  53. import com.vaadin.client.widget.grid.sort.SortOrder;
  54. import com.vaadin.client.widgets.Grid;
  55. import com.vaadin.client.widgets.Grid.Column;
  56. import com.vaadin.client.widgets.Grid.FooterRow;
  57. import com.vaadin.client.widgets.Grid.HeaderRow;
  58. import com.vaadin.shared.MouseEventDetails;
  59. import com.vaadin.shared.data.sort.SortDirection;
  60. import com.vaadin.shared.ui.Connect;
  61. import com.vaadin.shared.ui.grid.GridClientRpc;
  62. import com.vaadin.shared.ui.grid.GridConstants;
  63. import com.vaadin.shared.ui.grid.GridConstants.Section;
  64. import com.vaadin.shared.ui.grid.GridServerRpc;
  65. import com.vaadin.shared.ui.grid.GridState;
  66. import com.vaadin.shared.ui.grid.ScrollDestination;
  67. import com.vaadin.shared.ui.grid.SectionState;
  68. import com.vaadin.shared.ui.grid.SectionState.CellState;
  69. import com.vaadin.shared.ui.grid.SectionState.RowState;
  70. import elemental.json.JsonObject;
  71. /**
  72. * A connector class for the typed Grid component.
  73. *
  74. * @author Vaadin Ltd
  75. * @since 8.0
  76. */
  77. @Connect(com.vaadin.ui.Grid.class)
  78. public class GridConnector extends AbstractListingConnector
  79. implements HasComponentsConnector, SimpleManagedLayout, DeferredWorker {
  80. private Set<Runnable> refreshDetailsCallbacks = new HashSet<>();
  81. private class ItemClickHandler
  82. implements BodyClickHandler, BodyDoubleClickHandler {
  83. @Override
  84. public void onClick(GridClickEvent event) {
  85. if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
  86. fireItemClick(event.getTargetCell(), event.getNativeEvent());
  87. }
  88. }
  89. @Override
  90. public void onDoubleClick(GridDoubleClickEvent event) {
  91. if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
  92. fireItemClick(event.getTargetCell(), event.getNativeEvent());
  93. }
  94. }
  95. private void fireItemClick(CellReference<?> cell,
  96. NativeEvent mouseEvent) {
  97. String rowKey = getRowKey((JsonObject) cell.getRow());
  98. String columnId = columnToIdMap.get(cell.getColumn());
  99. getRpcProxy(GridServerRpc.class).itemClick(rowKey, columnId,
  100. MouseEventDetailsBuilder
  101. .buildMouseEventDetails(mouseEvent));
  102. }
  103. }
  104. /* Map to keep track of all added columns */
  105. private Map<CustomColumn, String> columnToIdMap = new HashMap<>();
  106. private Map<String, CustomColumn> idToColumn = new HashMap<>();
  107. /* Child component list for HasComponentsConnector */
  108. private List<ComponentConnector> childComponents;
  109. private ItemClickHandler itemClickHandler = new ItemClickHandler();
  110. private boolean rowHeightScheduled = false;
  111. /**
  112. * Gets the string identifier of the given column in this grid.
  113. *
  114. * @param column
  115. * the column whose id to get
  116. * @return the string id of the column
  117. */
  118. public String getColumnId(Column<?, ?> column) {
  119. return columnToIdMap.get(column);
  120. }
  121. /**
  122. * Gets the column corresponding to the given string identifier.
  123. *
  124. * @param columnId
  125. * the id of the column to get
  126. * @return the column with the given id
  127. */
  128. public CustomColumn getColumn(String columnId) {
  129. return idToColumn.get(columnId);
  130. }
  131. @Override
  132. @SuppressWarnings("unchecked")
  133. public Grid<JsonObject> getWidget() {
  134. return (Grid<JsonObject>) super.getWidget();
  135. }
  136. /**
  137. * Method called for a row details refresh. Runs all callbacks if any
  138. * details were shown and clears the callbacks.
  139. *
  140. * @param detailsShown
  141. * True if any details were set visible
  142. */
  143. protected void detailsRefreshed(boolean detailsShown) {
  144. if (detailsShown) {
  145. refreshDetailsCallbacks.forEach(Runnable::run);
  146. }
  147. refreshDetailsCallbacks.clear();
  148. }
  149. /**
  150. * Method target for when one single details has been updated and we might
  151. * need to scroll it into view.
  152. *
  153. * @param rowIndex
  154. * index of updated row
  155. */
  156. protected void singleDetailsOpened(int rowIndex) {
  157. addDetailsRefreshCallback(() -> {
  158. if (rowHasDetails(rowIndex)) {
  159. getWidget().scrollToRow(rowIndex);
  160. }
  161. });
  162. }
  163. /**
  164. * Add a single use details runnable callback for when we get a call to
  165. * {@link #detailsRefreshed(boolean)}.
  166. *
  167. * @param refreshCallback
  168. * Details refreshed callback
  169. */
  170. private void addDetailsRefreshCallback(Runnable refreshCallback) {
  171. refreshDetailsCallbacks.add(refreshCallback);
  172. }
  173. /**
  174. * Check if we have details for given row.
  175. *
  176. * @param rowIndex
  177. * @return
  178. */
  179. private boolean rowHasDetails(int rowIndex) {
  180. JsonObject row = getWidget().getDataSource().getRow(rowIndex);
  181. return row != null && row.hasKey(GridState.JSONKEY_DETAILS_VISIBLE)
  182. && !row.getString(GridState.JSONKEY_DETAILS_VISIBLE).isEmpty();
  183. }
  184. @Override
  185. protected void init() {
  186. super.init();
  187. updateWidgetStyleNames();
  188. // Remove default headers when initializing Grid widget
  189. while (getWidget().getHeaderRowCount() > 0) {
  190. getWidget().removeHeaderRow(0);
  191. }
  192. registerRpc(GridClientRpc.class, new GridClientRpc() {
  193. @Override
  194. public void scrollToRow(int row, ScrollDestination destination) {
  195. Scheduler.get().scheduleFinally(
  196. () -> getWidget().scrollToRow(row, destination));
  197. // Add details refresh listener and handle possible detail for
  198. // scrolled row.
  199. addDetailsRefreshCallback(() -> {
  200. if (rowHasDetails(row)) {
  201. getWidget().scrollToRow(row, destination);
  202. }
  203. });
  204. }
  205. @Override
  206. public void scrollToStart() {
  207. Scheduler.get()
  208. .scheduleFinally(() -> getWidget().scrollToStart());
  209. }
  210. @Override
  211. public void scrollToEnd() {
  212. Scheduler.get()
  213. .scheduleFinally(() -> getWidget().scrollToEnd());
  214. addDetailsRefreshCallback(() -> {
  215. if (rowHasDetails(getWidget().getDataSource().size() - 1)) {
  216. getWidget().scrollToEnd();
  217. }
  218. });
  219. }
  220. @Override
  221. public void recalculateColumnWidths() {
  222. getWidget().recalculateColumnWidths();
  223. }
  224. });
  225. getWidget().addSortHandler(this::handleSortEvent);
  226. getWidget().setRowStyleGenerator(rowRef -> {
  227. JsonObject json = rowRef.getRow();
  228. return json.hasKey(GridState.JSONKEY_ROWSTYLE)
  229. ? json.getString(GridState.JSONKEY_ROWSTYLE)
  230. : null;
  231. });
  232. getWidget().setCellStyleGenerator(cellRef -> {
  233. JsonObject row = cellRef.getRow();
  234. if (!row.hasKey(GridState.JSONKEY_CELLSTYLES)) {
  235. return null;
  236. }
  237. Column<?, JsonObject> column = cellRef.getColumn();
  238. if (column instanceof CustomColumn) {
  239. String id = ((CustomColumn) column).getConnectorId();
  240. JsonObject cellStyles = row
  241. .getObject(GridState.JSONKEY_CELLSTYLES);
  242. if (cellStyles.hasKey(id)) {
  243. return cellStyles.getString(id);
  244. }
  245. }
  246. return null;
  247. });
  248. getWidget().addColumnVisibilityChangeHandler(event -> {
  249. if (event.isUserOriginated()) {
  250. getRpcProxy(GridServerRpc.class).columnVisibilityChanged(
  251. getColumnId(event.getColumn()), event.isHidden());
  252. }
  253. });
  254. getWidget().addColumnReorderHandler(event -> {
  255. if (event.isUserOriginated()) {
  256. List<String> newColumnOrder = mapColumnsToIds(
  257. event.getNewColumnOrder());
  258. List<String> oldColumnOrder = mapColumnsToIds(
  259. event.getOldColumnOrder());
  260. getRpcProxy(GridServerRpc.class)
  261. .columnsReordered(newColumnOrder, oldColumnOrder);
  262. }
  263. });
  264. getWidget().addColumnResizeHandler(event -> {
  265. Column<?, JsonObject> column = event.getColumn();
  266. getRpcProxy(GridServerRpc.class).columnResized(getColumnId(column),
  267. column.getWidthActual());
  268. });
  269. // Handling row height changes
  270. getWidget().addRowHeightChangedHandler(event -> {
  271. getLayoutManager().setNeedsMeasureRecursively(GridConnector.this);
  272. getLayoutManager().layoutNow();
  273. });
  274. /* Item click events */
  275. getWidget().addBodyClickHandler(itemClickHandler);
  276. getWidget().addBodyDoubleClickHandler(itemClickHandler);
  277. layout();
  278. }
  279. @SuppressWarnings("unchecked")
  280. @OnStateChange("columnOrder")
  281. void updateColumnOrder() {
  282. Scheduler.get()
  283. .scheduleFinally(() -> getWidget().setColumnOrder(
  284. getState().columnOrder.stream().map(this::getColumn)
  285. .toArray(size -> new Column[size])));
  286. }
  287. @OnStateChange("columnResizeMode")
  288. void updateColumnResizeMode() {
  289. getWidget().setColumnResizeMode(getState().columnResizeMode);
  290. }
  291. /**
  292. * Updates the grid header section on state change.
  293. */
  294. @OnStateChange("header")
  295. void updateHeader() {
  296. final Grid<JsonObject> grid = getWidget();
  297. final SectionState state = getState().header;
  298. while (grid.getHeaderRowCount() > 0) {
  299. grid.removeHeaderRow(0);
  300. }
  301. for (RowState rowState : state.rows) {
  302. HeaderRow row = grid.appendHeaderRow();
  303. if (rowState.defaultHeader) {
  304. grid.setDefaultHeaderRow(row);
  305. }
  306. updateStaticRow(rowState, row);
  307. }
  308. grid.setHeaderVisible(state.visible);
  309. }
  310. @OnStateChange({ "bodyRowHeight", "headerRowHeight", "footerRowHeight" })
  311. void updateRowHeight() {
  312. if (rowHeightScheduled) {
  313. return;
  314. }
  315. Scheduler.get().scheduleFinally(() -> {
  316. GridState state = getState();
  317. if (getWidget().isAttached() && rowHeightNeedsReset()) {
  318. getWidget().resetSizesFromDom();
  319. }
  320. updateContainerRowHeigth(getWidget().getEscalator().getBody(),
  321. state.bodyRowHeight);
  322. updateContainerRowHeigth(getWidget().getEscalator().getHeader(),
  323. state.headerRowHeight);
  324. updateContainerRowHeigth(getWidget().getEscalator().getFooter(),
  325. state.footerRowHeight);
  326. rowHeightScheduled = false;
  327. });
  328. rowHeightScheduled = true;
  329. }
  330. private boolean rowHeightNeedsReset() {
  331. GridState state = getState();
  332. // Body
  333. boolean bodyAutoCalc = state.bodyRowHeight < 0;
  334. // Header
  335. boolean headerAutoCalc = state.headerRowHeight < 0;
  336. boolean headerReset = headerAutoCalc && hasVisibleContent(state.header);
  337. // Footer
  338. boolean footerAutoCalc = state.footerRowHeight < 0;
  339. boolean footerReset = footerAutoCalc && hasVisibleContent(state.footer);
  340. return bodyAutoCalc || headerReset || footerReset;
  341. }
  342. private boolean hasVisibleContent(SectionState state) {
  343. return state.visible && !state.rows.isEmpty();
  344. }
  345. private void updateContainerRowHeigth(RowContainer container,
  346. double height) {
  347. if (height >= 0) {
  348. container.setDefaultRowHeight(height);
  349. }
  350. }
  351. private void updateStaticRow(RowState rowState,
  352. Grid.StaticSection.StaticRow row) {
  353. rowState.cells
  354. .forEach((columnId, cellState) -> updateStaticCellFromState(
  355. row.getCell(getColumn(columnId)), cellState));
  356. for (Map.Entry<CellState, Set<String>> cellGroupEntry : rowState.cellGroups
  357. .entrySet()) {
  358. Set<String> group = cellGroupEntry.getValue();
  359. Grid.Column<?, ?>[] columns = group.stream().map(idToColumn::get)
  360. .toArray(size -> new Grid.Column<?, ?>[size]);
  361. // Set state to be the same as first in group.
  362. updateStaticCellFromState(row.join(columns),
  363. cellGroupEntry.getKey());
  364. }
  365. row.setStyleName(rowState.styleName);
  366. }
  367. private void updateStaticCellFromState(Grid.StaticSection.StaticCell cell,
  368. CellState cellState) {
  369. switch (cellState.type) {
  370. case TEXT:
  371. cell.setText(cellState.text);
  372. break;
  373. case HTML:
  374. cell.setHtml(cellState.html);
  375. break;
  376. case WIDGET:
  377. ComponentConnector connector = (ComponentConnector) cellState.connector;
  378. if (connector != null) {
  379. cell.setWidget(connector.getWidget());
  380. } else {
  381. // This happens if you do setVisible(false) on the component on
  382. // the server side
  383. cell.setWidget(null);
  384. }
  385. break;
  386. default:
  387. throw new IllegalStateException(
  388. "unexpected cell type: " + cellState.type);
  389. }
  390. cell.setStyleName(cellState.styleName);
  391. }
  392. /**
  393. * Updates the grid footer section on state change.
  394. */
  395. @OnStateChange("footer")
  396. void updateFooter() {
  397. final Grid<JsonObject> grid = getWidget();
  398. final SectionState state = getState().footer;
  399. while (grid.getFooterRowCount() > 0) {
  400. grid.removeFooterRow(0);
  401. }
  402. for (RowState rowState : state.rows) {
  403. FooterRow row = grid.appendFooterRow();
  404. updateStaticRow(rowState, row);
  405. }
  406. grid.setFooterVisible(state.visible);
  407. }
  408. @OnStateChange({ "sortColumns", "sortDirs" })
  409. void updateSortOrder() {
  410. List<SortOrder> sortOrder = new ArrayList<SortOrder>();
  411. String[] sortColumns = getState().sortColumns;
  412. SortDirection[] sortDirs = getState().sortDirs;
  413. for (int i = 0; i < sortColumns.length; i++) {
  414. sortOrder
  415. .add(new SortOrder(getColumn(sortColumns[i]), sortDirs[i]));
  416. }
  417. getWidget().setSortOrder(sortOrder);
  418. }
  419. @Override
  420. public void setDataSource(DataSource<JsonObject> dataSource) {
  421. super.setDataSource(dataSource);
  422. getWidget().setDataSource(dataSource);
  423. }
  424. /**
  425. * Adds a column to the Grid widget. For each column a communication id
  426. * stored for client to server communication.
  427. *
  428. * @param column
  429. * column to add
  430. * @param id
  431. * communication id
  432. */
  433. public void addColumn(CustomColumn column, String id) {
  434. assert !columnToIdMap.containsKey(column) && !columnToIdMap
  435. .containsValue(id) : "Column with given id already exists.";
  436. getWidget().addColumn(column);
  437. columnToIdMap.put(column, id);
  438. idToColumn.put(id, column);
  439. }
  440. /**
  441. * Removes a column from Grid widget. This method also removes communication
  442. * id mapping for the column.
  443. *
  444. * @param column
  445. * column to remove
  446. */
  447. public void removeColumn(CustomColumn column) {
  448. assert columnToIdMap
  449. .containsKey(column) : "Given Column does not exist.";
  450. getWidget().removeColumn(column);
  451. String id = columnToIdMap.remove(column);
  452. idToColumn.remove(id);
  453. }
  454. /**
  455. * Method called by {@code CustomColumn} when its renderer changes. This
  456. * method is used to maintain hierarchical renderer wrap in
  457. * {@code TreeGrid}.
  458. *
  459. * @param column
  460. * the column which now has a new renderer
  461. *
  462. * @since 8.1
  463. */
  464. public void onColumnRendererChanged(CustomColumn column) {
  465. // NO-OP
  466. }
  467. @Override
  468. public void onUnregister() {
  469. super.onUnregister();
  470. }
  471. @Override
  472. public boolean isWorkPending() {
  473. return getWidget().isWorkPending();
  474. }
  475. @Override
  476. public void layout() {
  477. getWidget().onResize();
  478. }
  479. /**
  480. * Sends sort information from an event to the server-side of the Grid.
  481. *
  482. * @param event
  483. * the sort event
  484. */
  485. private void handleSortEvent(SortEvent<JsonObject> event) {
  486. List<String> columnIds = new ArrayList<>();
  487. List<SortDirection> sortDirections = new ArrayList<>();
  488. for (SortOrder so : event.getOrder()) {
  489. if (columnToIdMap.containsKey(so.getColumn())) {
  490. columnIds.add(columnToIdMap.get(so.getColumn()));
  491. sortDirections.add(so.getDirection());
  492. }
  493. }
  494. String[] colArray = columnIds.toArray(new String[0]);
  495. SortDirection[] dirArray = sortDirections.toArray(new SortDirection[0]);
  496. if (!Arrays.equals(colArray, getState().sortColumns)
  497. || !Arrays.equals(dirArray, getState().sortDirs)) {
  498. // State has actually changed, send to server
  499. getRpcProxy(GridServerRpc.class).sort(colArray, dirArray,
  500. event.isUserOriginated());
  501. }
  502. }
  503. /* HasComponentsConnector */
  504. @Override
  505. public void updateCaption(ComponentConnector connector) {
  506. // Details components don't support captions.
  507. }
  508. @Override
  509. public List<ComponentConnector> getChildComponents() {
  510. if (childComponents == null) {
  511. return Collections.emptyList();
  512. }
  513. return childComponents;
  514. }
  515. @Override
  516. public void setChildComponents(List<ComponentConnector> children) {
  517. childComponents = children;
  518. }
  519. @Override
  520. public HandlerRegistration addConnectorHierarchyChangeHandler(
  521. ConnectorHierarchyChangeHandler handler) {
  522. return ensureHandlerManager()
  523. .addHandler(ConnectorHierarchyChangeEvent.TYPE, handler);
  524. }
  525. @Override
  526. public GridState getState() {
  527. return (GridState) super.getState();
  528. }
  529. @Override
  530. public boolean hasTooltip() {
  531. // Always check for generated descriptions.
  532. return true;
  533. }
  534. @Override
  535. public TooltipInfo getTooltipInfo(Element element) {
  536. CellReference<JsonObject> cell = getWidget().getCellReference(element);
  537. if (cell != null) {
  538. JsonObject row = cell.getRow();
  539. if (row != null && (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)
  540. || row.hasKey(GridState.JSONKEY_CELLDESCRIPTION))) {
  541. Column<?, JsonObject> column = cell.getColumn();
  542. if (column instanceof CustomColumn) {
  543. JsonObject cellDescriptions = row
  544. .getObject(GridState.JSONKEY_CELLDESCRIPTION);
  545. String id = ((CustomColumn) column).getConnectorId();
  546. if (cellDescriptions != null
  547. && cellDescriptions.hasKey(id)) {
  548. return new TooltipInfo(cellDescriptions.getString(id));
  549. } else if (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)) {
  550. return new TooltipInfo(row
  551. .getString(GridState.JSONKEY_ROWDESCRIPTION));
  552. }
  553. }
  554. }
  555. }
  556. if (super.hasTooltip()) {
  557. return super.getTooltipInfo(element);
  558. } else {
  559. return null;
  560. }
  561. }
  562. @Override
  563. protected void sendContextClickEvent(MouseEventDetails details,
  564. EventTarget eventTarget) {
  565. // if element is the resize indicator, ignore the event
  566. if (isResizeHandle(eventTarget)) {
  567. WidgetUtil.clearTextSelection();
  568. return;
  569. }
  570. EventCellReference<JsonObject> eventCell = getWidget().getEventCell();
  571. Section section = eventCell.getSection();
  572. String rowKey = null;
  573. if (eventCell.isBody() && eventCell.getRow() != null) {
  574. rowKey = getRowKey(eventCell.getRow());
  575. }
  576. String columnId = getColumnId(eventCell.getColumn());
  577. getRpcProxy(GridServerRpc.class).contextClick(eventCell.getRowIndex(),
  578. rowKey, columnId, section, details);
  579. WidgetUtil.clearTextSelection();
  580. }
  581. private boolean isResizeHandle(EventTarget eventTarget) {
  582. if (Element.is(eventTarget)) {
  583. Element e = Element.as(eventTarget);
  584. if (e.getClassName().contains("-column-resize-handle")) {
  585. return true;
  586. }
  587. }
  588. return false;
  589. }
  590. private List<String> mapColumnsToIds(List<Column<?, JsonObject>> columns) {
  591. return columns.stream().map(this::getColumnId).filter(Objects::nonNull)
  592. .collect(Collectors.toList());
  593. }
  594. }