2016-05-17 12 views
1

Ich bin neu in Eclipse RCP/Plug-Ins und SWT. Ich möchte Tabellenobjekte per Drag-and-Drop neu anordnen.Tabellenzeilen per Drag-and-Drop neu anordnen?

Ich habe eine TableViewer, die eine Tabelle mit meinen benutzerdefinierten Elementen des Typs ITask enthält (jede meiner benutzerdefinierten Elemente ist in TableItem verpackt). Alle Tutorials, die ich gefunden habe, sind über Bäume oder ziehen zwischen verschiedenen Tabellen, was ich nicht brauche.

Also ich möchte wissen, wie Sie die Tabellenzeilen per Drag-and-Drop neu anordnen.

+0

http: //www.java2s/Tutorial/Java/0280_SWT/DragandDropinsideTable.htm – SomeDude

+0

Sind Ihre TableItems einfache Texte oder POJOs? Wenn ITask von POJO-s implementiert wird, ist das verlinkte Beispiel nicht genug für Sie. –

+0

@AdamHorvath meine ITask-Elemente sind nicht nur einfache Textelemente. Sie haben String-Name-Felder, die in der Tabelle angezeigt werden, so dass der Benutzer sie sehen kann, aber in der Tat enthalten sie Algorithmen und andere wichtige Felder. – Nicholas

Antwort

0

Es ist ein bisschen lang, aber Sie können dies mit einigen Änderungen in Ihrem Code arbeiten. Ich habe die Importe nicht berücksichtigt; Eclipse kann das automatisch für Sie erledigen.

Ich verwendete Spring's BeanUtils-Klasse, aber Sie können eine beliebige lib (oder schreiben Sie Ihre eigenen), die POJOs deepcopy können. Ich nehme an, dass Ihre ITask eine setOrder (int) -Methode hat und serialisierbar ist (und für einen POJO qualifiziert)

Sie müssen einen Transfer-Typ für Ihre ITask erstellen: SimpleObjectTransfer ist IBMs Code von Eclipse GEF. Sie können Google/GrepCode es.

public final class TaskTransfer extends SimpleObjectTransfer { 

public static final TaskTransfer INSTANCE = new TaskTransfer(); 

private TaskTransfer() { 
} 

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

A 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; 
} 
} 

A 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; 
} 
} 

und legen Sie einen Code so etwas wie dies in Ihrer Ansicht:

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

Vielen Dank für Ihre Antwort. Kann ich 'LocalSelectionTransfer' anstelle eines eigenen Übertragungstyps verwenden? – Nicholas