2016-05-17 51 views
1

我是Eclipse RCP/Plug-ins和SWT的新手。我想通过拖放来重新排列表格项目。通过拖放对表格行重新排序?

我有一个TableViewer其中包含一个表与我的自定义元素类型ITask(我的自定义元素包装在TableItem)。我发现的所有教程都是关于树或在不同表格之间拖动的,这不是我所需要的。

所以我想知道如何通过拖放重新排序表行。

+0

HTTP://www.java2s .com/Tutorial/Java/0280__SWT/DragandDropinsideTable.htm – SomeDude

+0

你的TableItem是简单文本还是POJO?如果ITask是由POJO-s实现的,那么这个链接的例子对你来说是不够的。 –

+0

@AdamHorvath我的ITask元素不仅仅是简单的文本元素。它们具有表格中显示的字符串名称字段,因此用户可以看到它们,但实际上它们包含算法和其他重要字段。 – Nicholas

回答

0

这有点长,但是你可以在代码中做一些改变。我没有列入进口; Eclipse可以自动为你做。

我使用了Spring的BeanUtils类,但是您可以使用任何可以深度拷贝POJO的lib(或者自己写)。我假设你的ITask有一个setOrder(int)方法并且是可序列化的(并且它符合POJO)

您需要为ITask创建Transfer-type:SimpleObjectTransfer是来自Eclipse GEF的IBM代码。你可以Google/GrepCode它。

public final class TaskTransfer extends SimpleObjectTransfer { 

public static final TaskTransfer INSTANCE = new TaskTransfer(); 

private TaskTransfer() { 
} 

@Override 
protected String getTypeNamePrefix() { 
    return "TASK_TRANSFER_FORMAT"; 
} 
} 

一个ViewerDropAdapter:

public class MyDropAdapter<TM extends ITask> extends ViewerDropAdapter { 

private final Class<TM> targetModelClass; 
private List<TM> listOfModels; 

protected MyDropAdapter(Viewer viewer, Class<TM> targetModelClass, List<TM> listOfModels) { 
    super(viewer); 
    this.listOfModels = listOfModels; 
    this.targetModelClass = targetModelClass; 
} 

@Override 
public boolean performDrop(Object arg0) { 
    boolean ret = false; 
    TM targetModel = targetModelClass.cast(determineTarget(getCurrentEvent())); 

    if (targetModel != null) { 
     if (List.class.isAssignableFrom(arg0.getClass())) { 
      ret = processDropToTable(targetModel, arg0); 
      getViewer().refresh(); 
     } 
    } 
    return ret; 
} 

public final boolean processDropToTable(TM targetModel, Object data) { 

    List<TM> transferredModels = (List<TM>) data; 
    List<TM> copyOfTransferredModels = transferredModels; 

    switch (getCurrentOperation()) { 
    case DND.DROP_COPY: 
     copyOfTransferredModels = deepCopyBeanList(transferredModels, new String[]{}); 
     break; 
    case DND.DROP_MOVE: 
     // moving 
     break; 
    default: 
     throw new UnsupportedOperationException(getCurrentOperation() + " is not supported!"); 
    } 
    adjustPosition(transferredModels, copyOfTransferredModels, targetModel); 

    return true; 
} 

private void adjustPosition(List<TM> transferredModels, List<TM> copyOfTransferredModels, TM targetModel) { 
    int transferredObjectPosition = listOfModels.indexOf(transferredModels.get(0)); 
    listOfModels.removeAll(copyOfTransferredModels); 
    addModelsToNewLocation(copyOfTransferredModels, targetModel, listOfModels, transferredObjectPosition); 
    for (int i = 0; i < listOfModels.size(); i++) { 
     int orderPosition = i * 10 + 10; 
     listOfModels.get(i).setOrder(orderPosition); 
    } 
} 

protected void addModelsToNewLocation(List<TM> transferredModels, TM targetModel, List<TM> targetList, int transferredObjectPosition) { 
    switch (determineLocation(getCurrentEvent())) { 
    case LOCATION_AFTER: 
    case LOCATION_ON: 
     int i; 
     if (!transferredModels.contains(targetModel)) { 
      i = targetList.indexOf(targetModel) + 1; 
     } else { 
      i = transferredObjectPosition; 
     } 
     targetList.addAll(i, transferredModels); 
     break; 
    case LOCATION_BEFORE: 
     if (!transferredModels.contains(targetModel)) { 
      i = targetList.indexOf(targetModel); 
     } else { 
      i = transferredObjectPosition; 
     } 
     targetList.addAll(i, transferredModels); 

     break; 
    case LOCATION_NONE: 
    default: 
     break; 
    } 
} 

private List<TM> deepCopyBeanList(List<TM> transferredModels, String[] ignoreProperties) { 
    List<TM> targetList = new LinkedList<TM>(); 

    for (TM element : transferredModels) { 
     try { 
      @SuppressWarnings("unchecked") 
      TM copy = (TM) element.getClass().newInstance(); 
      BeanUtils.copyProperties(element, copy, ignoreProperties); 
      targetList.add(copy); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 
    return targetList; 
} 

@Override 
public boolean validateDrop(Object arg0, int arg1, TransferData arg2) { 
    boolean ret = false; 
    for (Transfer t : new Transfer[]{TaskTransfer.INSTANCE}) { 
     if (t.isSupportedType(arg2)) { 
      ret = true; 
      break; 
     } 
    } 
    return ret; 
} 
} 

一个的DragSourceListener

public class MyDragSourceListener implements DragSourceListener { 
private final Viewer dragSourceViewer; 
private final boolean multiObjectsEnabled; 
private final Class<?> transferrableElementClass; 
private Object[] draggedObjects; 

public MyDragSourceListener(Viewer dragSourceViewer, boolean multiObjectsEnabled, Class<?> transferrableElementClass) { 
    this.dragSourceViewer = dragSourceViewer; 
    this.multiObjectsEnabled = multiObjectsEnabled; 
    this.transferrableElementClass = transferrableElementClass; 
} 

@Override 
public void dragStart(DragSourceEvent event) { 
    Control source = ((DragSource) event.getSource()).getControl(); 

    draggedObjects = null; 

    if (dragSourceViewer.getControl().equals(source)) { 
     if (multiObjectsEnabled) { 
      draggedObjects = ((StructuredSelection) dragSourceViewer.getSelection()).toArray(); 
     } else { 
      draggedObjects = new Object[]{((StructuredSelection) dragSourceViewer.getSelection()).getFirstElement()}; 
     } 
    } 
    event.doit = draggedObjects.length > 0 && transferredDataIsSupported(); 
} 

private boolean transferredDataIsSupported() { 
    boolean ret = true; 
    for (Object o : draggedObjects) { 
     if (o == null || !transferrableElementClass.isAssignableFrom(o.getClass())) { 
      ret = false; 
      break; 
     } 
    } 
    return ret; 
} 

@Override 
public void dragSetData(DragSourceEvent event) { 
    event.data = Arrays.asList(draggedObjects); 
} 

@Override 
public void dragFinished(DragSourceEvent event) { 
    if (event.detail != DND.DROP_NONE) { 
     dragSourceViewer.refresh(); 
    } 
    draggedObjects = null; 
} 
} 

和地点代码有点像这样在你的视野:

List<ITask> tasks = new WritableList(new ArrayList<ITask>(), ITask.class); 

// Let's say tableViewerTasks is your TableViewer's name 

DragSource sourceTasks = new DragSource(tblTasks, DND.DROP_MOVE); 
sourceTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE}); 
sourceTasks.addDragListener(new MyDragSourceListener(tableViewerTasks, true, ITask.class)); 

DropTarget targetTasks = new DropTarget(tblTasks, DND.DROP_MOVE); 
targetTasks.setTransfer(new Transfer[]{TaskTransfer.INSTANCE}); 
targetTasks.addDropListener(new MyDropAdapter<ITask>(tableViewerTasks, ITask.class, tasks)); 
+0

谢谢你的回答。我可以使用'LocalSelectionTransfer'而不是创建自己的传输类型吗? – Nicholas