0

I am developing a multipage Form Editor to edit/create a customized XML file in Eclipse. structure is looks like:

  • Implementation class is MyXMLFormEditor which extends FormEditor.
  • Each page of FormEditor extends FormPage (i.e. MyXMLFormPage extends FormPage).
  • Between FormEditor and actual XML file I am maintaining JDOM model.
  • Also I implemented dirty flag handling. So user’s inputs into form editor gets saved into JDOM till the time user presses Save button. When user presses save button JDOM is written/serialized into XML file.

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 (i.e. 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.

Following is my code snippet

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

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? It would be good if the approach make use of existing undo/redo framework of Eclipse PDE or workbench.

AndroidLearner
  • 4,500
  • 4
  • 31
  • 62
User_86
  • 265
  • 1
  • 4
  • 13
  • you could look at gef examples - it basically uses the command pattern, the relevant class name if I remember correctly is CommandStack – Scorpion Jan 07 '13 at 09:41
  • also, looks like a duplicate of http://stackoverflow.com/questions/14120203/how-to-implement-undo-redo-functionality-into-eclipse-formeditor – Scorpion Jan 07 '13 at 09:59
  • The code here seems to be the exact copy of what was posted in the duplicate question as highlighted by @Scorpion. Was the answer on that question not satisfactory? You should respond on the original question. – Waqas Ilyas Jan 07 '13 at 12:08

1 Answers1

0

There are a couple of important points to make about the pattern used by multi-page editor implementations in Eclipse. There may be other ways of doing it, but the editors in Eclipse seem to adhere to these points:

  • Maintain a model of the data that's shared by the pages in the editor (you're doing this).
  • Only refresh a page with the model data when the page is about to be displayed. Don't try to keep non-displayed pages in sync with the model.
  • When you perform an undo or redo, make the appropriate changes to the model (per @Scorpion's comment) and then refresh the current page.
  • Each page should have a its-ok-to-leave-this-page method (I don't remember the name) which is called to make sure that the displayed data is error free enough to allow the page to be changed (you don't want errors on non-displayed data).
  • Pages have an about-to-leave-this-page method which is called to save any changes to the model before switching pages. Most pages don't do anything here because the model is modified sometimes by every keystroke, but the source page would use this method to replace the model completely with the parse results on the text editor contents.

What this means is that your forms don't have to perform the undo/redo themselves. Rather, the classes representing the multipage editor pages will interact with the model as it's changed and then pass the correct data to be displayed to the forms.

The forms will need to listen for the undo/redo key events and pass those along to the model via the command pattern.

Chris Gerken
  • 16,221
  • 6
  • 44
  • 59