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

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