package org.archstudio.eclipse.ui.editors;
import static com.google.common.base.Preconditions.checkNotNull;
import org.archstudio.eclipse.core.startup.InstantiateArchStudio;
import org.archstudio.eclipse.ui.IFocusEditorListener;
import org.archstudio.eclipse.ui.XadlEditorMatchingStrategy;
import org.archstudio.eclipse.ui.views.AbstractArchStudioOutlinePage;
import org.archstudio.editormanager.IEditorManager;
import org.archstudio.filemanager.CantOpenFileException;
import org.archstudio.filemanager.IFileManager;
import org.archstudio.filemanager.IFileManagerListener;
import org.archstudio.myx.fw.MyxRegistry;
import org.archstudio.myx.fw.Services;
import org.archstudio.resources.IResources;
import org.archstudio.swtutils.Banner;
import org.archstudio.swtutils.SWTWidgetUtils;
import org.archstudio.sysutils.DelayedExecuteOnceThread;
import org.archstudio.sysutils.UIDGenerator;
import org.archstudio.xarchadt.IXArchADT;
import org.archstudio.xarchadt.IXArchADTModelListener;
import org.archstudio.xarchadt.ObjRef;
import org.archstudio.xarchadt.XArchADTModelEvent;
import org.archstudio.xarchadt.variability.IXArchADTVariabilityListener;
import org.archstudio.xarchadt.variability.XArchADTVariabilityEvent;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.operations.UndoRedoActionGroup;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
public abstract class AbstractArchStudioEditor<B extends AbstractArchStudioEditorMyxComponent> extends EditorPart
implements ISelectionChangedListener, IXArchADTModelListener, IFocusEditorListener, IFileManagerListener,
IXArchADTVariabilityListener {
protected final MyxRegistry myxRegistry = MyxRegistry.getSharedInstance();
protected final B brick;
protected final Services services = new Services();
protected boolean hasBanner = false;
protected boolean updateOnSelectionChange = true;
protected boolean updateOutlineOnXArchFlatEvent = true;
protected boolean updateEditorOnXArchFlatEvent = true;
protected boolean handleUnattachedXArchFlatEvents = false;
protected String editorName = null;
protected Image icon = null;
protected String secondaryText = null;
protected IXArchADT xarch;
protected IFileManager fileman;
protected IEditorManager editorManager;
protected IResources resources;
protected AbstractArchStudioOutlinePage outlinePage = null;
protected ObjRef documentRootRef = null;
protected Composite parent = null;
protected String uniqueEditorID = null;
private final DelayedExecuteOnceThread updateThread = new DelayedExecuteOnceThread(250, new Runnable() {
@Override
public void run() {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (updateEditorOnXArchFlatEvent) {
updateEditor();
}
if (updateOutlineOnXArchFlatEvent) {
updateOutlinePage();
}
}
});
};
});
public AbstractArchStudioEditor(Class<B> brickClass, String editorName) {
super();
InstantiateArchStudio.instantiate();
this.brick = myxRegistry.waitForBrick(brickClass);
this.uniqueEditorID = UIDGenerator.generateUID(editorName);
this.editorName = editorName;
myxRegistry.registerObject(brick, this);
services.add(this);
xarch = services.add(brick.getXarch());
fileman = services.add(brick.getFileManager());
editorManager = services.add(brick.getEditorManager());
resources = services.add(brick.getResources());
updateThread.start();
}
protected void setHasBanner(boolean hasBanner) {
this.hasBanner = hasBanner;
}
protected void setUpdateOnSelectionChange(boolean updateOnSelectionChange) {
this.updateOnSelectionChange = updateOnSelectionChange;
}
protected void setUpdateOutlineOnXArchFlatEvent(boolean update) {
this.updateOutlineOnXArchFlatEvent = update;
}
protected void setUpdateEditorOnXArchFlatEvent(boolean update) {
this.updateEditorOnXArchFlatEvent = update;
}
protected void setHandleUnattachedXArchFlatEvents(boolean handle) {
this.handleUnattachedXArchFlatEvents = handle;
}
protected void setBannerInfo(Image icon, String secondaryText) {
this.icon = icon;
this.secondaryText = secondaryText;
}
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
if (input instanceof IFileEditorInput) {
IFile f = ((IFileEditorInput) input).getFile();
try {
f.refreshLocal(IResource.DEPTH_ONE, null);
}
catch (CoreException e) {
e.printStackTrace();
}
}
if (!(input instanceof IFileEditorInput) && !(input instanceof IPathEditorInput)) {
throw new PartInitException("Input to " + editorName + " must be an XML file");
}
XadlEditorMatchingStrategy xadlChecker = new XadlEditorMatchingStrategy();
if (!xadlChecker.matches(null, input)) {
throw new PartInitException("Input to " + editorName + " must have root tag <xArch>");
}
if (input instanceof IFileEditorInput) {
IFile f = ((IFileEditorInput) input).getFile();
ObjRef ref = null;
try {
ref = fileman.open(uniqueEditorID, f);
}
catch (CantOpenFileException cofe) {
throw new PartInitException("Can't open file.", cofe);
}
setPartName(f.getName() + " - " + super.getPartName());
setSite(site);
setInput(input);
setDocumentRootRef(ref);
}
else if (input instanceof IPathEditorInput) {
IPath p = ((IPathEditorInput) input).getPath();
java.io.File f = p.toFile();
ObjRef ref = null;
try {
ref = fileman.open(uniqueEditorID, f);
}
catch (CantOpenFileException cofe) {
throw new PartInitException("Can't open file.", cofe);
}
setPartName(f.getName() + " - " + super.getPartName());
setSite(site);
setInput(input);
setDocumentRootRef(ref);
}
outlinePage = createOutlinePage();
if (outlinePage != null) {
outlinePage.addSelectionChangedListener(this);
}
// enable undo/redo
IActionBars actionBars = site.getActionBars();
IUndoContext undoContext = PlatformUI.getWorkbench().getOperationSupport().getUndoContext();
UndoRedoActionGroup undoRedo = new UndoRedoActionGroup(this.getSite(), undoContext, true);
undoRedo.fillActionBars(actionBars);
actionBars.updateActionBars();
}
protected abstract AbstractArchStudioOutlinePage createOutlinePage();
public void setDocumentRootRef(ObjRef documentRootRef) {
this.documentRootRef = documentRootRef;
}
public ObjRef getDocumentRootRef() {
return documentRootRef;
}
@Override
protected void setInput(IEditorInput input) {
super.setInput(input);
}
@Override
public void createPartControl(Composite parent) {
this.parent = parent;
updateEditor();
}
@Override
public void dispose() {
clearEditor();
if (outlinePage != null) {
outlinePage.removeSelectionChangedListener(this);
}
updateThread.terminate();
if (documentRootRef != null) {
fileman.close(uniqueEditorID, documentRootRef);
}
myxRegistry.unregisterObject(brick, this);
super.dispose();
}
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (updateOnSelectionChange) {
updateEditor();
}
}
public void clearEditor() {
// IWorkbenchPartSite site = getSite();
// if (site != null) {
// site.getShell().getDisplay().syncExec(new Runnable() {
//
// @Override
// public void run() {
if (parent.isDisposed()) {
return;
}
Control[] children = parent.getChildren();
for (int i = children.length - 1; i >= 0; i--) {
children[i].dispose();
}
// }
// });
// }
}
public void updateOutlinePage() {
if (outlinePage != null) {
outlinePage.updateOutlinePage();
}
}
public void updateEditor() {
clearEditor();
// getSite().getShell().getDisplay().syncExec(new Runnable() {
//
// @Override
// public void run() {
ScrolledComposite sc = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
sc.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
sc.setBackgroundMode(SWT.INHERIT_DEFAULT);
sc.setExpandHorizontal(true);
sc.getVerticalBar().setIncrement(10);
sc.getVerticalBar().setPageIncrement(50);
Composite c = new Composite(sc, SWT.NONE);
c.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
sc.setContent(c);
c.setBackgroundMode(SWT.INHERIT_DEFAULT);
SWTWidgetUtils.makeWheelFriendly(sc, c);
GridLayout gridLayout = new GridLayout(1, true);
gridLayout.marginTop = 5;
gridLayout.marginBottom = 5;
gridLayout.marginLeft = 5;
gridLayout.marginRight = 5;
gridLayout.verticalSpacing = 5;
c.setLayout(gridLayout);
if (hasBanner) {
Composite header = new Banner(c, icon, editorName, secondaryText,
resources.getColor(IResources.COLOR_BANNER_BRIGHT),
resources.getColor(IResources.COLOR_BANNER_DARK));
header.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
}
createEditorContents(c);
c.pack();
parent.layout(true);
// }
// });
}
public abstract void createEditorContents(Composite parent);
@Override
public void doSave(IProgressMonitor monitor) {
fileman.save(documentRootRef, monitor);
firePropertyChange(PROP_DIRTY);
}
@Override
public void doSaveAs() {
// TODO Auto-generated method stub
}
@Override
public void fileDirtyStateChanged(ObjRef xArchRef, boolean dirty) {
checkNotNull(xArchRef);
if (xArchRef.equals(this.documentRootRef)) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
firePropertyChange(IEditorPart.PROP_DIRTY);
}
});
}
}
@Override
public void fileSaving(ObjRef xArchRef, IProgressMonitor monitor) {
}
@Override
public boolean isDirty() {
return fileman.isDirty(documentRootRef);
}
@Override
public boolean isSaveAsAllowed() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setFocus() {
parent.getChildren()[0].setFocus();
}
@Override
@SuppressWarnings("all")
public Object getAdapter(Class key) {
if (key.equals(IContentOutlinePage.class)) {
return outlinePage;
}
return super.getAdapter(key);
}
public void doUpdate() {
updateThread.execute();
}
public void doUpdateNow() {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
updateEditor();
updateOutlinePage();
}
});
}
@Override
public final void handleXArchADTModelEvent(XArchADTModelEvent evt) {
//if((!evt.getIsAttached()) && (!handleUnattachedXArchFlatEvents)){
// return;
//}
if (documentRootRef == null) {
return;
}
if (documentRootRef.equals(xarch.getDocumentRootRef(evt.getSource()))) {
updateThread.execute();
doHandleXArchADTModelEvent(evt);
}
}
public void doHandleXArchADTModelEvent(XArchADTModelEvent evt) {
}
@Override
public void focusEditor(String editorName, ObjRef[] refs) {
if (editorName.equals(this.editorName)) {
if (outlinePage != null) {
outlinePage.focusEditor(editorName, refs);
}
}
}
@Override
public void focusEditor(ObjRef[] refs) {
if (outlinePage != null) {
outlinePage.focusEditor(editorName, refs);
}
}
protected void showMessage(String message) {
MessageDialog.openError(getEditorSite().getShell(), "Error", message);
}
protected void showError(IStatus status) {
ErrorDialog.openError(getEditorSite().getShell(), "Error", status.getMessage(), status);
}
public Composite getParentComposite() {
return parent;
}
@Override
public void handleXArchADTVariabilityEvent(XArchADTVariabilityEvent evt) {
if (documentRootRef == null) {
return;
}
if (documentRootRef.equals(evt.getDocumentRootRef())) {
updateThread.execute();
doHandleXArchADTVariabilityEvent(evt);
}
}
public void doHandleXArchADTVariabilityEvent(XArchADTVariabilityEvent evt) {
}
}