Thursday, December 9, 2010

Saving the workbench on exit.

This is was one big thing on my To Do list. Finally I implemented it into TutoGEF. I had two people asking about it also. So here we go. The procedure will not hurt a bit. We have to change a few things here and there in the already existing code but nothing mind blowing. We start out in MyGraphicalEditor by overriding the methods setInput() and doSave():
    
    @Override 
    public void doSave(final IProgressMonitor progressMonitor) {
        editorSaving = true;
        final File file = ((MyEditorInput) getEditorInput()).getFile();
        if (file != null) {
            WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
                public void execute(final IProgressMonitor monitor) {
                    try {
                        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                        ObjectOutputStream out = new ObjectOutputStream(outStream);
                        out.writeObject(getModel());
                        FileOutputStream fos = new FileOutputStream (file);
                        fos.write(outStream.toByteArray());
                        fos.close();
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            try {
                new ProgressMonitorDialog(getSite().getWorkbenchWindow()
                        .getShell()).run(false, true, op);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        editorSaving = false;
    }


We are using the ObjectOutputStream to save our model (Enterprise) to a file. The path to the file is held in the MyEditorInput class which we are going to update later on. The saving part is done. 

Next we are going to load the model right back once TutoGEF is started. We do so by putting our loading routine into setInput():

    @Override
    protected void setInput(IEditorInput input) {
        super.setInput(input);

        File file = ((MyEditorInput) input).getFile();
        if (file != null && file.exists()) {
            try {
                FileInputStream is = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(is);
                setModel((Enterprise) ois.readObject());
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
   
            if (!editorSaving) {
                if (getGraphicalViewer() != null) {
                    getGraphicalViewer().setContents(getModel());
                }
            }
        }
    }

Again we are retrieving the file from MyEditorInput and use the ObjectInputStream to recreate our model which is then passed to the Viewer to its work.

Up next is the MyEditorInput class. We need to extend it with the ability to hold a File:

public class MyEditorInput implements IEditorInput {

    // ...
    private File file = null;
    // ...
First the file needs to be created. I chose the path to the current workspace of TutoGEF and the name passed to the MyEditorInput constructor as the file's location:

    // ...
    public MyEditorInput(String name) {
        this.name = name;
        file = new File(ResourcesPlugin.getWorkspace().getRoot().getRawLocation() + "/" + name + ".session.saved");
    }
    // ...

Do not forget the getter method:

  public File getFile() {
        return file;
  }
The big work is done. Now there a few left over alterations left in order for the ObjectOutput- and ObjectInputStream to work properly.

In our model we need to update the Node, NodePropertySource and Connection classes to implement Serializable:

public class Node  implements IAdaptable, Serializable { 
// ... 
public class NodePropertySource implements IPropertySource, Serializable {
// ...
public class Connection implements Serializable {
// ...

The last step is to remove the org.eclipse.swt.graphics.Color property from the Service model. It is not serializable and will throw an error on saving the workbench. We will keep the ability to save the Color but through 3 Integers rather than the Color class:

    //private Color color;
    private int red;
    private int green;
    private int blue;
This forces us to update a few more methods in this class. I removed the createRandomColor() method and added the following to the constructor:
        // ...
    public Service() {
        //this.color = createRandomColor();
        red = (new Double(Math.random() * 128)).intValue() + 128;
        green = (new Double(Math.random() * 128)).intValue() + 128;
        blue = (new Double(Math.random() * 128)).intValue() + 128;
    }
    // ...

The getter and setter methods are also being altered:

    public void setColor(int red, int blue, int green) {
        this.red = red;
        this.green = green;
        this.blue = blue;
        //Color oldColor = this.color;
        //this.color = color;
        //getListeners().firePropertyChange(PROPERTY_COLOR, oldColor, color);

        getListeners().firePropertyChange(PROPERTY_COLOR, null, null);
    }

    public Color getColor() {
        //return color;
        return new Color(null,red,green,blue);
    }

Last but not least we will update the clone() routine:

       @Override
    public Object clone() throws CloneNotSupportedException { 
        // ...
        //srv.setColor(color);
        srv.setColor(red,green,blue);
        // ...
    }

And that was it! 

Now we are able to load and save the current state of the Editor. Next time you fire up TutoGEF all Editparts appear in the same position and color like they were when you closed it.

Here you can find the updated TutoGEF project.

Update July 8th 2011:

An alternativ to removing the org.eclipse.swt.graphics.Color from Service model is to declare it transient instead.
 
private transient Color color;
 
This way the ObjectStream ignores the Color class and keeps on doing its work. This way of course we would lose the color information.

4 comments:

Anonymous said...

thanks a lot :) .can you guide us how to save using XML file ?

Anonymous said...

hi again can what about save as ? I tried to modify your code but it dosen t work

Anonymous said...

does it Possibile to generate XML file?

Anonymous said...

Any one give me the source code for this project,I tried it but my editor is not being saved.