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.

GridDropTargetConnector.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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.Objects;
  18. import java.util.Optional;
  19. import com.google.gwt.dom.client.Element;
  20. import com.google.gwt.dom.client.NativeEvent;
  21. import com.google.gwt.dom.client.TableRowElement;
  22. import com.google.gwt.user.client.Window;
  23. import com.vaadin.client.ServerConnector;
  24. import com.vaadin.client.WidgetUtil;
  25. import com.vaadin.client.extensions.DropTargetExtensionConnector;
  26. import com.vaadin.client.widget.escalator.RowContainer;
  27. import com.vaadin.client.widgets.Escalator;
  28. import com.vaadin.shared.ui.Connect;
  29. import com.vaadin.shared.ui.grid.DropLocation;
  30. import com.vaadin.shared.ui.grid.DropMode;
  31. import com.vaadin.shared.ui.grid.GridDropTargetRpc;
  32. import com.vaadin.shared.ui.grid.GridDropTargetState;
  33. import com.vaadin.shared.ui.grid.GridState;
  34. import com.vaadin.ui.GridDropTarget;
  35. import elemental.events.Event;
  36. import elemental.json.JsonObject;
  37. /**
  38. * Makes Grid an HTML5 drop target. This is the client side counterpart of
  39. * {@link GridDropTarget}.
  40. *
  41. * @author Vaadin Ltd
  42. * @since
  43. */
  44. @Connect(GridDropTarget.class)
  45. public class GridDropTargetConnector extends
  46. DropTargetExtensionConnector {
  47. /**
  48. * Current style name
  49. */
  50. private String currentStyleName;
  51. private GridConnector gridConnector;
  52. /**
  53. * Class name to apply when an element is dragged over a row and the
  54. * location is {@link DropLocation#ON_TOP}.
  55. */
  56. private String styleDragCenter;
  57. /**
  58. * Class name to apply when an element is dragged over a row and the
  59. * location is {@link DropLocation#ABOVE}.
  60. */
  61. private String styleDragTop;
  62. /**
  63. * Class name to apply when an element is dragged over a row and the
  64. * location is {@link DropLocation#BELOW}.
  65. */
  66. private String styleDragBottom;
  67. @Override
  68. protected void extend(ServerConnector target) {
  69. gridConnector = (GridConnector) target;
  70. super.extend(target);
  71. }
  72. @Override
  73. protected void sendDropEventToServer(String dataTransferText,
  74. Event dropEvent) {
  75. String rowKey = null;
  76. DropLocation dropLocation = null;
  77. Optional<TableRowElement> targetRow = getTargetRow(
  78. (Element) dropEvent.getTarget());
  79. if (targetRow.isPresent()) {
  80. rowKey = getRowData(targetRow.get())
  81. .getString(GridState.JSONKEY_ROWKEY);
  82. dropLocation = getDropLocation(targetRow.get(),
  83. (NativeEvent) dropEvent);
  84. }
  85. getRpcProxy(GridDropTargetRpc.class)
  86. .drop(dataTransferText, rowKey, dropLocation);
  87. }
  88. private JsonObject getRowData(TableRowElement row) {
  89. int rowIndex = ((Escalator.AbstractRowContainer) getGridBody())
  90. .getLogicalRowIndex(row);
  91. return gridConnector.getDataSource().getRow(rowIndex);
  92. }
  93. /**
  94. * Returns the location of the event within the row.
  95. */
  96. private DropLocation getDropLocation(Element target, NativeEvent event) {
  97. if (getState().dropMode == DropMode.BETWEEN) {
  98. if (getRelativeY(target, event) < (target.getOffsetHeight() / 2)) {
  99. return DropLocation.ABOVE;
  100. } else {
  101. return DropLocation.BELOW;
  102. }
  103. }
  104. return DropLocation.ON_TOP;
  105. }
  106. private int getRelativeY(Element element, NativeEvent event) {
  107. int relativeTop = element.getAbsoluteTop() - Window.getScrollTop();
  108. return WidgetUtil.getTouchOrMouseClientY(event) - relativeTop;
  109. }
  110. @Override
  111. protected void onDragEnter(Event event) {
  112. // Generate style names for the drop target
  113. String styleRow =
  114. gridConnector.getWidget().getStylePrimaryName() + "-row";
  115. styleDragCenter = styleRow + STYLE_SUFFIX_DRAG_CENTER;
  116. styleDragTop = styleRow + STYLE_SUFFIX_DRAG_TOP;
  117. styleDragBottom = styleRow + STYLE_SUFFIX_DRAG_BOTTOM;
  118. super.onDragEnter(event);
  119. }
  120. @Override
  121. protected void setTargetIndicator(Event event) {
  122. getTargetRow(((Element) event.getTarget())).ifPresent(target -> {
  123. // Get required class name
  124. String className = getTargetClassName(target, (NativeEvent) event);
  125. // Add or replace class name if changed
  126. if (!target.hasClassName(className)) {
  127. if (currentStyleName != null) {
  128. target.removeClassName(currentStyleName);
  129. }
  130. target.addClassName(className);
  131. currentStyleName = className;
  132. }
  133. });
  134. }
  135. private String getTargetClassName(Element target, NativeEvent event) {
  136. String className;
  137. switch (getDropLocation(target, event)) {
  138. case ABOVE:
  139. className = styleDragTop;
  140. break;
  141. case BELOW:
  142. className = styleDragBottom;
  143. break;
  144. case ON_TOP:
  145. default:
  146. className = styleDragCenter;
  147. break;
  148. }
  149. return className;
  150. }
  151. @Override
  152. protected void removeTargetIndicator(Event event) {
  153. // Remove all possible style names
  154. getTargetRow((Element) event.getTarget()).ifPresent(e -> {
  155. e.removeClassName(styleDragCenter);
  156. e.removeClassName(styleDragTop);
  157. e.removeClassName(styleDragBottom);
  158. });
  159. }
  160. private Optional<TableRowElement> getTargetRow(Element source) {
  161. while (!Objects.equals(source, getGridBody().getElement())) {
  162. if (TableRowElement.is(source)) {
  163. return Optional.of(source.cast());
  164. }
  165. source = source.getParentElement();
  166. }
  167. return Optional.empty();
  168. }
  169. @Override
  170. protected Element getDropTargetElement() {
  171. return getGridBody().getElement();
  172. }
  173. private Escalator getEscalator() {
  174. return gridConnector.getWidget().getEscalator();
  175. }
  176. private RowContainer.BodyRowContainer getGridBody() {
  177. return getEscalator().getBody();
  178. }
  179. @Override
  180. public GridDropTargetState getState() {
  181. return (GridDropTargetState) super.getState();
  182. }
  183. }