SWT DND

 DragSource And DropTarget
DragSource是數據傳輸過程中的數據提供者,而DropTarget是數據接收者。他們分別綁定SWT的widget,需要注意的是同一widget只能幫定在一個DragSource或DropTarget上

Transfer
在DragSource 和 DropTarget之間傳遞數據的載體。
Transfer實際上是一個提供數據在Java representation與platform specific representation之間交互的抽象類.在Java對象與特定的平臺之間進行format
Transfer是傳輸的 載體,TransferData真正的利用JNI將數據和本地操作系統發生關係。TransferData包含了很多特定於平臺的公用的屬性,應用不應該 直接去訪問這些屬性。如果真的有必要去訪問這些屬性,那麼我們可以通過擴展Transfer類來完成對特定平臺的額外操作。
另外,Transfer不只是可以用在DND中,也可以單獨拿出來使用,例如實現Clipboard,可以在copy時將數據暫存於Clipboard中,past時再取出。這個和DND的在Drag時將數據暫存於Clipboard中,Drop時再取出類似。

DragSourceEvent & DropTargetEvent
DND主要通過event來傳遞數據。event.doit--drag是否啓動, event.data--保存數據, event.currentDataType--dnd的數據類型...

例子:
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;

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(){

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章