/**
* Copyright (c) 2006, 2007 Borland Software Corporation
*
* 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:
* bblajer - initial API and implementation
*/
package org.eclipse.gmf.runtime.lite.parts;
import java.io.IOException;
import java.util.Collections;
import java.util.EventObject;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.GraphicalViewer;
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.editparts.ScalableRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.gef.ui.actions.StackAction;
import org.eclipse.gef.ui.actions.WorkbenchPartAction;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences;
import org.eclipse.gef.ui.parts.GraphicalEditor;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.gef.ui.parts.SelectionSynchronizer;
import org.eclipse.gef.ui.views.palette.PaletteViewerPage;
import org.eclipse.gmf.internal.runtime.lite.Activator;
import org.eclipse.gmf.runtime.lite.properties.PropertySourceProvider;
import org.eclipse.gmf.runtime.lite.properties.RootUndoablePropertySheetEntry;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.views.properties.PropertySheetPage;
/**
* @author bblajer
*/
public class DiagramDisplayer implements IDiagramOutlineHost {
private TransactionalEditingDomain editingDomain;
private PaletteRoot paletteRoot;
private PropertySheetPage undoablePropertySheetPage;
private GraphicalViewer graphicalViewer;
private ActionRegistry actionRegistry;
private UpdatableActionGroup stackActions = new UpdatableActionGroup();
private EditDomain myEditDomain;
private IDiagramManager myDiagramManager;
private FlyoutPaletteComposite mySplitter;
private PaletteViewerProvider myPaletteViewerProvider;
private PaletteViewerPage myPalettePage;
private SelectionSynchronizer synchronizer;
private Control myTopLevelControl;
private CommandStackListener commandStackListener = new CommandStackListener() {
public void commandStackChanged(EventObject event) {
stackActions.update();
}
};
private UpdatableActionGroup editPartActions = new UpdatableActionGroup();
private ISelectionListener selectionListener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
editPartActions.update();
}
};
private UpdatableActionGroup propertyActions = new UpdatableActionGroup();
private IPropertyListener propertyListener = new IPropertyListener() {
public void propertyChanged(Object source, int propId) {
propertyActions.update();
}
};
/**
* Constructs a new instance of the diagram displayer.
*/
public DiagramDisplayer(IDiagramManager diagramManager, EditDomain gefEditDomain, TransactionalEditingDomain emfEditingDomain) {
myDiagramManager = diagramManager;
assert gefEditDomain != null;
assert emfEditingDomain != null;
setEditDomain(gefEditDomain);
editingDomain = emfEditingDomain;
gefEditDomain.setCommandStack(createCommandStack());
getCommandStack().addCommandStackListener(commandStackListener);
myDiagramManager.getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(selectionListener);
myDiagramManager.getSite().getPart().addPropertyListener(propertyListener);
}
private CommandStack createCommandStack() {
CommandStackAdapterManager manager = (CommandStackAdapterManager) EcoreUtil.getExistingAdapter(editingDomain.getResourceSet(), CommandStackAdapterManager.class);
if (manager == null) {
manager = new CommandStackAdapterManager();
editingDomain.getResourceSet().eAdapters().add(manager);
}
manager.acquire();
return manager.getCommandStack();
}
public void dispose() {
// remove CommandStackListener
getCommandStack().removeCommandStackListener(commandStackListener);
// remove selection listener
myDiagramManager.getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(selectionListener);
myDiagramManager.getSite().getPart().removePropertyListener(propertyListener);
getEditDomain().setActiveTool(null);
CommandStackAdapterManager manager = (CommandStackAdapterManager) EcoreUtil.getExistingAdapter(getEditingDomain().getResourceSet(), CommandStackAdapterManager.class);
assert manager != null;
manager.release();
if (manager.isReleased()) {
getEditingDomain().getResourceSet().eAdapters().remove(manager);
}
// dispose the ActionRegistry (will dispose all actions)
getActionRegistry().dispose();
}
protected ZoomManager getZoomManager() {
return getZoomManager(getGraphicalViewer());
}
private ZoomManager getZoomManager(GraphicalViewer viewer) {
// get zoom manager from root edit part
RootEditPart rootEditPart = viewer.getRootEditPart();
ZoomManager zoomManager = null;
if (rootEditPart instanceof ScalableFreeformRootEditPart) {
zoomManager = ((ScalableFreeformRootEditPart) rootEditPart).getZoomManager();
} else if (rootEditPart instanceof ScalableRootEditPart) {
zoomManager = ((ScalableRootEditPart) rootEditPart).getZoomManager();
}
return zoomManager;
}
protected PaletteRoot getPaletteRoot() {
if (paletteRoot == null) {
paletteRoot = new PaletteRoot();
myDiagramManager.configurePalette(paletteRoot);
}
return paletteRoot;
}
public CommandStack getCommandStack() {
return myEditDomain.getCommandStack();
}
protected PropertySheetPage getPropertySheetPage() {
if (undoablePropertySheetPage == null) {
undoablePropertySheetPage = new PropertySheetPage();
RootUndoablePropertySheetEntry rootEntry = new RootUndoablePropertySheetEntry(getCommandStack(), undoablePropertySheetPage);
rootEntry.setPropertySourceProvider(new PropertySourceProvider(myDiagramManager.getDomainAdapterFactory()));
undoablePropertySheetPage.setRootEntry(rootEntry);
}
return undoablePropertySheetPage;
}
/**
* 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);
}
/**
* 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);
propertyActions.addAction(action);
}
/**
* 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);
editPartActions.addAction(action);
}
/**
* 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);
stackActions.addAction(action);
}
public ActionRegistry getActionRegistry() {
if (actionRegistry == null)
actionRegistry = new ActionRegistry();
return actionRegistry;
}
public TransactionalEditingDomain getEditingDomain() {
return editingDomain;
}
public void createViewer(Composite parent) {
if (myDiagramManager.isFlyoutPalette()) {
mySplitter = new FlyoutPaletteComposite(parent, SWT.NONE, myDiagramManager.getSite().getPage(), getPaletteViewerProvider(), getPalettePreferences());
createGraphicalViewer(mySplitter);
myTopLevelControl = mySplitter;
} else {
SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
createGraphicalViewer(sashForm);
getPaletteViewerProvider().createPaletteViewer(sashForm);
sashForm.setWeights(new int[] {85, 15}); //TODO: allow customization and persistence
myTopLevelControl = sashForm;
}
}
/**
* Creates the GraphicalViewer on the specified <code>Composite</code>.
* @param parent the parent composite
*/
protected void createGraphicalViewer(Composite parent) {
GraphicalViewer viewer = new ScrollingGraphicalViewer();
viewer.createControl(parent);
setGraphicalViewer(viewer);
hookGraphicalViewer();
myDiagramManager.configureGraphicalViewer();
initializeGraphicalViewer();
}
/**
* Sets the graphicalViewer for this diagram displayer.
* @param viewer the graphical viewer
*/
protected void setGraphicalViewer(GraphicalViewer viewer) {
myEditDomain.addViewer(viewer);
graphicalViewer = viewer;
if (mySplitter != null) {
mySplitter.setGraphicalControl(graphicalViewer.getControl());
}
}
public GraphicalViewer getGraphicalViewer() {
return graphicalViewer;
}
/**
* Hooks the GraphicalViewer to the rest of the Editor. By default, the viewer
* is added to the SelectionSynchronizer, which can be used to keep 2 or more
* EditPartViewers in sync. The viewer is also registered as the ISelectionProvider
* for the Editor's PartSite.
*/
protected void hookGraphicalViewer() {
getSelectionSynchronizer().addViewer(getGraphicalViewer());
myDiagramManager.getSite().setSelectionProvider(getGraphicalViewer());
}
/**
* @see GraphicalEditor#initializeGraphicalViewer()
*/
protected void initializeGraphicalViewer() {
if (mySplitter != null) {
mySplitter.hookDropTargetListener(getGraphicalViewer());
}
myDiagramManager.initializeGraphicalViewer();
}
/**
* Returns the selection syncronizer object. The synchronizer can be used to sync the
* selection of 2 or more EditPartViewers.
* @return the syncrhonizer
*/
public final SelectionSynchronizer getSelectionSynchronizer() {
if (synchronizer == null)
synchronizer = new SelectionSynchronizer();
return synchronizer;
}
public void setFocus() {
getGraphicalViewer().getControl().setFocus();
}
private PaletteViewerProvider getPaletteViewerProvider() {
if (myPaletteViewerProvider == null)
myPaletteViewerProvider = createPaletteViewerProvider();
return myPaletteViewerProvider;
}
/**
* 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 PaletteViewerProvider(myEditDomain);
}
protected void setEditDomain(EditDomain ed) {
myEditDomain = ed;
myEditDomain.setPaletteRoot(getPaletteRoot());
}
public EditDomain getEditDomain() {
return myEditDomain;
}
public Control getTopLevelControl() {
return myTopLevelControl;
}
public Control getGraphicalControl() {
return getGraphicalViewer().getControl();
}
/**
* Returns a FlyoutPreferences object that stores the flyout
* settings in the lite runtime plugin.
* @return the FlyoutPreferences object used to save the flyout palette's preferences
*/
private FlyoutPreferences getPalettePreferences() {
return FlyoutPaletteComposite
.createFlyoutPreferences(Activator.getDefault().getPluginPreferences());
}
public PaletteViewerPage getPalettePage() {
if (myPalettePage == null) {
myPalettePage = new CustomPalettePage(getPaletteViewerProvider());
}
return myPalettePage;
}
private class CustomPalettePage extends PaletteViewerPage {
public CustomPalettePage(PaletteViewerProvider provider) {
super(provider);
}
public void createControl(Composite parent) {
super.createControl(parent);
if (mySplitter != null)
mySplitter.setExternalViewer(viewer);
}
public void dispose() {
if (mySplitter != null)
mySplitter.setExternalViewer(null);
super.dispose();
}
}
/**
* @deprecated Use {@link #save(Map, IProgressMonitor)} instead.
*/
public void save(IProgressMonitor progressMonitor) throws CoreException {
save(Collections.emptyMap(), progressMonitor);
}
public void save(Map<?, ?> options, IProgressMonitor progressMonitor) throws CoreException {
if (progressMonitor == null) {
progressMonitor = new NullProgressMonitor();
}
progressMonitor.beginTask("Saving", getEditingDomain().getResourceSet().getResources().size());
try {
for(Resource next : getEditingDomain().getResourceSet().getResources()) {
if (next.isLoaded() && !getEditingDomain().isReadOnly(next)) {
next.save(options);
}
progressMonitor.worked(1);
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), 0, "Error writing file.", e);
throw new CoreException(status);
} finally {
progressMonitor.done();
}
}
}