package org.simantics.modeling.ui.componentTypeEditor; import org.eclipse.core.runtime.IExecutableExtension; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.TextEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.EditorPart; import org.simantics.Simantics; import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.procedure.Listener; import org.simantics.layer0.Layer0; import org.simantics.scl.compiler.errors.CompilationError; import org.simantics.scl.ui.editor.SCLTextEditorNew; import org.simantics.scl.ui.editor.TextAndErrors; import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest; import org.simantics.structural2.scl.procedural.ProceduralComponentTypeCompilationException; import org.simantics.ui.workbench.IResourceEditorInput; import org.simantics.ui.workbench.TitleUpdater; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.SWTUtils; public class SCLEditorBase extends EditorPart implements IExecutableExtension { Resource inputResource; SCLTextEditorNew editor; String originalText; protected TextAndErrors getTextAndErrors(ReadGraph graph, Resource resource) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); String text = graph.getValue(resource, Bindings.STRING); Resource componentType = graph.getPossibleObject(inputResource, L0.PropertyOf); CompilationError[] errors = CompilationError.EMPTY_ARRAY; if(componentType != null) { try { graph.syncRequest(new CompileProceduralComponentTypeRequest(componentType)); } catch(ProceduralComponentTypeCompilationException e) { errors = e.errors; } } return new TextAndErrors(text, errors); } @Override public void createPartControl(Composite parent) { editor = new SCLTextEditorNew(parent, 0); Simantics.getSession().asyncRequest(new ResourceRead(inputResource) { @Override public TextAndErrors perform(ReadGraph graph) throws DatabaseException { return getTextAndErrors(graph, inputResource); } }, new Listener() { @Override public void execute(final TextAndErrors textAndErrors) { SWTUtils.asyncExec(editor, new Runnable() { @Override public void run() { if (editor.isDisposed()) return; // FIXME Every graph change new overrides user's current modifications originalText = textAndErrors.text; boolean textDiffers = !originalText.equals(editor.getContent()); editor.setContent(textDiffers ? originalText : null, textAndErrors.errors); firePropertyChange(PROP_DIRTY); // This condition is only true for the first time when the editor is initialized // This fixes platform issue #5192 https://www.simantics.org/redmine/issues/5192 if (textDiffers) editor.getUndoManager().reset(); } }); } @Override public void exception(Throwable t) { ErrorLogger.defaultLogError(t); } @Override public boolean isDisposed() { return editor.isDisposed(); } }); editor.viewer.addTextListener(new ITextListener() { @Override public void textChanged(TextEvent event) { firePropertyChange(PROP_DIRTY); } }); } @Override public void setFocus() { editor.setFocus(); } protected void save(WriteGraph graph, Resource resource, String text) throws DatabaseException { graph.claimValue(resource, text); } @Override public void doSave(IProgressMonitor monitor) { this.originalText = editor.getContent(); firePropertyChange(PROP_DIRTY); try { Simantics.getSession().syncRequest(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { graph.markUndoPoint(); save(graph, inputResource, originalText); Layer0Utils.addCommentMetadata(graph, "Saved SCL Module " + graph.getRelatedValue2(inputResource, Layer0.getInstance(graph).HasName, Bindings.STRING)); } }); } catch (DatabaseException e) { e.printStackTrace(); } } @Override public void doSaveAs() { } protected String computeTitle(ReadGraph graph, Resource inputResource) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); Resource parent = graph.getPossibleObject(inputResource, L0.PropertyOf); if(parent == null) return "No parent"; return graph.getPossibleRelatedValue(parent, L0.HasName) + " (Code)"; } @Override public void init(IEditorSite site, final IEditorInput input) throws PartInitException { setSite(site); setInput(input); this.inputResource = ((IResourceEditorInput)input).getResource(); Simantics.getSession().asyncRequest( new UniqueRead() { @Override public String perform(ReadGraph graph) throws DatabaseException { return computeTitle(graph, inputResource); } }, new TitleUpdater(site.getShell().getDisplay(), partName -> { setPartName(partName); setTitleToolTip(partName); }, () -> editor != null && editor.isDisposed())); } @Override public boolean isDirty() { return !editor.getContent().equals(originalText); } @Override public boolean isSaveAsAllowed() { return false; } }