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.

VDragEvent.java 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright 2000-2013 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.ui.dd;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import com.google.gwt.dom.client.Document;
  20. import com.google.gwt.dom.client.NativeEvent;
  21. import com.google.gwt.dom.client.Node;
  22. import com.google.gwt.dom.client.Style.Unit;
  23. import com.google.gwt.dom.client.TableElement;
  24. import com.google.gwt.dom.client.TableSectionElement;
  25. import com.google.gwt.event.dom.client.MouseOverEvent;
  26. import com.google.gwt.user.client.Element;
  27. import com.google.gwt.user.client.Event;
  28. import com.google.gwt.user.client.EventListener;
  29. import com.vaadin.client.BrowserInfo;
  30. import com.vaadin.client.Util;
  31. /**
  32. * DragEvent used by Vaadin client side engine. Supports components, items,
  33. * properties and custom payload (HTML5 style).
  34. *
  35. *
  36. */
  37. public class VDragEvent {
  38. private static final int DEFAULT_OFFSET = 10;
  39. private static int eventId = 0;
  40. private VTransferable transferable;
  41. private NativeEvent currentGwtEvent;
  42. private NativeEvent startEvent;
  43. private int id;
  44. private HashMap<String, Object> dropDetails = new HashMap<String, Object>();
  45. private Element elementOver;
  46. VDragEvent(VTransferable t, NativeEvent startEvent) {
  47. transferable = t;
  48. this.startEvent = startEvent;
  49. id = eventId++;
  50. }
  51. public VTransferable getTransferable() {
  52. return transferable;
  53. }
  54. /**
  55. * Returns the the latest {@link NativeEvent} that relates to this drag and
  56. * drop operation. For example on {@link VDropHandler#dragEnter(VDragEvent)}
  57. * this is commonly a {@link MouseOverEvent}.
  58. *
  59. * @return
  60. */
  61. public NativeEvent getCurrentGwtEvent() {
  62. return currentGwtEvent;
  63. }
  64. public void setCurrentGwtEvent(NativeEvent event) {
  65. currentGwtEvent = event;
  66. }
  67. int getEventId() {
  68. return id;
  69. }
  70. /**
  71. * Detecting the element on which the the event is happening may be
  72. * problematic during drag and drop operation. This is especially the case
  73. * if a drag image (often called also drag proxy) is kept under the mouse
  74. * cursor (see {@link #createDragImage(Element, boolean)}. Drag and drop
  75. * event handlers (like the one provided by {@link VDragAndDropManager} )
  76. * should set elmentOver field to reflect the the actual element on which
  77. * the pointer currently is (drag image excluded). {@link VDropHandler}s can
  78. * then more easily react properly on drag events by reading the element via
  79. * this method.
  80. *
  81. * @return the element in {@link VDropHandler} on which mouse cursor is on
  82. */
  83. public Element getElementOver() {
  84. if (elementOver != null) {
  85. return elementOver;
  86. } else if (currentGwtEvent != null) {
  87. return currentGwtEvent.getEventTarget().cast();
  88. }
  89. return null;
  90. }
  91. public void setElementOver(Element targetElement) {
  92. elementOver = targetElement;
  93. }
  94. /**
  95. * Sets the drag image used for current drag and drop operation. Drag image
  96. * is displayed next to mouse cursor during drag and drop.
  97. * <p>
  98. * The element to be used as drag image will automatically get CSS style
  99. * name "v-drag-element".
  100. *
  101. * TODO decide if this method should be here or in {@link VTransferable} (in
  102. * HTML5 it is in DataTransfer) or {@link VDragAndDropManager}
  103. *
  104. * TODO should be possible to override behavior. Like to proxy the element
  105. * to HTML5 DataTransfer
  106. *
  107. * @param node
  108. */
  109. public void setDragImage(Element node) {
  110. setDragImage(node, DEFAULT_OFFSET, DEFAULT_OFFSET);
  111. }
  112. /**
  113. * TODO consider using similar smaller (than map) api as in Transferable
  114. *
  115. * TODO clean up when drop handler changes
  116. *
  117. * @return
  118. */
  119. public Map<String, Object> getDropDetails() {
  120. return dropDetails;
  121. }
  122. /**
  123. * Sets the drag image used for current drag and drop operation. Drag image
  124. * is displayed next to mouse cursor during drag and drop.
  125. * <p>
  126. * The element to be used as drag image will automatically get CSS style
  127. * name "v-drag-element".
  128. *
  129. * @param element
  130. * the dom element to be positioned next to mouse cursor
  131. * @param offsetX
  132. * the horizontal offset of drag image from mouse cursor
  133. * @param offsetY
  134. * the vertical offset of drag image from mouse cursor
  135. */
  136. public void setDragImage(Element element, int offsetX, int offsetY) {
  137. element.getStyle().setMarginLeft(offsetX, Unit.PX);
  138. element.getStyle().setMarginTop(offsetY, Unit.PX);
  139. VDragAndDropManager.get().setDragElement(element);
  140. }
  141. /**
  142. * @return the current Element used as a drag image (aka drag proxy) or null
  143. * if drag image is not currently set for this drag operation.
  144. */
  145. public Element getDragImage() {
  146. return (Element) VDragAndDropManager.get().getDragElement();
  147. }
  148. /**
  149. * Automatically tries to create a proxy image from given element.
  150. *
  151. * @param element
  152. * @param alignImageToEvent
  153. * if true, proxy image is aligned to start event, else next to
  154. * mouse cursor
  155. */
  156. public void createDragImage(Element element, boolean alignImageToEvent) {
  157. Element cloneNode = (Element) element.cloneNode(true);
  158. if (BrowserInfo.get().isIE()) {
  159. if (cloneNode.getTagName().toLowerCase().equals("tr")) {
  160. TableElement table = Document.get().createTableElement();
  161. TableSectionElement tbody = Document.get().createTBodyElement();
  162. table.appendChild(tbody);
  163. tbody.appendChild(cloneNode);
  164. cloneNode = table.cast();
  165. }
  166. }
  167. syncContent(element, cloneNode);
  168. if (alignImageToEvent) {
  169. int absoluteTop = element.getAbsoluteTop();
  170. int absoluteLeft = element.getAbsoluteLeft();
  171. int clientX = Util.getTouchOrMouseClientX(startEvent);
  172. int clientY = Util.getTouchOrMouseClientY(startEvent);
  173. int offsetX = absoluteLeft - clientX;
  174. int offsetY = absoluteTop - clientY;
  175. setDragImage(cloneNode, offsetX, offsetY);
  176. } else {
  177. setDragImage(cloneNode);
  178. }
  179. }
  180. /**
  181. * Do additional content sync between <code>original</code> element and its
  182. * <code>copy</code> if needed.
  183. *
  184. * @since 7.1
  185. * @param original
  186. * original element
  187. * @param copy
  188. * copy of original element
  189. */
  190. protected void syncContent(Element original, Element copy) {
  191. for (int i = 0; i < original.getChildCount(); i++) {
  192. Node child = original.getChild(i);
  193. if (child instanceof Element) {
  194. syncContent((Element) child, (Element) copy.getChild(i));
  195. }
  196. }
  197. doSyncContent(original, copy);
  198. }
  199. private void doSyncContent(Element original, Element copy) {
  200. EventListener eventListener = Event.getEventListener(original);
  201. if (eventListener instanceof VDragCloneAware) {
  202. ((VDragCloneAware) eventListener).initDragImageCopy(copy);
  203. }
  204. }
  205. }