Le « glisser-déposer », ou Drag and Drop, n’est pas géré nativement par GWT. Afin de palier à ce manque, un certains nombres d'implémentations ont été élaborées.
Le choix de Viaxoft s’est porté sur dnd-gwt, et ceux pour deux raisons :

  • Cette API présente l’avantage d’être non invasive, de n’impliquer aucune génération de code annexe.
  • « dnd » permet la réutilisation directe des widgets de GWT et de nos composites.


Cette note survole les grands principes autours desquels s’articule cette librairie.

AbsolutePanel containingPanel = new AbsolutePanel();
containingPanel.setPixelSize(w, h);
containingPanel.getElement().getStyle().setProperty("position","relative");
PickupDragController dragController = new PickupDragController(containingPanel, true);

//Paramétrage du comportement DnD
//On interdit les selections mulitples et aux Widgets draggables d'être déposés hors des drop zones
dragController.setBehaviorBoundaryPanelDrop(false);
dragController.setBehaviorMultipleSelection(false);


Une fois un DragController défini, n’importe quel widget implémentant SourcesMouseEvents peut être transformé en élément « draggable ». On pourrait donc penser être limité aux Image, Label et FocusPanel. Cependant tout composite implémentant l’interface est lui-même éligible. Le DragController permet notamment de distinguer un composite dans son ensemble de sa partie réalisant le Drag & Drop.

class TextAndPicto extends Composite implements SourcesMouseEvents{
  TextField text;
  Image picto;
  public LabelAndPicto(TextField text, Image picto)
  {
   this.text = text;
   this.picto=picto;
   HorizontalPanel mainPanel = new HorizontalPanel();
   mainPanel.add(picto);
    mainPanel.add(text);
   initWidget(mainPanel);
  }

  public void addMouseListener(MouseListener listener) {
   picto.addMouseListener(listener);

  }

  public void removeMouseListener(MouseListener listener) {
   picto.removeMouseListener(listener);
...

   TextAndPicto w = new TextAndPicto(new TextBox(), new Image("pictoViaxeo/clients.gif"));
   dragController.makeDraggable(w,w.getImage());


Enfin le DropController permet de définir le comportement des widgets sur lesquels pourront être déposés les éléments « draggables ». Le constructeur prend en paramètre le widget qui servira de « drop zone », et les 4 méthodes suivantes sont définies par l’interface afin de gérer son comportement : onEnter, onLeave, onDrop et onPreviewDrop. Les deux premières sont appelées lorsqu’un item est « dragué » au dessus de la drop zone. La troisième détermine les actions à prendre consécutivement à la dépose du dit item. Et enfin, onPreviewDrop permet d’effectuer des contrôles préalables avant l’exécution d’onDrop.

 public class DropZoneListener extends SimpleDropController {
  private VerticalPanel panel;

  public DropZoneListener(Widget dropTarget) {
   super(dropTarget);
   panel = (VerticalPanel)dropTarget;
  }

  public void onDrop(DragContext context) {
   super.onDrop(context);
   for(SmartWidget smartWidget : (List)context.selectedWidgets)
    panel.add(smartWidget);
   }

  public void onEnter(DragContext context) {
   super.onEnter(context);
   panel.addStyleName("viaxeo-DnD-Liste-Header-seleted");
   }

  public void onLeave(DragContext context) {
   super.onLeave(context);
   panel.removeStyleName("viaxeo-DnD-Liste-Header-seleted");
   }

  public void onPreviewDrop(DragContext context) throws VetoDragException {
   super.onPreviewDrop(context);
   }

}


Dnd-gwt propose un large panel de DropController allant du GridConstrainedDropController (gestion du drop par grilles) au FlexTableRowDropController (ajout/suppression dynamique de lignes dans une FlexTable).