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.

GridDragSourceExtensionConnector.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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.List;
  19. import java.util.stream.Collectors;
  20. import com.google.gwt.dom.client.NativeEvent;
  21. import com.google.gwt.dom.client.TableRowElement;
  22. import com.vaadin.client.ServerConnector;
  23. import com.vaadin.client.extensions.DragSourceExtensionConnector;
  24. import com.vaadin.client.widget.escalator.RowContainer;
  25. import com.vaadin.client.widget.grid.selection.SelectionModel;
  26. import com.vaadin.client.widgets.Escalator;
  27. import com.vaadin.client.widgets.Grid;
  28. import com.vaadin.shared.Range;
  29. import com.vaadin.shared.ui.Connect;
  30. import com.vaadin.shared.ui.grid.GridDragSourceExtensionState;
  31. import com.vaadin.ui.GridDragSourceExtension;
  32. import elemental.events.Event;
  33. import elemental.json.Json;
  34. import elemental.json.JsonArray;
  35. import elemental.json.JsonObject;
  36. import elemental.json.JsonValue;
  37. /**
  38. * Adds HTML5 drag and drop functionality to a {@link com.vaadin.client.widgets.Grid
  39. * Grid}'s rows. This is the client side counterpart of {@link
  40. * GridDragSourceExtension}.
  41. *
  42. * @author Vaadin Ltd
  43. * @since
  44. */
  45. @Connect(GridDragSourceExtension.class)
  46. public class GridDragSourceExtensionConnector extends
  47. DragSourceExtensionConnector {
  48. private GridConnector gridConnector;
  49. @Override
  50. protected void extend(ServerConnector target) {
  51. this.gridConnector = (GridConnector) target;
  52. // Set newly added rows draggable
  53. getGridBody().setNewEscalatorRowCallback(
  54. rows -> rows.forEach(this::setDraggable));
  55. // Add drag listeners to body element
  56. addDragListeners(getGridBody().getElement());
  57. }
  58. @Override
  59. protected void onDragStart(Event event) {
  60. super.onDragStart(event);
  61. if (event.getTarget() instanceof TableRowElement) {
  62. TableRowElement row = (TableRowElement) event.getTarget();
  63. int rowIndex = ((Escalator.AbstractRowContainer) getGridBody())
  64. .getLogicalRowIndex(row);
  65. JsonObject rowData = gridConnector.getDataSource().getRow(rowIndex);
  66. // Generate drag data. Dragged row or all the selected rows
  67. JsonValue dragData = dragMultipleRows(rowData) ? toJsonArray(
  68. getSelectedVisibleRows().stream().map(this::getDragData)
  69. .collect(Collectors.toList()))
  70. : getDragData(rowData);
  71. // Set drag data in DataTransfer object
  72. ((NativeEvent) event).getDataTransfer()
  73. .setData(GridDragSourceExtensionState.DATA_TYPE_DRAG_DATA,
  74. dragData.toJson());
  75. }
  76. }
  77. /**
  78. * Tells if multiple rows are dragged. Returns true if multiple selection is
  79. * allowed and a selected row is dragged.
  80. *
  81. * @param draggedRow
  82. * Data of dragged row.
  83. * @return {@code true} if multiple rows are dragged, {@code false}
  84. * otherwise.
  85. */
  86. private boolean dragMultipleRows(JsonObject draggedRow) {
  87. SelectionModel<JsonObject> selectionModel = getGrid()
  88. .getSelectionModel();
  89. return selectionModel.isSelectionAllowed()
  90. && selectionModel instanceof MultiSelectionModelConnector.MultiSelectionModel
  91. && selectionModel.isSelected(draggedRow);
  92. }
  93. /**
  94. * Collects the data of all selected visible rows.
  95. *
  96. * @return List of data of all selected visible rows.
  97. */
  98. private List<JsonObject> getSelectedVisibleRows() {
  99. return getSelectedRowsInRange(getEscalator().getVisibleRowRange());
  100. }
  101. /**
  102. * Get all selected rows from a subset of rows defined by {@code range}.
  103. *
  104. * @param range
  105. * Range of indexes.
  106. * @return List of data of all selected rows in the given range.
  107. */
  108. private List<JsonObject> getSelectedRowsInRange(Range range) {
  109. List<JsonObject> selectedRows = new ArrayList<>();
  110. for (int i = range.getStart(); i < range.getEnd(); i++) {
  111. JsonObject row = gridConnector.getDataSource().getRow(i);
  112. if (SelectionModel.isItemSelected(row)) {
  113. selectedRows.add(row);
  114. }
  115. }
  116. return selectedRows;
  117. }
  118. /**
  119. * Converts a list of {@link JsonObject}s to a {@link JsonArray}.
  120. *
  121. * @param objects
  122. * List of json objects.
  123. * @return Json array containing all json objects.
  124. */
  125. private JsonArray toJsonArray(List<JsonObject> objects) {
  126. JsonArray array = Json.createArray();
  127. for (int i = 0; i < objects.size(); i++) {
  128. array.set(i, objects.get(i));
  129. }
  130. return array;
  131. }
  132. /**
  133. * Gets drag data from the row data if exists or returns complete row data
  134. * otherwise.
  135. *
  136. * @param row
  137. * Row data.
  138. * @return Drag data if present or row data otherwise.
  139. */
  140. private JsonObject getDragData(JsonObject row) {
  141. return row.hasKey(GridDragSourceExtensionState.JSONKEY_DRAG_DATA)
  142. ? row.getObject(GridDragSourceExtensionState.JSONKEY_DRAG_DATA)
  143. : row;
  144. }
  145. @Override
  146. public void onUnregister() {
  147. super.onUnregister();
  148. // Remove draggable from all row elements in the escalator
  149. Range visibleRange = getEscalator().getVisibleRowRange();
  150. for (int i = visibleRange.getStart(); i < visibleRange.getEnd(); i++) {
  151. removeDraggable(getGridBody().getRowElement(i));
  152. }
  153. // Remove drag listeners from body element
  154. removeDragListeners(getGridBody().getElement());
  155. // Remove callback for newly added rows
  156. getGridBody().setNewEscalatorRowCallback(null);
  157. }
  158. private Grid<JsonObject> getGrid() {
  159. return gridConnector.getWidget();
  160. }
  161. private Escalator getEscalator() {
  162. return getGrid().getEscalator();
  163. }
  164. private RowContainer.BodyRowContainer getGridBody() {
  165. return getEscalator().getBody();
  166. }
  167. @Override
  168. public GridDragSourceExtensionState getState() {
  169. return (GridDragSourceExtensionState) super.getState();
  170. }
  171. }