package org.simantics.diagram.profile.function; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeMap; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.simantics.Simantics; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.NodeContext; 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.WriteRequest; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.Instances; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.diagram.profile.view.ResourcePair; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.layer0.Layer0; import org.simantics.scenegraph.loader.ScenegraphLoaderUtils; import org.simantics.scenegraph.profile.ProfileUtils; import org.simantics.scl.reflection.annotations.SCLValue; import org.simantics.scl.runtime.function.FunctionImpl1; import org.simantics.scl.runtime.tuple.Tuple; import org.simantics.scl.runtime.tuple.Tuple2; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.utils.strings.StringUtils; public class All { @SCLValue(type = "ReadGraph -> Resource -> Resource -> [Resource]") public static List profileChildren(ReadGraph graph, Resource resource, Resource context) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); List listedChildren = ListUtils.toList(graph, context); if(listedChildren.isEmpty()) { DiagramResource DIA = DiagramResource.getInstance(graph); TreeMap priorityChildren = new TreeMap(); for(Resource child : graph.getObjects(context, L0.IsComposedOf)) { Double p = graph.getPossibleRelatedValue(child, DIA.Profile_priority, Bindings.DOUBLE); if(p != null) priorityChildren.put(p, child); } return new ArrayList(priorityChildren.values()); } else { return listedChildren; } } @SCLValue(type = "ReadGraph -> Resource -> Variable -> [(String, Resource)]") public static List availableProfiles(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { Resource runtimeDiagram = ScenegraphLoaderUtils.getPossibleResourceSelection(graph, context); if(runtimeDiagram == null) return Collections.emptyList(); Layer0 L0 = Layer0.getInstance(graph); DiagramResource DIA = DiagramResource.getInstance(graph); String modelURI = graph.getPossibleRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasModelURI); if (modelURI == null) return Collections.emptyList(); Resource model = graph.getPossibleResource(modelURI); if (model == null) return Collections.emptyList(); Instances query = graph.adapt(DIA.Profile, Instances.class); ArrayList result = new ArrayList(); for(Resource profile : query.find(graph, model)) { if(!graph.hasStatement(profile, L0.Abstract)) { String name = graph.getRelatedValue(profile, L0.HasName, Bindings.STRING); result.add(new Tuple2(name, profile)); } } return result; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> b") public static Object profileEntrySelected(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { return new FunctionImpl1() { public void processRecursively(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry, boolean checked) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); if(graph.isInstanceOf(entry, DIA.Profile)) { Set singleSelGroups = new HashSet(); for(Resource child : ProfileUtils.getProfileChildren(graph, entry)) { if(checked && graph.isInstanceOf(child, DIA.ProfileEntry)) { //enable only one item from single selection groups. Resource group = graph.getPossibleObject(child, DIA.ProfileEntry_HasGroup); if (group != null && graph.isInstanceOf(group, DIA.SingleSelectionGroup)) { if (singleSelGroups.contains(group)) continue; singleSelGroups.add(group); } } processRecursively(graph, runtimeDiagram, runtimeProfile, child, checked); } } else if(graph.isInstanceOf(entry, DIA.ProfileEntry)) { Resource group = graph.getPossibleObject(entry, DIA.ProfileEntry_HasGroup); if (group != null && graph.isInstanceOf(group, DIA.SingleSelectionGroup)) { if(checked) { //enable selected item from single selection groups, disable the rest. Collection entries = graph.getObjects(group, DIA.ProfileEntry_HasGroup_Inverse); for (Resource e : entries) { deactivate(graph, runtimeDiagram, runtimeProfile, e); } activate(graph, runtimeDiagram, runtimeProfile, entry); } else { deactivate(graph, runtimeDiagram, runtimeProfile, entry); } } else { if(checked) { activate(graph, runtimeDiagram, runtimeProfile, entry); } else { deactivate(graph, runtimeDiagram, runtimeProfile, entry); } } } } private void activate(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry) throws DatabaseException { if(graph.isImmutable(runtimeProfile)) { Resource activationState = ProfileUtils.claimProfileActivationState(graph, runtimeDiagram, runtimeProfile, entry); if(activationState != null) graph.claim(activationState, SimulationResource.getInstance(graph).IsActive, null, entry); } else { graph.claim(runtimeProfile, SimulationResource.getInstance(graph).IsActive, null, entry); } } private void deactivate(WriteGraph graph, Resource runtimeDiagram, Resource runtimeProfile, Resource entry) throws DatabaseException { if(graph.isImmutable(runtimeProfile)) { Resource activationState = ProfileUtils.claimProfileActivationState(graph, runtimeDiagram, runtimeProfile, entry); if(activationState != null) graph.denyStatement(activationState, SimulationResource.getInstance(graph).IsActive, entry); } else { graph.denyStatement(runtimeProfile, SimulationResource.getInstance(graph).IsActive, entry); } } @Override public Boolean apply(Object _event) { Event event = (Event)_event; if(event.detail == SWT.CHECK) { final TreeItem item = (TreeItem)event.item; Tree tree = item.getParent(); GraphExplorer explorer = (GraphExplorer)tree.getData("GraphExplorer"); final Resource runtimeDiagram = (Resource)explorer.getRoot().getConstant(BuiltinKeys.INPUT); final boolean checked = item.getChecked(); NodeContext context = (NodeContext)item.getData(); final ResourcePair entry = (ResourcePair)context.getConstant(BuiltinKeys.INPUT); try { VirtualGraphSupport support = Simantics.getSession().getService(VirtualGraphSupport.class); Simantics.getSession().syncRequest(new WriteRequest(support.getWorkspacePersistent("profiles")) { @Override public void perform(WriteGraph graph) throws DatabaseException { DiagramResource DIA = DiagramResource.getInstance(graph); Resource runtimeProfile = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile); processRecursively(graph, runtimeDiagram, runtimeProfile, entry.getSecond(), checked); } }); } catch (DatabaseException e) { e.printStackTrace(); } } return null; } }; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> b") public static Object selectedProfile(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { Resource runtimeDiagram = ScenegraphLoaderUtils.getResourceSelection(graph, context); if(runtimeDiagram == null) return ""; Layer0 L0 = Layer0.getInstance(graph); DiagramResource DIA = DiagramResource.getInstance(graph); Resource profile = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile); if(profile == null) return null; String name = graph.getPossibleRelatedValue(profile, L0.HasName, Bindings.STRING); return StringUtils.safeString(name); } @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") public static Object activeProfileModifier(ReadGraph graph, final Resource resource, final Variable context) throws DatabaseException { return new FunctionImpl1() { @Override public String apply(final String key) { VirtualGraphSupport support = Simantics.getSession().getService(VirtualGraphSupport.class); Simantics.getSession().asyncRequest(new WriteRequest(support.getWorkspacePersistent("profiles")) { public Resource selected(List avail, String text) { for(Tuple a : avail) if(a.get(0).equals(text)) return (Resource)a.get(1); return null; } @Override public void perform(WriteGraph graph) throws DatabaseException { Resource runtimeDiagram = ScenegraphLoaderUtils.getResourceSelection(graph, context); List avail = (List)availableProfiles(graph, resource, context); final Resource profile = selected(avail, key); DiagramResource DIA = DiagramResource.getInstance(graph); Resource current = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile); if(profile.equals(current)) return; graph.deny(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile); graph.claim(runtimeDiagram, DIA.RuntimeDiagram_HasRuntimeProfile, null, profile); // Set this profile as the default profile for this model String modelURI = graph.getRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasModelURI); Resource model = graph.getResource(modelURI); graph.deny(model, DIA.HasActiveProfile); graph.claim(model, DIA.HasActiveProfile, profile); // Set this profile as the default profile for this diagram Resource configuration = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration); graph.deny(configuration, DIA.HasActiveProfile); graph.claim(configuration, DIA.HasActiveProfile, profile); } }); return null; } }; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource") public static Resource singleResourceSelection(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { return ScenegraphLoaderUtils.getPossibleResourceSelection(graph, context); } }