Includes the class in the widgets package build. Change-Id: If72430d3005f7af0029070a72976853baac195a1tags/7.5.0.beta1
@@ -0,0 +1,241 @@ | |||
/* | |||
* Copyright 2000-2014 Vaadin Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||
* use this file except in compliance with the License. You may obtain a copy of | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.client.ui.dd; | |||
import com.google.gwt.dom.client.NativeEvent; | |||
import com.google.gwt.event.dom.client.KeyCodes; | |||
import com.google.gwt.event.shared.HandlerRegistration; | |||
import com.google.gwt.user.client.Event; | |||
import com.google.gwt.user.client.Event.NativePreviewEvent; | |||
import com.google.gwt.user.client.Event.NativePreviewHandler; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.vaadin.client.WidgetUtil; | |||
import com.vaadin.client.widgets.Grid; | |||
/** | |||
* A simple event handler for elements that can be drag and dropped. Properly | |||
* handles drag start, cancel and end. For example, used in {@link Grid} column | |||
* header reordering. | |||
* <p> | |||
* The showing of the dragged element, drag hints and reacting to drop/cancel is | |||
* delegated to {@link DragAndDropCallback} implementation. | |||
* | |||
* @since | |||
* @author Vaadin Ltd | |||
*/ | |||
public class DragAndDropHandler { | |||
/** | |||
* Callback interface for drag and drop. | |||
*/ | |||
public interface DragAndDropCallback { | |||
/** | |||
* Called when the drag has started. The drag can be canceled by | |||
* returning {@code false}. | |||
* | |||
* @param startEvent | |||
* the original event that started the drag | |||
* @return {@code true} if the drag is OK to start, {@code false} to | |||
* cancel | |||
*/ | |||
boolean onDragStart(NativeEvent startEvent); | |||
/** | |||
* Called on drag. | |||
* | |||
* @param event | |||
* the event related to the drag | |||
*/ | |||
void onDragUpdate(NativePreviewEvent event); | |||
/** | |||
* Called after the has ended on a drop or cancel. | |||
*/ | |||
void onDragEnd(); | |||
/** | |||
* Called when the drag has ended on a drop. | |||
*/ | |||
void onDrop(); | |||
/** | |||
* Called when the drag has been canceled. | |||
*/ | |||
void onDragCancel(); | |||
} | |||
private HandlerRegistration dragStartNativePreviewHandlerRegistration; | |||
private HandlerRegistration dragHandlerRegistration; | |||
private boolean dragging; | |||
private DragAndDropCallback callback; | |||
private final NativePreviewHandler dragHandler = new NativePreviewHandler() { | |||
@Override | |||
public void onPreviewNativeEvent(NativePreviewEvent event) { | |||
if (dragging) { | |||
final int typeInt = event.getTypeInt(); | |||
switch (typeInt) { | |||
case Event.ONKEYDOWN: | |||
int keyCode = event.getNativeEvent().getKeyCode(); | |||
if (keyCode == KeyCodes.KEY_ESCAPE) { | |||
// end drag if ESC is hit | |||
cancelDrag(event); | |||
} | |||
break; | |||
case Event.ONMOUSEMOVE: | |||
case Event.ONTOUCHMOVE: | |||
callback.onDragUpdate(event); | |||
// prevent text selection on IE | |||
event.getNativeEvent().preventDefault(); | |||
break; | |||
case Event.ONTOUCHCANCEL: | |||
cancelDrag(event); | |||
break; | |||
case Event.ONTOUCHEND: | |||
/* Avoid simulated event on drag end */ | |||
event.getNativeEvent().preventDefault(); | |||
//$FALL-THROUGH$ | |||
case Event.ONMOUSEUP: | |||
callback.onDragUpdate(event); | |||
callback.onDrop(); | |||
stopDrag(); | |||
event.cancel(); | |||
break; | |||
default: | |||
break; | |||
} | |||
} else { | |||
stopDrag(); | |||
} | |||
} | |||
}; | |||
/** | |||
* This method can be called to trigger drag and drop on any grid element | |||
* that can be dragged and dropped. | |||
* | |||
* @param dragStartingEvent | |||
* the drag triggering event, usually a {@link Event#ONMOUSEDOWN} | |||
* or {@link Event#ONTOUCHSTART} event on the draggable element | |||
* | |||
* @param callback | |||
* the callback that will handle actual drag and drop related | |||
* operations | |||
*/ | |||
public void onDragStartOnDraggableElement( | |||
final NativeEvent dragStartingEvent, | |||
final DragAndDropCallback callback) { | |||
dragStartNativePreviewHandlerRegistration = Event | |||
.addNativePreviewHandler(new NativePreviewHandler() { | |||
private int startX = WidgetUtil | |||
.getTouchOrMouseClientX(dragStartingEvent); | |||
private int startY = WidgetUtil | |||
.getTouchOrMouseClientY(dragStartingEvent); | |||
@Override | |||
public void onPreviewNativeEvent(NativePreviewEvent event) { | |||
final int typeInt = event.getTypeInt(); | |||
if (typeInt == -1 | |||
&& event.getNativeEvent().getType() | |||
.toLowerCase().contains("pointer")) { | |||
/* | |||
* Ignore PointerEvents since IE10 and IE11 send | |||
* also MouseEvents for backwards compatibility. | |||
*/ | |||
return; | |||
} | |||
switch (typeInt) { | |||
case Event.ONMOUSEOVER: | |||
case Event.ONMOUSEOUT: | |||
// we don't care | |||
break; | |||
case Event.ONKEYDOWN: | |||
case Event.ONKEYPRESS: | |||
case Event.ONKEYUP: | |||
case Event.ONBLUR: | |||
case Event.ONFOCUS: | |||
// don't cancel possible drag start | |||
break; | |||
case Event.ONMOUSEMOVE: | |||
case Event.ONTOUCHMOVE: | |||
int currentX = WidgetUtil | |||
.getTouchOrMouseClientX(event | |||
.getNativeEvent()); | |||
int currentY = WidgetUtil | |||
.getTouchOrMouseClientY(event | |||
.getNativeEvent()); | |||
if (Math.abs(startX - currentX) > 3 | |||
|| Math.abs(startY - currentY) > 3) { | |||
removeNativePreviewHandlerRegistration(); | |||
startDrag(dragStartingEvent, event, callback); | |||
} | |||
break; | |||
default: | |||
// on any other events, clean up this preview | |||
// listener | |||
removeNativePreviewHandlerRegistration(); | |||
break; | |||
} | |||
} | |||
}); | |||
} | |||
private void startDrag(NativeEvent startEvent, | |||
NativePreviewEvent triggerEvent, DragAndDropCallback callback) { | |||
if (callback.onDragStart(startEvent)) { | |||
dragging = true; | |||
// just capture something to prevent text selection in IE | |||
Event.setCapture(RootPanel.getBodyElement()); | |||
this.callback = callback; | |||
dragHandlerRegistration = Event | |||
.addNativePreviewHandler(dragHandler); | |||
callback.onDragUpdate(triggerEvent); | |||
} | |||
} | |||
private void stopDrag() { | |||
dragging = false; | |||
if (dragHandlerRegistration != null) { | |||
dragHandlerRegistration.removeHandler(); | |||
dragHandlerRegistration = null; | |||
} | |||
Event.releaseCapture(RootPanel.getBodyElement()); | |||
if (callback != null) { | |||
callback.onDragEnd(); | |||
callback = null; | |||
} | |||
} | |||
private void cancelDrag(NativePreviewEvent event) { | |||
callback.onDragCancel(); | |||
callback.onDragEnd(); | |||
stopDrag(); | |||
event.cancel(); | |||
event.getNativeEvent().preventDefault(); | |||
} | |||
private void removeNativePreviewHandlerRegistration() { | |||
if (dragStartNativePreviewHandlerRegistration != null) { | |||
dragStartNativePreviewHandlerRegistration.removeHandler(); | |||
dragStartNativePreviewHandlerRegistration = null; | |||
} | |||
} | |||
} |
@@ -67,7 +67,6 @@ import com.google.gwt.user.client.ui.FlowPanel; | |||
import com.google.gwt.user.client.ui.HasEnabled; | |||
import com.google.gwt.user.client.ui.HasWidgets; | |||
import com.google.gwt.user.client.ui.ResizeComposite; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.ToggleButton; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.BrowserInfo; | |||
@@ -79,6 +78,7 @@ import com.vaadin.client.renderers.ComplexRenderer; | |||
import com.vaadin.client.renderers.Renderer; | |||
import com.vaadin.client.renderers.WidgetRenderer; | |||
import com.vaadin.client.ui.SubPartAware; | |||
import com.vaadin.client.ui.dd.DragAndDropHandler; | |||
import com.vaadin.client.widget.escalator.Cell; | |||
import com.vaadin.client.widget.escalator.ColumnConfiguration; | |||
import com.vaadin.client.widget.escalator.EscalatorUpdater; | |||
@@ -210,228 +210,6 @@ public class Grid<T> extends ResizeComposite implements | |||
HEADER, BODY, FOOTER | |||
} | |||
/** | |||
* A simple event handler for elements that can be drag and dropped. Loosely | |||
* based on {@link com.vaadin.client.ui.dd.VDragAndDropManager}, but without | |||
* any Vaadin related stuff. Properly handles drag start, cancel and end. | |||
* For example, used in {@link Grid} column header reordering. | |||
* <p> | |||
* The showing of the dragged element, drag hints and reacting to | |||
* drop/cancel is delegated to {@link DragAndDropCallback} implementation. | |||
* | |||
* @author Vaadin Ltd | |||
*/ | |||
private static class DragAndDropHandler { | |||
/** | |||
* Callback interface for drag and drop. | |||
*/ | |||
public interface DragAndDropCallback { | |||
/** | |||
* Called when the drag has started. The drag can be canceled by | |||
* returning {@code false}. | |||
* | |||
* @param startEvent | |||
* the original event that started the drag | |||
* @return {@code true} if the drag is OK to start, {@code false} to | |||
* cancel | |||
*/ | |||
boolean onDragStart(NativeEvent startEvent); | |||
/** | |||
* Called on drag. | |||
* | |||
* @param event | |||
* the event related to the drag | |||
*/ | |||
void onDragUpdate(NativePreviewEvent event); | |||
/** | |||
* Called after the has ended on a drop or cancel. | |||
*/ | |||
void onDragEnd(); | |||
/** | |||
* Called when the drag has ended on a drop. | |||
*/ | |||
void onDrop(); | |||
/** | |||
* Called when the drag has been canceled. | |||
*/ | |||
void onDragCancel(); | |||
} | |||
private HandlerRegistration dragStartNativePreviewHandlerRegistration; | |||
private HandlerRegistration dragHandlerRegistration; | |||
private boolean dragging; | |||
private DragAndDropCallback callback; | |||
private final NativePreviewHandler dragHandler = new NativePreviewHandler() { | |||
@Override | |||
public void onPreviewNativeEvent(NativePreviewEvent event) { | |||
if (dragging) { | |||
final int typeInt = event.getTypeInt(); | |||
switch (typeInt) { | |||
case Event.ONKEYDOWN: | |||
int keyCode = event.getNativeEvent().getKeyCode(); | |||
if (keyCode == KeyCodes.KEY_ESCAPE) { | |||
// end drag if ESC is hit | |||
cancelDrag(event); | |||
} | |||
break; | |||
case Event.ONMOUSEMOVE: | |||
case Event.ONTOUCHMOVE: | |||
callback.onDragUpdate(event); | |||
// prevent text selection on IE | |||
event.getNativeEvent().preventDefault(); | |||
break; | |||
case Event.ONTOUCHCANCEL: | |||
cancelDrag(event); | |||
break; | |||
case Event.ONTOUCHEND: | |||
/* Avoid simulated event on drag end */ | |||
event.getNativeEvent().preventDefault(); | |||
//$FALL-THROUGH$ | |||
case Event.ONMOUSEUP: | |||
callback.onDragUpdate(event); | |||
callback.onDrop(); | |||
stopDrag(); | |||
event.cancel(); | |||
break; | |||
default: | |||
break; | |||
} | |||
} else { | |||
stopDrag(); | |||
} | |||
} | |||
}; | |||
private static Logger getLogger() { | |||
return Logger.getLogger(DragAndDropHandler.class.getName()); | |||
} | |||
/** | |||
* This method can be called to trigger drag and drop on any grid | |||
* element that can be dragged and dropped. | |||
* | |||
* @param dragStartingEvent | |||
* the drag triggering event, usually a | |||
* {@link Event#ONMOUSEDOWN} or {@link Event#ONTOUCHSTART} | |||
* event on the draggable element | |||
* | |||
* @param callback | |||
* the callback that will handle actual drag and drop related | |||
* operations | |||
*/ | |||
public void onDragStartOnDraggableElement( | |||
final NativeEvent dragStartingEvent, | |||
final DragAndDropCallback callback) { | |||
dragStartNativePreviewHandlerRegistration = Event | |||
.addNativePreviewHandler(new NativePreviewHandler() { | |||
private int startX = WidgetUtil | |||
.getTouchOrMouseClientX(dragStartingEvent); | |||
private int startY = WidgetUtil | |||
.getTouchOrMouseClientY(dragStartingEvent); | |||
@Override | |||
public void onPreviewNativeEvent( | |||
NativePreviewEvent event) { | |||
final int typeInt = event.getTypeInt(); | |||
if (typeInt == -1 | |||
&& event.getNativeEvent().getType() | |||
.toLowerCase().contains("pointer")) { | |||
/* | |||
* Ignore PointerEvents since IE10 and IE11 send | |||
* also MouseEvents for backwards compatibility. | |||
*/ | |||
return; | |||
} | |||
switch (typeInt) { | |||
case Event.ONMOUSEOVER: | |||
case Event.ONMOUSEOUT: | |||
// we don't care | |||
break; | |||
case Event.ONKEYDOWN: | |||
case Event.ONKEYPRESS: | |||
case Event.ONKEYUP: | |||
case Event.ONBLUR: | |||
case Event.ONFOCUS: | |||
// don't cancel possible drag start | |||
break; | |||
case Event.ONMOUSEMOVE: | |||
case Event.ONTOUCHMOVE: | |||
int currentX = WidgetUtil | |||
.getTouchOrMouseClientX(event | |||
.getNativeEvent()); | |||
int currentY = WidgetUtil | |||
.getTouchOrMouseClientY(event | |||
.getNativeEvent()); | |||
if (Math.abs(startX - currentX) > 3 | |||
|| Math.abs(startY - currentY) > 3) { | |||
removeNativePreviewHandlerRegistration(); | |||
startDrag(dragStartingEvent, event, | |||
callback); | |||
} | |||
break; | |||
default: | |||
// on any other events, clean up this preview | |||
// listener | |||
removeNativePreviewHandlerRegistration(); | |||
break; | |||
} | |||
} | |||
}); | |||
} | |||
private void startDrag(NativeEvent startEvent, | |||
NativePreviewEvent triggerEvent, DragAndDropCallback callback) { | |||
if (callback.onDragStart(startEvent)) { | |||
dragging = true; | |||
// just capture something to prevent text selection in IE | |||
Event.setCapture(RootPanel.getBodyElement()); | |||
this.callback = callback; | |||
dragHandlerRegistration = Event | |||
.addNativePreviewHandler(dragHandler); | |||
callback.onDragUpdate(triggerEvent); | |||
} | |||
} | |||
private void stopDrag() { | |||
dragging = false; | |||
if (dragHandlerRegistration != null) { | |||
dragHandlerRegistration.removeHandler(); | |||
dragHandlerRegistration = null; | |||
} | |||
Event.releaseCapture(RootPanel.getBodyElement()); | |||
if (callback != null) { | |||
callback.onDragEnd(); | |||
callback = null; | |||
} | |||
} | |||
private void cancelDrag(NativePreviewEvent event) { | |||
callback.onDragCancel(); | |||
callback.onDragEnd(); | |||
stopDrag(); | |||
event.cancel(); | |||
event.getNativeEvent().preventDefault(); | |||
} | |||
private void removeNativePreviewHandlerRegistration() { | |||
if (dragStartNativePreviewHandlerRegistration != null) { | |||
dragStartNativePreviewHandlerRegistration.removeHandler(); | |||
dragStartNativePreviewHandlerRegistration = null; | |||
} | |||
} | |||
} | |||
/** | |||
* Abstract base class for Grid header and footer sections. | |||
* |
@@ -55,6 +55,7 @@ | |||
<include name="com/vaadin/client/renderers/*.java" /> | |||
<include name="com/vaadin/client/ui/SubPartAware.java" /> | |||
<include name="com/vaadin/client/ui/VProgressBar.java" /> | |||
<include name="com/vaadin/client/ui/dd/DragAndDropHandler.java" /> | |||
<include name="com/vaadin/client/VSchedulerImpl.java" /> | |||
<include name="com/vaadin/shared/ui/grid/*.java" /> |