Eclipse GEF 拖放区分文件扩展名



我正在实现EMF+GEF编辑器,还希望支持Drag&从包/项目资源管理器中删除。到目前为止,我在本教程中取得了不错的进展:https://eclipse.org/articles/Article-GEF-dnd/GEF-dnd.html

然而,现在我被困在这里:我需要根据文件类型创建不同的对象。例如,当我删除一个XML文件时,我想创建一个类型为A的对象,而当我删除TXT文件时,则希望创建类型为B的对象。

我可以访问handleDrop()事件上的文件名,但问题是在createTargetRequest(),当我设置工厂类型时,有关扩展名的信息不可用。

即访问((String[])getCurrentEvent().data)[0]的函数isComponentXML()导致异常。

protected Request createTargetRequest() {
    CreateRequest request = new CreateRequest();
    if(isComponentXML()){
        request.setFactory(componentfactory);
    } else if (isControlFile()){
        request.setFactory(filefactory);
    }
}

有人能建议我在createTargetRequest()期间访问文件名或树对象的方法吗?

是否将所有内容都设置为FileTransfer而非TextTransfer?如果您从某个Eclipse视图(如PackageExplorer或ProjectExplorer)执行DND,则transfer可能是StructuredSelection。因此,请考虑下面的2个代码片段>:

对于文件:

if (getCurrentEvent().data instanceof String[]) {
   insertFileNamesFromStringArray(filesList, (String[]) getCurrentEvent().data);
}

对于结构化选择:

if (getCurrentEvent().data instanceof IStructuredSelection) {
   Object[] array = ((IStructuredSelection)getCurrentEvent().data).toArray();
   for (int j = 0; j < array.length; j++) {
      if (array[j] instanceof IFile) {
        IFile dropFile = (IFile)array[j];
        filesList.add(dropFile.getLocation().toOSString());
      }
   }
}

所以,我现在确实创建了自己的解决方案,尽管它可能不是最好的,我仍然希望有人能想出其他东西并在这里分享。然而,如果其他人有这个问题,并且不知道如何继续下去:

我基本上创建了自己的RequestTargetDropListener,然后将其添加到我的EditPartPolicies中。用于确定正确对象(根据文件扩展名)的逻辑被添加到Policy中的getCommand(...)。对于那些仍然不知道我在做什么的人,下面有一个循序渐进的指南。


步骤1:创建自己的请求对象:

public class FileTransferRequest extends Request implements DropRequest {
    public static final String TYPE = "FILE_TRANSFER"; // for comparison 
    private Point location;  // stores where the new Object should be displayed
    private String filepath; // this is the data bit...
    public FileTransferRequest() {
        setType(TYPE); // set the type of the request so we can recognise it later
    }
    /* GETTERS AND SETTERS */
    @Override public Point getLocation() { return this.location; }
    public void setLocation(Point location) { this.location = location; }
    public void setFilePath(String filepath){ this.filepath = filepath; }
    public String getFilePath(){ return this.filepath; }
}

步骤2:创建TargetDropListener

public class ResourceTransferDropTargetListener extends AbstractTransferDropTargetListener{
    public ResourceTransferDropTargetListener(EditPartViewer viewer, Transfer xfer) {
        super(viewer, xfer);
    }
    public ResourceTransferDropTargetListener(EditPartViewer viewer) {
          super(viewer, FileTransfer.getInstance());
    }
    @Override public boolean isEnabled(DropTargetEvent event) {
        return true; // maybe you want some smarter code here
    }
    // creates a new Request, will be called by getTargetRequest() if necessary
    @Override protected Request createTargetRequest() {
        return new FileTransferRequest();
    }
    // this routine is called repeatedly and sets the x/y coordinates of the mouse pointer
    @Override protected void updateTargetRequest() {
        ((FileTransferRequest)getTargetRequest()).setLocation(getDropLocation());
    }
    // prevent moving, we want to copy the file... 
    @Override protected void handleDragOver() {
        getCurrentEvent().detail = DND.DROP_COPY;
        super.handleDragOver();
    }
    // called on drop. THIS IS WHERE WE GET ACCESS TO THE FILE NAME (for the first time)
    @Override protected void handleDrop() {
        ((FileTransferRequest)getTargetRequest()).setFilePath(getFilepath());
        super.handleDrop();
    }
    // a helper for the function above... returns only one element (for multiple selections you will have to change something here and above)
    private String getFilepath(){
        return ((String[])getCurrentEvent().data)[0];
    }
}

步骤3:在MyEditor.java 中注册处理程序

....
@Override
protected void initializeGraphicalViewer() {
    super.initializeGraphicalViewer();
    getGraphicalViewer().setContents(/* whatever you are displaying */);
    // add the TransferDropTargetListener to the Editor
    getGraphicalViewer().addDropTargetListener(new
        ResourceTransferDropTargetListener(getGraphicalViewer()));
}
.....

步骤4:这是重要的部分。TargetDropListener将尝试查找实现策略的EditPolicy,该策略对应于YourRequest.TYPE。因此,我们需要创建一个新的EditPolicy或扩展一个旧的。(我选择扩展现有的一个,因为我想保持它的简单性,而不是干扰许多文件…)

步骤4a:将请求类型添加到EditPolicy。如果它"被问到"它能处理什么,它将返回其EditPart

public class MyXYLayoutPolicy extends XYLayoutEditPolicy {
    // This function will be called to find out what types it can handle. 
    // We need to return an EditPart to signal that we can. 
    // FileTransferRequest.TYPE serves as the identifier
    @Override public EditPart getTargetEditPart(Request request) {
        if(request.getType().equals(FileTransferRequest.TYPE)){
            return getHost();
        }
        // if the previous didn't trigger, return what it would have done normally
        return super.getTargetEditPart(request); 
    }
    ....
}

步骤4b:返回正确的EditPart后,将调用getCommand(...),因此我们需要返回命令
我会让Command的实现留给您自己研究,但如果您正在寻求帮助:这是一个查找信息的好地方。(也适用于全球环境基金的其他事项)
提示:扩展Command并实现execute()undo()

public class MyXYLayoutPolicy extends XYLayoutEditPolicy {
    ....
    @Override public Command getCommand(Request request) {
        if(request.getType().equals(FileTransferRequest.TYPE)){ // for file DND
            return handleFileTransferRequest(request);
        }
        return super.getCommand(request);
    }
    private Command handleFileTransferRequest(Request request){
        FileTransferRequest req = (FileTransferRequest) request;
        if(req.getFilePath().endsWith(".xml")){ // XML file
            System.out.println("XML");
            XMLCreateCommand command = new XMLCreateCommand();
            command.setLocation(req.getLocation());
            command.setParent((Graph)(getHost().getModel())); 
            Component c = GraphFactory.eINSTANCE.createComponent();
            c.setName(req.getFilePath);
            command.setComponent(c); 
            return command;
        } else if(((FileTransferRequest) request).getFilePath().endsWith(".txt")){ 
            System.out.println("TXT");
            TXTCreateCommand command = new TXTCreateCommand();
            command.setLocation(req.getLocation());
            command.setParent((Graph)(getHost().getModel())); 
            TXTFile f = GraphFactory.eINSTANCE.createTXTFile();
            f.setName(req.getFilePath());
            command.setFile(f);
            return command;
        } else {
            return null; // a FileTransferRequest, but not a type we know...
        }
    }
    ....
}

最新更新