package net.advanced.eclipse.sample.views; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.dnd.FileTransfer; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.part.ViewPart; /** * @Title: DragAndDrop.java * @Copyright: * @Company: * @Created on 2005-12-02 14:34:40 * @author 孙其弘 * @version $Revision: 1.11 $ * @since 1.0 */ public class DragAndDrop extends ViewPart{ private Tree dragTree; private Table dropTable; private TextTransfer textTransfer; private FileTransfer fileTransfer; public void createPartControl(Composite parent){ /* Transfer是一个可以提供数据在Java representation与platform specific representation * 之间交互的抽象类.下面是几个format: * TextTransfer String "hello world" * RTFTransfer String "{//rtf1//b//i hello world}" * FileTransfer String[] new String[] {file1.getAbsolutePath(), file2.getAbsolutePath()} * * TransferData包含了很多特定于平台的公用的属性,应用不应该直接去访问这些属性。 * 如果真的有必要去访问这些属性,那么我们可以通过扩展Transfer类来完成对特定平台的额外操作。 */ textTransfer=TextTransfer.getInstance(); fileTransfer=FileTransfer.getInstance(); dragTree=new Tree(parent,SWT.FULL_SELECTION|SWT.SINGLE); for(int i=0;i<10;i++){ TreeItem item=new TreeItem(dragTree,SWT.NONE); item.setText("treeitem"+i); for(int i2=0;i2<5;i2++){ TreeItem subitem=new TreeItem(item,SWT.NONE); subitem.setText("subtreeitem"+i2); } } //将dragLabel指定为DragSource(一个widget只能帮定在一个DragSource), //并允许数据可以从DragSource被MOVE或COPY DragSource source=new DragSource(dragTree,DND.DROP_MOVE|DND.DROP_COPY); source.setTransfer(new Transfer[] { textTransfer });// 指定允许的传输类型 source.addDragListener(new MyDragSourceListener()); dropTable=new Table(parent,SWT.BORDER|SWT.FULL_SELECTION|SWT.SINGLE); fillTable(); // 将dropTable指定为Drop Target, DropTarget target=new DropTarget(dropTable,DND.DROP_MOVE|DND.DROP_COPY|DND.DROP_DEFAULT); target.setTransfer(new Transfer[] {textTransfer }); target.addDropListener(new MyDropTargetListener()); } class MyDragSourceListener implements DragSourceListener{ // 指定拖动开始的执行策略。 public void dragStart(DragSourceEvent event){ if(((DragSource)event.widget).getControl() instanceof Tree){ TreeItem selection = DragAndDrop.this.dragTree.getSelection()[0]; if(selection.getText().length()==0){ event.doit=false; } } } //dragSetData方法在dragStart通过之后才被调用。这个方法可能会因为同一种传输类型多次set或 //不同的多种传输类型的set而被多次调用,象windows等有些平台中,dropTarget可以在鼠标移动的 //过程中请求数据,但是在Motif等平台中,只可以在drop操作完成之后才可以请求数据,所以在这个方 //法中不要假设drag and drop操作已经完成.在这个方法中是无法知道data将被drop到哪里. //set的Data也要符合指定的Transfer的format类型。 public void dragSetData(DragSourceEvent event){ if(TextTransfer.getInstance().isSupportedType(event.dataType)){ if(((DragSource)event.widget).getControl() instanceof Tree){ TreeItem selection = DragAndDrop.this.dragTree.getSelection()[0]; event.data=selection.getText(); } } } // 根据事先指定好的操作类型来处理操作结果 public void dragFinished(DragSourceEvent event){ if(event.detail==DND.DROP_MOVE){ if(((DragSource)event.widget).getControl() instanceof Tree){ TreeItem selection = DragAndDrop.this.dragTree.getSelection()[0]; selection.removeAll(); } } } } class MyDropTargetListener implements DropTargetListener{ //dragEnter事件在drag and drop动作开始,并且鼠标进入了target widget的范围内时被调用。 public void dragEnter(DropTargetEvent event){ //在dragEnter中应用可以定义default operation.如果一个drop target在创建的时候被指定为 //带有DND.DROP_DEFAULT,那么在拖动的过程中如果没有辅助按键被按下,则drop target就是DND.DROP_DEFAULT的。 //应用可以通过改变event.detail来指定default operation。如果应用没有具体指定DND.DROP_DEFAULT的操作, //平台会默认将DND.DROP_DEFAULT设置为DND.DROP_MOVE。 //另外DND.DROP_DEFAULT的值也可以在dragOperationChanged中设置。 if(event.detail==DND.DROP_DEFAULT){ //给event.detail赋的值必须是event.operations中的一个,event.operations中 //的操作都是DragSource所支持的. if((event.operations&DND.DROP_COPY)!=0){ event.detail=DND.DROP_COPY; }else{ event.detail=DND.DROP_NONE; } } //drop target可以选择性的按照传输类型来处理.dragEnter event有两个属性 //event.currentType 是应用设置的默认类型,以TransferData对象形式表现, //event.dataTypes 是drag source支持的所有类型的列表,以TransferData数组形式表现, //我们可以将event.currentType设置成event.dataTypes中的任意一个。 //这些属性也可以在dragOver, dragOperationChanged以及dropAccept事件中设置。 for(int i=0;i<event.dataTypes.length;i++){ if(textTransfer.isSupportedType(event.dataTypes[i])){ event.currentDataType=event.dataTypes[i]; //只允许COPY if(event.detail!=DND.DROP_COPY){ event.detail=DND.DROP_NONE; } break; } } } //dragOver event在光标进入drop target widget时会被重复不停的调用. //如果光标是静止的,dragOver event依然会有规则的按一定时间间隔被调用. //这个方法一般在drop target是table或tree时用得比较多,可以根据不同的item而改变操作. public void dragOver(DropTargetEvent event){ //event.feedback设置当widget处于光标下时应该给用户一个什么样的feedback. //dragOver event.feedback 值描述 //DND.FEEDBACK_SELECT 使光标下的item被选中,限于table and trees. //DND.FEEDBACK_SCROLL 使widget可以滚动以便于用户可以drop在当前看不见的item上,限于table and trees. //DND.FEEDBACK_EXPAND 使当前光标下的item展开以便于用户在sub item上drop,限于trees. //DND.FEEDBACK_INSERT_BEFORE 在item处于光标下之前显示一个插入标记,限于tables and trees. //DND.FEEDBACK_INSERT_AFTER 在item处于光标下之后显示一个插入标记,限于tables and trees. //DND.FEEDBACK_NONE 没有任何效果. event.feedback=DND.FEEDBACK_SELECT|DND.FEEDBACK_SCROLL; if(textTransfer.isSupportedType(event.currentDataType)){ String t=(String)(textTransfer.nativeToJava(event.currentDataType)); if(t!=null){ System.out.println(t); } } } //当用户按下或放开辅助按键时,例如Ctrl, Shift, Command, Option。则dragOperationChanged事件发生。 //辅助按键可以改变即将进行的操作。例如: //Ctrl key is down, a copy is requested, //Ctrl and Shift keys are both down, a link is requested //Shift key is down, a move is requested //When no modifier keys are pressed, the default operation is requested. public void dragOperationChanged(DropTargetEvent event){ if(event.detail==DND.DROP_DEFAULT){ event.detail=DND.DROP_COPY; }else{ event.detail=DND.DROP_NONE; } // allow text to be moved but files should only be copied if(fileTransfer.isSupportedType(event.currentDataType)){ if(event.detail!=DND.DROP_COPY){ event.detail=DND.DROP_NONE; } } } //当光标离开drop target widget时,dragLeave事件发生. 如果你在dragEnter中分配了一些资源, //就应该在dragLeave中释放.dragLeave事件在用户通过Escape键取消Drag and Drop操作时也会发生 //刚好在drop操作被执行之前. public void dragLeave(DropTargetEvent event){ } //dropAccept事件为应用提供了最后一次定义数据类型的机会,定义的数据类型将被返回到drop事件. //这些是通过向event.currentDataType赋event.dataTypes中的值来实现的. public void dropAccept(DropTargetEvent event){ } //如果在之前的事件中得到了有效的操作和currentDataType,那么当用户在drop target上松开鼠标时,drop事件会发生。 //event.data属性包含了请求到的数据,event.type包含了Transfer的类型. //data是event.currentDataType中定义的类型. public void drop(DropTargetEvent event){ if(textTransfer.isSupportedType(event.currentDataType)){ String text=(String)event.data; TableItem item=new TableItem(dropTable,SWT.NONE); item.setText(text); } if(fileTransfer.isSupportedType(event.currentDataType)){ String[] files=(String[])event.data; for(int i=0;i<files.length;i++){ TableItem item=new TableItem(dropTable,SWT.NONE); item.setText(files[i]); } } } } public void fillTable(){ dropTable.setHeaderVisible(true); dropTable.setLinesVisible(true); TableColumn partName =new TableColumn(dropTable,SWT.LEFT); partName.setResizable(true); partName.setText("NAME"); partName.setWidth(250); TableColumn employeeName=new TableColumn(dropTable,SWT.LEFT); employeeName.setResizable(true); employeeName.setText("SIZE"); employeeName.setWidth(120); for(int i=0;i<10;i++){ TableItem item=new TableItem(dropTable,SWT.NONE); item.setText(new String[]{"tableitem"+i,100+i+""}); } } public void setFocus(){ } }