Hi,
I am creating a dialog with two lists of items where the user can select items from list #1 and drag them to list #2. A classic example... When dragging an item to list #2, the user can select where in the list the item will be dropped (order is important). To do this, I had to use two TreeViewers (and not TableViewers or ListViewers) so that I can "insert" the dropped item and not just append it to the end of the list (Lists and Tables won't provide that functionality). All of this works, except for two little details that I can't figure how to fix:
- Since my viewers are trees and not lists, how can I remove the tree arborescence and make it look like a List? (My content provider returns a one-level collection of elements, so it looks like a List, but I still see the initial dashes (---) at the beginning of each row)
- Drag and drop from list #1 to list #2 is fine, but when I reorder the items in list #2 by dragging items up and down, I have a problem when dragging items up. I am removing the item being dragged inside dragFinished(DragSourceEvent) and that piece of code is removing the item at the newly dragged index instead of the original index. Check the following code fragments for further explanations. Is there a better way to do this, so that I can freely drag items from both lists as well as within the same list?
Creation of TreeViewers
Transfer[] transferTypes = new Transfer[] {LocalSelectionTransfer.getTransfer()};
availableListWidget = new TreeViewer(availableColumnsGroup);
availableListWidget.setContentProvider(getTreeContentProvider());
availableListWidget.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
availableListWidget.getTree().setToolTipText("Double-click to move item to selected list.");
availableListWidget.addDragSupport(DND.DROP_MOVE, transferTypes, getDragSourceListener(availableListWidget, availableObjects));
availableListWidget.addDropSupport(DND.DROP_MOVE, transferTypes, getDropTargetListener(availableListWidget, availableObjects));
availableListWidget.setInput(availableObjects);
selectedListWidget = new TreeViewer(selectedColumnsGroup);
selectedListWidget.setContentProvider(getTreeContentProvider());
selectedListWidget.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
selectedListWidget.getTree().setToolTipText("Double-click to remove item from selected list.");
selectedListWidget.addDragSupport(DND.DROP_MOVE, transferTypes, getDragSourceListener(selectedListWidget, selectedObjects));
selectedListWidget.addDropSupport(DND.DROP_MOVE, transferTypes, getDropTargetListener(selectedListWidget, selectedObjects));
selectedListWidget.setInput(selectedObjects);
getDragSourceListener(...)
private DragSourceListener getDragSourceListener(final TreeViewer viewer, final List<T> model)
{
return new DragSourceListener()
{
@Override
public void dragStart(DragSourceEvent event)
{
}
@Override
public void dragSetData(DragSourceEvent event)
{
StructuredSelection selection = (StructuredSelection)viewer.getSelection();
event.data = selection.getFirstElement();
LocalSelectionTransfer.getTransfer().setSelection(selection);
}
@Override
public void dragFinished(DragSourceEvent event)
{
if(event.detail == DND.DROP_MOVE && event.doit)
{
StructuredSelection selection = (StructuredSelection)LocalSelectionTransfer.getTransfer().getSelection();
model.remove(selection.getFirstElement());
viewer.setInput(model);
}
}
};
}
getDropTargetListener(...)
private DropTargetListener getDropTargetListener(final TreeViewer viewer, final List<T> model)
{
ViewerDropAdapter adapter = new ViewerDropAdapter(viewer)
{
private Object nextTo = null;
@SuppressWarnings("unchecked")
@Override
public boolean performDrop(Object data)
{
if (data != null)
{
StructuredSelection selection = (StructuredSelection)LocalSelectionTransfer.getTransfer().getSelection();
if(nextTo == null)
model.add((T)selection.getFirstElement());
else
{
for (int i = 0; i < model.size(); i++)
{
T item = model.get(i);
if(item == nextTo)
{
model.add(i, (T)selection.getFirstElement());
break;
}
}
}
viewer.setInput(model);
}
return true;
}
@Override
public boolean validateDrop(Object target, int operation, TransferData transferType)
{
nextTo = target;
return (LocalSelectionTransfer.getTransfer().isSupportedType(transferType));
}
@Override
public void dragOver(DropTargetEvent event)
{
super.dragOver(event);
event.feedback = DND.FEEDBACK_INSERT_BEFORE;
}
};
adapter.setScrollEnabled(true);
adapter.setExpandEnabled(true);
adapter.setSelectionFeedbackEnabled(true);
adapter.setFeedbackEnabled(true);
return adapter;
}
Thanks for your help.