package org.simantics.selectionview; import java.util.function.Consumer; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.IWorkbenchSite; import org.simantics.Simantics; import org.simantics.browsing.ui.common.ErrorLogger; import org.simantics.browsing.ui.common.views.IFilterArea; import org.simantics.browsing.ui.common.views.IFilterAreaProvider; import org.simantics.browsing.ui.swt.PartNameListener; import org.simantics.databoard.Bindings; import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; import org.simantics.db.common.procedure.adapter.DisposableAsyncListener; import org.simantics.db.common.procedure.adapter.ListenerSupport; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.request.WriteResultRequest; import org.simantics.db.common.utils.Logger; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ServiceNotFoundException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.management.ISessionContext; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.scenegraph.ontology.ScenegraphResources; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.ui.ISelectionUtils; import org.simantics.utils.ui.jface.ActiveSelectionProvider; abstract public class ModelledTabContributor implements PropertyTabContributor, ListenerSupport { static class InputRead extends UniqueRead> { private Object input; InputRead(Object input) { this.input = input; } @Override public Pair perform(ReadGraph graph) throws DatabaseException { Variable resultVariable = null; Resource resultResource = null; if(input instanceof ISelection) { Variable var = ISelectionUtils.filterSingleSelection((ISelection)input, Variable.class); if(var != null) resultVariable = var; Resource res = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); if(res != null) resultResource = res; } else if (input instanceof Resource) { resultResource = (Resource)input; } return Pair.make(resultVariable, resultResource); } }; static class InputListener extends DisposableAsyncListener> { final Resource runtime; public InputListener(Resource runtime) { this.runtime = runtime; } @Override public void execute(AsyncReadGraph graph, final Pair result) { Simantics.getSession().async(new WriteRequest(Simantics.getSession().getService(VirtualGraph.class)) { @Override public void perform(WriteGraph graph) throws DatabaseException { ScenegraphResources SG = ScenegraphResources.getInstance(graph); if(result.first != null) { String uri = result.first.getURI(graph); graph.claimLiteral(runtime, SG.Runtime_HasVariable, uri, Bindings.STRING); } if(result.second != null) { graph.deny(runtime, SG.Runtime_HasResource); graph.claim(runtime, SG.Runtime_HasResource, result.second); } } }); } @Override public void exception(AsyncReadGraph graph, Throwable throwable) { Logger.defaultLogError(throwable); } } protected Resource runtime; // For ListenerSupport (supporting DB request listeners) protected boolean disposed = false; protected ISelection input = StructuredSelection.EMPTY; protected ISelectionProvider selectionProvider = new ActiveSelectionProvider(); abstract public void createControls(Composite body, IWorkbenchSite site); public IFilterArea getFilterArea() { return null; } public void requestFocus() { } public ISelectionProvider getSelectionProvider() { return selectionProvider; } public Read getPartNameReadRequest(final ISelection forSelection) { return new UniqueRead() { private String forResource(ReadGraph graph, Resource resource) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); String name = NameUtils.getSafeName(graph, resource); Resource type = graph.getPossibleType(resource, L0.Entity); if(type != null) { name += " : " + NameUtils.getSafeName(graph, type); } return name; } @Override public String perform(ReadGraph graph) throws DatabaseException { Resource resource = ISelectionUtils.filterSingleSelection(forSelection, Resource.class); if(resource != null) return forResource(graph, resource); Variable variable = ISelectionUtils.filterSingleSelection(forSelection, Variable.class); if(variable != null) { Resource represents = variable.getPossibleRepresents(graph); if(represents != null) return forResource(graph, represents); } return "Selection"; } }; } public void updatePartName(ISelection forSelection, Consumer updateCallback) { Read read = getPartNameReadRequest(forSelection); if (read == null) { updateCallback.accept("Selection"); } else { Simantics.getSession().asyncRequest(read, new PartNameListener(updateCallback, this)); } } public void updatePartName(Consumer updateCallback) { updatePartName(input, updateCallback); } protected void dispose() { this.disposed = true; } @Override public void exception(Throwable t) { ErrorLogger.defaultLogError("PropertyTabContributorImpl received unexpected exception.", t); } @Override public boolean isDisposed() { return disposed; } public Control createControl(Composite parent, final IWorkbenchSite site) { class TabComposite extends Composite { public TabComposite(Composite parent) { super(parent, 0); GridLayoutFactory.fillDefaults().applyTo(parent); GridDataFactory.fillDefaults().span(1, 1).grab(true, true).applyTo(this); Composite body = this; GridLayoutFactory.fillDefaults().spacing(0, 0).equalWidth(false).numColumns(1).applyTo(body); try { ModelledTabContributor.this.createControls(body, site); } catch (Throwable t) { ErrorLogger.defaultLogError(t); } } } final TabComposite tc = new TabComposite(parent); tc.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event e) { ModelledTabContributor.this.dispose(); } }); return tc; } @Override public IPropertyTab create(Composite parent, IWorkbenchSite site, ISessionContext context, Object input) { IPropertyTab tab = new Tab(site, parent); tab.createControl((Composite) tab.getControl(), context); return tab; } class Tab extends Composite implements IPropertyTab2, IFilterAreaProvider { final IWorkbenchSite site; private InputListener listener; public Tab(IWorkbenchSite site, Composite parent) { super(parent, SWT.NONE); this.site = site; try { runtime = Simantics.getSession().sync(new WriteResultRequest(Simantics.getSession().getService(VirtualGraph.class)) { @Override public Resource perform(WriteGraph graph) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); ScenegraphResources SG = ScenegraphResources.getInstance(graph); Resource runtime = graph.newResource(); graph.claim(runtime, L0.InstanceOf, null, SG.Runtime); return runtime; } }); } catch (ServiceNotFoundException e) { Logger.defaultLogError(e); } catch (DatabaseException e) { Logger.defaultLogError(e); } } @Override public void createControl(Composite parent, ISessionContext context) { Control c = ModelledTabContributor.this.createControl(parent, site); c.addListener(SWT.Dispose, new Listener() { public void handleEvent(Event e) { if(listener != null) { listener.dispose(); listener = null; } } }); } @Override public Control getControl() { return this; } @Override public boolean isDisposed() { return super.isDisposed(); } @Override public void requestFocus() { ModelledTabContributor.this.requestFocus(); } @Override public void setInput(ISessionContext context, ISelection selection, boolean force) { ModelledTabContributor.this.input = selection; if(listener != null) listener.dispose(); listener = new InputListener(runtime); try { Simantics.getSession().syncRequest(new InputRead(ModelledTabContributor.this.input), listener); } catch (DatabaseException e) { Logger.defaultLogError(e); } } @Override public ISelectionProvider getSelectionProvider() { return ModelledTabContributor.this.getSelectionProvider(); } @Override public IFilterArea getFilterArea() { return ModelledTabContributor.this.getFilterArea(); } @Override public void updatePartName(Consumer updateCallback) { ModelledTabContributor.this.updatePartName(input, updateCallback); } } }