我正在实现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());
}
}
}
所以,我现在确实创建了自己的解决方案,尽管它可能不是最好的,我仍然希望有人能想出其他东西并在这里分享。然而,如果其他人有这个问题,并且不知道如何继续下去:
我基本上创建了自己的Request
和TargetDropListener
,然后将其添加到我的EditPart
的Policies
中。用于确定正确对象(根据文件扩展名)的逻辑被添加到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...
}
}
....
}