Eclipse e4 文本编辑器应用程序的自定义 ISaveHandler 和 IWindowCloseHandler

Custom ISaveHandler and IWindowCloseHandler for Eclipse e4 text editor app

与问题“Custom message when closing a part in Eclipse RCP 4”相关 我还有一个带有多个编辑器部分的 Eclipse RCP 4 应用程序(实现 MDirtyable 和 @Persist)。

零件可以关闭。当用户关闭一个部分时,应该有一个自定义弹出窗口,询问用户是否真的想保存该部分。

此外,当用户关闭应用程序时,弹出窗口应提示用户 close/save 脏部分。 基本上它是为了删除默认的关闭 eclipse e4 对话框。

我在生命周期class.

实现了自定义ISaveHandler和IWindowCloseHandler订阅应用程序启动完成事件UIEvents.UILifeCycle.APP_STARTUP_COMPLETE

自定义 IWindowCloseHandler 工作正常(就对话框而言)但自定义 ISaveHandler 不行。

ISaveHandler.save returns Whosebug 错误定义如下:

@Override
public boolean save(MPart dirtyPart, boolean confirm) {
    EPartService partService = dirtyPart.getContext().get(EPartService.class);
    //Try to close the part and save the document to disc by 
    //calling the @Persist method
    return partService.savePart(dirtyPart, confirm);

}

我附上了完整的 LifeCycleManager class:

public class LifeCycleManager {
@Inject IEventBroker eventBroker;

@ProcessAdditions
public void processAdditions(MApplication application, EModelService modelService){
     MWindow window =(MWindow)modelService.find("application-trimmedwindow", application);
     eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE,
                          new AppStartupCompleteEventHandler(window, modelService, application));
}
public class AppStartupCompleteEventHandler implements EventHandler {
    private MWindow theWindow;
    private MApplication app;
    private ISaveHandler saveHandler;

    AppStartupCompleteEventHandler(MWindow window, EModelService modelService, MApplication application){
        theWindow = window;
        app = application;
    }

    @Override
    public void handleEvent(Event event) {
        theWindow.getContext().set(ISaveHandler.class, new ISaveHandler() {
            @Override
            public boolean save(MPart dirtyPart, boolean confirm) {
                System.out.println("PARTE PARA SALVAR..." + dirtyPart.getLabel());
                EPartService partService = dirtyPart.getContext().get(EPartService.class);
                //partService.hidePart(dirtyPart,true);
                return partService.savePart(dirtyPart, confirm);
                //return true;
            }

            @Override
            public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) {
                return false;
            }
            @Override
            public Save promptToSave(MPart dirtyPart) {
                return promptToSaveDialog(dirtyPart);
            }
            @Override
            public Save[] promptToSave(Collection<MPart> dirtyParts) {
                return null;
            }
        });
        saveHandler  = (ISaveHandler)theWindow.getContext().get(ISaveHandler.class);
        theWindow.getContext().set(IWindowCloseHandler.class, new IWindowCloseHandler() {
            @Override
            public boolean close(MWindow window) {
                List<MHandler> listHandlers = window.getHandlers();
                System.out.println(listHandlers.size());
                Shell shell = (Shell) window.getWidget();
                if (MessageDialog.openConfirm(shell, "Close Nastran Editor", "Do you really want to close the entire application?")) {
                    Collection<EPartService> allPartServices = getAllPartServices(app);
                    if (containsDirtyParts(allPartServices)) {
                        return iterateOverDirtyParts( allPartServices);
                    }
                else {
                    return true;
                }
            }
            return false;
        }});
}
private Collection<EPartService> getAllPartServices(MApplication application) {
    List<EPartService> partServices = new ArrayList<EPartService>();
    EModelService modelService = application.getContext().get(EModelService.class);
    List<MWindow> elements = modelService.findElements(application, MWindow.class, EModelService.IN_ACTIVE_PERSPECTIVE,
            new ElementMatcher(null, MWindow.class, (List<String>) null));
    for (MWindow w : elements) {
        if (w.isVisible() && w.isToBeRendered()) {
            EPartService partService = w.getContext().get(EPartService.class);
            if (partService != null) {
                partServices.add(partService);
            }
        }
    }
    return partServices;
}
private boolean containsDirtyParts(Collection<EPartService> partServices) {
    for (EPartService partService : partServices) {
        if (!partService.getDirtyParts().isEmpty()) return true;
    }
    return false;
}
private  boolean iterateOverDirtyParts(Collection<EPartService> allPartServices) {
    for (EPartService partService : allPartServices) {
        Collection<MPart> dirtyParts = partService.getDirtyParts();
        for(MPart dirtyPart : dirtyParts) {
            switch(saveHandler.promptToSave(dirtyPart)) {
                case NO: break;
                case YES:
                    saveHandler.save(dirtyPart, false);
                    break;
                case CANCEL:return false;
            }
        }
    }
    return true;
}
private Save promptToSaveDialog(MPart dirtyPart) {
    MessageDialog dialog = new MessageDialog( (Shell)theWindow.getWidget(), "Save file", null,
            "'"+dirtyPart.getLabel()+"' has been modified. Save changes?", MessageDialog.QUESTION, new String[] { "YES", "NO", "CANCEL" }, 0);
        switch (dialog.open()){
            case 0: return Save.YES;
            case 1: return Save.NO;
            case 2: return Save.CANCEL;
            default:return Save.CANCEL;
        }
}
}
}///END of LifeCycleManager

ISaveHandlersave 方法是从 EPartService savePart 方法中调用的,因此您不能再次调用 savePart

相反,您应该只调用部件的 @Persist 方法。所以像:

@Override
public boolean save(final MPart dirtyPart, final boolean confirm)
{
  if (confirm)
   {
     switch (promptToSave(dirtyPart))
     {
       default:
       case NO:
         return true;
       case CANCEL:
         return false;
       case YES:
         break;
     }
   }

  try
   {
     ContextInjectionFactory.invoke(dirtyPart.getObject(), Persist.class, dirtyPart.getContext());
   }
  catch (final InjectionException ex)
   {
     // TODO ignore or log error
   }

  return true;
}