/**
* <copyright>
* </copyright>
*
*
*/
package ssl.resource.ssl.ui;
/**
* A text editor for 'ssl' models.
*/
public class SslEditor extends org.eclipse.ui.editors.text.TextEditor implements org.eclipse.emf.edit.domain.IEditingDomainProvider {
private ssl.resource.ssl.ui.SslHighlighting highlighting;
private org.eclipse.jface.text.source.projection.ProjectionSupport projectionSupport;
private ssl.resource.ssl.ui.SslCodeFoldingManager codeFoldingManager;
private ssl.resource.ssl.ui.SslBackgroundParsingStrategy bgParsingStrategy = new ssl.resource.ssl.ui.SslBackgroundParsingStrategy();
private java.util.Collection<ssl.resource.ssl.ISslBackgroundParsingListener> bgParsingListeners = new java.util.ArrayList<ssl.resource.ssl.ISslBackgroundParsingListener>();
private ssl.resource.ssl.ui.SslColorManager colorManager = new ssl.resource.ssl.ui.SslColorManager();
private ssl.resource.ssl.ui.SslOutlinePage outlinePage;
private ssl.resource.ssl.ISslTextResource resource;
private org.eclipse.core.resources.IResourceChangeListener resourceChangeListener = new ModelResourceChangeListener();
private ssl.resource.ssl.ui.SslPropertySheetPage propertySheetPage;
private org.eclipse.emf.edit.domain.EditingDomain editingDomain;
private org.eclipse.emf.edit.provider.ComposedAdapterFactory adapterFactory;
private ssl.resource.ssl.ui.ISslBracketHandler bracketHandler;
public SslEditor() {
super();
setSourceViewerConfiguration(new ssl.resource.ssl.ui.SslEditorConfiguration(this, colorManager));
initializeEditingDomain();
org.eclipse.core.resources.ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceChangeListener, org.eclipse.core.resources.IResourceChangeEvent.POST_CHANGE);
}
/**
* A custom document listener that triggers background parsing if needed.
*/
private final class DocumentListener implements org.eclipse.jface.text.IDocumentListener {
public void documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent event) {
}
public void documentChanged(org.eclipse.jface.text.DocumentEvent event) {
bgParsingStrategy.parse(event, getResource(), SslEditor.this);
}
}
/**
* Reacts to changes of the text resource displayed in the editor and resources
* cross-referenced by it. Cross-referenced resources are unloaded, the displayed
* resource is reloaded. An attempt to resolve all proxies in the displayed
* resource is made after each change.
* The code pretty much corresponds to what EMF generates for a tree editor.
*/
private class ModelResourceChangeListener implements org.eclipse.core.resources.IResourceChangeListener {
public void resourceChanged(org.eclipse.core.resources.IResourceChangeEvent event) {
org.eclipse.core.resources.IResourceDelta delta = event.getDelta();
try {
class ResourceDeltaVisitor implements org.eclipse.core.resources.IResourceDeltaVisitor {
protected org.eclipse.emf.ecore.resource.ResourceSet resourceSet = editingDomain.getResourceSet();
public boolean visit(org.eclipse.core.resources.IResourceDelta delta) {
if (delta.getResource().getType() != org.eclipse.core.resources.IResource.FILE) {
return true;
}
int deltaKind = delta.getKind();
if (deltaKind == org.eclipse.core.resources.IResourceDelta.CHANGED && delta.getFlags() != org.eclipse.core.resources.IResourceDelta.MARKERS) {
org.eclipse.emf.ecore.resource.Resource changedResource = resourceSet.getResource(org.eclipse.emf.common.util.URI.createURI(delta.getFullPath().toString()), false);
if (changedResource != null) {
changedResource.unload();
ssl.resource.ssl.ISslTextResource currentResource = getResource();
if (changedResource.equals(currentResource)) {
// reload the resource displayed in the editor
resourceSet.getResource(currentResource.getURI(), true);
}
if (currentResource != null && currentResource.getErrors().isEmpty()) {
org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(currentResource);
}
// reset the selected element in outline and properties by text position
if (highlighting != null) {
highlighting.setEObjectSelection();
}
}
}
return true;
}
}
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor();
delta.accept(visitor);
} catch (org.eclipse.core.runtime.CoreException exception) {
ssl.resource.ssl.ui.SslUIPlugin.logError("Unexpected Error: ", exception);
}
}
}
public void initializeEditor() {
super.initializeEditor();
setEditorContextMenuId("SimulatorSpecificationLanguage.resource.EditorContext");
}
public Object getAdapter(@SuppressWarnings("rawtypes") Class required) {
if (org.eclipse.ui.views.contentoutline.IContentOutlinePage.class.equals(required)) {
return getOutlinePage();
} else if (required.equals(org.eclipse.ui.views.properties.IPropertySheetPage.class)) {
return getPropertySheetPage();
}
return super.getAdapter(required);
}
public void createPartControl(org.eclipse.swt.widgets.Composite parent) {
super.createPartControl(parent);
// Code Folding
org.eclipse.jface.text.source.projection.ProjectionViewer viewer = (org.eclipse.jface.text.source.projection.ProjectionViewer) getSourceViewer();
// Occurrence initiation, need ITextResource and ISourceViewer.
highlighting = new ssl.resource.ssl.ui.SslHighlighting(getResource(), viewer, colorManager, this);
projectionSupport = new org.eclipse.jface.text.source.projection.ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors());
projectionSupport.install();
// turn projection mode on
viewer.doOperation(org.eclipse.jface.text.source.projection.ProjectionViewer.TOGGLE);
codeFoldingManager = new ssl.resource.ssl.ui.SslCodeFoldingManager(viewer, this);
}
protected void doSetInput(org.eclipse.ui.IEditorInput editorInput) throws org.eclipse.core.runtime.CoreException {
super.doSetInput(editorInput);
initializeResourceObject(editorInput);
org.eclipse.jface.text.IDocument document = getDocumentProvider().getDocument(getEditorInput());
document.addDocumentListener(new DocumentListener());
}
private void initializeResourceObject(org.eclipse.ui.IEditorInput editorInput) {
org.eclipse.ui.part.FileEditorInput input = (org.eclipse.ui.part.FileEditorInput) editorInput;
org.eclipse.core.resources.IFile inputFile = input.getFile();
ssl.resource.ssl.mopp.SslNature.activate(inputFile.getProject());
String path = inputFile.getFullPath().toString();
org.eclipse.emf.common.util.URI uri = org.eclipse.emf.common.util.URI.createPlatformResourceURI(path, true);
org.eclipse.emf.ecore.resource.ResourceSet resourceSet = editingDomain.getResourceSet();
ssl.resource.ssl.ISslTextResource loadedResource = (ssl.resource.ssl.ISslTextResource) resourceSet.getResource(uri, false);
if (loadedResource == null) {
try {
org.eclipse.emf.ecore.resource.Resource demandLoadedResource = null;
// here we do not use getResource(), because 'resource' might be null, which is ok
// when initializing the resource object
ssl.resource.ssl.ISslTextResource currentResource = this.resource;
if (currentResource != null && !currentResource.getURI().fileExtension().equals(uri.fileExtension())) {
// do not attempt to load if file extension has changed in a 'save as' operation
}
else {
demandLoadedResource = resourceSet.getResource(uri, true);
}
if (demandLoadedResource instanceof ssl.resource.ssl.ISslTextResource) {
setResource((ssl.resource.ssl.ISslTextResource) demandLoadedResource);
} else {
// the resource was not loaded by an EMFText resource, but some other EMF resource
ssl.resource.ssl.ui.SslUIPlugin.showErrorDialog("No EMFText resource.", "The file '" + uri.lastSegment() + "' of type '" + uri.fileExtension() + "' can not be handled by the SslEditor.");
// close this editor because it can not present the resource
close(false);
}
} catch (Exception e) {
ssl.resource.ssl.ui.SslUIPlugin.logError("Exception while loading resource in " + this.getClass().getSimpleName() + ".", e);
}
} else {
setResource(loadedResource);
}
}
public void dispose() {
colorManager.dispose();
super.dispose();
}
protected void performSave(boolean overwrite, org.eclipse.core.runtime.IProgressMonitor progressMonitor) {
super.performSave(overwrite, progressMonitor);
// Save code folding state
codeFoldingManager.saveCodeFoldingStateFile(getResource().getURI().toString());
}
public void registerTextPresentationListener(org.eclipse.jface.text.ITextPresentationListener listener) {
org.eclipse.jface.text.source.ISourceViewer viewer = getSourceViewer();
if (viewer instanceof org.eclipse.jface.text.TextViewer) {
((org.eclipse.jface.text.TextViewer) viewer).addTextPresentationListener(listener);
}
}
public void invalidateTextRepresentation() {
org.eclipse.jface.text.source.ISourceViewer viewer = getSourceViewer();
if (viewer != null) {
viewer.invalidateTextPresentation();
}
highlighting.resetValues();
}
public void setFocus() {
super.setFocus();
this.invalidateTextRepresentation();
}
protected void performSaveAs(org.eclipse.core.runtime.IProgressMonitor progressMonitor) {
org.eclipse.ui.part.FileEditorInput input = (org.eclipse.ui.part.FileEditorInput) getEditorInput();
String path = input.getFile().getFullPath().toString();
org.eclipse.emf.ecore.resource.ResourceSet resourceSet = editingDomain.getResourceSet();
org.eclipse.emf.common.util.URI platformURI = org.eclipse.emf.common.util.URI.createPlatformResourceURI(path, true);
org.eclipse.emf.ecore.resource.Resource oldFile = resourceSet.getResource(platformURI, true);
super.performSaveAs(progressMonitor);
// load and resave - input has been changed to new path by super
org.eclipse.ui.part.FileEditorInput newInput = (org.eclipse.ui.part.FileEditorInput) getEditorInput();
String newPath = newInput.getFile().getFullPath().toString();
org.eclipse.emf.common.util.URI newPlatformURI = org.eclipse.emf.common.util.URI.createPlatformResourceURI(newPath, true);
org.eclipse.emf.ecore.resource.Resource newFile = resourceSet.createResource(newPlatformURI);
// if the extension is the same, saving was already performed by super by saving
// the plain text
if (platformURI.fileExtension().equals(newPlatformURI.fileExtension())) {
oldFile.unload();
// save code folding state, is it possible with a new name
codeFoldingManager.saveCodeFoldingStateFile(getResource().getURI().toString());
}
else {
newFile.getContents().clear();
newFile.getContents().addAll(oldFile.getContents());
try {
oldFile.unload();
if (newFile.getErrors().isEmpty()) {
newFile.save(null);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public org.eclipse.emf.ecore.resource.ResourceSet getResourceSet() {
return editingDomain.getResourceSet();
}
public ssl.resource.ssl.ISslTextResource getResource() {
assert resource != null;
return resource;
}
private void setResource(ssl.resource.ssl.ISslTextResource resource) {
assert resource != null;
this.resource = resource;
if (this.resource.getErrors().isEmpty()) {
org.eclipse.emf.ecore.util.EcoreUtil.resolveAll(this.resource);
}
}
private Object getOutlinePage() {
if (outlinePage == null) {
outlinePage = new ssl.resource.ssl.ui.SslOutlinePage(this);
outlinePage.addSelectionChangedListener(highlighting);
highlighting.addSelectionChangedListener(outlinePage);
}
return outlinePage;
}
public org.eclipse.ui.views.properties.IPropertySheetPage getPropertySheetPage() {
if (propertySheetPage == null) {
propertySheetPage = new ssl.resource.ssl.ui.SslPropertySheetPage();
// add a slightly modified adapter factory that does not return any editors for
// properties. this way, a model can never be modified through the properties view.
propertySheetPage.setPropertySourceProvider(new org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider(adapterFactory) {
protected org.eclipse.ui.views.properties.IPropertySource createPropertySource(Object object, org.eclipse.emf.edit.provider.IItemPropertySource itemPropertySource) {
return new org.eclipse.emf.edit.ui.provider.PropertySource(object, itemPropertySource) {
protected org.eclipse.ui.views.properties.IPropertyDescriptor createPropertyDescriptor(org.eclipse.emf.edit.provider.IItemPropertyDescriptor itemPropertyDescriptor) {
return new org.eclipse.emf.edit.ui.provider.PropertyDescriptor(object, itemPropertyDescriptor) {
public org.eclipse.jface.viewers.CellEditor createPropertyEditor(org.eclipse.swt.widgets.Composite composite) {
return null;
}
};
}
};
}
});
highlighting.addSelectionChangedListener(propertySheetPage);
}
return propertySheetPage;
}
public org.eclipse.emf.edit.domain.EditingDomain getEditingDomain() {
return editingDomain;
}
private void initializeEditingDomain() {
adapterFactory = new org.eclipse.emf.edit.provider.ComposedAdapterFactory(org.eclipse.emf.edit.provider.ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
adapterFactory.addAdapterFactory(new org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory());
adapterFactory.addAdapterFactory(new org.eclipse.emf.ecore.provider.EcoreItemProviderAdapterFactory());
adapterFactory.addAdapterFactory(new org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory());
org.eclipse.emf.common.command.BasicCommandStack commandStack = new org.eclipse.emf.common.command.BasicCommandStack();
// CommandStackListeners can listen for changes. Not sure whether this is needed.
editingDomain = new org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain(adapterFactory,commandStack, new java.util.LinkedHashMap<org.eclipse.emf.ecore.resource.Resource, Boolean>());
}
/**
* Sets the caret to the offset of the given element.
*
* @param element has to be contained in the resource of this editor.
*/
public void setCaret(org.eclipse.emf.ecore.EObject element, String text) {
try {
if (element == null || text == null || text.equals("")) {
return;
}
org.eclipse.jface.text.source.ISourceViewer viewer = getSourceViewer();
ssl.resource.ssl.ISslTextResource textResource = (ssl.resource.ssl.ISslTextResource) element.eResource();
ssl.resource.ssl.ISslLocationMap locationMap = textResource.getLocationMap();
int destination = locationMap.getCharStart(element);
int length = locationMap.getCharEnd(element) + 1 - destination;
ssl.resource.ssl.ISslTextScanner lexer = getResource().getMetaInformation().createLexer();
try {
lexer.setText(viewer.getDocument().get(destination, length));
ssl.resource.ssl.ISslTextToken token = lexer.getNextToken();
String tokenText = token.getText();
while (tokenText != null) {
if (token.getText().equals(text)) {
destination += token.getOffset();
break;
}
token = lexer.getNextToken();
tokenText = token.getText();
}
} catch (org.eclipse.jface.text.BadLocationException e) {
}
destination = ((org.eclipse.jface.text.source.projection.ProjectionViewer) viewer).modelOffset2WidgetOffset(destination);
if (destination < 0) {
destination = 0;
}
viewer.getTextWidget().setSelection(destination);
} catch (Exception e) {
ssl.resource.ssl.ui.SslUIPlugin.logError("Exception in setCaret()", e);
}
}
protected org.eclipse.jface.text.source.ISourceViewer createSourceViewer(org.eclipse.swt.widgets.Composite parent, org.eclipse.jface.text.source.IVerticalRuler ruler, int styles) {
org.eclipse.jface.text.source.ISourceViewer viewer = new org.eclipse.jface.text.source.projection.ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles);
// ensure decoration support has been created and configured.
getSourceViewerDecorationSupport(viewer);
return viewer;
}
public void addBackgroundParsingListener(ssl.resource.ssl.ISslBackgroundParsingListener listener) {
bgParsingListeners.add(listener);
}
public void notifyBackgroundParsingFinished() {
for (ssl.resource.ssl.ISslBackgroundParsingListener listener : bgParsingListeners) {
listener.parsingCompleted(getResource());
}
}
public ssl.resource.ssl.ui.ISslBracketHandler getBracketHandler() {
return bracketHandler;
}
public void setBracketHandler(ssl.resource.ssl.ui.ISslBracketHandler bracketHandler) {
this.bracketHandler = bracketHandler;
}
public void createActions() {
super.createActions();
java.util.ResourceBundle resourceBundle = new java.util.ResourceBundle() {
public java.util.Enumeration<String> getKeys() {
java.util.List<String> keys = new java.util.ArrayList<String>(3);
keys.add("SelectAnnotationRulerAction.QuickFix.label");
keys.add("SelectAnnotationRulerAction.QuickFix.tooltip");
keys.add("SelectAnnotationRulerAction.QuickFix.description");
return java.util.Collections.enumeration(keys);
}
public Object handleGetObject(String key) {
if (key.equals("SelectAnnotationRulerAction.QuickFix.label")) return "&Quick Fix";
if (key.equals("SelectAnnotationRulerAction.QuickFix.tooltip")) return "Quick Fix";
if (key.equals("SelectAnnotationRulerAction.QuickFix.description")) return "Runs Quick Fix on the annotation's line";
return null;
}
};
setAction(org.eclipse.ui.texteditor.ITextEditorActionConstants.RULER_CLICK, new org.eclipse.ui.texteditor.SelectMarkerRulerAction(resourceBundle, "SelectAnnotationRulerAction.", this, getVerticalRuler()) {
public void run() {
runWithEvent(null);
}
public void runWithEvent(org.eclipse.swt.widgets.Event event) {
org.eclipse.jface.text.ITextOperationTarget operation = (org.eclipse.jface.text.ITextOperationTarget) getAdapter(org.eclipse.jface.text.ITextOperationTarget.class);
final int opCode = org.eclipse.jface.text.source.ISourceViewer.QUICK_ASSIST;
if (operation != null && operation.canDoOperation(opCode)) {
org.eclipse.jface.text.Position position = getPosition();
if (position != null) {
selectAndReveal(position.getOffset(), position.getLength());
}
operation.doOperation(opCode);
}
}
private org.eclipse.jface.text.Position getPosition() {
org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel model = getAnnotationModel();
org.eclipse.jface.text.source.IAnnotationAccessExtension annotationAccess = getAnnotationAccessExtension();
org.eclipse.jface.text.IDocument document = getDocument();
if (model == null) return null;
java.util.Iterator<?> iter = model.getAnnotationIterator();
int layer = Integer.MIN_VALUE;
while (iter.hasNext()) {
org.eclipse.jface.text.source.Annotation annotation = (org.eclipse.jface.text.source.Annotation) iter.next();
if (annotation.isMarkedDeleted()) continue;
int annotationLayer = annotationAccess.getLayer(annotation);
if (annotationAccess != null) if (annotationLayer < layer) continue;
org.eclipse.jface.text.Position position = model.getPosition(annotation);
if (!includesRulerLine(position, document)) {
continue;
}
return position;
}
return null;
}
});
}
}