| Java, Eclipse and Web programming Tutorials |
Version 0.2
Copyright © 2008, 2009 Lars Vogel
19.11.2009
| Revision History | ||
|---|---|---|
| Revision 0.1 | 16.10.2009 | Lars Vogel |
| Created Article | ||
| Revision 0.2 | 19.11.2009 | Lars Vogel |
| Working example | ||
Table of Contents
Eclipse supports Drag and Drop based on transfer types defined as a subclass "org.eclipse.swt.dnd.Transfer". Every UI element can define if it provides a certain transfer type as source and if it accepts a certain transfer type as destination.
Eclipse provides several pre-defined transfer types, to define your own transfer type it is recommended to subclass "org.eclipse.swt.dnd.ByteArrayTransfer".
The following will demonstrate the usage of drag and drop for your own domain object between two JFace viewers (table and tree). The example in this article will just transfer Text. For a comprehensive description of drag and drop please check the articles in the appendix.
Create a new Eclipse RCP project "de.vogella.dnd.jface" with two views.
See Eclipes RCP for information on how to create Eclipse RCP applications and views.
Create the following model class.
package de.vogella.dnd.jface.model;
public class Todo {
private String shortDescription;
private String longDescription;
public String getShortDescription() {
return shortDescription;
}
public void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getLongDescription() {
return longDescription;
}
public void setLongDescription(String longDescription) {
this.longDescription = longDescription;
}
}
Create the following content providers (Singletons).
package de.vogella.dnd.jface.model;
import java.util.ArrayList;
import java.util.List;
public enum ContentProvider {
INSTANCE;
public List<Todo> getModel(){
List<Todo> list = new ArrayList<Todo>();
Todo todo = new Todo("Java", "Learn the Closure proposal");
list.add(todo);
todo = new Todo("Eclipse", "Learn more about the RCP platform");
list.add(todo);
return list;
}
}
package de.vogella.dnd.jface.model;
import java.util.ArrayList;
import java.util.List;
public enum ContentProviderTree {
INSTANCE;
List<String> list = new ArrayList<String>();
private ContentProviderTree() {
list.add("Branch1");
list.add("Branch1");
}
public List<String> getModel(){
return list;
}
}
Create the following label and content provider for your JFace viewers.
package de.vogella.dnd.jface.viewers;
import java.util.List;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import de.vogella.dnd.jface.model.Todo;
public class TableContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object inputElement) {
List<Todo> list = (List<Todo>) inputElement;
return list.toArray();
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
package de.vogella.dnd.jface.viewers;
import java.util.List;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
public class TreeContentProvider implements ITreeContentProvider {
@Override
public Object[] getChildren(Object parentElement) {
return null;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return false;
}
@Override
public Object[] getElements(Object inputElement) {
List<String> list = (List<String>) inputElement;
return list.toArray();
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
package de.vogella.dnd.jface.viewers;
import org.eclipse.jface.viewers.BaseLabelProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.graphics.Image;
import de.vogella.dnd.jface.model.Todo;
public class TableLabelProvider extends BaseLabelProvider implements
ITableLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
Todo todo = (Todo) element;
switch (columnIndex) {
case 0:
return todo.getShortDescription();
case 1:
return todo.getLongDescription();
}
return "Not supported";
}
}
package de.vogella.dnd.jface.viewers;
import org.eclipse.jface.viewers.LabelProvider;
public class TreeLabelProvider extends LabelProvider {
@Override
public String getText(Object element) {
String s = (String) element;
return s;
}
}
Create the following Drop and Drag listener which will be later assigned to the views.
package de.vogella.dnd.jface.dnd;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import de.vogella.dnd.jface.model.Todo;
public class MyDragListener implements DragSourceListener {
private final TableViewer viewer;
public MyDragListener(TableViewer viewer) {
this.viewer = viewer;
}
@Override
public void dragFinished(DragSourceEvent event) {
System.out.println("Finshed Drag");
}
@Override
public void dragSetData(DragSourceEvent event) {
// Here you do the convertion to the type which is expected.
IStructuredSelection selection = (IStructuredSelection) viewer
.getSelection();
Todo firstElement = (Todo) selection.getFirstElement();
if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
event.data = firstElement.getShortDescription() + " " + firstElement.getLongDescription();
}
}
@Override
public void dragStart(DragSourceEvent event) {
System.out.println("Start Drag");
}
}
package de.vogella.dnd.jface.dnd;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import de.vogella.dnd.jface.model.ContentProviderTree;
public class MyDropListener extends ViewerDropAdapter {
private final Viewer viewer;
public MyDropListener(Viewer viewer) {
super(viewer);
this.viewer = viewer;
}
@Override
public void drop(DropTargetEvent event) {
int location = this.determineLocation(event);
String target = (String) determineTarget(event);
String translatedLocation ="";
switch (location){
case 1 :
translatedLocation = "Dropped before the target ";
break;
case 2 :
translatedLocation = "Dropped after the target ";
break;
case 3 :
translatedLocation = "Dropped on the target ";
break;
case 4 :
translatedLocation = "Dropped into nothing ";
break;
}
System.out.println(translatedLocation);
System.out.println("The drop was done on the element: " + target );
super.drop(event);
}
// This method performs the actual drop
// We simply add the String we receive to the model and trigger a refresh of the
// viewer by calling its setInput method.
@Override
public boolean performDrop(Object data) {
ContentProviderTree.INSTANCE.getModel().add( data.toString());
viewer.setInput(ContentProviderTree.INSTANCE.getModel());
return false;
}
@Override
public boolean validateDrop(Object target, int operation,
TransferData transferType) {
return true;
}
}
Adjust your views. The first view will show a table and will allow that elements will be dragged from it. The second view accepts drops.
package de.vogella.dnd.jface.view;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import de.vogella.dnd.jface.dnd.MyDragListener;
import de.vogella.dnd.jface.model.ContentProvider;
import de.vogella.dnd.jface.viewers.TableContentProvider;
import de.vogella.dnd.jface.viewers.TableLabelProvider;
public class TableView extends ViewPart {
@Override
public void createPartControl(Composite parent) {
TableViewer viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
int operations = DND.DROP_COPY| DND.DROP_MOVE;
Transfer[] transferTypes = new Transfer[]{TextTransfer.getInstance()};
viewer.addDragSupport(operations, transferTypes , new MyDragListener(viewer));
viewer.setContentProvider(new TableContentProvider());
viewer.setLabelProvider(new TableLabelProvider());
viewer.setInput(ContentProvider.INSTANCE.getModel());
}
@Override
public void setFocus() {
}
}
package de.vogella.dnd.jface.view;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import de.vogella.dnd.jface.dnd.MyDropListener;
import de.vogella.dnd.jface.model.ContentProviderTree;
import de.vogella.dnd.jface.viewers.TreeContentProvider;
import de.vogella.dnd.jface.viewers.TreeLabelProvider;
public class TreeView extends ViewPart {
@Override
public void createPartControl(Composite parent) {
TreeViewer viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
int operations = DND.DROP_COPY | DND.DROP_MOVE;
Transfer[] transferTypes = new Transfer[]{TextTransfer.getInstance()};
viewer.addDropSupport(operations, transferTypes, new MyDropListener(viewer));
viewer.setContentProvider(new TreeContentProvider());
viewer.setLabelProvider(new TreeLabelProvider());
viewer.setInput(ContentProviderTree.INSTANCE.getModel());
}
@Override
public void setFocus() {
}
}
Thank you for practicing with this tutorial.
Please note that I maintain this website in my private time. If you like the information I'm providing please help me by donating.For questions and discussion around this article please use the www.vogella.de Google Group. Also if you note an error in this article please post the error and if possible the correction to the Group.
I believe the following is a very good guideline for asking questions in general and also for the Google group How To Ask Questions The Smart Way.
http://www.vogella.de/code/codeeclipse.html Source Code of Examples