@Override public void performDragOver(DropTargetEvent event) { if (!ArtifactTransfer.getInstance().isSupportedType(event.currentDataType)) { event.detail = DND.DROP_NONE; return; } final ArtifactData artData = ArtifactTransfer.getInstance().nativeToJava(event.currentDataType); if (artData == null) { event.detail = DND.DROP_NONE; return; } for (Artifact art : artData.getArtifacts()) { if (art.isOfType(CoreArtifactTypes.UniversalGroup)) { event.detail = DND.DROP_NONE; return; } } Tree tree = treeViewer.getTree(); TreeItem dragOverTreeItem = tree.getItem(treeViewer.getTree().toControl(event.x, event.y)); event.feedback = DND.FEEDBACK_EXPAND; event.detail = DND.DROP_NONE; // Set as COPY if drag item over group (copy versus move will be determined on drop if (dragOverTreeItem != null && ((GroupExplorerItem) dragOverTreeItem.getData()).isUniversalGroup()) { event.detail = DND.DROP_COPY; tree.setInsertMark(null, false); } // Handle re-ordering within same group else if (dragOverTreeItem != null && !((GroupExplorerItem) dragOverTreeItem.getData()).isUniversalGroup()) { GroupExplorerItem dragOverGroupItem = (GroupExplorerItem) dragOverTreeItem.getData(); IStructuredSelection selectedItem = (IStructuredSelection) treeViewer.getSelection(); Object obj = selectedItem.getFirstElement(); if (obj instanceof GroupExplorerItem) { GroupExplorerItem droppingGroupItem = (GroupExplorerItem) obj; // the group to move must belong to the same group as the member to insert before/after if (dragOverGroupItem.getParentItem().equals(droppingGroupItem.getParentItem())) { if (isFeedbackAfter) { event.feedback = DND.FEEDBACK_INSERT_AFTER; } else { event.feedback = DND.FEEDBACK_INSERT_BEFORE; } event.detail = DND.DROP_MOVE; } } else { if (isFeedbackAfter) { event.feedback = DND.FEEDBACK_INSERT_AFTER; } else { event.feedback = DND.FEEDBACK_INSERT_BEFORE; } event.detail = DND.DROP_COPY; } } else { tree.setInsertMark(null, false); } }
/** * The <code>ArtifactTransfer</code> class is used to transfer an array of <code>Artifact</code>s from one part to * another in a drag and drop operation or a cut, copy, paste action. * <p> * In every drag and drop operation there is a <code>DragSource</code> and a <code>DropTarget</code>. When a drag occurs * a <code>Transfer</code> is used to marshall the drag data from the source into a byte array. If a drop occurs another * <code>Transfer</code> is used to marshall the byte array into drop data for the target. * </p> * <p> * When a <code>CutAction</code> or a <code>CopyAction</code> is performed, this transfer is used to place references to * the selected resources on the <code>Clipboard</code>. When a <code>PasteAction</code> is performed, the references on * the clipboard are used to move or copy the resources to the selected destination. * </p> * <p> * This class can be used for a <code>Viewer<code> or an SWT component directly. * A singleton is provided which may be serially reused (see <code>getInstance</code>). It is not intended to be * subclassed. * </p> * * @see org.eclipse.jface.viewers.StructuredViewer * @see org.eclipse.swt.dnd.DropTarget * @see org.eclipse.swt.dnd.DragSource * @author Robert A. Fisher */ public class ArtifactTransfer extends ByteArrayTransfer { /** Singleton instance. */ private static final ArtifactTransfer instance = new ArtifactTransfer(); // Create a unique ID to make sure that different Eclipse // applications use different "types" of <code>ResourceTransfer</code> private static final String TYPE_NAME = "artifact-transfer-format:" + System.currentTimeMillis() + ":" + instance.hashCode(); // $NON-NLS-2$//$NON-NLS-1$ private static final int TYPEID = registerType(TYPE_NAME); public static ArtifactTransfer getInstance() { return instance; } @Override protected int[] getTypeIds() { return new int[] {TYPEID}; } @Override protected String[] getTypeNames() { return new String[] {TYPE_NAME}; } @Override protected void javaToNative(Object data, TransferData transferData) { if (!(data instanceof ArtifactData)) { return; } ArtifactData artData = (ArtifactData) data; /** * The resource serialization format is: (int) number of artifacts Then, the following for each * resource: (int) artID (int) tagID Then the following (int) urlLength (int) sourceLength * (chars) url (chars) source */ try { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream dataOut = new DataOutputStream(out); // write the number of resources dataOut.writeInt(artData.getArtifacts().length); for (Artifact artifact : artData.getArtifacts()) { writeArtifact(dataOut, artifact); } dataOut.writeInt(artData.getUrl().length()); dataOut.writeInt(artData.getSource().length()); dataOut.writeChars(artData.getUrl()); dataOut.writeChars(artData.getSource()); // cleanup dataOut.close(); out.close(); byte[] bytes = out.toByteArray(); super.javaToNative(bytes, transferData); } catch (Exception e) { // it's best to send nothing if there were problems } } @Override public ArtifactData nativeToJava(TransferData transferData) { /** * The resource serialization format is: (int) number of artifacts Then, the following for each * resource: (int) artID (int) tagID */ byte[] bytes = (byte[]) super.nativeToJava(transferData); if (bytes == null) { return null; } DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes)); try { int count = in.readInt(); Artifact[] artifacts = new Artifact[count]; for (int i = 0; i < count; i++) { artifacts[i] = readArtifact(in); } int urlLength = in.readInt(); int sourceLength = in.readInt(); String url = ""; for (int x = 0; x < urlLength; x++) { url += in.readChar(); } String source = ""; for (int x = 0; x < sourceLength; x++) { source += in.readChar(); } return new ArtifactData(artifacts, url, source); } catch (Exception ex) { OseeLog.log(Activator.class, Level.SEVERE, ex); return null; } } /** Reads a resource from the given stream. */ private Artifact readArtifact(DataInputStream dataIn) throws OseeCoreException, IOException { int artID = dataIn.readInt(); int branchId = dataIn.readInt(); return ArtifactQuery.getArtifactFromId(artID, BranchManager.getBranch(branchId)); } /** * Writes the given resource to the given stream. * * @throws OseeCoreException */ private void writeArtifact(DataOutputStream dataOut, Artifact artifact) throws IOException, OseeCoreException { dataOut.writeInt(artifact.getArtId()); dataOut.writeInt(artifact.getFullBranch().getId()); } }