package com.realpersist.gef.editor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GEFPlugin;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.DeleteAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.actions.PrintAction;
import org.eclipse.gef.ui.actions.RedoAction;
import org.eclipse.gef.ui.actions.SaveAction;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.gef.ui.actions.StackAction;
import org.eclipse.gef.ui.actions.UndoAction;
import org.eclipse.gef.ui.actions.UpdateAction;
import org.eclipse.gef.ui.actions.WorkbenchPartAction;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;
import com.realpersist.gef.action.SchemaContextMenuProvider;
import com.realpersist.gef.model.Schema;
/**
* Editor implementation based on the the example editor skeleton that is built in <i>Building
* an editor </i> in chapter <i>Introduction to GEF </i>
*/
public class SchemaDiagramEditor extends GraphicalEditorWithFlyoutPalette
implements
CommandStackListener,
ISelectionListener
{
private Schema schema;
/** the undoable <code>IPropertySheetPage</code> */
private PropertySheetPage undoablePropertySheetPage;
/** the graphical viewer */
private GraphicalViewer graphicalViewer;
/** the list of action ids that are to EditPart actions */
private List editPartActionIDs = new ArrayList();
/** the list of action ids that are to CommandStack actions */
private List stackActionIDs = new ArrayList();
/** the list of action ids that are editor actions */
private List editorActionIDs = new ArrayList();
/** the overview outline page */
private OverviewOutlinePage overviewOutlinePage;
/** the editor's action registry */
private ActionRegistry actionRegistry;
/** the <code>EditDomain</code> */
private DefaultEditDomain editDomain;
/** the dirty state */
private boolean isDirty;
/**
* No-arg constructor
*/
public SchemaDiagramEditor()
{
editDomain = new DefaultEditDomain(this);
setEditDomain(editDomain);
}
/**
* Initializes the editor.
*/
public void init(IEditorSite site, IEditorInput input) throws PartInitException
{
// store site and input
setSite(site);
setInput(input);
// add CommandStackListener
getCommandStack().addCommandStackListener(this);
// add selection change listener
getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this);
// initialize actions
createActions();
}
/** the selection listener implementation */
public void selectionChanged(IWorkbenchPart part, ISelection selection)
{
updateActions(editPartActionIDs);
}
/**
* The <code>CommandStackListener</code> that listens for
* <code>CommandStack </code> changes.
*/
public void commandStackChanged(EventObject event)
{
updateActions(stackActionIDs);
setDirty(getCommandStack().isDirty());
}
/**
* Returns the <code>GraphicalViewer</code> of this editor.
*
* @return the <code>GraphicalViewer</code>
*/
public GraphicalViewer getGraphicalViewer()
{
return graphicalViewer;
}
public void dispose()
{
// remove CommandStackListener
getCommandStack().removeCommandStackListener(this);
// remove selection listener
getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this);
// dispos3 the ActionRegistry (will dispose all actions)
getActionRegistry().dispose();
// important: always call super implementation of dispose
super.dispose();
}
/**
* Adaptable implementation for Editor
*/
public Object getAdapter(Class adapter)
{
// we need to handle common GEF elements we created
if (adapter == GraphicalViewer.class || adapter == EditPartViewer.class)
return getGraphicalViewer();
else if (adapter == CommandStack.class)
return getCommandStack();
else if (adapter == EditDomain.class)
return getEditDomain();
else if (adapter == ActionRegistry.class)
return getActionRegistry();
else if (adapter == IPropertySheetPage.class)
return getPropertySheetPage();
else if (adapter == IContentOutlinePage.class)
return getOverviewOutlinePage();
// the super implementation handles the rest
return super.getAdapter(adapter);
}
/**
* Saves the schema model to the file
*
* @see EditorPart#doSave
*/
public void doSave(IProgressMonitor monitor)
{
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objectOut = new ObjectOutputStream(out);
objectOut.writeObject(schema);
objectOut.close();
IFile file = ((IFileEditorInput) getEditorInput()).getFile();
file.setContents(new ByteArrayInputStream(out.toByteArray()), true, false, monitor);
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
getCommandStack().markSaveLocation();
}
/**
* Save as not allowed
*/
public void doSaveAs()
{
throw new UnsupportedOperationException();
}
/**
* Save as not allowed
*/
public boolean isSaveAsAllowed()
{
return false;
}
/**
* Indicates if the editor has unsaved changes.
*
* @see EditorPart#isDirty
*/
public boolean isDirty()
{
return isDirty;
}
/**
* Returns the <code>CommandStack</code> of this editor's
* <code>EditDomain</code>.
*
* @return the <code>CommandStack</code>
*/
public CommandStack getCommandStack()
{
return getEditDomain().getCommandStack();
}
/**
* Returns the schema model associated with the editor
*
* @return an instance of <code>Schema</code>
*/
public Schema getSchema()
{
return schema;
}
/**
* @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
*/
protected void setInput(IEditorInput input)
{
super.setInput(input);
IFile file = ((IFileEditorInput) input).getFile();
try
{
setPartName(file.getName());
InputStream is = file.getContents(true);
ObjectInputStream ois = new ObjectInputStream(is);
schema = (Schema) ois.readObject();
ois.close();
}
catch (Exception e)
{
e.printStackTrace();
schema = getContent();
}
}
/**
* Creates a PaletteViewerProvider that will be used to create palettes for
* the view and the flyout.
*
* @return the palette provider
*/
protected PaletteViewerProvider createPaletteViewerProvider()
{
return new SchemaPaletteViewerProvider(editDomain);
}
/**
* Creates a new <code>GraphicalViewer</code>, configures, registers and
* initializes it.
*
* @param parent
* the parent composite
* @return a new <code>GraphicalViewer</code>
*/
protected void createGraphicalViewer(Composite parent)
{
IEditorSite editorSite = getEditorSite();
GraphicalViewer viewer = new GraphicalViewerCreator(editorSite).createViewer(parent);
GraphicalViewerKeyHandler graphicalViewerKeyHandler = new GraphicalViewerKeyHandler(viewer);
KeyHandler parentKeyHandler = graphicalViewerKeyHandler.setParent(getCommonKeyHandler());
viewer.setKeyHandler(parentKeyHandler);
// hook the viewer into the EditDomain
getEditDomain().addViewer(viewer);
// acticate the viewer as selection provider for Eclipse
getSite().setSelectionProvider(viewer);
viewer.setContents(schema);
ContextMenuProvider provider = new SchemaContextMenuProvider(viewer, getActionRegistry());
viewer.setContextMenu(provider);
getSite().registerContextMenu("com.realpersist.gef.editor.contextmenu", provider, viewer);
this.graphicalViewer = viewer;
}
protected KeyHandler getCommonKeyHandler()
{
KeyHandler sharedKeyHandler = new KeyHandler();
sharedKeyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0), getActionRegistry().getAction(
GEFActionConstants.DELETE));
sharedKeyHandler.put(KeyStroke.getPressed(SWT.F2, 0), getActionRegistry().getAction(
GEFActionConstants.DIRECT_EDIT));
return sharedKeyHandler;
}
/**
* Sets the dirty state of this editor.
*
* <p>
* An event will be fired immediately if the new state is different than the
* current one.
*
* @param dirty
* the new dirty state to set
*/
protected void setDirty(boolean dirty)
{
if (isDirty != dirty)
{
isDirty = dirty;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
/**
* Creates actions and registers them to the ActionRegistry.
*/
protected void createActions()
{
addStackAction(new UndoAction(this));
addStackAction(new RedoAction(this));
addEditPartAction(new DeleteAction((IWorkbenchPart) this));
addEditorAction(new SaveAction(this));
addEditorAction(new PrintAction(this));
}
/**
* Adds an <code>EditPart</code> action to this editor.
*
* <p>
* <code>EditPart</code> actions are actions that depend and work on the
* selected <code>EditPart</code>s.
*
* @param action
* the <code>EditPart</code> action
*/
protected void addEditPartAction(SelectionAction action)
{
getActionRegistry().registerAction(action);
editPartActionIDs.add(action.getId());
}
/**
* Adds an <code>CommandStack</code> action to this editor.
*
* <p>
* <code>CommandStack</code> actions are actions that depend and work on
* the <code>CommandStack</code>.
*
* @param action
* the <code>CommandStack</code> action
*/
protected void addStackAction(StackAction action)
{
getActionRegistry().registerAction(action);
stackActionIDs.add(action.getId());
}
/**
* Adds an editor action to this editor.
*
* <p>
* <Editor actions are actions that depend and work on the editor.
*
* @param action
* the editor action
*/
protected void addEditorAction(WorkbenchPartAction action)
{
getActionRegistry().registerAction(action);
editorActionIDs.add(action.getId());
}
/**
* Adds an action to this editor's <code>ActionRegistry</code>. (This is
* a helper method.)
*
* @param action
* the action to add.
*/
protected void addAction(IAction action)
{
getActionRegistry().registerAction(action);
}
/**
* Updates the specified actions.
*
* @param actionIds
* the list of ids of actions to update
*/
protected void updateActions(List actionIds)
{
for (Iterator ids = actionIds.iterator(); ids.hasNext();)
{
IAction action = getActionRegistry().getAction(ids.next());
if (null != action && action instanceof UpdateAction)
((UpdateAction) action).update();
}
}
/**
* Returns the action registry of this editor.
*
* @return the action registry
*/
protected ActionRegistry getActionRegistry()
{
if (actionRegistry == null)
actionRegistry = new ActionRegistry();
return actionRegistry;
}
/**
* Returns the overview for the outline view.
*
* @return the overview
*/
protected OverviewOutlinePage getOverviewOutlinePage()
{
if (null == overviewOutlinePage && null != getGraphicalViewer())
{
RootEditPart rootEditPart = getGraphicalViewer().getRootEditPart();
if (rootEditPart instanceof ScalableFreeformRootEditPart)
{
overviewOutlinePage = new OverviewOutlinePage((ScalableFreeformRootEditPart) rootEditPart);
}
}
return overviewOutlinePage;
}
/**
* Returns the undoable <code>PropertySheetPage</code> for this editor.
*
* @return the undoable <code>PropertySheetPage</code>
*/
protected PropertySheetPage getPropertySheetPage()
{
if (null == undoablePropertySheetPage)
{
undoablePropertySheetPage = new PropertySheetPage();
undoablePropertySheetPage.setRootEntry(GEFPlugin.createUndoablePropertySheetEntry(getCommandStack()));
}
return undoablePropertySheetPage;
}
/*
*/
protected void firePropertyChange(int propertyId)
{
super.firePropertyChange(propertyId);
updateActions(editorActionIDs);
}
/**
* @return the preferences for the Palette Flyout
*/
protected FlyoutPreferences getPalettePreferences()
{
return new PaletteFlyoutPreferences();
}
/**
* @return the PaletteRoot to be used with the PaletteViewer
*/
protected PaletteRoot getPaletteRoot()
{
return new PaletteViewerCreator().createPaletteRoot();
}
/**
* Returns the content of this editor
*
* @return the model object
*/
private Schema getContent()
{
return new ContentCreator().getContent();
}
private static ImageDescriptor create(String iconPath, String name)
{
return AbstractUIPlugin.imageDescriptorFromPlugin("com.realpersist.gef.schemaeditor", iconPath + name);
}
/* $codepro.preprocessor.if version <= 3.1 $
//Necessary for Eclipse 3.1
protected org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences getPalettePreferences() {
// TODO what should be returned here?
return null;
}
$codepro.preprocessor.endif $ */
}