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 30KB

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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /*
  2. * Copyright 2000-2018 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.communication.StateChangeEvent;
  42. import com.vaadin.client.connectors.AbstractListingConnector;
  43. import com.vaadin.client.connectors.grid.ColumnConnector.CustomColumn;
  44. import com.vaadin.client.data.AbstractRemoteDataSource;
  45. import com.vaadin.client.data.DataSource;
  46. import com.vaadin.client.ui.SimpleManagedLayout;
  47. import com.vaadin.client.widget.escalator.RowContainer;
  48. import com.vaadin.client.widget.grid.CellReference;
  49. import com.vaadin.client.widget.grid.DataAvailableEvent;
  50. import com.vaadin.client.widget.grid.DataAvailableHandler;
  51. import com.vaadin.client.widget.grid.EventCellReference;
  52. import com.vaadin.client.widget.grid.events.BodyClickHandler;
  53. import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler;
  54. import com.vaadin.client.widget.grid.events.GridClickEvent;
  55. import com.vaadin.client.widget.grid.events.GridDoubleClickEvent;
  56. import com.vaadin.client.widget.grid.sort.SortEvent;
  57. import com.vaadin.client.widget.grid.sort.SortOrder;
  58. import com.vaadin.client.widgets.Grid;
  59. import com.vaadin.client.widgets.Grid.Column;
  60. import com.vaadin.client.widgets.Grid.FooterRow;
  61. import com.vaadin.client.widgets.Grid.HeaderRow;
  62. import com.vaadin.client.widgets.Grid.SelectionColumn;
  63. import com.vaadin.client.widgets.Grid.StaticSection.StaticCell;
  64. import com.vaadin.shared.MouseEventDetails;
  65. import com.vaadin.shared.data.sort.SortDirection;
  66. import com.vaadin.shared.ui.Connect;
  67. import com.vaadin.shared.ui.grid.GridClientRpc;
  68. import com.vaadin.shared.ui.grid.GridConstants;
  69. import com.vaadin.shared.ui.grid.GridConstants.Section;
  70. import com.vaadin.shared.ui.grid.GridServerRpc;
  71. import com.vaadin.shared.ui.grid.GridState;
  72. import com.vaadin.shared.ui.grid.ScrollDestination;
  73. import com.vaadin.shared.ui.grid.SectionState;
  74. import com.vaadin.shared.ui.grid.SectionState.CellState;
  75. import com.vaadin.shared.ui.grid.SectionState.RowState;
  76. import elemental.json.JsonObject;
  77. /**
  78. * A connector class for the typed Grid component.
  79. *
  80. * @author Vaadin Ltd
  81. * @since 8.0
  82. */
  83. @Connect(com.vaadin.ui.Grid.class)
  84. public class GridConnector extends AbstractListingConnector
  85. implements HasComponentsConnector, SimpleManagedLayout, DeferredWorker {
  86. private Set<Runnable> refreshDetailsCallbacks = new HashSet<>();
  87. /**
  88. * Server-to-client RPC implementation for GridConnector.
  89. * <p>
  90. * The scrolling methods must trigger the scrolling only after any potential
  91. * resizing or other similar action triggered from the server side within
  92. * the same round trip has had a chance to happen, so there needs to be a
  93. * delay. The delay is done with <code>scheduleDeferred</code> rather than
  94. * <code>scheduleFinally</code> because otherwise the order of the
  95. * operations isn't guaranteed.
  96. *
  97. */
  98. private class GridConnectorClientRpc implements GridClientRpc {
  99. private final Grid<JsonObject> grid;
  100. private HandlerRegistration dataAvailableHandlerRegistration = null;
  101. private boolean recalculateScheduled = false;
  102. private GridConnectorClientRpc(Grid<JsonObject> grid) {
  103. this.grid = grid;
  104. }
  105. @Override
  106. public void scrollToRow(int row, ScrollDestination destination) {
  107. Scheduler.get().scheduleDeferred(() -> {
  108. grid.scrollToRow(row, destination);
  109. // Add details refresh listener and handle possible detail
  110. // for scrolled row.
  111. addDetailsRefreshCallback(() -> {
  112. if (rowHasDetails(row)) {
  113. grid.scrollToRow(row, destination);
  114. }
  115. });
  116. });
  117. }
  118. @Override
  119. public void scrollToStart() {
  120. Scheduler.get().scheduleDeferred(() -> grid.scrollToStart());
  121. }
  122. @Override
  123. public void scrollToEnd() {
  124. Scheduler.get().scheduleDeferred(() -> {
  125. grid.scrollToEnd();
  126. addDetailsRefreshCallback(() -> {
  127. if (rowHasDetails(grid.getDataSource().size() - 1)) {
  128. grid.scrollToEnd();
  129. }
  130. });
  131. });
  132. }
  133. @Override
  134. public void recalculateColumnWidths() {
  135. if (recalculateScheduled) {
  136. return;
  137. }
  138. // Must be scheduled so that possible refreshAll has time to clear
  139. // the cache.
  140. recalculateScheduled = true;
  141. Scheduler.get().scheduleFinally(() -> {
  142. // If cache has been cleared, wait for data to become available.
  143. // Don't trigger another attempt if there is already a handler
  144. // waiting, that one will trigger the call when calculations are
  145. // possible and clear out the registration afterwards.
  146. if (((AbstractRemoteDataSource<JsonObject>) getDataSource())
  147. .getCachedRange().length() == 0
  148. && getDataSource().size() > 0) {
  149. if (dataAvailableHandlerRegistration == null) {
  150. dataAvailableHandlerRegistration = grid
  151. .addDataAvailableHandler(
  152. new DataAvailableHandler() {
  153. @Override
  154. public void onDataAvailable(
  155. DataAvailableEvent event) {
  156. if (event.getAvailableRows()
  157. .length() == 0
  158. && getDataSource()
  159. .size() > 0) {
  160. // Cache not populated yet,
  161. // wait for next call.
  162. return;
  163. }
  164. grid.recalculateColumnWidths();
  165. if (dataAvailableHandlerRegistration != null) {
  166. dataAvailableHandlerRegistration
  167. .removeHandler();
  168. dataAvailableHandlerRegistration = null;
  169. }
  170. }
  171. });
  172. }
  173. } else if (dataAvailableHandlerRegistration == null) {
  174. grid.recalculateColumnWidths();
  175. }
  176. recalculateScheduled = false;
  177. });
  178. }
  179. }
  180. private class ItemClickHandler
  181. implements BodyClickHandler, BodyDoubleClickHandler {
  182. @Override
  183. public void onClick(GridClickEvent event) {
  184. if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
  185. fireItemClick(event.getTargetCell(), event.getNativeEvent());
  186. }
  187. }
  188. @Override
  189. public void onDoubleClick(GridDoubleClickEvent event) {
  190. if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
  191. fireItemClick(event.getTargetCell(), event.getNativeEvent());
  192. }
  193. }
  194. private void fireItemClick(CellReference<?> cell,
  195. NativeEvent mouseEvent) {
  196. String rowKey = getRowKey((JsonObject) cell.getRow());
  197. String columnId = columnToIdMap.get(cell.getColumn());
  198. int rowIndex = cell.getRowIndex();
  199. getRpcProxy(GridServerRpc.class).itemClick(rowKey, columnId,
  200. MouseEventDetailsBuilder.buildMouseEventDetails(mouseEvent),
  201. rowIndex);
  202. }
  203. }
  204. /* Map to keep track of all added columns */
  205. private Map<CustomColumn, String> columnToIdMap = new HashMap<>();
  206. private Map<String, CustomColumn> idToColumn = new HashMap<>();
  207. /* Child component list for HasComponentsConnector */
  208. private List<ComponentConnector> childComponents;
  209. private ItemClickHandler itemClickHandler = new ItemClickHandler();
  210. private boolean rowHeightScheduled = false;
  211. /**
  212. * Gets the string identifier of the given column in this grid.
  213. *
  214. * @param column
  215. * the column whose id to get
  216. * @return the string id of the column
  217. */
  218. public String getColumnId(Column<?, ?> column) {
  219. return columnToIdMap.get(column);
  220. }
  221. /**
  222. * Gets the column corresponding to the given string identifier.
  223. *
  224. * @param columnId
  225. * the id of the column to get
  226. * @return the column with the given id
  227. */
  228. public CustomColumn getColumn(String columnId) {
  229. return idToColumn.get(columnId);
  230. }
  231. @Override
  232. @SuppressWarnings("unchecked")
  233. public Grid<JsonObject> getWidget() {
  234. return (Grid<JsonObject>) super.getWidget();
  235. }
  236. /**
  237. * Method called for a row details refresh. Runs all callbacks if any
  238. * details were shown and clears the callbacks.
  239. *
  240. * @param detailsShown
  241. * True if any details were set visible
  242. */
  243. protected void detailsRefreshed(boolean detailsShown) {
  244. if (detailsShown) {
  245. refreshDetailsCallbacks.forEach(Runnable::run);
  246. }
  247. refreshDetailsCallbacks.clear();
  248. }
  249. /**
  250. * Method target for when one single details has been updated and we might
  251. * need to scroll it into view.
  252. *
  253. * @param rowIndex
  254. * index of updated row
  255. */
  256. protected void singleDetailsOpened(int rowIndex) {
  257. addDetailsRefreshCallback(() -> {
  258. if (rowHasDetails(rowIndex)) {
  259. getWidget().scrollToRow(rowIndex);
  260. }
  261. });
  262. }
  263. /**
  264. * Add a single use details runnable callback for when we get a call to
  265. * {@link #detailsRefreshed(boolean)}.
  266. *
  267. * @param refreshCallback
  268. * Details refreshed callback
  269. */
  270. private void addDetailsRefreshCallback(Runnable refreshCallback) {
  271. refreshDetailsCallbacks.add(refreshCallback);
  272. }
  273. /**
  274. * Check if we have details for given row.
  275. *
  276. * @param rowIndex
  277. * @return
  278. */
  279. private boolean rowHasDetails(int rowIndex) {
  280. JsonObject row = getWidget().getDataSource().getRow(rowIndex);
  281. return row != null && row.hasKey(GridState.JSONKEY_DETAILS_VISIBLE)
  282. && !row.getString(GridState.JSONKEY_DETAILS_VISIBLE).isEmpty();
  283. }
  284. @Override
  285. protected void init() {
  286. super.init();
  287. updateWidgetStyleNames();
  288. Grid<JsonObject> grid = getWidget();
  289. // Trigger early redraw of both grid static sections.
  290. grid.setHeaderVisible(!grid.isHeaderVisible());
  291. grid.setFooterVisible(!grid.isFooterVisible());
  292. registerRpc(GridClientRpc.class, new GridConnectorClientRpc(grid));
  293. grid.addSortHandler(this::handleSortEvent);
  294. grid.setRowStyleGenerator(rowRef -> {
  295. JsonObject json = rowRef.getRow();
  296. return json.hasKey(GridState.JSONKEY_ROWSTYLE)
  297. ? json.getString(GridState.JSONKEY_ROWSTYLE)
  298. : null;
  299. });
  300. grid.setCellStyleGenerator(cellRef -> {
  301. JsonObject row = cellRef.getRow();
  302. if (!row.hasKey(GridState.JSONKEY_CELLSTYLES)) {
  303. return null;
  304. }
  305. Column<?, JsonObject> column = cellRef.getColumn();
  306. if (column instanceof CustomColumn) {
  307. String id = ((CustomColumn) column).getConnectorId();
  308. JsonObject cellStyles = row
  309. .getObject(GridState.JSONKEY_CELLSTYLES);
  310. if (cellStyles.hasKey(id)) {
  311. return cellStyles.getString(id);
  312. }
  313. }
  314. return null;
  315. });
  316. grid.addColumnVisibilityChangeHandler(event -> {
  317. if (event.isUserOriginated()) {
  318. getRpcProxy(GridServerRpc.class).columnVisibilityChanged(
  319. getColumnId(event.getColumn()), event.isHidden());
  320. }
  321. });
  322. grid.addColumnReorderHandler(event -> {
  323. if (event.isUserOriginated()) {
  324. List<String> newColumnOrder = mapColumnsToIds(
  325. event.getNewColumnOrder());
  326. List<String> oldColumnOrder = mapColumnsToIds(
  327. event.getOldColumnOrder());
  328. getRpcProxy(GridServerRpc.class)
  329. .columnsReordered(newColumnOrder, oldColumnOrder);
  330. }
  331. });
  332. grid.addColumnResizeHandler(event -> {
  333. Column<?, JsonObject> column = event.getColumn();
  334. getRpcProxy(GridServerRpc.class).columnResized(getColumnId(column),
  335. column.getWidthActual());
  336. });
  337. // Handling row height changes
  338. grid.addRowHeightChangedHandler(event -> {
  339. getLayoutManager().setNeedsMeasureRecursively(GridConnector.this);
  340. getLayoutManager().layoutNow();
  341. });
  342. /* Item click events */
  343. grid.addBodyClickHandler(itemClickHandler);
  344. grid.addBodyDoubleClickHandler(itemClickHandler);
  345. layout();
  346. }
  347. @Override
  348. public void onStateChanged(StateChangeEvent stateChangeEvent) {
  349. super.onStateChanged(stateChangeEvent);
  350. if (!getState().columnOrder.containsAll(idToColumn.keySet())) {
  351. updateColumns();
  352. } else if (stateChangeEvent.hasPropertyChanged("columnOrder")) {
  353. updateColumnOrder();
  354. }
  355. if (stateChangeEvent.hasPropertyChanged("header")) {
  356. updateHeader();
  357. }
  358. if (stateChangeEvent.hasPropertyChanged("footer")) {
  359. updateFooter();
  360. }
  361. }
  362. void updateColumnOrder() {
  363. getWidget().setColumnOrder(getState().columnOrder.stream()
  364. .map(this::getColumn).toArray(size -> new CustomColumn[size]));
  365. }
  366. @OnStateChange("columnResizeMode")
  367. void updateColumnResizeMode() {
  368. getWidget().setColumnResizeMode(getState().columnResizeMode);
  369. }
  370. /**
  371. * Updates the grid header section on state change.
  372. */
  373. void updateHeader() {
  374. final Grid<JsonObject> grid = getWidget();
  375. final SectionState state = getState().header;
  376. while (grid.getHeaderRowCount() > 0) {
  377. grid.removeHeaderRow(0);
  378. }
  379. for (RowState rowState : state.rows) {
  380. HeaderRow row = grid.appendHeaderRow();
  381. if (rowState.defaultHeader) {
  382. grid.setDefaultHeaderRow(row);
  383. }
  384. updateStaticRow(rowState, row);
  385. }
  386. grid.setHeaderVisible(state.visible);
  387. }
  388. @OnStateChange({ "bodyRowHeight", "headerRowHeight", "footerRowHeight" })
  389. void updateRowHeight() {
  390. if (rowHeightScheduled) {
  391. return;
  392. }
  393. Scheduler.get().scheduleFinally(() -> {
  394. GridState state = getState();
  395. Grid<JsonObject> grid = getWidget();
  396. if (grid.isAttached() && rowHeightNeedsReset()) {
  397. grid.resetSizesFromDom();
  398. }
  399. updateContainerRowHeigth(grid.getEscalator().getBody(),
  400. state.bodyRowHeight);
  401. updateContainerRowHeigth(grid.getEscalator().getHeader(),
  402. state.headerRowHeight);
  403. updateContainerRowHeigth(grid.getEscalator().getFooter(),
  404. state.footerRowHeight);
  405. rowHeightScheduled = false;
  406. });
  407. rowHeightScheduled = true;
  408. }
  409. private boolean rowHeightNeedsReset() {
  410. GridState state = getState();
  411. // Body
  412. boolean bodyAutoCalc = state.bodyRowHeight < 0;
  413. // Header
  414. boolean headerAutoCalc = state.headerRowHeight < 0;
  415. boolean headerReset = headerAutoCalc && hasVisibleContent(state.header);
  416. // Footer
  417. boolean footerAutoCalc = state.footerRowHeight < 0;
  418. boolean footerReset = footerAutoCalc && hasVisibleContent(state.footer);
  419. return bodyAutoCalc || headerReset || footerReset;
  420. }
  421. private boolean hasVisibleContent(SectionState state) {
  422. return state.visible && !state.rows.isEmpty();
  423. }
  424. private void updateContainerRowHeigth(RowContainer container,
  425. double height) {
  426. if (height >= 0) {
  427. container.setDefaultRowHeight(height);
  428. }
  429. }
  430. private void updateStaticRow(RowState rowState,
  431. Grid.StaticSection.StaticRow row) {
  432. rowState.cells
  433. .forEach((columnId, cellState) -> updateStaticCellFromState(
  434. row.getCell(getColumn(columnId)), cellState));
  435. for (Map.Entry<CellState, Set<String>> cellGroupEntry : rowState.cellGroups
  436. .entrySet()) {
  437. Set<String> group = cellGroupEntry.getValue();
  438. Grid.Column<?, ?>[] columns = group.stream().map(idToColumn::get)
  439. .toArray(size -> new Grid.Column<?, ?>[size]);
  440. // Set state to be the same as first in group.
  441. updateStaticCellFromState(row.join(columns),
  442. cellGroupEntry.getKey());
  443. }
  444. row.setStyleName(rowState.styleName);
  445. }
  446. private void updateStaticCellFromState(Grid.StaticSection.StaticCell cell,
  447. CellState cellState) {
  448. switch (cellState.type) {
  449. case TEXT:
  450. cell.setText(cellState.text);
  451. break;
  452. case HTML:
  453. cell.setHtml(cellState.html);
  454. break;
  455. case WIDGET:
  456. ComponentConnector connector = (ComponentConnector) cellState.connector;
  457. if (connector != null) {
  458. cell.setWidget(connector.getWidget());
  459. } else {
  460. // This happens if you do setVisible(false) on the component on
  461. // the server side
  462. cell.setWidget(null);
  463. }
  464. break;
  465. default:
  466. throw new IllegalStateException(
  467. "unexpected cell type: " + cellState.type);
  468. }
  469. cell.setStyleName(cellState.styleName);
  470. cell.setDescription(cellState.description);
  471. cell.setDescriptionContentMode(cellState.descriptionContentMode);
  472. }
  473. /**
  474. * Updates the grid footer section on state change.
  475. */
  476. void updateFooter() {
  477. final Grid<JsonObject> grid = getWidget();
  478. final SectionState state = getState().footer;
  479. while (grid.getFooterRowCount() > 0) {
  480. grid.removeFooterRow(0);
  481. }
  482. for (RowState rowState : state.rows) {
  483. FooterRow row = grid.appendFooterRow();
  484. updateStaticRow(rowState, row);
  485. }
  486. grid.setFooterVisible(state.visible);
  487. }
  488. @OnStateChange({ "sortColumns", "sortDirs" })
  489. void updateSortOrder() {
  490. List<SortOrder> sortOrder = new ArrayList<SortOrder>();
  491. String[] sortColumns = getState().sortColumns;
  492. SortDirection[] sortDirs = getState().sortDirs;
  493. for (int i = 0; i < sortColumns.length; i++) {
  494. sortOrder
  495. .add(new SortOrder(getColumn(sortColumns[i]), sortDirs[i]));
  496. }
  497. getWidget().setSortOrder(sortOrder);
  498. }
  499. @Override
  500. public void setDataSource(DataSource<JsonObject> dataSource) {
  501. super.setDataSource(dataSource);
  502. getWidget().setDataSource(dataSource);
  503. }
  504. /**
  505. * Adds a column to the Grid widget. For each column a communication id
  506. * stored for client to server communication.
  507. *
  508. * @param column
  509. * column to add
  510. * @param id
  511. * communication id
  512. */
  513. public void addColumn(CustomColumn column, String id) {
  514. assert !columnToIdMap.containsKey(column) && !columnToIdMap
  515. .containsValue(id) : "Column with given id already exists.";
  516. columnToIdMap.put(column, id);
  517. idToColumn.put(id, column);
  518. if (idToColumn.keySet().containsAll(getState().columnOrder)) {
  519. // All columns are available.
  520. updateColumns();
  521. }
  522. }
  523. /**
  524. * Updates the widgets columns to match the map in this connector.
  525. */
  526. protected void updateColumns() {
  527. List<Column<?, JsonObject>> currentColumns = getWidget().getColumns();
  528. List<CustomColumn> columnOrder = getState().columnOrder.stream()
  529. .map(this::getColumn).collect(Collectors.toList());
  530. if (isColumnOrderCorrect(currentColumns, columnOrder)) {
  531. // All up to date
  532. return;
  533. }
  534. Grid<JsonObject> grid = getWidget();
  535. // Remove old column
  536. currentColumns.stream()
  537. .filter(col -> !(columnOrder.contains(col)
  538. || col instanceof SelectionColumn))
  539. .forEach(grid::removeColumn);
  540. // Add new columns
  541. grid.addColumns(columnOrder.stream()
  542. .filter(col -> !currentColumns.contains(col))
  543. .toArray(CustomColumn[]::new));
  544. // Make sure order is correct.
  545. grid.setColumnOrder(
  546. columnOrder.toArray(new CustomColumn[columnOrder.size()]));
  547. }
  548. private boolean isColumnOrderCorrect(List<Column<?, JsonObject>> current,
  549. List<CustomColumn> order) {
  550. List<Column<?, JsonObject>> columnsToCompare = current;
  551. if (current.size() > 0 && current.get(0) instanceof SelectionColumn) {
  552. // Remove selection column.
  553. columnsToCompare = current.subList(1, current.size());
  554. }
  555. return columnsToCompare.equals(order);
  556. }
  557. /**
  558. * Removes the given column from mappings in this Connector.
  559. *
  560. * @param column
  561. * column to remove from the mapping
  562. */
  563. public void removeColumnMapping(CustomColumn column) {
  564. assert columnToIdMap
  565. .containsKey(column) : "Given Column does not exist.";
  566. // Remove mapping. Columns are removed from Grid when state changes.
  567. String id = columnToIdMap.remove(column);
  568. idToColumn.remove(id);
  569. }
  570. /**
  571. * Method called by {@code CustomColumn} when its renderer changes. This
  572. * method is used to maintain hierarchical renderer wrap in
  573. * {@code TreeGrid}.
  574. *
  575. * @param column
  576. * the column which now has a new renderer
  577. *
  578. * @since 8.1
  579. */
  580. public void onColumnRendererChanged(CustomColumn column) {
  581. // NO-OP
  582. }
  583. @Override
  584. public void onUnregister() {
  585. super.onUnregister();
  586. }
  587. @Override
  588. public boolean isWorkPending() {
  589. return getWidget().isWorkPending();
  590. }
  591. @Override
  592. public void layout() {
  593. getWidget().onResize();
  594. }
  595. /**
  596. * Sends sort information from an event to the server-side of the Grid.
  597. *
  598. * @param event
  599. * the sort event
  600. */
  601. private void handleSortEvent(SortEvent<JsonObject> event) {
  602. List<String> columnIds = new ArrayList<>();
  603. List<SortDirection> sortDirections = new ArrayList<>();
  604. for (SortOrder so : event.getOrder()) {
  605. if (columnToIdMap.containsKey(so.getColumn())) {
  606. columnIds.add(columnToIdMap.get(so.getColumn()));
  607. sortDirections.add(so.getDirection());
  608. }
  609. }
  610. String[] colArray = columnIds.toArray(new String[0]);
  611. SortDirection[] dirArray = sortDirections.toArray(new SortDirection[0]);
  612. if (!Arrays.equals(colArray, getState().sortColumns)
  613. || !Arrays.equals(dirArray, getState().sortDirs)) {
  614. // State has actually changed, send to server
  615. getRpcProxy(GridServerRpc.class).sort(colArray, dirArray,
  616. event.isUserOriginated());
  617. }
  618. }
  619. /* HasComponentsConnector */
  620. @Override
  621. public void updateCaption(ComponentConnector connector) {
  622. // Details components don't support captions.
  623. }
  624. @Override
  625. public List<ComponentConnector> getChildComponents() {
  626. if (childComponents == null) {
  627. return Collections.emptyList();
  628. }
  629. return childComponents;
  630. }
  631. @Override
  632. public void setChildComponents(List<ComponentConnector> children) {
  633. childComponents = children;
  634. }
  635. @Override
  636. public HandlerRegistration addConnectorHierarchyChangeHandler(
  637. ConnectorHierarchyChangeHandler handler) {
  638. return ensureHandlerManager()
  639. .addHandler(ConnectorHierarchyChangeEvent.TYPE, handler);
  640. }
  641. @Override
  642. public GridState getState() {
  643. return (GridState) super.getState();
  644. }
  645. @Override
  646. public boolean hasTooltip() {
  647. // Always check for generated descriptions.
  648. return true;
  649. }
  650. @Override
  651. public TooltipInfo getTooltipInfo(Element element) {
  652. CellReference<JsonObject> cell = getWidget().getCellReference(element);
  653. if (cell != null) {
  654. JsonObject row = cell.getRow();
  655. TooltipInfo tooltip = getHeaderFooterTooltip(cell);
  656. if (tooltip != null) {
  657. return tooltip;
  658. }
  659. if (row != null && (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)
  660. || row.hasKey(GridState.JSONKEY_CELLDESCRIPTION))) {
  661. Column<?, JsonObject> column = cell.getColumn();
  662. if (column instanceof CustomColumn) {
  663. JsonObject cellDescriptions = row
  664. .getObject(GridState.JSONKEY_CELLDESCRIPTION);
  665. String id = ((CustomColumn) column).getConnectorId();
  666. if (cellDescriptions != null
  667. && cellDescriptions.hasKey(id)) {
  668. return new TooltipInfo(cellDescriptions.getString(id),
  669. ((CustomColumn) column)
  670. .getTooltipContentMode());
  671. } else if (row.hasKey(GridState.JSONKEY_ROWDESCRIPTION)) {
  672. return new TooltipInfo(
  673. row.getString(GridState.JSONKEY_ROWDESCRIPTION),
  674. getState().rowDescriptionContentMode);
  675. }
  676. }
  677. }
  678. }
  679. if (super.hasTooltip()) {
  680. return super.getTooltipInfo(element);
  681. }
  682. return null;
  683. }
  684. private TooltipInfo getHeaderFooterTooltip(CellReference cell) {
  685. Section section = Section.BODY;
  686. if (cell instanceof EventCellReference) {
  687. // Header or footer
  688. section = ((EventCellReference) cell).getSection();
  689. }
  690. StaticCell staticCell = null;
  691. if (section == Section.HEADER) {
  692. staticCell = getWidget().getHeaderRow(cell.getRowIndex())
  693. .getCell(cell.getColumn());
  694. } else if (section == Section.FOOTER) {
  695. staticCell = getWidget().getFooterRow(cell.getRowIndex())
  696. .getCell(cell.getColumn());
  697. }
  698. if (staticCell != null && staticCell.getDescription() != null) {
  699. return new TooltipInfo(staticCell.getDescription(),
  700. staticCell.getDescriptionContentMode());
  701. }
  702. return null;
  703. }
  704. @Override
  705. protected void sendContextClickEvent(MouseEventDetails details,
  706. EventTarget eventTarget) {
  707. // if element is the resize indicator, ignore the event
  708. if (isResizeHandle(eventTarget)) {
  709. WidgetUtil.clearTextSelection();
  710. return;
  711. }
  712. EventCellReference<JsonObject> eventCell = getWidget().getEventCell();
  713. Section section = eventCell.getSection();
  714. String rowKey = null;
  715. if (eventCell.isBody() && eventCell.getRow() != null) {
  716. rowKey = getRowKey(eventCell.getRow());
  717. }
  718. String columnId = getColumnId(eventCell.getColumn());
  719. getRpcProxy(GridServerRpc.class).contextClick(eventCell.getRowIndex(),
  720. rowKey, columnId, section, details);
  721. WidgetUtil.clearTextSelection();
  722. }
  723. private boolean isResizeHandle(EventTarget eventTarget) {
  724. if (Element.is(eventTarget)) {
  725. Element e = Element.as(eventTarget);
  726. if (e.getClassName().contains("-column-resize-handle")) {
  727. return true;
  728. }
  729. }
  730. return false;
  731. }
  732. private List<String> mapColumnsToIds(List<Column<?, JsonObject>> columns) {
  733. return columns.stream().map(this::getColumnId).filter(Objects::nonNull)
  734. .collect(Collectors.toList());
  735. }
  736. }