简体   繁体   English

如何在 Eclipse FormEditor 中实现撤消/重做功能?

[英]How to implement undo/redo functionality into Eclipse FormEditor?

I am developing a multipage Form Editor to edit/create a customized XML file in Eclipse.我正在开发一个多页表单编辑器来在 Eclipse 中编辑/创建一个自定义的 XML 文件。

  1. Implementation class is MyXMLFormEditor which extends FormEditor.实现类是 MyXMLFormEditor,它扩展了 FormEditor。

  2. Each page of FormEditor extends FormPage (ie MyXMLFormPage extends FormPage). FormEditor 的每一页都扩展了FormPage(即MyXMLFormPage 扩展了FormPage)。

  3. Between FormEditor and actual XML file I am maintaining JDOM model.在 FormEditor 和实际 XML 文件之间,我正在维护 JDOM 模型。

  4. Also I implemented dirty flag handling.我还实现了脏标志处理。 So user's inputs into form editor gets saved into JDOM till the time user presses Save button.因此,用户在表单编辑器中的输入会被保存到 JDOM 中,直到用户按下“保存”按钮为止。 When user presses save button JDOM is written/serialized into XML file.当用户按下保存按钮时,JDOM 被写入/序列化为 XML 文件。

In an editor with above functionality I would like to implement undo/redo functionality as follow:在具有上述功能的编辑器中,我想实现如下撤消/重做功能:

  • When editor is dirty (user changed something into form editor and it is not saved) undo operation should revert back the changes in form editor as well as JDOM to its original state (ie the state when editor was non-dirty) and redo operation should again bring back the changes into FormEditor as well as JDOM and editor should become dirty.当编辑器变脏时(用户在表单编辑器中更改了某些内容但未保存)撤消操作应将表单编辑器和 JDOM 中的更改恢复到其原始状态(即编辑器非脏时的状态),重做操作应再次将更改带回 FormEditor 以及 JDOM,编辑器应该变脏。

Following is my code snippet:以下是我的代码片段:

MyXMLFormEditor.java MyXMLFormEditor.java

public class MyXMLFormEditor extends FormEditor {

    MyXMLFormEditor(){
                                super();                                
                                }

                @Override
                protected FormToolkit createToolkit(Display display) {
                                // Create a toolkit that shares colors between editors.
                                return new FormToolkit(Activator.getDefault().getFormColors(display));
                }

                @Override
                public void init(IEditorSite site, IEditorInput editorInput) {
                                setSite(site);
                                mSite = site;
                                setInput(editorInput);
                                try {
                                                super.init(site, editorInput);
                                } catch (PartInitException e1) {
                                                e1.printStackTrace();
                                }
                                if (!(editorInput instanceof IFileEditorInput))
                                                try {
                                                                throw new PartInitException("Invalid Input: Must be IFileEditorInput");
                                                                } catch (PartInitException e) {
                                                                                e.printStackTrace();
                                                                }
                                setPartName(fileName);
                }
                public void setUpProgFile(IEditorSite site, IEditorInput editorInput){                       
                                IFileEditorInput fileInput = ((IFileEditorInput) editorInput);

                                //create document builder and prepare JDom model for xml file.
                }


                @Override
                protected void addPages() {
                                try {
                                                //add 'Main' page
                                                objMyXMLFormPage = new MyXMLFormPage (this, "FirstPage","Main");
                                                //set rootNode of MyXMLFormPage 
                                                objMyXMLFormPage.rootNode = getRootNode();
                                                objMyXMLFormPage.filePath = filePath;
                                                objMyXMLFormPage.document = document;
                                                addPage(objMyXMLFormPage);

                                } catch (PartInitException e) {
                                                e.printStackTrace();
                                }
                }

                @Override
                public void doSave(IProgressMonitor monitor) {
                                System.out.println("MyXMLFormEditor: doSave");

                                //logic to write jdom contents into xml file.
                                objMyXMLFormPage.setDirty(false);
                }

                @Override
                public void doSaveAs() {
                                System.out.println("MyXMLFormEditor: doSaveAs");
                }
                @Override
                public boolean isSaveAsAllowed() {
                                System.out.println("MyXMLFormEditor: isSaveAsAllowed");
                                return true;
                }

}

MyXMLFormPage .java MyXMLFormPage .java

public class MyXMLFormPage  extends FormPage{

                //private members declaration.

                public MyXMLFormPage (MyXMLFormEditor editor,String title, String id) {
                                // initialize the editor and set its title and name.
                                super(editor,title,id );
                                }

                @Override
                public void createFormContent(IManagedForm managedForm) {
                    // Set page title
                                super.createFormContent(managedForm);

                                FormToolkit mMyXMLFormPage Toolkit = managedForm.getToolkit();

                                //Logic to creat UI and populating its contents from JDom

                }


                private void makeEditorDirty() {
                                updateJdom =  true;       
                                setDirty(true);                                                   
                }

                private void updateJDom() {
                                if(updateJdom){
                                                System.out.println("*** Jdom updated ***");
                                                updateJdom = false;
                                }
                }

                @Override
                public boolean isDirty() {
                                return isDirtyFlag;
                }

                protected void setDirty(boolean value) {
                                isDirtyFlag = value;
                                dirtyStateChanged();
                }

                public void dirtyStateChanged() {
                                getEditor().editorDirtyStateChanged();

                }

                @Override
                public boolean isSaveAsAllowed() {
                                System.out.println("MyXMLFormPage .isSaveAsAllowed");
                      return false;
                   }

                @Override
                public void doSave(IProgressMonitor monitor) {
                                System.out.println("MyXMLFormPage .doSave");
                }

}

Can anyone provide me pointer/samples on how to implement undo/redo functionality into FormEditor?任何人都可以向我提供有关如何在 FormEditor 中实现撤消/重做功能的指针/示例吗? It would be good if the approach make use of existing undo/redo framework of Eclipse PDE or workbench.如果该方法利用 Eclipse PDE 或工作台的现有撤消/重做框架,那就太好了。

You need to read the following resources.您需要阅读以下资源。 It may seem like extra work but believe me your job will be a lot easier and these articles aren't really long.这似乎是额外的工作,但相信我,你的工作会轻松很多,而且这些文章并不长。

The basic steps you need to perform are:您需要执行的基本步骤是:

1) Add action handlers for undo/redo operations in your editor 1) 在编辑器中为撤销/重做操作添加动作处理程序

@Override
public void init(IEditorSite site, IEditorInput editorInput) {
    ...

    UndoRedoActionGroup historyActionGroup = new UndoRedoActionGroup(editorSite, myUndoContext, true);
    historyActionGroup.fillActionBars(editorSite.getActionBars());
}

If you are thinking what is myUndoContext , you will know this from reading the first article.如果您在想什么是myUndoContext ,您将通过阅读第一篇文章了解这一点。

2) Create your own IUndoableOperation implementations for different types of modifications that the user can make on your data. 2) 为用户可以对您的数据进行的不同类型的修改创建您自己的IUndoableOperation实现。 It could be a single operation that handles all your modifications if it only depends on something like XPath->"new value", or id->"new value".如果它只依赖于诸如 XPath->"new value" 或 id->"new value" 之类的东西,它可能是处理所有修改的单个操作。 Or you could have a range of different operations for modifying each type of your data model.或者您可以有一系列不同的操作来修改每种类型的数据模型。 Its up to you.由你决定。

3) Make each and every modification to your data only through the operations you created 3)通过您创建的操作对您的数据进行每一次修改

MyDataModifyingOperation op = new MyDataModifyingOperation(xpath, newValue, oldValue);
op.addContext(myUndoContext);
IStatus status = OperationHistoryFactory.getOperationHistory().execute(operation, null, null);

Once you get the basic stuff working you will need to look at some other advanced stuff, like adding some kind of change listening mechanism on the data model so that when undo/redo modify the data, you can update the UI.一旦你得到了基本的东西,你就需要看看其他一些高级的东西,比如在数据模型上添加某种更改监听机制,以便在撤消/重做修改数据时,你可以更新 UI。 Also in most cases it is desirable that when you perform an operation you record UI selection state, so that on undo or subsequent redos you can restore selection to the element that was modified so that the user immediately recognizes what changed when Ctrl+z/Ctrl+y was pressed.同样在大多数情况下,当您执行操作时记录 UI 选择状态是可取的,以便在撤消或后续重做时,您可以将选择恢复到已修改的元素,以便用户在 Ctrl+z/Ctrl 时立即识别更改的内容+y 被按下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM