package org.jbpm.gd.common.editor;
import java.util.ArrayList;
import java.util.EventObject;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.INestableKeyBindingService;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart;
import org.jbpm.gd.common.model.SemanticElement;
import org.jbpm.gd.common.model.SemanticElementFactory;
import org.jbpm.gd.common.notation.NotationElementFactory;
import org.jbpm.gd.common.notation.RootContainer;
import org.jbpm.gd.common.xml.XmlAdapter;
import org.jbpm.gd.common.xml.XmlAdapterFactory;
import org.jbpm.gd.jpdl.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public abstract class Editor extends XMLMultiPageEditorPart implements
ITabbedPropertySheetPageContributor {
private ActionRegistry actionRegistry;
private EditDomain editDomain;
private CommandStackListener commandStackListener;
private boolean isDirty = false;
private ISelectionListener selectionListener;
private SelectionSynchronizer selectionSynchronizer;
private SemanticElementFactory semanticElementFactory;
private NotationElementFactory notationElementFactory;
private RootContainer rootContainer;
private GraphPage graphPage;
private StructuredTextEditor sourcePage;
private MenuManager sourceContextMenuManager;
private ContentProvider contentProvider;
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
super.init(site, input);
initActionRegistry();
initEditDomain();
initCommandStackListener();
initSelectionListener();
initSelectionSynchronizer();
}
protected void createPages() {
super.createPages();
initSourcePage();
initGraphPage();
setActivePage(0);
checkReadOnly();
}
protected void addPage(int index, IEditorPart part, String label) {
try {
addPage(index, part, getEditorInput());
setPageText(index, label);
} catch (PartInitException e) {
Logger.logError("Could not create editor page", e);
}
}
public String getContributorId() {
return getSite().getId();
}
private void initActionRegistry() {
actionRegistry = new ActionRegistry(this);
}
private void initEditDomain() {
editDomain = new DefaultEditDomain(this);
}
private void initSelectionSynchronizer() {
selectionSynchronizer = createSelectionSynchronizer();
}
private void initCommandStackListener() {
commandStackListener = new CommandStackListener() {
public void commandStackChanged(EventObject event) {
handleCommandStackChanged();
}
};
getCommandStack().addCommandStackListener(commandStackListener);
}
private void initSelectionListener() {
selectionListener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part,
ISelection selection) {
getActionRegistry().updateEditPartActions();
}
};
ISelectionService selectionService = getSite().getWorkbenchWindow()
.getSelectionService();
selectionService.addSelectionListener(selectionListener);
}
protected void initGraphPage() {
graphPage = new GraphPage(this);
addPage(0, graphPage, "Diagram");
getContentProvider().addNotationInfo(getRootContainer(), getEditorInput());
}
protected void initSourcePage() {
int pageCount = getPageCount();
for (int i = 0; i < pageCount; i++) {
if (getEditor(i) instanceof StructuredTextEditor) {
sourcePage = (StructuredTextEditor) getEditor(i);
SemanticElement semanticElement = getSemanticElement(sourcePage);
CreationFactory factory = new CreationFactory(semanticElement.getElementId(), getSemanticElementFactory(), getNotationElementFactory());
setRootContainer((RootContainer)factory.getNewObject());
getRootContainer().setSemanticElement(semanticElement);
semanticElement.addPropertyChangeListener(getRootContainer());
}
}
if (sourcePage != null) {
initSourcePageContextMenu(sourcePage.getTextViewer()
.getTextWidget());
}
}
private SemanticElement getSemanticElement(
StructuredTextEditor sourcePage) {
Node node = getDocumentElement(sourcePage);
XmlAdapterFactory factory = new XmlAdapterFactory(node.getOwnerDocument(), getSemanticElementFactory());
XmlAdapter xmlAdapter = factory.adapt(node);
SemanticElement semanticElement = createMainElement();
xmlAdapter.initialize(semanticElement);
return semanticElement;
}
private Node getDocumentElement(StructuredTextEditor sourcePage) {
Node result = null;
Document document = (Document) sourcePage
.getAdapter(Document.class);
if (document != null) {
result = (Node) document.getDocumentElement();
}
return result;
}
private void initSourcePageContextMenu(final Control control) {
sourceContextMenuManager = new MenuManager("#PopupMenu");
sourceContextMenuManager.setRemoveAllWhenShown(true);
sourceContextMenuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager m) {
fillContextMenu(m);
}
});
Menu menu = sourceContextMenuManager.createContextMenu(control);
getSite().registerContextMenu(
"org.jbpm.ui.editor.DesignerEditor.SourcePopupMenu",
sourceContextMenuManager, getSite().getSelectionProvider());
control.setMenu(menu);
}
private void fillContextMenu(final IMenuManager menuManager) {
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void handleCommandStackChanged() {
getActionRegistry().updateStackActions();
if (!isDirty() && getCommandStack().isDirty() && editAllowed()) {
setDirty(true);
}
}
private boolean editAllowed() {
return true;
}
protected void pageChange(int newPageIndex) {
if (newPageIndex == 0) {
IKeyBindingService service = getSite().getKeyBindingService();
if (service instanceof INestableKeyBindingService) {
INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
nestableService.activateKeyBindingService(null);
}
}
super.pageChange(newPageIndex);
}
public void setDirty(boolean dirty) {
isDirty = dirty;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
public boolean isDirty() {
return isDirty || super.isDirty();
}
public ActionRegistry getActionRegistry() {
return actionRegistry;
}
public GraphPage getGraphPage() {
return graphPage;
}
public EditDomain getEditDomain() {
return editDomain;
}
public CommandStack getCommandStack() {
return editDomain.getCommandStack();
}
public void setSelectionSynchronizer(
SelectionSynchronizer selectionSynchronizer) {
this.selectionSynchronizer = selectionSynchronizer;
}
public SelectionSynchronizer getSelectionSynchronizer() {
return selectionSynchronizer;
}
public SemanticElementFactory getSemanticElementFactory() {
if (semanticElementFactory == null) {
semanticElementFactory = new SemanticElementFactory(getContributorId());
}
return semanticElementFactory;
}
public NotationElementFactory getNotationElementFactory() {
if (notationElementFactory == null) {
notationElementFactory = new NotationElementFactory();
}
return notationElementFactory;
}
public RootContainer getRootContainer() {
return rootContainer;
}
public void setRootContainer(RootContainer rootContainer) {
this.rootContainer = rootContainer;
}
public ContentProvider getContentProvider() {
if (contentProvider == null) {
contentProvider = createContentProvider();
}
return contentProvider;
}
public GraphicalViewer getGraphicalViewer() {
return getGraphPage().getDesignerModelViewer();
}
public OutlineViewer getOutlineViewer() {
return getGraphPage().getOutlineViewer();
}
public Object getAdapter(Class adapter) {
Object result = null;
if (adapter == CommandStack.class) {
result = getCommandStack();
} else if (adapter == IContentOutlinePage.class) {
return getOutlineViewer();
} else if (adapter == IPropertySheetPage.class) {
return new TabbedPropertySheetPage(this);
} else if (adapter == org.eclipse.gef.GraphicalViewer.class) {
return getGraphicalViewer();
} else {
result = super.getAdapter(adapter);
}
return result;
}
public void doSave(IProgressMonitor monitor) {
if (!checkReadOnly()) return;
super.doSave(monitor);
getGraphPage().doSave(monitor);
boolean saved = getContentProvider().saveToInput(getEditorInput(), getRootContainer());
if (saved) {
getCommandStack().markSaveLocation();
setDirty(false);
firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
public void dispose() {
super.dispose();
}
protected SelectionSynchronizer createSelectionSynchronizer() {
return new SelectionSynchronizer();
}
private boolean checkReadOnly() {
IFile inputFile = ((FileEditorInput)getEditorInput()).getFile();
IContainer inputFolder = (IContainer)inputFile.getParent();
IFile notationInfoFile = inputFolder.getFile(new Path(getContentProvider().getNotationInfoFileName(inputFile.getName())));
IFile diagramImageFile = inputFolder.getFile(new Path(getContentProvider().getDiagramImageFileName(inputFile.getName())));
String readOnlyFiles = "";
ArrayList readOnlyFilesList = new ArrayList();
if (inputFile.isReadOnly()) {
readOnlyFiles += ("- " + inputFile.getFullPath().toOSString() + "\n");
readOnlyFilesList.add(inputFile);
}
if (notationInfoFile.exists() && notationInfoFile.isReadOnly()) {
readOnlyFiles += ("- " + notationInfoFile.getFullPath().toOSString() + "\n");
readOnlyFilesList.add(notationInfoFile);
}
if (diagramImageFile.exists() && diagramImageFile.isReadOnly()) {
readOnlyFiles += ("- " + diagramImageFile.getFullPath().toOSString() + "\n");
readOnlyFilesList.add(diagramImageFile);
}
if (readOnlyFilesList.isEmpty()) return true;
boolean answer = MessageDialog.openQuestion(
getSite().getShell(),
"Read-only Input Files Detected",
"The following files have a read-only indicator which needs to be changed to read-write in order to be able to save the process correctly.\n\n" +
readOnlyFiles + "\n" +
"Do you want to perform this change now?");
if (answer) {
try {
ResourceAttributes resourceAttributes = new ResourceAttributes();
resourceAttributes.setReadOnly(false);
for (int i = 0; i < readOnlyFilesList.size(); i++) {
((IFile)readOnlyFilesList.get(i)).setResourceAttributes(resourceAttributes);
}
return false;
} catch (CoreException e) {
Logger.logError("Error while trying to set files writeable", e);
return true;
}
} else {
return true;
}
}
protected abstract ContentProvider createContentProvider();
protected abstract SemanticElement createMainElement();
protected abstract GraphicalViewer createGraphicalViewer();
protected abstract OutlineViewer createOutlineViewer();
}