I am developing a multipage Form Editor to edit/create a customized XML file in Eclipse.
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:
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.
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
@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.
2) Create your own IUndoableOperation
implementations for different types of modifications that the user can make on your data. 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". 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
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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With