com.oubeichen.gefexp.ShapesEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.oubeichen.gefexp.ShapesEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2005 Elias Volanakis and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Elias Volanakis - initial API and implementation
?*******************************************************************************/
package com.oubeichen.gefexp;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.dnd.TemplateTransferDragSourceListener;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.gef.requests.SimpleFactory;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.parts.ContentOutlinePage;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.gef.ui.parts.TreeViewer;

import com.oubeichen.gefexp.model.Connection;
import com.oubeichen.gefexp.model.EllipticalShape;
import com.oubeichen.gefexp.model.RectangularShape;
import com.oubeichen.gefexp.model.Shape;
import com.oubeichen.gefexp.model.ShapesDiagram;
import com.oubeichen.gefexp.model.TriangularShape;
import com.oubeichen.gefexp.parts.ShapesEditPartFactory;
import com.oubeichen.gefexp.parts.ShapesTreeEditPartFactory;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * A graphical editor with flyout palette that can edit .shapes files. The
 * binding between the .shapes file extension and this editor is done in
 * plugin.xml
 * 
 * @author Elias Volanakis
 */
public class ShapesEditor extends GraphicalEditorWithFlyoutPalette {

    /** This is the root of the editor's model. */
    private ShapesDiagram diagram;
    /** Palette component, holding the tools and shapes. */
    private static PaletteRoot PALETTE_MODEL;

    /** Create a new ShapesEditor instance. This is called by the Workspace. */
    public ShapesEditor() {
        setEditDomain(new DefaultEditDomain(this));
    }

    /**
     * Configure the graphical viewer before it receives contents.
     * <p>
     * This is the place to choose an appropriate RootEditPart and
     * EditPartFactory for your editor. The RootEditPart determines the behavior
     * of the editor's "work-area". For example, GEF includes zoomable and
     * scrollable root edit parts. The EditPartFactory maps model elements to
     * edit parts (controllers).
     * </p>
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditor#configureGraphicalViewer()
     */
    @Override
    protected void configureGraphicalViewer() {
        super.configureGraphicalViewer();

        GraphicalViewer viewer = getGraphicalViewer();
        viewer.setEditPartFactory(new ShapesEditPartFactory());
        viewer.setRootEditPart(new ScalableFreeformRootEditPart());
        viewer.setKeyHandler(new GraphicalViewerKeyHandler(viewer));

        // configure the context menu provider
        ContextMenuProvider cmProvider = new ShapesEditorContextMenuProvider(viewer, getActionRegistry());
        viewer.setContextMenu(cmProvider);
        getSite().registerContextMenu(cmProvider, viewer);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.gef.ui.parts.GraphicalEditor#commandStackChanged(java.util
     * .EventObject)
     */
    @Override
    public void commandStackChanged(EventObject event) {
        firePropertyChange(IEditorPart.PROP_DIRTY);
        super.commandStackChanged(event);
    }

    private void createOutputStream(OutputStream os) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(os);
        oos.writeObject(getModel());
        oos.close();
    }

    private void createRawOutput(ByteArrayOutputStream out) throws IOException {
        /*StringBuffer sb = new StringBuffer();
        Iterator it = getModel().getChildren()
        .iterator(), conit;
        HashSet<Connection> hs = new HashSet<Connection>();
        sb.append("Shapes:\n"
        + getModel().getChildren()
              .size() + "\n");// shape
        while (it.hasNext()) {
           Shape sp = (Shape) it.next();
           sb.append(sp.toString() + "\n");
           sb.append("height:\n"
           + sp.getSize().height
           + "\nwidth:\n"
           + sp.getSize().width + "\n");
           sb.append("location:\n"
           + sp.getLocation().x + " "
           + sp.getLocation().y + "\n");
           conit = sp.getSourceConnections()
           .iterator();
           while (conit.hasNext()) {
        hs.add((Connection) conit.next());
           }
           conit = sp.getTargetConnections()
           .iterator();
           while (conit.hasNext()) {
        hs.add((Connection) conit.next());
           }
           sb.append("\n");// ?
        }
            
        sb.append("Connections:\n" + hs.size()
        + "\n");
        it = hs.iterator();
        while (it.hasNext()) {
           Connection con = (Connection) it
           .next();
           sb.append(con.getSource()
           .toString() + "\n");
           sb.append(con.getTarget()
           .toString() + "\n");
           sb.append("\n");// ?
        }
        out.write(sb.toString().getBytes());*/

        Document document = DocumentHelper.createDocument();
        Element root = document.addElement("diagram");// 
        Element shaperoot = root.addElement("shapes");
        Iterator it = getModel().getChildren().iterator(), conit;
        HashSet<Connection> hs = new HashSet<Connection>();
        while (it.hasNext()) {//shape
            Shape sp = (Shape) it.next();
            Element shapeElm = shaperoot.addElement("shape");
            shapeElm.addElement("name").addText(sp.toString());
            shapeElm.addElement("height").addText(String.valueOf(sp.getSize().height));
            shapeElm.addElement("width").addText(String.valueOf(sp.getSize().width));
            shapeElm.addElement("locx").addText(String.valueOf(sp.getLocation().x));
            shapeElm.addElement("locy").addText(String.valueOf(sp.getLocation().y));
            conit = sp.getSourceConnections().iterator();
            while (conit.hasNext()) {
                hs.add((Connection) conit.next());
            }
            conit = sp.getTargetConnections().iterator();
            while (conit.hasNext()) {
                hs.add((Connection) conit.next());
            }
        }
        Element connroot = root.addElement("connections");
        it = hs.iterator();
        while (it.hasNext()) {
            Element connElm = connroot.addElement("connection");
            Connection con = (Connection) it.next();
            connElm.addElement("source").addText(con.getSource().toString());
            connElm.addElement("target").addText(con.getTarget().toString());
        }
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8"); // XML?        
        XMLWriter writer;
        try {
            writer = new XMLWriter(out, format);
            writer.write(document);
            writer.close();
        } catch (IOException ex) {
            System.err.println("Cannot create output file!");
            ex.printStackTrace();
        }
        out.close();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#
     * createPaletteViewerProvider()
     */
    @Override
    protected PaletteViewerProvider createPaletteViewerProvider() {
        return new PaletteViewerProvider(getEditDomain()) {
            @Override
            protected void configurePaletteViewer(PaletteViewer viewer) {
                super.configurePaletteViewer(viewer);
                // create a drag source listener for this palette viewer
                // together with an appropriate transfer drop target listener,
                // this will enable
                // model element creation by dragging a
                // CombinatedTemplateCreationEntries
                // from the palette into the editor
                // @see ShapesEditor#createTransferDropTargetListener()
                viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
            }
        };
    }

    /**
     * Create a transfer drop target listener. When using a
     * CombinedTemplateCreationEntry tool in the palette, this will enable model
     * element creation by dragging from the palette.
     * 
     * @see #createPaletteViewerProvider()
     */
    private TransferDropTargetListener createTransferDropTargetListener() {
        return new TemplateTransferDropTargetListener(getGraphicalViewer()) {
            @Override
            protected CreationFactory getFactory(Object template) {
                return new SimpleFactory((Class) template);
            }
        };
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor
     * )
     */
    @Override
    public void doSave(IProgressMonitor monitor) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            IFile file = ((IFileEditorInput) getEditorInput()).getFile();
            if (!file.getName().contains(".raw.obsp")) {
                createOutputStream(out);
            } else {
                createRawOutput(out);
            }
            file.setContents(new ByteArrayInputStream(out.toByteArray()), true, // keep
                    // saving,
                    // even
                    // if
                    // IFile
                    // is
                    // out
                    // of
                    // sync
                    // with
                    // the
                    // Workspace
                    false, // dont keep history
                    monitor); // progress monitor
            getCommandStack().markSaveLocation();
        } catch (CoreException ce) {
            ce.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.ISaveablePart#doSaveAs()
     */
    @Override
    public void doSaveAs() {
        // Show a SaveAs dialog
        Shell shell = getSite().getWorkbenchWindow().getShell();
        SaveAsDialog dialog = new SaveAsDialog(shell);
        dialog.setOriginalFile(((IFileEditorInput) getEditorInput()).getFile());
        dialog.open();

        IPath path = dialog.getResult();
        if (path != null) {
            // try to save the editor's contents under a different file name
            final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
            try {
                new ProgressMonitorDialog(shell).run(false, // don't fork
                        false, // not cancelable
                        new WorkspaceModifyOperation() { // run this operation
                            @Override
                            public void execute(final IProgressMonitor monitor) {
                                ByteArrayOutputStream out = new ByteArrayOutputStream();
                                try {
                                    if (!file.getName().contains(".raw.obsp")) {
                                        createOutputStream(out);
                                    } else {
                                        createRawOutput(out);
                                    }
                                    file.create(new ByteArrayInputStream(out.toByteArray()), // contents
                                            true, // keep saving, even if
                                            // IFile
                                            // is out of sync with
                                            // the
                                            // Workspace
                                            monitor); // progress monitor
                                } catch (CoreException ce) {
                                    ce.printStackTrace();
                                } catch (IOException ioe) {
                                    ioe.printStackTrace();
                                }
                            }
                        });
                // set input to the new file
                setInput(new FileEditorInput(file));
                getCommandStack().markSaveLocation();
            } catch (InterruptedException ie) {
                // should not happen, since the monitor dialog is not cancelable
                ie.printStackTrace();
            } catch (InvocationTargetException ite) {
                ite.printStackTrace();
            }
        }
    }

    @Override
    public Object getAdapter(Class type) {
        if (type == IContentOutlinePage.class)
            return new ShapesOutlinePage(new TreeViewer());
        return super.getAdapter(type);
    }

    ShapesDiagram getModel() {
        return diagram;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#getPaletteRoot
     * ()
     */
    @Override
    protected PaletteRoot getPaletteRoot() {
        if (PALETTE_MODEL == null)
            PALETTE_MODEL = ShapesEditorPaletteFactory.createPalette();
        return PALETTE_MODEL;
    }

    private void handleLoadException(Exception e) {
        System.err.println("** Load failed. Using default model. **");
        //e.printStackTrace();
        diagram = new ShapesDiagram();
    }

    /**
     * Set up the editor's inital content (after creation).
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#initializeGraphicalViewer()
     */
    @Override
    protected void initializeGraphicalViewer() {
        super.initializeGraphicalViewer();
        GraphicalViewer viewer = getGraphicalViewer();
        viewer.setContents(getModel()); // set the contents of this editor

        // listen for dropped parts
        viewer.addDropTargetListener(createTransferDropTargetListener());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
     */
    @Override
    public boolean isSaveAsAllowed() {
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
     */
    @Override
    protected void setInput(IEditorInput input) {
        super.setInput(input);
        try {
            IFile file = ((IFileEditorInput) input).getFile();
            if (!file.getName().contains(".raw.obsp")) {//XXX.raw.obsp
                ObjectInputStream in = new ObjectInputStream(file.getContents());
                diagram = (ShapesDiagram) in.readObject();
                in.close();
            } else {
                diagram = new ShapesDiagram();

                /*InputStreamReader isr = new InputStreamReader(file.getContents());
                BufferedReader reader = new BufferedReader(isr);
                String tempString, name;
                ArrayList<String> shapename = new ArrayList<String>();
                int shapenum, connnum;
                reader.readLine();//"Shape:"
                tempString = reader.readLine();//shape number
                try{
                   shapenum = Integer.parseInt(tempString);
                }catch(NumberFormatException ex){
                   shapenum = 0;
                }
                for(int i = 0;i < shapenum;i++){
                   int height, width, x, y;
                    name = reader.readLine();//shape name
                    shapename.add(name);
                    reader.readLine();//"height:"
                    tempString = reader.readLine();//shape height
                    try{
                       height = Integer.parseInt(tempString);
                    }catch(NumberFormatException ex){
                       height = 0;
                    }
                    reader.readLine();//"width:"
                    tempString = reader.readLine();//shape width
                    try{
                       width = Integer.parseInt(tempString);
                    }catch(NumberFormatException ex){
                       width = 0;
                    }
                    reader.readLine();//"location:"
                    tempString = reader.readLine();//shape location
                    try{
                       x = Integer.parseInt(tempString.split(" ")[0]);
                    }catch(NumberFormatException ex){
                       x = 0;
                    }
                    try{
                       y = Integer.parseInt(tempString.split(" ")[1]);
                    }catch(NumberFormatException ex){
                       y = 0;
                    }
                    reader.readLine();//empty line
                    //add to the diagram
                    Shape sp;
                    if(name.contains("Ellipse")){
                       sp = new EllipticalShape();
                    }else if(name.contains("Triangle")){
                       sp = new TriangularShape();
                    }else if(name.contains("Rectangle")){
                       sp = new RectangularShape();
                    }else{
                       System.err.println("Shape unsupported!");
                       sp = new EllipticalShape();
                    }
                    sp.setSize(new Dimension(width, height));
                    sp.setLocation(new Point(x, y));
                    diagram.addChild(sp);
                }
                    
                reader.readLine();//"Connections:"
                tempString = reader.readLine();//connection num
                try{
                   connnum = Integer.parseInt(tempString);
                }catch(NumberFormatException ex){
                   connnum = 0;
                }
                    
                for(int i = 0;i < connnum;i++)
                {
                   String source = reader.readLine();
                   String target = reader.readLine();
                   reader.readLine();//empty line
                   int sourceindex = shapename.indexOf(source);
                   int targetindex = shapename.indexOf(target);
                   if(sourceindex == -1 || targetindex == -1)
                   {
                      System.err.println("Cannot find this shape!");
                      continue;
                   }
                   Shape sourceshape = (Shape) diagram.getChildren().get(sourceindex);
                   Shape targetshape = (Shape) diagram.getChildren().get(targetindex);
                   Connection conn = new Connection(sourceshape, targetshape);
                }
                    
                reader.close();*/

                SAXReader reader = new SAXReader();
                Document document;
                try {
                    reader.setEncoding("UTF-8");
                    document = reader.read(file.getContents());//
                } catch (DocumentException ex) {
                    System.err.println("Cannot read input file!");
                    ex.printStackTrace();
                    throw new CoreException(null);
                }
                Element root = document.getRootElement();
                Element shaperoot = root.element("shapes");
                List list = shaperoot.elements("shape");
                Iterator it = list.iterator();
                ArrayList<String> shapename = new ArrayList<String>();
                while (it.hasNext()) {
                    Element shapeElm = (Element) it.next();
                    int height, width, x, y;
                    String name = shapeElm.elementText("name");
                    try {
                        height = Integer.parseInt(shapeElm.elementText("height"));
                        width = Integer.parseInt(shapeElm.elementText("width"));
                        x = Integer.parseInt(shapeElm.elementText("locx"));
                        y = Integer.parseInt(shapeElm.elementText("locy"));
                        Shape sp;
                        if (name.contains("Ellipse")) {
                            sp = new EllipticalShape();
                        } else if (name.contains("Triangle")) {
                            sp = new TriangularShape();
                        } else if (name.contains("Rectangle")) {
                            sp = new RectangularShape();
                        } else {
                            System.err.println("Shape unsupported!");
                            sp = new EllipticalShape();
                        }
                        diagram.addChild(sp);
                        sp.setSize(new Dimension(width, height));
                        sp.setLocation(new Point(x, y));
                        shapename.add(name);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                Element connroot = root.element("connections");
                list = connroot.elements("connection");
                it = list.iterator();
                while (it.hasNext()) {
                    Element connElm = (Element) it.next();
                    String source = connElm.elementText("source");
                    String target = connElm.elementText("target");
                    int sourceindex = shapename.indexOf(source);
                    int targetindex = shapename.indexOf(target);
                    if (sourceindex == -1 || targetindex == -1) {
                        System.err.println("Cannot find this shape!");
                        continue;
                    }
                    Shape sourceshape = (Shape) diagram.getChildren().get(sourceindex);
                    Shape targetshape = (Shape) diagram.getChildren().get(targetindex);
                    new Connection(sourceshape, targetshape);
                }
            }
            setPartName(file.getName());
        } catch (CoreException e) {
            handleLoadException(e);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Creates an outline pagebook for this editor.
     */
    public class ShapesOutlinePage extends ContentOutlinePage {
        /**
         * Create a new outline page for the shapes editor.
         * 
         * @param viewer
         *            a viewer (TreeViewer instance) used for this outline page
         * @throws IllegalArgumentException
         *             if editor is null
         */
        public ShapesOutlinePage(EditPartViewer viewer) {
            super(viewer);
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite
         * )
         */
        @Override
        public void createControl(Composite parent) {
            // create outline viewer page
            getViewer().createControl(parent);
            // configure outline viewer
            getViewer().setEditDomain(getEditDomain());
            getViewer().setEditPartFactory(new ShapesTreeEditPartFactory());
            // configure & add context menu to viewer
            ContextMenuProvider cmProvider = new ShapesEditorContextMenuProvider(getViewer(), getActionRegistry());
            getViewer().setContextMenu(cmProvider);
            getSite().registerContextMenu("com.oubeichen.gefexp.outline.contextmenu", cmProvider,
                    getSite().getSelectionProvider());
            // hook outline viewer
            getSelectionSynchronizer().addViewer(getViewer());
            // initialize outline viewer with model
            getViewer().setContents(getModel());
            // show outline viewer
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.part.IPage#dispose()
         */
        @Override
        public void dispose() {
            // unhook outline viewer
            getSelectionSynchronizer().removeViewer(getViewer());
            // dispose
            super.dispose();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.part.IPage#getControl()
         */
        @Override
        public Control getControl() {
            return getViewer().getControl();
        }

        /**
         * @see org.eclipse.ui.part.IPageBookViewPage#init(org.eclipse.ui.part.IPageSite)
         */
        @Override
        public void init(IPageSite pageSite) {
            super.init(pageSite);
            ActionRegistry registry = getActionRegistry();
            IActionBars bars = pageSite.getActionBars();
            String id = ActionFactory.UNDO.getId();
            bars.setGlobalActionHandler(id, registry.getAction(id));
            id = ActionFactory.REDO.getId();
            bars.setGlobalActionHandler(id, registry.getAction(id));
            id = ActionFactory.DELETE.getId();
            bars.setGlobalActionHandler(id, registry.getAction(id));
        }
    }

}