通过拖放重新排序 table 行?

Reorder table rows via Drag-and-Drop?

我是 Eclipse RCP/Plug-ins 和 SWT 的新手。我想通过拖放重新排序 table 项。

我有一个 TableViewer,其中包含一个 table 和我的 ITask 类型的自定义元素(我的每个自定义元素都包含在 TableItem 中)。我找到的所有教程都是关于树或在不同 table 之间拖动的,这不是我需要的。

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

它有点长,但您可以通过一些更改在您的代码中使用它。我没有包括进口商品; Eclipse 可以自动为您完成。

我使用了 Spring 的 BeanUtils class,但您可以使用任何可以深度复制 POJO 的库(或编写您自己的库)。我假设您的 ITask 有一个 setOrder(int) 方法并且是可序列化的(并且它符合 POJO 的条件)

您需要为您的 ITask 创建一个传输类型:SimpleObjectTransfer 是 IBM 的代码,来自 Eclipse GEF。你可以 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));