/* @VaadinApache2LicenseForJavaFiles@ */ package com.vaadin.terminal.gwt.server; import java.io.PrintWriter; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.logging.Logger; import com.vaadin.event.Transferable; import com.vaadin.event.TransferableImpl; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DragSource; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.TargetDetails; import com.vaadin.event.dd.TargetDetailsImpl; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.ui.dd.DragEventType; import com.vaadin.terminal.Extension; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.VariableOwner; import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; import com.vaadin.ui.Component; import com.vaadin.ui.Root; public class DragAndDropService implements VariableOwner, ClientConnector { private int lastVisitId; private boolean lastVisitAccepted = false; private DragAndDropEvent dragEvent; private final AbstractCommunicationManager manager; private AcceptCriterion acceptCriterion; public DragAndDropService(AbstractCommunicationManager manager) { this.manager = manager; } @Override public void changeVariables(Object source, Map variables) { Object owner = variables.get("dhowner"); // Validate drop handler owner if (!(owner instanceof DropTarget)) { getLogger() .severe("DropHandler owner " + owner + " must implement DropTarget"); return; } // owner cannot be null here DropTarget dropTarget = (DropTarget) owner; lastVisitId = (Integer) variables.get("visitId"); // request may be dropRequest or request during drag operation (commonly // dragover or dragenter) boolean dropRequest = isDropRequest(variables); if (dropRequest) { handleDropRequest(dropTarget, variables); } else { handleDragRequest(dropTarget, variables); } } /** * Handles a drop request from the VDragAndDropManager. * * @param dropTarget * @param variables */ private void handleDropRequest(DropTarget dropTarget, Map variables) { DropHandler dropHandler = (dropTarget).getDropHandler(); if (dropHandler == null) { // No dropHandler returned so no drop can be performed. getLogger().fine( "DropTarget.getDropHandler() returned null for owner: " + dropTarget); return; } /* * Construct the Transferable and the DragDropDetails for the drop * operation based on the info passed from the client widgets (drag * source for Transferable, drop target for DragDropDetails). */ Transferable transferable = constructTransferable(dropTarget, variables); TargetDetails dropData = constructDragDropDetails(dropTarget, variables); DragAndDropEvent dropEvent = new DragAndDropEvent(transferable, dropData); if (dropHandler.getAcceptCriterion().accept(dropEvent)) { dropHandler.drop(dropEvent); } } /** * Handles a drag/move request from the VDragAndDropManager. * * @param dropTarget * @param variables */ private void handleDragRequest(DropTarget dropTarget, Map variables) { lastVisitId = (Integer) variables.get("visitId"); acceptCriterion = dropTarget.getDropHandler().getAcceptCriterion(); /* * Construct the Transferable and the DragDropDetails for the drag * operation based on the info passed from the client widgets (drag * source for Transferable, current target for DragDropDetails). */ Transferable transferable = constructTransferable(dropTarget, variables); TargetDetails dragDropDetails = constructDragDropDetails(dropTarget, variables); dragEvent = new DragAndDropEvent(transferable, dragDropDetails); lastVisitAccepted = acceptCriterion.accept(dragEvent); } /** * Construct DragDropDetails based on variables from client drop target. * Uses DragDropDetailsTranslator if available, otherwise a default * DragDropDetails implementation is used. * * @param dropTarget * @param variables * @return */ @SuppressWarnings("unchecked") private TargetDetails constructDragDropDetails(DropTarget dropTarget, Map variables) { Map rawDragDropDetails = (Map) variables .get("evt"); TargetDetails dropData = dropTarget .translateDropTargetDetails(rawDragDropDetails); if (dropData == null) { // Create a default DragDropDetails with all the raw variables dropData = new TargetDetailsImpl(rawDragDropDetails, dropTarget); } return dropData; } private boolean isDropRequest(Map variables) { return getRequestType(variables) == DragEventType.DROP; } private DragEventType getRequestType(Map variables) { int type = (Integer) variables.get("type"); return DragEventType.values()[type]; } @SuppressWarnings("unchecked") private Transferable constructTransferable(DropTarget dropHandlerOwner, Map variables) { final Component sourceComponent = (Component) variables .get("component"); variables = (Map) variables.get("tra"); Transferable transferable = null; if (sourceComponent != null && sourceComponent instanceof DragSource) { transferable = ((DragSource) sourceComponent) .getTransferable(variables); } if (transferable == null) { transferable = new TransferableImpl(sourceComponent, variables); } return transferable; } @Override public boolean isEnabled() { return isConnectorEnabled(); } @Override public boolean isImmediate() { return true; } void printJSONResponse(PrintWriter outWriter) throws PaintException { if (isDirty()) { outWriter.print(", \"dd\":"); JsonPaintTarget jsonPaintTarget = new JsonPaintTarget(manager, outWriter, false); jsonPaintTarget.startTag("dd"); jsonPaintTarget.addAttribute("visitId", lastVisitId); if (acceptCriterion != null) { jsonPaintTarget.addAttribute("accepted", lastVisitAccepted); acceptCriterion.paintResponse(jsonPaintTarget); } jsonPaintTarget.endTag("dd"); jsonPaintTarget.close(); lastVisitId = -1; lastVisitAccepted = false; acceptCriterion = null; dragEvent = null; } } private boolean isDirty() { if (lastVisitId > 0) { return true; } return false; } @Override public SharedState getState() { // TODO Auto-generated method stub return null; } @Override public String getConnectorId() { return VDragAndDropManager.DD_SERVICE; } @Override public boolean isConnectorEnabled() { // Drag'n'drop can't be disabled return true; } @Override public List retrievePendingRpcCalls() { return null; } @Override public RpcManager getRpcManager(Class rpcInterface) { // TODO Use rpc for drag'n'drop return null; } @Override public Class getStateType() { return SharedState.class; } @Override public void requestRepaint() { // TODO Auto-generated method stub } @Override public ClientConnector getParent() { // TODO Auto-generated method stub return null; } @Override public void requestRepaintAll() { // TODO Auto-generated method stub } @Override public void setParent(ClientConnector parent) { // TODO Auto-generated method stub } @Override public void attach() { // TODO Auto-generated method stub } @Override public void detach() { // TODO Auto-generated method stub } @Override public Collection getExtensions() { // TODO Auto-generated method stub return Collections.emptySet(); } @Override public void removeExtension(Extension extension) { // TODO Auto-generated method stub } private Logger getLogger() { return Logger.getLogger(DragAndDropService.class.getName()); } @Override public Root getRoot() { return null; } }