package fr.lteconsulting.hexa.client.ui.miracle;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
public class DragDrop
{
public interface Callback<T>
{
String getGhostInnerHTML( T cookie, Element source );
void onDragDropFinished( T cookie, Element source, Element destination );
}
private static class CaptureWidget extends FocusPanel implements MouseMoveHandler, MouseUpHandler
{
int startX = -1;
int startY = -1;
Ghost<?> ghost = null;
boolean fDragging = false;
public CaptureWidget()
{
addMouseMoveHandler( this );
addMouseUpHandler( this );
Style style = getElement().getStyle();
// workaround for IE8 opacity
// http://code.google.com/p/google-web-toolkit/issues/detail?id=5538
style.setProperty( "filter", "alpha(opacity=0)" );
style.setOpacity( 0 );
style.setZIndex( 0 );// 1000);
style.setMargin( 0, Style.Unit.PX );
style.setBorderStyle( BorderStyle.NONE );
style.setBackgroundColor( "blue" );
setPixelSize( RootPanel.get().getOffsetWidth(), RootPanel.get().getOffsetHeight() );
}
void start( int x, int y, Ghost<?> ghost )
{
startX = x;
startY = y;
this.ghost = ghost;
fDragging = false;
DOM.setCapture( getElement() );
}
@Override
public void onMouseUp( MouseUpEvent event )
{
DOM.releaseCapture( getElement() );
RootPanel.get().remove( this );
if( fDragging )
{
RootPanel.get().remove( ghost );
event.preventDefault();
event.stopPropagation();
Element target = DOM.eventGetTarget( DOM.eventGetCurrentEvent() );
ghost.signalFinish( target );
}
else
{
}
}
@Override
public void onMouseMove( MouseMoveEvent event )
{
// move the ghost
int x = event.getClientX();
int y = event.getClientY();
if( fDragging )
{
ghost.getElement().getStyle().clearDisplay();
// instead of ghost.w/2
int w = ghost.getElement().getClientWidth();
int h = ghost.getElement().getClientHeight();
ghost.getElement().getStyle().setLeft( x - w / 2, Unit.PX );
ghost.getElement().getStyle().setTop( y - h / 2, Unit.PX );
}
else
{
int d = x - startX;
d = d * d;
int d2 = y - startY;
d = d + d2 * d2;
if( d > 25 )
{
ghost.updateInnerHTML();
int w = ghost.getElement().getClientWidth();
int h = ghost.getElement().getClientHeight();
ghost.getElement().getStyle().setDisplay( Display.NONE );
fDragging = true;
RootPanel.get().add( ghost, x - w / 2, y - h / 2 );
}
}
}
}
private static class Ghost<T> extends Widget
{
Element source;
Callback<T> callback;
T cookie;
public Ghost( int x, int y, int w, int h, Element source, Callback<T> callback, T cookie )
{
this.source = source;
this.callback = callback;
this.cookie = cookie;
Element ghost = DOM.createDiv();
Style style = ghost.getStyle();
style.setPosition( Position.FIXED );
style.setLeft( x, Unit.PX );
style.setTop( y, Unit.PX );
// style.setWidth( w, Unit.PX );
// style.setHeight( h, Unit.PX );
// style.setBackgroundColor( "rgba(200,200,200,0.5)" );
style.setProperty( "pointerEvents", "none" );
setElement( ghost );
}
void updateInnerHTML()
{
String html = callback.getGhostInnerHTML( cookie, source );
if( html == null )
getElement().setInnerHTML( source.getString() );
else
getElement().setInnerHTML( html );
}
void signalFinish( Element destination )
{
if( source == destination )
return;
callback.onDragDropFinished( cookie, source, destination );
}
}
public static <T> void initiate( Element element, Callback<T> callback, T cookie, Event event )
{
int x = event.getClientX();
int y = event.getClientY();
int w = element.getClientWidth();
int h = element.getClientHeight();
CaptureWidget captureWidget = new CaptureWidget();
Ghost<T> ghost = new Ghost<T>( x, y, w, h, element, callback, cookie );
// append the ghost to the body of the document
RootPanel.get().add( captureWidget );
// capture the mouse on the captureWidget and update the ghost position
captureWidget.start( x, y, ghost );
event.preventDefault();
event.stopPropagation();
}
}