package org.framed.orm.ui.editor;
import java.io.IOException;
import java.util.EventObject;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorActionBarContributor;
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.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.framed.orm.model.Model;
import org.framed.orm.model.Shape;
import org.framed.orm.model.OrmPackage;
import org.framed.orm.model.Type;
/**
*
* This {@link MultiPageEditorPart} has as pages the behaviour {@link ORMGraphicalEditor} and the
* data {@link ORMGraphicalEditor}.
*
* @author Kay Bierzynski
* @author Lars Schütze
* */
public class ORMMultiPageEditor extends MultiPageEditorPart implements ISelectionListener,
CommandStackListener, IResourceChangeListener {
/**
* The behaviour {@link ORMGraphicalEditor}, which is manages through this editor.
* */
private ORMGraphicalEditor behaviourEditor;
/**
* The data {@link ORMGraphicalEditor}, which is manages through this editor.
* */
private ORMGraphicalEditor dataEditor;
/**
* The {@link EditorChangeNotifier} of this editor.
* */
private EditorChangeNotifier changeNotifier;
/**
* The input {@link Resource} of this editor, which contains the emf model.
* */
private Resource resource;
/**
* The name of the file, which contains the model resources. This variable is necessary for the
* creation of custom title for this edito.
*/
private String inputFilename;
/**
* The constructor of this class, where {@link MultiPageEditorPart#MultiPageEditorPart()} is
* called, inputFilename and changeNotifier are initialized and a listener to the model resources
* is added.
* */
public ORMMultiPageEditor() {
super();
inputFilename = "";
changeNotifier = null;
ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
}
/**
* A setter for the {@link EditorChangeNotifier} of this editor.
* */
public void setEditorChangeNotifier(final EditorChangeNotifier changeNotifier) {
this.changeNotifier = changeNotifier;
}
/**
* This method creates a custom title for this editor out of resource file name, the genral model
* element term and the specific model/{@link Type} element name of the model element which is the content of
* the viewer of data/behaviour {@link ORMGraphicalEditor}.
* */
public void createCustomTitleForEditor(final Object model) {
if (model instanceof Model || model instanceof Shape) {
final String modelClassName = model.getClass().getSimpleName();
setTitle(inputFilename + " " + modelClassName.substring(0, modelClassName.length() - 4));
if (model instanceof Shape) {
Shape shape = ((Shape) model);
if (shape.getType() == Type.COMPARTMENT_TYPE) {
setTitle(inputFilename + " " + "CompartmentType" + " " + shape.getName());
}
if (shape.getType() == Type.GROUP) {
setTitle(inputFilename + " " + "Group" + " " + shape.getName());
}
}
}
}
/**
* A getter for name of input resource file.
*
* @return inputFilename String
* */
public String getInputFileName() {
return inputFilename;
}
/** {@inheritDoc} */
@Override
public void setTitleImage(final Image titleImage) {
super.setTitleImage(titleImage);
}
/**
* This method creates the beahvior {@link ORMGraphicalEditor} and adds the behaviour editor as a
* page to this editor.
*/
private void createBehaviorEditorPage() {
try {
behaviourEditor = new ORMGraphicalEditor(this, resource, false);
int index = addPage(behaviourEditor, getEditorInput());
setPageText(index, "Behavior");
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(), "Error creating nested orm editor", null,
e.getStatus());
}
}
/**
* This method creates the data {@link ORMGraphicalEditor} and adds the behaviour data as a page
* to this editor.
*/
private void createDataEditorPage() {
try {
dataEditor = new ORMGraphicalEditor(this, resource, true);
int index = addPage(dataEditor, getEditorInput());
setPageText(index, "Data");
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(), "Error creating nested orm editor", null,
e.getStatus());
}
}
/** {@inheritDoc} In this method the title image of this editor is set as well. */
@Override
protected void createPages() {
createBehaviorEditorPage();
createDataEditorPage();
// set TitleImage of this ORMMultiPageEditor with background color of the viewer of the
// behaivorEditor
Image img =
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/rosi-icon-smaller.gif")
.createImage();
img.setBackground(behaviourEditor.getGraphicalControl().getBackground());
setTitleImage(img);
}
/**
* {@inheritDoc} The implementation of the {@link ORMMultiPageEditor} tests if the editor input is
* from type {@link IFileEditorInput}, adds a selection listener and initializes the input
* resource.
*/
@Override
public void init(final IEditorSite site, final IEditorInput editorInput) throws PartInitException {
if (!(editorInput instanceof IFileEditorInput)) {
throw new PartInitException("Invalid Input: Must be IFileEditorInput");
}
super.init(site, editorInput);
getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this);
initializeResource(editorInput);
}
/**
* This method initializes the model resource, which serves as input for this editor.
* */
private void initializeResource(final IEditorInput editorInput) {
OrmPackage.eINSTANCE.eClass(); // This initializes the OrmPackage singleton implementation.
ResourceSet resourceSet = new ResourceSetImpl();
if (editorInput instanceof IFileEditorInput) {
IFileEditorInput fileInput = (IFileEditorInput) editorInput;
IFile file = fileInput.getFile();
inputFilename = file.getName();
resource = resourceSet.createResource(URI.createURI(file.getLocationURI().toString()));
try {
resource.load(null);
} catch (IOException e) {
// TODO do something smarter.
e.printStackTrace();
resource = null;
}
}
}
/**
* {@inheritDoc} The implementation of the {@link ORMMultiPageEditor} saves the all editor, which
* work on the same input resource and are registered through a page.
*/
@Override
public void doSave(final IProgressMonitor monitor) {
for (int i = 0; i < getPageCount(); i++) {
IEditorPart editorPart = getEditor(i);
if (editorPart.isDirty()) {
editorPart.doSave(monitor);
}
}
}
/**
* Does at the moment nothing, because {@link ORMGraphicalEditor#doSaveAs()} isn't implemented.
* */
@Override
public void doSaveAs() {
if (behaviourEditor.equals(getActiveEditor())) {
behaviourEditor.doSaveAs();
setInput(behaviourEditor.getEditorInput());
}
if (dataEditor.equals(getActiveEditor())) {
dataEditor.doSaveAs();
setInput(dataEditor.getEditorInput());
}
}
/**
* {@inheritDoc} At the moment this method returns always true, because SaveAs functionalty isn't
* implemented.
*/
@Override
public boolean isSaveAsAllowed() {
return true;
}
/** This method enables select action for the active editor. */
@Override
public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
if (this.equals(getSite().getPage().getActiveEditor())) {
if (behaviourEditor.equals(getActiveEditor())) {
behaviourEditor.selectionChanged(getActiveEditor(), selection);
}
if (dataEditor.equals(getActiveEditor()))
dataEditor.selectionChanged(getActiveEditor(), selection);
}
}
/**
* {@inheritDoc} This method needs to be overriden so that when you switch between the editors the
* actionbarcontributer takes the actionregistry/graphicalViewer/CommandStack from the active
* editor.
* */
@Override
protected void pageChange(final int newPageIndex) {
super.pageChange(newPageIndex);
IEditorPart activeEditor = getEditor(newPageIndex);
IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor();
if (contributor != null && contributor instanceof ORMGraphicalEditorActionBarContributor) {
((ORMGraphicalEditorActionBarContributor) contributor).setActiveEditor(activeEditor);
}
}
/**
* Called when the CommandStack state of the active editor has changed.
* */
@Override
public void commandStackChanged(EventObject event) {
if (this.equals(getSite().getPage().getActiveEditor())) {
if (behaviourEditor.equals(getActiveEditor())) {
behaviourEditor.commandStackChanged(event);
}
if (dataEditor.equals(getActiveEditor())) {
dataEditor.commandStackChanged(event);
}
}
}
/**
* Closes all project files on project close.
*/
@Override
public void resourceChanged(final IResourceChangeEvent event) {
if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
for (int i = 0; i < pages.length; i++) {
if (((FileEditorInput) behaviourEditor.getEditorInput()).getFile().getProject()
.equals(event.getResource())) {
IEditorPart editorPart = pages[i].findEditor(behaviourEditor.getEditorInput());
pages[i].closeEditor(editorPart, true);
}
}
}
});
}
}
/**
* A getter for behaviour editor, which registered by this editor.
*
* @reutrn {@link ORMGraphicalEditor}
* */
public ORMGraphicalEditor getBehaviorEditor() {
return behaviourEditor;
}
/**
* A getter for data editor, which registered by this editor.
*
* @reutrn {@link ORMGraphicalEditor}
* */
public ORMGraphicalEditor getDataEditor() {
return dataEditor;
}
/**
* Sets the object obj as content in the behavior editor and data editor
*
* @param obj The object which will be set as content
*/
public void setContents(final Object obj) {
/*
* first, check which editor type we will get when setting the object as content. The palette
* will be updated
*/
getBehaviorEditor().getOwnViewer().setContents(obj);
getDataEditor().getOwnViewer().setContents(obj);
}
}