工作台窗口的editor区域默认是显示的,而且它支持拖拽操作。在eclipse里面,把一个文件拖到editor区域,就会自动打开该文件的editor.该特性是在iworkbenchwindowconfigurer 中设置。
在password gate中,当拖动password gate view中的一个group 或者 service到editor区域,会在editor显示该项的属性。
要实现此特性,有四部分是必须的。
1 实现必要的transfer类型,而且定义editor要支持哪些类型。在password gate中,transfer是localselectiontransfer.transfer用来进行数据的序列化,它可以支持在同一个程序,或不同程序间拖拽。
2 因为在拖拽传递的过程中editor input 要实现序列化,所以要实现ipersistableelement接口。
3 加入一个释放适配器,当一个元素被扔到editor区域,它可以知道如何进行操作,其实就是打开该元素的editor.
4 使password view能够进行拖操作,它要提供供拖的元素。
下面进行代码实现。
在rcp的workbenchwindowadvisor. prewindowopen中定义要求editor area支持的拖入对象的类型,以及打开相应editor的事件。
applicationworkbenchwindowadvisor.prewindowopen()
01 public void prewindowopen() { 02 ...... 03 configurer.addeditorareatransfer(localselectiontransfer.getinstance()); 04 configurer.configureeditorareadroplistener(new editorareadropadapter( 05 configurer.getwindow())); 06 } |
row 03定义了editor area支持的transfer为localselectiontransfer, localselectiontransfer为自己实现的传输介质类。row 04定义了对拖入editor area的对象的处理方法。editorareadropadapter实现了droptargetlistener接口,用来监听editor area中的drop事件,它会打开拖入editor area的对象所对应的editor,如果同时拖入多个对象,它会打开每个对象对应的editor.
|
editorareadropadapter.java |
01 public class editorareadropadapter extends droptargetadapter { 02 private iworkbenchwindow window; 03 04 public editorareadropadapter(iworkbenchwindow window) { 05 this.window = window; 06 } 07 08 public void dragenter(droptargetevent event) { 09 // always indicate a copy 10 event.detail = dnd.drop_copy; 11 } 12 13 public void dragoperationchanged(droptargetevent event) { 14 // always indicate a copy 15 event.detail = dnd.drop_copy; 16 } 17 18 public void drop(final droptargetevent event) { 19 display d = window.getshell().getdisplay(); 20 final iworkbenchpage page = window.getactivepage(); 21 if (page != null) { 22 d.asyncexec(new runnable() { 23 public void run() { 24 asyncdrop(event, page); 25 } 26 }); 27 } 28 } 29 30 private void asyncdrop(droptargetevent event, iworkbenchpage page) { 31 if (localselectiontransfer.getinstance().issupportedtype( 32 event.currentdatatype)) { 33 structuredselection selection = (structuredselection) event.data; 34 for (iterator iter = selection.iterator(); iter.hasnext();) { 35 object o = iter.next(); 36 if (o instanceof record) { 37 ieditorinput input = new recordeditorinput((record) o); 38 try { 39 page.openeditor(input, recordeditor.id); 40 } catch (exception e) { 41 pwdgateplugin.log("open ediotr recordeditor", e); 42 } 43 } else if (o instanceof group) { 44 ieditorinput input = new groupeditorinput((group) o); 45 try { 46 page.openeditor(input, groupeditor.id); 47 } catch (partinitexception e) { 48 pwdgateplugin.log("open ediotr groupeditor", e); 49 } 50 } 51 } 52 } 53 } 54 } |
row 18,用来处理drop事件,row 30的asyncdrop()方法用来打来相应对象的editor.
现在editor area已经可以接收拖入对象了。下一步要使一个view支持拖出对象的功能。下面的例子是在pass gate view中的createpartcontrol()方法中为一个treeviewer添加拖出功能。
|
passgateview.java |
01 private void initdraganddrop() { 02 transfer[] transfer = new transfer[] { localselectiontransfer 03 .getinstance() }; 04 localselectiondragadapter adapter = new localselectiondragadapter( 05 viewer); 06 viewer.adddragsupport(dnd.drop_move | dnd.drop_copy, transfer, adapter); 07 08 localselectiondropadapter dropadapter = new localselectiondropadapter( 09 viewer); 10 viewer.adddropsupport(dnd.drop_move | dnd.drop_copy, transfer, 11 dropadapter); 12 } |
row 06 为treeviewer添加了监听拖动的事件,当在treeviewer中有拖动时,localselectiondragadapter把拖动的对象放入localselectiontransfer中,通过其传到 editor area中。
|
localselectiondragadapter.java |
01 public class localselectiondragadapter extends dragsourceadapter { 02 03 iselectionprovider selectionprovider; 04 05 public localselectiondragadapter(iselectionprovider provider) { 06 selectionprovider = provider; 07 } 08 09 public void dragfinished(dragsourceevent event) { 10 // todo auto-generated method stub 11 super.dragfinished(event); 12 system.out 13 .println("dragsourcelistener.dragfinished(dragsourceevent event)"); 14 } 15 16 public void dragsetdata(dragsourceevent event) { 17 system.out 18 .println("dragsourcelistener.dragsetdata(dragsourceevent event)"); 19 dragsource dragsource = (dragsource) event.widget; 20 control control = dragsource.getcontrol(); 21 if (control != control.getdisplay().getfocuscontrol()) { 22 event.doit = false; 23 return; 24 } 25 26 istructuredselection selection = (istructuredselection) selectionprovider 27 .getselection(); 28 29 if (selection.isempty()) { 30 event.doit = false; 31 return; 32 } 33 localselectiontransfer.getinstance().setselection(selection); 34 event.doit = true; 35 } 36 37 public void dragstart(dragsourceevent event) { 38 system.out 39 .println("dragsourcelistener.dragstart(dragsourceevent event)"); 40 } 41 } |
row 33 ,将拖动的对象放入localselectiontransfer中。row 44 设置拖动有效,设为false的话,拖动无效。下面是localselectiontransfer的实现。很容易理解。
|
localselectiontransfer.java |
|
001 public class localselectiontransfer extends bytearraytransfer { 002 003 private static final string type_name = "local-selection-transfer-format"
+ (new long(system.currenttimemillis())).tostring(); //$non-nls-1$; 004 005 private static final int typeid = registertype(type_name); 006 007 private static final localselectiontransfer instance = new localselectiontransfer(); 008 009 private iselection selection; 010 011 private long selectionsettime; 012 013 /** 014 * only the singleton instance of this class may be used. 015 */ 016 private localselectiontransfer() { 017 } 018 019 /** 020 * returns the singleton. 021 * 022 * @return localselectiontransfer 023 */ 024 public static localselectiontransfer getinstance() { 025 return instance; 026 } 027 028 /** 029 * returns the local transfer data. 030 * 031 * @return the local transfer data 032 */ 033 public iselection getselection() { 034 return selection; 035 } 036 037 /** 038 * tests whether native drop data matches this transfer type. 039 * 040 * @param result 041 * result of converting the native drop data to java 042 * @return true if the native drop data does not match this transfer type. 043 * false otherwise. 044 */ 045 private boolean isinvalidnativetype(object result) { 046 return !(result instanceof byte[]) 047 || !type_name.equals(new string((byte[]) result)); 048 } 049 050 /** 051 * returns the type id used to identify this transfer. 052 * 053 * @return the type id used to identify this transfer. 054 */ 055 protected int[] gettypeids() { 056 return new int[] { typeid }; 057 } 058 059 /** 060 * returns the type name used to identify this transfer. 061 * 062 * @return the type name used to identify this transfer. 063 */ 064 protected string[] gettypenames() { 065 return new string[] { type_name }; 066 } 067 068 /** 069 * overrides org.eclipse.swt.dnd.bytearraytransfer#javatonative(object, 070 * transferdata). only encode the transfer type name since the selection is 071 * read and written in the same process. 072 * 073 * @see org.eclipse.swt.dnd.bytearraytransfer#javatonative(java.lang.object, 074 * org.eclipse.swt.dnd.transferdata) 075 */ 076 public void javatonative(object object, transferdata transferdata) { 077 byte[] check = type_name.getbytes(); 078 super.javatonative(check, transferdata); 079 } 080 081 /** 082 * overrides 083 * org.eclipse.swt.dnd.bytearraytransfer#nativetojava(transferdata). test if 084 * the native drop data matches this transfer type. 085 * 086 * @see org.eclipse.swt.dnd.bytearraytransfer#nativetojava(transferdata) 087 */ 088 public object nativetojava(transferdata transferdata) { 089 object result = super.nativetojava(transferdata); 090 if (isinvalidnativetype(result)) { 091 pwdgateplugin.log("invalid nattive type", new exception( 092 "invalid nattive type")); 093 } 094 return selection; 095 } 096 097 /** 098 * sets the transfer data for local use. 099 * 100 * @param s 101 * the transfer data 102 */ 103 public void setselection(iselection s) { 104 selection = s; 105 } 106 107 /** 108 * returns the time when the selection operation this transfer is associated 109 * with was started. 110 * 111 * @return the time when the selection operation has started 112 * 113 * @see org.eclipse.swt.events.typedevent#time 114 */ 115 public long getselectionsettime() { 116 return selectionsettime; 117 } 118 119 /** 120 * sets the time when the selection operation this transfer is associated 121 * with was started. if assigning this from an swt event, be sure to use 122 * <code>setselectiontime(event.time & 0xffff)</code> 123 * 124 * @param time 125 * the time when the selection operation was started 126 * 127 * @see org.eclipse.swt.events.typedevent#time 128 */ 129 public void setselectionsettime(long time) { 130 selectionsettime = time; 131 } 132 } |
其实不光是拖到area editor,以上例子稍加改造,也可以实现拖到别的控件中,任何control都可以添加托拽功能,例如可以从一个表格拖到另一个表格中,或拖到一个面板中。托拽功能让软件的可用性又提高了一个档次。