My favorites | Sign in
Project Logo
                
Search
for
Updated Today (15 hours ago) by fredsa
Labels: Featured
GettingStarted  
Getting started with gwt-dnd in your own application.

GWT Version Compatibility Matrix

If you are using GWT version... Then use gwt-dnd version... Which uses gwt-dnd API version...
GWT 1.6.4 gwt-dnd-2.6.5.jar 2.x
GWT 1.5.3 gwt-dnd-2.5.6.jar 2.x
GWT 1.5.2 gwt-dnd-2.5.6.jar 2.x
GWT 1.5.1 (1.5 RC2) gwt-dnd-2.5.6.jar 2.x
GWT 1.5.0 (1.5 RC1) gwt-dnd-2.5.6.jar 2.x
GWT 1.5M2 (1.5 Milestone 2) Do not use GWT1.5M2 as it does not work with gwt-dnd.
GWT 1.4.62 (1.4 Update 2) gwt-dnd-2.0.7.jar 2.x
GWT 1.4.61 (1.4 Update) gwt-dnd-2.0.7.jar 2.x
GWT 1.4.60 (1.4) gwt-dnd-2.0.7.jar 2.x
GWT 1.4.59 (1.4 RC2) gwt-dragdrop-1.2.6.jar 1.x API (deprecated)
GWT 1.4.10 (1.4 RC1) gwt-dragdrop-1.1.jar 1.x API (deprecated)
GWT 1.3.3 gwt1.3.3-dragdrop-2007-11-02.jar 0.x API (deprecated)

† Existing projects may continue to use the gwt-dnd 1.x API, while new projects should always start with the gwt-dnd 2.x API

‡ If you can, please upgrade to the latest GWT and gwt-dnd releases

Important GWT Bugs/Issues

GWT version GWT Issue Related gwt-dnd issue Comments
SVN trunk - - -
1.4 GWT issue 1583 Arrays.sort(Object[]) and Collections.sort(Object[]) are not stable gwt-dnd issue 19 Problem with overlapping drop targets in web mode When a draggable widget is dropped in an area where multiple drop targets (partially) overlap, the drop target that is selected is determined by the order in which the drop controllers were originally registered in hosted mode, but may be inconsistent in web mode.
1.3.3 (multiple) - See the 'Minor Issues to Consider for GWT 1.3.3' section in Getting Started with 1.x wiki.
- - gwt-dnd issue 26 There are multiple reports of IE6 crashing when images are being dragged, either directly, or part of another panel. It appears that image bundles, or at least large images or bundles are a factor. Try dragging smaller (or unbundled) images if you see problems in IE6. And, please report general findings on the gwt-dnd group, and any specific information on gwt-dnd issue 26.
- GWT issue 1953 - Beware of absolute panels attached to absolute panels.
- GWT Issue 1813 - RootPanel.get(id) fails to set 'position:relative' and 'overflow:hidden'

Adding gwt-dnd to an (Eclipse) GWT Project

  1. Download the latest gwt-dnd-<version>.jar and place it in a convenient location.
  2. (Optional) if you want to play with the demo (examples), you'll need to grab those from the Subversion trunk demo directory as there is no jar file for the demos (i.e. the com.allen_sauer.gwt.dnd.demo package). See the Using Source with Eclipse wiki for more details.
  3. Create a GWT Eclipse project as instructed here: http://code.google.com/webtoolkit/gettingstarted.html#NewEclipse
  4. mkdir MyProject
    cd MyProject
    projectCreator -eclipse MyProject
    applicationCreator -eclipse MyProject com.mycompany.client.MyApplication
  5. Import your new project via 'File > Import > Existing Project into Workspace'. Specify the MyProject directory you created in a previous step.
  6. Right-click on the project node in the Package Explorer and select 'Build Path > Add External Archives...'. Specify the downloaded gwt-dnd-<version>.jar.
  7. To ensure that the GWT command line scripts to continue to work, modify the -cp parameter value in both MyApplication-shell and MyApplication-compile to include the path to downloaded gwt-dnd-<version>.jar. You can add it just before the path to gwt-user.jar. Don't forget the path separator ';' or ':', depending on your platform.
  8. Make sure the GWT compiler can find the gwt-dnd source code. Modify MyProject/src/com/mycompany/MyApplication.gwt.xml to include these lines:
  9. 	<!-- Inherit gwt-dnd support                   -->
    	<inherits name='com.allen_sauer.gwt.dnd.gwt-dnd'/>

Tips

  1. While the Eclipse IDE is not strictly necessary, having a good IDE such as Eclispe will make your life a lot easier. Certainly feel free to use your IDE of choice.
  2. Consider developing in standards mode rather than quirks mode. See http://code.google.com/support/bin/answer.py?hl=en&answer=75723. To compare options, start here: http://www.quirksmode.org/css/quirksmode.html.
  3. If using standards mode, and the body (i.e. RootPanel.get()) is going to be your boundary panel, you'll want to ensure that the body actually has height; with only absolute positioned content, the height remains 0px. Usually setting 100% height on the HTML and BODY elements does the trick.
  4.   HTML, BODY {
        height: 100%;
      }
  5. Make sure you use an UncaughtExceptionHandler so that unexpected exceptions are not lost in web mode; see the example below on how to do this so that initialization exceptions do not prevent hosted mode from launching
  6. Realize that hosted mode is slower than (compiled-to-JavaScript) web mode. So, if things feels sluggish, try web mode to reassure yourself that your application will be fine.
  7. Be careful when adding a ClickListener directly to your draggable widget (or its drag handle):
    • In IE the listener will only file if drag sensitivity > 0
    • In Firefox the listener will always fire when the mouse is clicked, even at the the end of drag operation

How to add drag-and-drop functionality to your project

  1. Construct a PickupDragController, passing in two arguments:
  2. For each drop target within the boundary panel:
  3. For each widget which is to be draggable:

A simple example (Your first drag-n-drop project)

  1. Follow the instructions above to create an Eclipse project with gwt-dnd support
  2. Modify the onModuleLoad() method in your EntryPoint class as follows:
  3.   public void onModuleLoad() {
        // ensure the document BODY has dimensions in standards mode
        RootPanel.get().setPixelSize(600, 600);
    
        // workaround for GWT issue 1813
        // http://code.google.com/p/google-web-toolkit/issues/detail?id=1813
        RootPanel.get().getElement().getStyle().setProperty("position" , "relative");
    
        // create a DragController to manage drag-n-drop actions
        // note: This creates an implicit DropController for the boundary panel
        PickupDragController dragController = new PickupDragController(RootPanel.get(), true);
    
        // add a new image to the boundary panel and make it draggable
        Image img = new Image("http://code.google.com/webtoolkit/logo-185x175.png");
        RootPanel.get().add(img, 40, 30);
        dragController.makeDraggable(img);
      }

That's it, you're done.

Another, more complicated example (Your second drag-n-drop project)

  1. Again, follow the instructions above to create an Eclipse project with gwt-dnd support
  2. Add this CSS to the HTML or CSS file in your project:
  3. @CHARSET "UTF-8";
    
    .dragdrop-dropTarget-engage {
      background-color: #E0E8FF;
    }
    
    .getting-started-label {
      border: 1px solid #99AACC;
      background-color: #AACCFF;
      padding: 0.1em;
    }
    
    .getting-started-blue {
      border: 1px solid blue;
    }
  4. Use this code in your EntryPoint class:
  5. /*
     * Copyright 2007 Fred Sauer
     * 
     * 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.mycompany.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.google.gwt.user.client.Command;
    import com.google.gwt.user.client.DOM;
    import com.google.gwt.user.client.DeferredCommand;
    import com.google.gwt.user.client.Random;
    import com.google.gwt.user.client.ui.AbsolutePanel;
    import com.google.gwt.user.client.ui.DialogBox;
    import com.google.gwt.user.client.ui.Label;
    import com.google.gwt.user.client.ui.RootPanel;
    
    import com.allen_sauer.gwt.dnd.client.PickupDragController;
    import com.allen_sauer.gwt.dnd.client.drop.AbsolutePositionDropController;
    import com.allen_sauer.gwt.dnd.client.drop.DropController;
    import com.allen_sauer.gwt.dnd.client.util.DOMUtil;
    
    public class MyApplication implements EntryPoint {
      public void onModuleLoad() {
        // set uncaught exception handler
        GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
          public void onUncaughtException(Throwable throwable) {
            String text = "Uncaught exception: ";
            while (throwable != null) {
              StackTraceElement[] stackTraceElements = throwable.getStackTrace();
              text += throwable.toString() + "\n";
              for (int i = 0; i < stackTraceElements.length; i++) {
                text += "    at " + stackTraceElements[i] + "\n";
              }
              throwable = throwable.getCause();
              if (throwable != null) {
                text += "Caused by: ";
              }
            }
            DialogBox dialogBox = new DialogBox(true);
            DOM.setStyleAttribute(dialogBox.getElement(), "backgroundColor", "#ABCDEF");
            System.err.print(text);
            text = text.replaceAll(" ", "&nbsp;");
            dialogBox.setHTML("<pre>" + text + "</pre>");
            dialogBox.center();
          }
        });
    
        // use a deferred command so that the handler catches onModuleLoad2() exceptions
        DeferredCommand.addCommand(new Command() {
          public void execute() {
            onModuleLoad2();
          }
        });
      }
    
      private void onModuleLoad2() {
        // Create a boundary panel to constrain all drag operations
        AbsolutePanel boundaryPanel = new AbsolutePanel();
        boundaryPanel.setPixelSize(400, 300);
        boundaryPanel.addStyleName("getting-started-blue");
    
        // Create a drop target on which we can drop labels
        AbsolutePanel targetPanel = new AbsolutePanel();
        targetPanel.setPixelSize(300, 200);
        targetPanel.addStyleName("getting-started-blue");
    
        // Add both panels to the root panel
        RootPanel.get().add(boundaryPanel);
        boundaryPanel.add(targetPanel, 10, 10);
    
        // Create a DragController for each logical area where a set of draggable
        // widgets and drop targets will be allowed to interact with one another.
        PickupDragController dragController = new PickupDragController(boundaryPanel, true);
    
        // Positioner is always constrained to the boundary panel
        // Use 'true' to also constrain the draggable or drag proxy to the boundary panel
        dragController.setBehaviorConstrainedToBoundaryPanel(false);
    
        // Allow multiple widgets to be selected at once using CTRL-click
        dragController.setBehaviorMultipleSelection(true);
    
        // create a DropController for each drop target on which draggable widgets
        // can be dropped
        DropController dropController = new AbsolutePositionDropController(targetPanel);
    
        // Don't forget to register each DropController with a DragController
        dragController.registerDropController(dropController);
    
        // create a few randomly placed draggable labels
        for (int i = 1; i <= 5; i++) {
          // create a label and give it style
          Label label = new Label("Label #" + i, false);
          label.addStyleName("getting-started-label");
    
          // add it to the DOM so that offset width/height becomes available
          targetPanel.add(label, 0, 0);
    
          // determine random label location within target panel
          int left = Random.nextInt(DOMUtil.getClientWidth(targetPanel.getElement()) - label.getOffsetWidth());
          int top = Random.nextInt(DOMUtil.getClientHeight(targetPanel.getElement()) - label.getOffsetHeight());
    
          // move the label
          targetPanel.setWidgetPosition(label, left, top);
    
          // make the label draggable
          dragController.makeDraggable(label);
        }
      }
    }

More Working Examples

There are some working examples along with the demo source code for you to look at.

There's also the library source code if you want to see what makes it tick.


Hosted by Google Code