--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.simantics.district.selection.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Automatic-Module-Name: org.simantics.district.selection.ui
+Bundle-SymbolicName: org.simantics.district.selection.ui;singleton:=tr
+ ue
+Bundle-Name: Diagram element selection UI
+Bundle-Version: 1.0.0.qualifier
+Require-Bundle: javax.inject,org.eclipse.osgi,org.eclipse.jface,org.ec
+ lipse.e4.ui.model.workbench,org.eclipse.e4.ui.di,org.eclipse.e4.ui.se
+ rvices,org.eclipse.e4.core.di.annotations,org.eclipse.e4.ui.workbench
+ ,org.slf4j.api,org.simantics,org.simantics.district.region,org.simant
+ ics.district.selection,org.simantics.db.common,org.simantics.ui,com.f
+ amfamfam.silk;bundle-version="1.3.0",org.simantics.browsing.ui.common
+ ,org.eclipse.e4.core.contexts,org.eclipse.e4.core.di;bundle-version="
+ 1.6.100",org.simantics.district.region.ontology,org.simantics.distric
+ t.route.ontology,org.simantics.modeling.ontology,org.simantics.silk.o
+ ntology;bundle-version=1.1.0
+Bundle-ManifestVersion: 2
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-Vendor: Semantum oy
+Import-Package: javax.annotation;version="1.2.0"
+
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ fragment.e4xmi
--- /dev/null
+<?xml version="1.0" encoding="ASCII"?>
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/descriptor/basic" xmlns:commands="http://www.eclipse.org/ui/2010/UIModel/application/commands" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_BxaXACerEeWxCPrV0pAZQQ">
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_EI7oACerEeWxCPrV0pAZQQ" featurename="descriptors" parentElementId="xpath:/">
+ <elements xsi:type="basic:PartDescriptor" xmi:id="_KMklcCerEeWxCPrV0pAZQQ" elementId="org.simantics.district.selection.ui.parts.elementSelectionView" label="Diagram Element Selections" iconURI="platform:/plugin/org.simantics.silk.ontology/graph/images/table_go.png" tooltip="" category="District Network" contributionURI="bundleclass://org.simantics.district.selection.ui/org.simantics.district.selection.ui.parts.ElementSelectionView">
+ <tags>View</tags>
+ <tags>categoryTag:District</tags>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_aD4EkCVaEem-kMBxWCWPIg" featurename="menuContributions" parentElementId="xpath:/">
+ <elements xsi:type="menu:MenuContribution" xmi:id="_zFdSsCVaEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.menucontribution.openview" parentId="popup:#AprosDiagramPopup">
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_403skCVaEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.handledmanuitem.openview" label="Open Diagram Element Selection View" iconURI="platform:/plugin/com.famfamfam.silk/icons/table_key.png" command="_OdOfoCVcEem-kMBxWCWPIg"/>
+ </elements>
+ <elements xsi:type="menu:MenuContribution" xmi:id="_QOvjwCVgEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.menucontribution.selectionView.contextMenu" parentId="org.simantics.district.selection.ui.contextMenu">
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_ZKWM0CVgEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.contextMenu.createNewSelection" label="Create New Selection" iconURI="platform:/plugin/com.famfamfam.silk/icons/table_add.png" command="_rH7MsCVgEem-kMBxWCWPIg"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_Gl5QAC9tEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.contextMenu.editSelection" label="Edit Element Selection" iconURI="platform:/plugin/org.simantics.silk.ontology/graph/images/pencil.png" command="_dL1xIC7IEem4UIS68e_fsw"/>
+ <children xsi:type="menu:HandledMenuItem" xmi:id="_bVDmsC9tEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.contextMenu.deleteSelection" label="Delete Element Selection" iconURI="platform:/plugin/org.simantics.silk.ontology/graph/images/cross.png" command="_RfOU0C7PEem4UIS68e_fsw"/>
+ </elements>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_Sy-NUCVbEem-kMBxWCWPIg" featurename="commands" parentElementId="xpath:/">
+ <elements xsi:type="commands:Command" xmi:id="_OdOfoCVcEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.command.openview" commandName="Open Diagram Element Selection Table"/>
+ <elements xsi:type="commands:Command" xmi:id="_rH7MsCVgEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.command.createNewSelection" commandName="Create New Selection"/>
+ <elements xsi:type="commands:Command" xmi:id="_dL1xIC7IEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.command.editElementSelector" commandName="Edit Element Selection"/>
+ <elements xsi:type="commands:Command" xmi:id="_RfOU0C7PEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.command.deleteElementSelector" commandName="Delete Element Selection"/>
+ </fragments>
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_icxXQCVcEem-kMBxWCWPIg" featurename="handlers" parentElementId="xpath:/">
+ <elements xsi:type="commands:Handler" xmi:id="_k6qWACVcEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.handler.openselectiontableview" contributionURI="bundleclass://org.simantics.district.selection.ui/org.simantics.district.selection.ui.handlers.OpenElementSelectorTable" command="_OdOfoCVcEem-kMBxWCWPIg"/>
+ <elements xsi:type="commands:Handler" xmi:id="_0q9pMCVgEem-kMBxWCWPIg" elementId="org.simantics.district.selection.ui.handler.createNewSelection" contributionURI="bundleclass://org.simantics.district.selection.ui/org.simantics.district.selection.ui.handlers.CreateNewElementSelector" command="_rH7MsCVgEem-kMBxWCWPIg"/>
+ <elements xsi:type="commands:Handler" xmi:id="_YSif4C7IEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.handler.editElementSelector" contributionURI="bundleclass://org.simantics.district.selection.ui/org.simantics.district.selection.ui.handlers.EditElementSelector" command="_dL1xIC7IEem4UIS68e_fsw"/>
+ <elements xsi:type="commands:Handler" xmi:id="_U7VPUC7PEem4UIS68e_fsw" elementId="org.simantics.district.selection.ui.handler.deleteElementSelector" contributionURI="bundleclass://org.simantics.district.selection.ui/org.simantics.district.selection.ui.handlers.DeleteElementSelector" command="_RfOU0C7PEem4UIS68e_fsw"/>
+ </fragments>
+</fragment:ModelFragments>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+ <extension
+ id="org.simantics.district.selection.ui.fragment"
+ point="org.eclipse.e4.workbench.model">
+ <fragment
+ apply="notexists"
+ uri="fragment.e4xmi">
+ </fragment>
+ </extension>
+
+</plugin>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.simantics.district</groupId>
+ <artifactId>org.simantics.district.root</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.simantics.district.selection.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+
+</project>
--- /dev/null
+package org.simantics.district.selection.ui;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.simantics.Simantics;
+import org.simantics.browsing.ui.common.AdaptableHintContext;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.SyncListenerAdapter;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.layer0.QueryIndexUtils;
+import org.simantics.db.layer0.SelectionHints;
+import org.simantics.db.layer0.request.ActiveModels;
+import org.simantics.db.request.Read;
+import org.simantics.district.selection.ElementSelectionResource;
+import org.simantics.district.selection.ElementSelectionUtils;
+import org.simantics.district.selection.ElementSelector;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.runtime.Lists;
+import org.simantics.scl.runtime.function.FunctionImpl1;
+import org.simantics.ui.selection.AnyResource;
+import org.simantics.ui.selection.AnyVariable;
+import org.simantics.ui.selection.WorkbenchSelectionContentType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElementSelectorTableUI extends Composite {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ElementSelectorTableUI.class);
+
+ private TreeViewer viewer;
+ private TreeViewerColumn column1;
+ private TreeViewerColumn column2;
+
+ public ElementSelectorTableUI(ESelectionService selectionService, Composite parent, int style) {
+ super(parent, style);
+ parent.setLayout(new FillLayout());
+ // GridDataFactory.fillDefaults().grab(true, true).applyTo(this);
+ // GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this);
+ this.setLayout(new FillLayout());
+
+ viewer = new TreeViewer(this, SWT.FULL_SELECTION);
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ @Override
+ public void doubleClick(DoubleClickEvent event) {
+ TreeSelection selection = (TreeSelection) viewer.getSelection();
+ ElementSelector query = (ElementSelector) selection.getFirstElement();
+ try {
+ List<AdaptableHintContext> elements = Simantics.getSession().syncRequest(new Read<List<AdaptableHintContext>>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<AdaptableHintContext> perform(ReadGraph graph) throws DatabaseException {
+ Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
+ if (model == null) {
+ LOGGER.warn("No active model");
+ return Collections.emptyList();
+ }
+
+ List<Resource> result = query.selectElementsFrom(graph, model);
+ return Lists.map(new FunctionImpl1<Resource, AdaptableHintContext>() {
+ public AdaptableHintContext apply(Resource p0) {
+ AdaptableHintContext selectionElement = new SelectionElement(SelectionHints.STD_KEYS, graph);
+ selectionElement.setHint(SelectionHints.KEY_MAIN, p0);
+ selectionElement.setHint(SelectionHints.KEY_MODEL, model);
+ return selectionElement;
+ }
+ }, result);
+ }
+ });
+
+ selectionService.setPostSelection(new StructuredSelection(elements));
+ } catch (DatabaseException e) {
+ LOGGER.error("Element selection query failed", e);
+ }
+ }
+ });
+
+ viewer.setContentProvider(new ITreeContentProvider() {
+ @Override
+ public boolean hasChildren(Object element) {
+ return false;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement == null || !(inputElement instanceof Collection))
+ return new Object[0];
+
+ return ((Collection<?>)inputElement).toArray();
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ return null;
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ ITreeContentProvider.super.inputChanged(viewer, oldInput, newInput);
+ }
+ });
+
+ Simantics.getSession().asyncRequest(new SelectionsRequest(), new SyncListenerAdapter<Collection<ElementSelector>>() {
+ public void execute(ReadGraph graph, Collection<ElementSelector> result) {
+ parent.getDisplay().asyncExec(() -> {
+ viewer.setInput(result);
+ });
+ }
+
+ @Override
+ public void exception(ReadGraph graph, Throwable t) throws DatabaseException {
+ LOGGER.error("Error getting element selector list", t);
+ }
+
+ @Override
+ public boolean isDisposed() {
+ return ElementSelectorTableUI.this.isDisposed();
+ }
+ });
+
+ ColumnViewerToolTipSupport.enableFor(viewer);
+
+ Tree table = viewer.getTree();
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+
+ column1 = new TreeViewerColumn(viewer, SWT.NONE);
+ column1.getColumn().setText("Name");
+ column1.getColumn().setWidth(200);
+ column1.getColumn().setResizable(true);
+ column1.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ ElementSelector selector = (ElementSelector) element;
+ return selector.getName();
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ return null;
+ }
+ });
+
+ column2 = new TreeViewerColumn(viewer, SWT.NONE);
+ column2.getColumn().setText("Query");
+ column2.getColumn().setWidth(600);
+ column2.getColumn().setResizable(true);
+ column2.setLabelProvider(new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ ElementSelector selector = (ElementSelector) element;
+ return selector.getExpression();
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ return null;
+ }
+ });
+ }
+
+ public Tree getTree() {
+ return viewer.getTree();
+ }
+
+ public ElementSelector getSelectedItem() {
+ IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
+ return selection != null ? (ElementSelector) selection.getFirstElement() : null;
+ }
+
+ private final class SelectionElement extends AdaptableHintContext {
+ private final ReadGraph graph;
+
+ private SelectionElement(Key[] keys, ReadGraph graph) {
+ super(keys);
+ this.graph = graph;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
+ Resource element = getHint(SelectionHints.KEY_MAIN);
+ if (contentType instanceof AnyResource) {
+ return (T)element;
+ }
+ else if (contentType instanceof AnyVariable) {
+ try {
+ return (T)ElementSelector.getVariableForElement(graph, element);
+ } catch (DatabaseException e) {
+ return null;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ public static class SelectionsRequest implements Read<Collection<ElementSelector>> {
+ @Override
+ public Collection<ElementSelector> perform(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+
+ Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
+ if (model == null) {
+ return Collections.emptyList();
+ }
+
+ List<Resource> libs = QueryIndexUtils.searchByType(graph, model, ES.SelectionLibrary);
+ if (libs.isEmpty())
+ return Collections.emptyList();
+
+ Resource lib = libs.get(0);
+
+ List<ElementSelector> result = new ArrayList<>();
+ for (Resource selection : graph.getObjects(lib, L0.ConsistsOf)) {
+ if (!graph.isInstanceOf(selection, ES.Selection))
+ continue;
+
+ result.add(ElementSelector.getSelector(graph, selection));
+ }
+
+ return result;
+ }
+ }
+}
--- /dev/null
+package org.simantics.district.selection.ui.handlers;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.selection.ui.parts.EditSelectorDialog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CreateNewElementSelector {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CreateNewElementSelector.class);
+
+ @CanExecute
+ public boolean canExecute(ESelectionService selectionService) {
+ return true;
+ }
+
+ @Execute
+ public void createNewElementSelector(IEclipseContext context, IWorkbench workbench) {
+ Shell shell = context.getActive(Shell.class);
+ EditSelectorDialog dialog = new EditSelectorDialog(shell, null);
+ LOGGER.debug("Opening dialog");
+ int result = dialog.open();
+ LOGGER.debug("Dialog closed with result code " + result);
+ if (result == Window.OK) {
+ try {
+ dialog.writeSelection();
+ } catch (DatabaseException e) {
+ LOGGER.error("Writing new element selection failed", e);
+ }
+ }
+ }
+}
--- /dev/null
+package org.simantics.district.selection.ui.handlers;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.simantics.Simantics;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.selection.ElementSelector;
+import org.simantics.district.selection.ui.parts.ElementSelectionView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeleteElementSelector {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DeleteElementSelector.class);
+
+ @Inject
+ EPartService partService;
+
+ @CanExecute
+ public boolean canExecute(ESelectionService selectionService) {
+ MPart part = partService.getActivePart();
+ if (part == null) return false;
+
+ Object object = part.getObject();
+ if (object == null || !(object instanceof ElementSelectionView))
+ return false;
+
+ ElementSelectionView view = (ElementSelectionView)object;
+ return view.getSelectedItem() != null;
+ }
+
+ @Execute
+ public void editElementSelector(IEclipseContext context, IWorkbench workbench) {
+ MPart part = partService.getActivePart();
+ if (part == null) return;
+
+ Object object = part.getObject();
+ if (object == null || !(object instanceof ElementSelectionView))
+ return;
+
+ ElementSelectionView view = (ElementSelectionView)object;
+ ElementSelector selectedItem = view.getSelectedItem();
+
+ if (selectedItem == null)
+ return;
+
+ Simantics.getSession().async(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ graph.deny(selectedItem.getResource());
+ }
+ });
+ }
+}
--- /dev/null
+package org.simantics.district.selection.ui.handlers;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.workbench.IWorkbench;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.district.selection.ui.parts.EditSelectorDialog;
+import org.simantics.district.selection.ui.parts.ElementSelectionView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EditElementSelector {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(EditElementSelector.class);
+
+ @Inject
+ EPartService partService;
+
+ @CanExecute
+ public boolean canExecute(ESelectionService selectionService) {
+ MPart part = partService.getActivePart();
+ if (part == null) return false;
+
+ Object object = part.getObject();
+ if (object == null || !(object instanceof ElementSelectionView))
+ return false;
+
+ ElementSelectionView view = (ElementSelectionView)object;
+ return view.getSelectedItem() != null;
+ }
+
+ @Execute
+ public void editElementSelector(IEclipseContext context, IWorkbench workbench) {
+ MPart part = partService.getActivePart();
+ if (part == null) return;
+
+ Object object = part.getObject();
+ if (object == null || !(object instanceof ElementSelectionView))
+ return;
+
+ ElementSelectionView view = (ElementSelectionView)object;
+
+ Shell shell = context.getActive(Shell.class);
+ EditSelectorDialog dialog = new EditSelectorDialog(shell, view.getSelectedItem());
+
+ LOGGER.debug("Opening dialog");
+ int result = dialog.open();
+ LOGGER.debug("Dialog closed with result code " + result);
+ if (result == Window.OK) {
+ try {
+ dialog.writeSelection();
+ } catch (DatabaseException e) {
+ LOGGER.error("Writing new element selection failed", e);
+ }
+ }
+ }
+}
--- /dev/null
+package org.simantics.district.selection.ui.handlers;
+
+import org.eclipse.e4.core.di.annotations.CanExecute;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.simantics.ui.workbench.e4.E4WorkbenchUtils;
+
+public class OpenElementSelectorTable {
+
+ private static final String VIEW_ID = "org.simantics.diagram.selection.ui.elementSelectionView";
+
+ @CanExecute
+ public boolean canExecute(ESelectionService selectionService) {
+ return true;
+ }
+
+ @Execute
+ public void openPropertyTable(ESelectionService selectionService) {
+ E4WorkbenchUtils.openAndShowPart(VIEW_ID);
+ }
+
+}
--- /dev/null
+package org.simantics.district.selection.ui.parts;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.RowLayoutFactory;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.layer0.QueryIndexUtils;
+import org.simantics.db.layer0.request.ActiveModels;
+import org.simantics.db.request.Read;
+import org.simantics.db.request.WriteResult;
+import org.simantics.district.region.ontology.DiagramRegionsResource;
+import org.simantics.district.route.ontology.RouteResource;
+import org.simantics.district.selection.ElementSelectionResource;
+import org.simantics.district.selection.ElementSelectionUtils;
+import org.simantics.district.selection.ElementSelector;
+import org.simantics.district.selection.ElementSelector.AggregateCondition;
+import org.simantics.district.selection.ElementSelector.AggregateCondition.Type;
+import org.simantics.district.selection.ElementSelector.All;
+import org.simantics.district.selection.ElementSelector.Condition;
+import org.simantics.district.selection.ElementSelector.DiagramGenerator;
+import org.simantics.district.selection.ElementSelector.ExplicitGenerator;
+import org.simantics.district.selection.ElementSelector.Generator;
+import org.simantics.district.selection.ElementSelector.ModelGenerator;
+import org.simantics.district.selection.ElementSelector.PropertyCondition;
+import org.simantics.district.selection.ElementSelector.PropertySelector;
+import org.simantics.district.selection.ElementSelector.RegionCondition;
+import org.simantics.district.selection.ElementSelector.RouteCondition;
+import org.simantics.district.selection.ElementSelector.Selector;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.utils.datastructures.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EditSelectorDialog extends Dialog {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(EditSelectorDialog.class);
+
+ private ElementSelector elementSelector;
+
+ // Data for comboboxes
+ Map<Resource, String> diagrams;
+
+ private String[] regionNames;
+ private Resource[] regionResources;
+
+ private String[] routeNames;
+ private Resource[] routeResources;
+
+ // Dialog fields
+ private int generatorIndex;
+ private Combo sourceField;
+
+ private String name;
+ private Text nameField;
+
+ private Resource diagram;
+ private Combo diagramField;
+
+ private int selectorIndex;
+ private Combo selectorField;
+
+ private String propertyName;
+ private Text propertyField;
+
+ private int numberOfItems;
+ private Text nField;
+
+ private Condition condition;
+ private Button removeConditionButton;
+ private Text conditionLabel;
+
+ // Dialog area component
+ private Composite content;
+
+ @Inject
+ public EditSelectorDialog(Shell shell, ElementSelector elementSelector) {
+ super(shell);
+
+ this.elementSelector = elementSelector;
+ if (elementSelector != null) {
+ try {
+ Simantics.getSession().sync(new ReadRequest() {
+ @Override
+ public void run(ReadGraph graph) throws DatabaseException {
+ elementSelector.buildSelection(graph);
+ }
+ });
+ } catch (DatabaseException e1) {
+ LOGGER.error("Failed to read element selector resource " + elementSelector.getResource(), e1);
+ throw new RuntimeDatabaseException(e1);
+ }
+ }
+
+ final Map<Resource, String> regions = new HashMap<>();
+ final Map<Resource, String> routes = new HashMap<>();
+
+ try {
+ Simantics.getSession().syncRequest(new Read<Void>() {
+ @Override
+ public Void perform(ReadGraph graph) throws DatabaseException {
+ Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
+ List<Resource> regionCollection = QueryIndexUtils.searchByType(graph, model, DiagramRegionsResource.getInstance(graph).Region);
+ for (Resource r : regionCollection) {
+ String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
+ regions.put(r, name);
+ }
+
+ List<Resource> routeCollection = QueryIndexUtils.searchByType(graph, model, RouteResource.getInstance(graph).Route);
+ for (Resource r : routeCollection) {
+ String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
+ routes.put(r, name);
+ }
+ return null;
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to read routes and/or regions in the model", e);
+ }
+
+ regionNames = regions.values().toArray(new String[regions.size()]);
+ regionResources = regions.keySet().toArray(new Resource[regions.size()]);
+
+ routeNames = routes.values().toArray(new String[routes.size()]);
+ routeResources = routes.keySet().toArray(new Resource[routes.size()]);
+
+ name = elementSelector != null ? elementSelector.getName() : "";
+ propertyName = "";
+ numberOfItems = 1;
+ generatorIndex = 0;
+ selectorIndex = 0;
+ diagram = null;
+ condition = null;
+
+ if (elementSelector != null) {
+ Generator generator = elementSelector.getGenerator();
+ if (generator instanceof ModelGenerator) {
+ generatorIndex = 0;
+ }
+ else if (generator instanceof DiagramGenerator) {
+ generatorIndex = 1;
+ diagram = ((DiagramGenerator)generator).diagram;
+ }
+ else if (generator instanceof ExplicitGenerator) {
+ generatorIndex = 2;
+ // TODO: Management of explicit lists of elements
+ }
+ else {
+ throw new IllegalStateException("Unknown generator type " + generator.getClass().getName());
+ }
+
+ Selector selector = elementSelector.getSelector();
+ if (selector instanceof All) {
+ selectorIndex = 0;
+ }
+ else if (selector instanceof PropertySelector) {
+ PropertySelector propertySelector = (PropertySelector)selector;
+ selectorIndex = propertySelector.smallest ? 1 : 2;
+ propertyName = propertySelector.propertyName;
+ numberOfItems = propertySelector.resultCount;
+ }
+ else {
+ throw new IllegalStateException("Unknwon selector type " + selector.getClass().getName());
+ }
+
+ condition = elementSelector.getCondition();
+ }
+ }
+
+ @Override
+ protected void okPressed() {
+ generatorIndex = sourceField.getSelectionIndex();
+ if (generatorIndex == 1) {
+ int selectionIndex = diagramField.getSelectionIndex();
+ if (selectionIndex < 0) {
+ ErrorDialog.openError(getShell(), "Error", "Please select a diagram", new Status(IStatus.ERROR, "org.simantics.district.selection.ui", "No diagram selected"));
+ return;
+ }
+
+ diagram = new ArrayList<Resource>(diagrams.keySet()).get(selectionIndex);
+ }
+
+ name = nameField.getText();
+
+ selectorIndex = selectorField.getSelectionIndex();
+
+ propertyName = propertyField.getText();
+ String text = nField.getText();
+ numberOfItems = "".equals(text) ? 0 : Integer.parseInt(text);
+
+ super.okPressed();
+ }
+
+ public void writeSelection() throws DatabaseException {
+ Simantics.getSession().syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+
+ graph.markUndoPoint();
+
+ Resource lib = ElementSelectionUtils.ensureSelectionLibrary(graph);
+
+ // Selection
+ Resource selection;
+ if (elementSelector != null) {
+ selection = elementSelector.getResource();
+ graph.deny(selection);
+ }
+ else {
+ selection = graph.newResource();
+ }
+
+ graph.claim(selection, L0.InstanceOf, ES.Selection);
+ graph.claimLiteral(selection, L0.HasName, L0.String, UUID.randomUUID().toString());
+ graph.claimLiteral(selection, L0.HasLabel, L0.String, name);
+ graph.claim(selection, L0.PartOf, lib);
+
+ // Generator
+ Resource generator = graph.newResource();
+ Resource generatorType;
+ switch (generatorIndex) {
+ case 0:
+ generatorType = ES.Generator_Model;
+ break;
+ case 1:
+ generatorType = ES.Generator_Diagram;
+ Resource composite = graph.getPossibleObject(diagram, ModelingResources.getInstance(graph).DiagramToComposite);
+ graph.claim(generator, ES.Generator_HasDiagram, composite != null ? composite : diagram);
+ break;
+ case 2:
+ generatorType = ES.Generator_Explicit;
+ // TODO: Claim relations to current selection elements
+ break;
+ default: throw new IllegalStateException("Invalid source index " + generatorIndex);
+ }
+ graph.claim(generator, L0.InstanceOf, generatorType);
+ graph.claim(selection, ES.Selection_HasGenerator, generator);
+
+ // Selector
+ Resource selector = graph.newResource();
+ Resource selectorType;
+ switch (selectorIndex) {
+ case 0: selectorType = ES.Selector_All; break;
+ case 1: selectorType = ES.Selector_NLowest; break;
+ case 2: selectorType = ES.Selector_NHighest; break;
+ default: throw new IllegalStateException("Invalid selector index " + selectorIndex);
+ }
+ graph.claim(selector, L0.InstanceOf, selectorType);
+ graph.claim(selection, ES.Selection_HasSelector, selector);
+
+ if (selectorIndex > 0) {
+ graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, propertyName);
+ graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, numberOfItems);
+ }
+
+ // Condition
+ if (condition != null) {
+ graph.claim(selection, ES.Selection_HasCondition, condition.resource);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ // Set dialog title
+ getShell().setText("Edit element selector");
+
+ content = new Composite(parent, SWT.NONE);
+ GridLayoutFactory.swtDefaults().numColumns(3).applyTo(content);
+
+ // Name
+ Label nameLabel = new Label(content, SWT.NONE);
+ nameLabel.setText("Name");
+ GridDataFactory.swtDefaults().applyTo(nameLabel);
+
+ nameField = new Text(content, SWT.BORDER);
+ nameField.setEditable(true);
+ nameField.setText(name);
+ GridDataFactory.swtDefaults().span(2, 1).hint(200, SWT.DEFAULT).applyTo(nameField);
+
+ // Source
+ Label sourceLabel = new Label(content, SWT.NONE);
+ sourceLabel.setText("Source");
+ GridDataFactory.swtDefaults().applyTo(sourceLabel);
+
+ sourceField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
+ sourceField.setItems("Model", "Diagram", "Current selection");
+ sourceField.select(generatorIndex);
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(sourceField);
+
+ diagramField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(diagramField);
+ diagrams = ElementSelector.findDiagrams();
+ diagramField.setItems(diagrams.values().toArray(new String[diagrams.size()]));
+
+ int diagramIndex = diagram != null ? new ArrayList<>(diagrams.keySet()).indexOf(diagram) : -1;
+ diagramField.select(diagramIndex);
+
+ sourceField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ generatorIndex = sourceField.getSelectionIndex();
+ diagramField.setVisible(isDiagramFieldVisible());
+ }
+ });
+
+ sourceField.select(generatorIndex);
+ diagramField.setVisible(isDiagramFieldVisible());
+
+ // Selector
+ Label selectorLabel = new Label(content, SWT.NONE);
+ selectorLabel.setText("Select");
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorLabel);
+
+ selectorField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
+ selectorField.setItems("All", "N lowest", "N highest");
+ selectorField.select(selectorIndex);
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorField);
+
+ Composite selectorComposite = new Composite(content, SWT.NONE);
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorComposite);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(selectorComposite);
+
+ Label propertyLabel = new Label(selectorComposite, SWT.NONE);
+ propertyLabel.setText("Property name");
+ GridDataFactory.swtDefaults().applyTo(propertyLabel);
+
+ propertyField = new Text(selectorComposite, SWT.BORDER);
+ propertyField.setText(propertyName);
+ GridDataFactory.swtDefaults().hint(80, SWT.DEFAULT).applyTo(propertyField);
+
+ Label nLabel = new Label(selectorComposite, SWT.NONE);
+ nLabel.setText("Number of elements");
+ GridDataFactory.swtDefaults().applyTo(nLabel);
+
+ nField = new Text(selectorComposite, SWT.BORDER);
+ nField.setText(Integer.toString(numberOfItems));
+ GridDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(nField);
+
+ selectorField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ selectorIndex = selectorField.getSelectionIndex();
+ selectorComposite.setVisible(isSelectorCompositeVisible());
+ }
+ });
+
+ selectorField.select(selectorIndex);
+ selectorComposite.setVisible(isSelectorCompositeVisible());
+
+ // Condition
+ new Label(content, SWT.NONE).setText("Condition");
+ conditionLabel = new Text(content, SWT.READ_ONLY);
+ GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionLabel);
+
+ new Label(content, SWT.NONE);
+ Composite conditionPanel = new Composite(content, SWT.NONE);
+ GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionPanel);
+ GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(conditionPanel);
+ Button conditionButton = new Button(conditionPanel, SWT.PUSH);
+ conditionButton.setText("Edit...");
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(conditionButton);
+ removeConditionButton = new Button(conditionPanel, SWT.PUSH);
+ removeConditionButton.setText("Remove");
+ GridDataFactory.swtDefaults().span(1, 1).applyTo(removeConditionButton);
+
+ updateCondition();
+
+ conditionButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ ConditionDialog dialog = new ConditionDialog(getShell(), condition);
+ if (dialog.open() == Window.OK) {
+ try {
+ condition = dialog.createCondition();
+ } catch (DatabaseException e1) {
+ LOGGER.error("Creating a condition object failed", e1);
+ }
+
+ updateCondition();
+ }
+ }
+ });
+
+ removeConditionButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ condition = null;
+ updateCondition();
+ }
+ });
+
+ return content;
+ }
+
+ private void updateCondition() {
+ if (condition != null) {
+ removeConditionButton.setEnabled(true);
+ try {
+ conditionLabel.setText(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
+ } catch (DatabaseException e) {
+ LOGGER.error("Error getting expression string for " + condition.resource);
+ }
+ }
+ else {
+ conditionLabel.setText("No condition");
+ removeConditionButton.setEnabled(false);
+ }
+
+ content.layout();
+ }
+
+ private boolean isDiagramFieldVisible() {
+ return generatorIndex == 1;
+ }
+
+ private boolean isSelectorCompositeVisible() {
+ return selectorIndex != 0;
+ }
+
+ class ConditionDialog extends Dialog {
+ // Resource of the edited condition
+ private Resource existingResource;
+
+ // Inverse condition button
+ private boolean isInverse;
+ private Button inverseField;
+
+ // Condition type
+ private int typeIndex;
+ private Combo typeField;
+
+ // Type-specific control panels under a stack layout
+ private Composite stackPanel;
+ private StackLayout stack;
+
+ private Composite propertyPanel;
+ private Composite regionPanel;
+ private Composite routePanel;
+ private Composite aggregatePanel;
+
+ // Property condition
+ private Double lowerLimit;
+ private Double upperLimit;
+ private String propertyName;
+
+ private Text propertyNameField;
+ private Text lowerLimitField;
+ private Text upperLimitField;
+
+ // Region condition
+ private Resource region;
+ private Combo regionField;
+
+ // Route condition
+ private Resource route;
+ private Combo routeField;
+
+ // Aggregate condition
+ private List<Condition> subConditions;
+ private boolean isConjunction;
+
+ private org.eclipse.swt.widgets.List subConditionField;
+ private Combo operatorField;
+
+ public ConditionDialog(Shell shell, Condition condition) {
+ super(shell);
+
+ typeIndex = 0;
+ isInverse = false;
+ propertyName = "";
+ upperLimit = null;
+ lowerLimit = null;
+ subConditions = new ArrayList<>();
+
+ existingResource = condition != null ? condition.resource : null;
+
+ if (condition != null) {
+ if (condition instanceof PropertyCondition) {
+ typeIndex = 0;
+ PropertyCondition propertyCondition = (PropertyCondition)condition;
+ propertyName = propertyCondition.propertyName;
+ upperLimit = propertyCondition.upperLimit;
+ lowerLimit = propertyCondition.lowerLimit;
+ }
+ else if (condition instanceof RegionCondition) {
+ typeIndex = 1;
+ region = ((RegionCondition)condition).regionResource;
+ }
+ else if (condition instanceof RouteCondition) {
+ typeIndex = 2;
+ route = ((RouteCondition)condition).routeResource;
+ }
+ else if (condition instanceof AggregateCondition) {
+ typeIndex = 3;
+ subConditions = new ArrayList<>(((AggregateCondition)condition).conditions);
+ isConjunction = ((AggregateCondition)condition).type == Type.CONJUNCTION;
+ isInverse = ((AggregateCondition)condition).type == Type.NEGATION;
+ }
+ }
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ getShell().setText("Edit selector condition");
+
+ Composite content = (Composite)super.createDialogArea(parent);
+ GridLayoutFactory.swtDefaults().numColumns(1).applyTo(content);
+
+ GridDataFactory defaultWidth = GridDataFactory.swtDefaults().hint(200, SWT.DEFAULT);
+
+ // Is inverse
+ inverseField = new Button(content, SWT.CHECK);
+ inverseField.setText("Is inverse");
+ inverseField.setSelection(isInverse);
+
+ // Condition type
+ typeField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
+ typeField.setItems("Property value", "In region", "On route", "Combination");
+ typeField.select(typeIndex);
+
+ // Type-dependent stacked panels
+ stackPanel = new Composite(content, SWT.NONE);
+ stack = new StackLayout();
+ stackPanel.setLayout(stack);
+
+ // Property condition panel
+ propertyPanel = new Composite(stackPanel, SWT.NONE);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(propertyPanel);
+
+ new Label(propertyPanel, SWT.NONE).setText("Property name");
+ propertyNameField = new Text(propertyPanel, SWT.BORDER);
+ propertyNameField.setText(propertyName);
+ defaultWidth.applyTo(propertyNameField);
+
+ new Label(propertyPanel, SWT.NONE).setText("Lower limit");
+ lowerLimitField = new Text(propertyPanel, SWT.BORDER);
+ defaultWidth.applyTo(lowerLimitField);
+ if (lowerLimit != null) lowerLimitField.setText(lowerLimit.toString());
+
+ new Label(propertyPanel, SWT.NONE).setText("Upper limit");
+ upperLimitField = new Text(propertyPanel, SWT.BORDER);
+ defaultWidth.applyTo(upperLimitField);
+ if (upperLimit != null) upperLimitField.setText(upperLimit.toString());
+
+ // Region condition panel
+ regionPanel = new Composite(stackPanel, SWT.NONE);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(regionPanel);
+
+ new Label(regionPanel, SWT.NONE).setText("Region");
+ regionField = new Combo(regionPanel, SWT.BORDER | SWT.READ_ONLY);
+ regionField.setItems(regionNames);
+ defaultWidth.applyTo(regionField);
+
+ if (region != null) {
+ int regionIndex = Arrays.indexOf(regionResources, region);
+ regionField.select(regionIndex);
+ }
+ else {
+ regionField.select(0);
+ }
+
+ // Route condition panel
+ routePanel = new Composite(stackPanel, SWT.NONE);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(routePanel);
+
+ new Label(routePanel, SWT.NONE).setText("Route");
+ routeField = new Combo(routePanel, SWT.BORDER | SWT.READ_ONLY);
+ routeField.setItems(routeNames);
+ defaultWidth.applyTo(routeField);
+
+ if (route != null) {
+ int routeIndex = Arrays.indexOf(routeResources, route);
+ routeField.select(routeIndex);
+ }
+ else {
+ routeField.select(0);
+ }
+
+ // Aggregate condition panel
+ aggregatePanel = new Composite(stackPanel, SWT.NONE);
+ GridLayoutFactory.swtDefaults().numColumns(2).applyTo(aggregatePanel);
+
+ new Label(aggregatePanel, SWT.NONE).setText("Operator");
+ operatorField = new Combo(aggregatePanel, SWT.READ_ONLY);
+ operatorField.setItems("And", "Or");
+ operatorField.select(isConjunction ? 0 : 1);
+
+ new Label(aggregatePanel, SWT.NONE).setText("Sub-conditions");
+ Composite buttons = new Composite(aggregatePanel, SWT.NONE);
+ RowLayoutFactory.swtDefaults().justify(true).fill(true).extendedMargins(0, 0, 0, 0).type(SWT.HORIZONTAL).applyTo(buttons);
+
+ Button addButton = new Button(buttons, SWT.PUSH);
+ addButton.setText("Add");
+ Button removeButton = new Button(buttons, SWT.PUSH);
+ removeButton.setText("Remove");
+ Button editButton = new Button(buttons, SWT.PUSH);
+ editButton.setText("Edit");
+
+ new Label(aggregatePanel, SWT.NONE);
+ subConditionField = new org.eclipse.swt.widgets.List(aggregatePanel, SWT.BORDER);
+ GridDataFactory.swtDefaults().hint(200, 150).applyTo(subConditionField);
+ if (subConditions != null) {
+ Session session = Simantics.getSession();
+ List<String> items = new ArrayList<>();
+ for (Condition c : subConditions) {
+ try {
+ items.add(ElementSelector.getExpression(session, c.resource));
+ } catch (DatabaseException e1) {
+ LOGGER.error("Condition expression read failed", e1);
+ items.add("<Unknown expression>");
+ }
+ }
+
+ subConditionField.setItems(items.toArray(new String[items.size()]));
+ }
+
+ addButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ ConditionDialog conditionDialog = new ConditionDialog(getShell(), null);
+ if (conditionDialog.open() == Window.OK) {
+ Condition condition;
+ try {
+ condition = conditionDialog.createCondition();
+ subConditions.add(condition);
+
+ try {
+ subConditionField.add(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
+ } catch (DatabaseException e1) {
+ LOGGER.error("Condition expression read failed", e1);
+ subConditionField.add("<Unknown expression>");
+ }
+ } catch (DatabaseException e2) {
+ LOGGER.error("Create condition failed", e2);
+ }
+ }
+ }
+ });
+
+ removeButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = subConditionField.getSelectionIndex();
+ if (index >= 0) {
+ subConditionField.deselectAll();
+ subConditionField.remove(index);
+ subConditions.remove(index);
+
+ if (index < subConditions.size())
+ subConditionField.setSelection(index);
+ }
+
+ boolean selected = subConditionField.getSelectionIndex() >= 0;
+ removeButton.setEnabled(selected);
+ editButton.setEnabled(selected);
+ }
+ });
+
+ editButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = subConditionField.getSelectionIndex();
+ if (index >= 0) {
+ Condition condition = subConditions.get(index);
+ ConditionDialog conditionDialog = new ConditionDialog(getShell(), condition);
+ if (conditionDialog.open() == Window.OK) {
+ try {
+ condition = conditionDialog.createCondition();
+ subConditions.set(index, condition);
+
+ try {
+ subConditionField.setItem(index, ElementSelector.getExpression(Simantics.getSession(), condition.resource));
+ } catch (DatabaseException e1) {
+ LOGGER.error("Condition expression read failed", e1);
+ subConditionField.setItem(index, "<Unknown expression>");
+ }
+ } catch (DatabaseException e2) {
+ LOGGER.error("Create condition failed", e2);
+ }
+ }
+ }
+ }
+ });
+
+ subConditionField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ boolean selected = subConditionField.getSelectionIndex() >= 0;
+ removeButton.setEnabled(selected);
+ editButton.setEnabled(selected);
+ }
+ });
+
+ // Stack layout update
+ typeField.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateStack();
+ }
+ });
+
+ updateStack();
+
+ return content;
+ }
+
+ @Override
+ protected void okPressed() {
+ isInverse = inverseField.getSelection();
+
+ switch (typeIndex) {
+ case 0: // Property condition
+ propertyName = propertyNameField.getText();
+ try {
+ String lowerLimitText = lowerLimitField.getText();
+ lowerLimit = lowerLimitText.equals("") ? null : Double.valueOf(lowerLimitText);
+ String upperLimitText = upperLimitField.getText();
+ upperLimit = upperLimitText.equals("") ? null : Double.valueOf(upperLimitText);
+ }
+ catch (NumberFormatException e) {
+ ErrorDialog.openError(getShell(), "Error", "Invalid numeric value: " + e.getMessage(), new Status(OK, "org.simantics.district.selection.ui", e.getMessage()));
+ return;
+ }
+ break;
+ case 1: { // Region condition
+ int selectionIndex = regionField.getSelectionIndex();
+ if (selectionIndex < 0) {
+ ErrorDialog.openError(getShell(), "Error", "Please select a region", new Status(OK, "org.simantics.district.selection.ui", "No region selection"));
+ return;
+ }
+ region = regionResources[selectionIndex];
+ break;
+ }
+ case 2: // Route condition
+ route = routeResources[routeField.getSelectionIndex()];
+ break;
+ case 3: // Aggregate condition
+ isConjunction = operatorField.getSelectionIndex() == 0;
+ break;
+ }
+
+ super.okPressed();
+ }
+
+ protected Condition createCondition() throws DatabaseException {
+ if (isInverse && !(typeIndex == 3 && !isConjunction)) {
+ Resource resource0 = createCondition0();
+
+ // Create a negation
+ Resource resource = Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ Resource r = graph.newResource();
+ graph.claim(r, L0.InstanceOf, ES.Negation);
+ graph.claim(r, ES.HasSubcondition, resource0);
+ return r;
+ }
+ });
+
+ return ElementSelector.getCondition(Simantics.getSession(), resource);
+ }
+ else {
+ return ElementSelector.getCondition(Simantics.getSession(), createCondition0());
+ }
+ }
+
+ private Resource createCondition0() throws DatabaseException {
+ switch (typeIndex) {
+ case 0: return createPropertyCondition();
+ case 1: return createRegionCondition();
+ case 2: return createRouteCondition();
+ case 3: return createAggregateCondition();
+ default: throw new IllegalStateException("Invalid condition type code " + typeIndex);
+ }
+ }
+
+ private Resource createPropertyCondition() throws DatabaseException {
+ return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ Resource r = graph.newResource();
+ graph.claim(r, L0.InstanceOf, ES.PropertyCondition);
+ graph.claimLiteral(r, ES.PropertyCondition_HasPropertyName, propertyName);
+ if (lowerLimit != null)
+ graph.claimLiteral(r, ES.PropertyCondition_HasLowerLimit, L0.Double, lowerLimit);
+ if (upperLimit != null)
+ graph.claimLiteral(r, ES.PropertyCondition_HasUpperLimit, L0.Double, upperLimit);
+
+ return r;
+ }
+ });
+ }
+
+ private Resource createAggregateCondition() throws DatabaseException {
+ return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ Resource r;
+ if (existingResource != null) {
+ // Reuse existing resource
+ r = existingResource;
+ // Clear any previous statements
+ graph.deny(existingResource);
+ }
+ else {
+ r = graph.newResource();
+ }
+
+ Resource type;
+ type = isConjunction ? ES.Conjunction : isInverse ? ES.Negation : ES.Disjunction;
+
+ graph.claim(r, L0.InstanceOf, type);
+ for (Condition c : subConditions) {
+ graph.claim(r, ES.HasSubcondition, c.resource);
+ }
+
+ return r;
+ }
+ });
+ }
+
+ private Resource createRouteCondition() throws DatabaseException {
+ return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ Resource r = graph.newResource();
+ graph.claim(r, L0.InstanceOf, ES.RouteCondition);
+ graph.claim(r, ES.RouteCondition_HasRoute, route);
+ return r;
+ }
+ });
+ }
+
+ private Resource createRegionCondition() throws DatabaseException {
+ return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+ Layer0 L0 = Layer0.getInstance(graph);
+
+ Resource r = graph.newResource();
+ graph.claim(r, L0.InstanceOf, ES.RegionCondition);
+ graph.claim(r, ES.RegionCondition_HasRegion, region);
+ return r;
+ }
+ });
+ }
+
+ private void updateStack() {
+ typeIndex = typeField.getSelectionIndex();
+ switch (typeIndex) {
+ case 0: stack.topControl = propertyPanel; break;
+ case 1: stack.topControl = regionPanel; break;
+ case 2: stack.topControl = routePanel; break;
+ case 3: stack.topControl = aggregatePanel; break;
+ }
+
+ stackPanel.layout();
+ }
+ }
+}
--- /dev/null
+package org.simantics.district.selection.ui.parts;
+
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.menu.MHandledToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
+import org.eclipse.e4.ui.services.EMenuService;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.simantics.district.selection.ElementSelector;
+import org.simantics.district.selection.ui.ElementSelectorTableUI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElementSelectionView {
+ private static final String CONTEXT_MENU_ID = "org.simantics.district.selection.ui.contextMenu";
+ private static final String POPUP_ID = "org.simantics.district.selection.ui.selectiontable.popup";
+ private static final String CREATE_NEW_ID = "org.simantics.district.selection.ui.command.createNewSelection";
+ private static final String CREATE_NEW_LABEL = "Create New Element Selection Query";
+ private static final String CREATE_NEW_ICON = "platform:/plugin/com.famfamfam.silk/icons/add.png";
+ private static final String EDIT_ID = "org.simantics.district.selection.ui.command.editElementSelector";
+ private static final String EDIT_LABEL = "Edit Element Selection Query";
+ private static final String EDIT_ICON = "platform:/plugin/com.famfamfam.silk/icons/pencil.png";
+ private static final String DELETE_ID = "org.simantics.district.selection.ui.command.deleteElementSelector";
+ private static final String DELETE_LABEL = "Delete Element Selection Query";
+ private static final String DELETE_ICON = "platform:/plugin/com.famfamfam.silk/icons/cross.png";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ElementSelectionView.class);
+
+ private ElementSelectorTableUI table;
+
+ @Inject
+ private ESelectionService selectionService;
+
+ @Inject
+ public void init(MPart part, MApplication app) {
+ // Command is contributed via fragment
+ MHandledToolItem createItem = MMenuFactory.INSTANCE.createHandledToolItem();
+ createItem.setCommand(app.getCommand(CREATE_NEW_ID));
+ createItem.setLabel(CREATE_NEW_LABEL);
+ createItem.setIconURI(CREATE_NEW_ICON);
+ MHandledToolItem editItem = MMenuFactory.INSTANCE.createHandledToolItem();
+ editItem.setCommand(app.getCommand(EDIT_ID));
+ editItem.setLabel(EDIT_LABEL);
+ editItem.setIconURI(EDIT_ICON);
+ MHandledToolItem deleteItem = MMenuFactory.INSTANCE.createHandledToolItem();
+ deleteItem.setCommand(app.getCommand(DELETE_ID));
+ deleteItem.setLabel(DELETE_LABEL);
+ deleteItem.setIconURI(DELETE_ICON);
+
+ MToolBar toolBar = MMenuFactory.INSTANCE.createToolBar();
+ toolBar.setToBeRendered(true);
+
+ List<MToolBarElement> children = toolBar.getChildren();
+ children.add(createItem);
+ children.add(editItem);
+ children.add(deleteItem);
+
+ part.setToolbar(toolBar);
+
+ MPopupMenu popupMenu = MMenuFactory.INSTANCE.createPopupMenu();
+ popupMenu.setElementId(POPUP_ID);
+
+ List<MMenuContribution> menuContributions = app.getMenuContributions();
+ for (MMenuContribution menuContribution : menuContributions) {
+ if (CONTEXT_MENU_ID.equals(menuContribution.getParentId())) {
+ popupMenu.getChildren().addAll(menuContribution.getChildren());
+ }
+ }
+
+ part.getMenus().add(popupMenu);
+ }
+
+ @PostConstruct
+ public void createPartControl(Composite parent, EMenuService menuService) {
+ table = new ElementSelectorTableUI(selectionService, parent, SWT.BORDER);
+ if (!(menuService.registerContextMenu(this.table.getTree(), POPUP_ID)))
+ LOGGER.warn("Could not register context menu {}", POPUP_ID);
+ }
+
+ @Focus
+ public void setFocus() {
+ table.setFocus();
+ }
+
+ public ElementSelector getSelectedItem() {
+ return table.getSelectedItem();
+ }
+}
L0.Ontology.global true
L0.HasResourceClass "org.simantics.district.selection.ElementSelectionResource"
+ES.SelectionLibrary <T L0.Library
+
ES.Selection <T L0.Entity
>-- ES.Selection.HasGenerator --> ES.Generator <R L0.HasProperty : L0.FunctionalRelation
>-- ES.Selection.HasCondition --> ES.Condition <R L0.HasProperty : L0.FunctionalRelation
public final Resource RouteCondition_HasRoute;
public final Resource RouteCondition_HasRoute_Inverse;
public final Resource Selection;
+ public final Resource SelectionLibrary;
public final Resource Selection_HasCondition;
public final Resource Selection_HasCondition_Inverse;
public final Resource Selection_HasGenerator;
public static final String RouteCondition_HasRoute = "http://www.simantics.org/ElementSelection-1.0/RouteCondition/HasRoute";
public static final String RouteCondition_HasRoute_Inverse = "http://www.simantics.org/ElementSelection-1.0/RouteCondition/HasRoute/Inverse";
public static final String Selection = "http://www.simantics.org/ElementSelection-1.0/Selection";
+ public static final String SelectionLibrary = "http://www.simantics.org/ElementSelection-1.0/SelectionLibrary";
public static final String Selection_HasCondition = "http://www.simantics.org/ElementSelection-1.0/Selection/HasCondition";
public static final String Selection_HasCondition_Inverse = "http://www.simantics.org/ElementSelection-1.0/Selection/HasCondition/Inverse";
public static final String Selection_HasGenerator = "http://www.simantics.org/ElementSelection-1.0/Selection/HasGenerator";
RouteCondition_HasRoute = getResourceOrNull(graph, URIs.RouteCondition_HasRoute);
RouteCondition_HasRoute_Inverse = getResourceOrNull(graph, URIs.RouteCondition_HasRoute_Inverse);
Selection = getResourceOrNull(graph, URIs.Selection);
+ SelectionLibrary = getResourceOrNull(graph, URIs.SelectionLibrary);
Selection_HasCondition = getResourceOrNull(graph, URIs.Selection_HasCondition);
Selection_HasCondition_Inverse = getResourceOrNull(graph, URIs.Selection_HasCondition_Inverse);
Selection_HasGenerator = getResourceOrNull(graph, URIs.Selection_HasGenerator);
--- /dev/null
+package org.simantics.district.selection;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.QueryIndexUtils;
+import org.simantics.db.layer0.request.PossibleActiveModel;
+import org.simantics.db.request.WriteResult;
+import org.simantics.layer0.Layer0;
+
+public class ElementSelectionUtils {
+ public static Resource ensureSelectionLibrary(RequestProcessor graph) throws DatabaseException {
+ return graph.syncRequest(new WriteResult<Resource>() {
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+
+ Resource model = graph.sync(new PossibleActiveModel(Simantics.getProjectResource()));
+ if (model == null) return null;
+
+ List<Resource> libs = QueryIndexUtils.searchByTypeShallow(graph, model, ES.SelectionLibrary);
+ if (libs.isEmpty()) {
+ Resource lib = graph.newResource();
+ Layer0 L0 = Layer0.getInstance(graph);
+ graph.claim(lib, L0.InstanceOf, ES.SelectionLibrary);
+ graph.claim(model, L0.ConsistsOf, lib);
+ graph.claimLiteral(lib, L0.HasName, L0.String, UUID.randomUUID().toString(), Bindings.STRING);
+ return lib;
+ }
+ else {
+ return libs.get(0);
+ }
+ }
+ });
+ }
+
+}
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.simantics.Simantics;
import org.simantics.db.ReadGraph;
+import org.simantics.db.RequestProcessor;
import org.simantics.db.Resource;
import org.simantics.db.common.request.ResourceRead;
import org.simantics.db.common.utils.ListUtils;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.QueryIndexUtils;
import org.simantics.db.layer0.request.ActiveModels;
import org.simantics.db.layer0.request.ActiveRuns;
import org.simantics.db.layer0.request.Configuration;
+import org.simantics.db.layer0.request.PossibleActiveModel;
import org.simantics.db.layer0.variable.RVI;
import org.simantics.db.layer0.variable.Variable;
import org.simantics.db.layer0.variable.Variables;
+import org.simantics.db.request.Read;
import org.simantics.diagram.stubs.DiagramResource;
import org.simantics.district.network.ontology.DistrictNetworkResource;
import org.simantics.district.region.ontology.DiagramRegionsResource;
public class ElementSelector {
String name;
String expression;
- Integer count;
+
Resource resource;
Generator generator;
static DiagramResource DIA;
static DistrictNetworkResource DN;
+ private static Logger LOGGER = LoggerFactory.getLogger(ElementSelector.class);
+
ElementSelector(ReadGraph graph, Resource resource) throws DatabaseException {
super();
DN = DistrictNetworkResource.getInstance(graph);
this.resource = resource;
- this.count = -1;
try {
this.name = graph.getRelatedValue(resource, L0.HasLabel);
- this.expression = buildExpression(graph, resource);
+ this.expression = getExpression(graph, resource);
} catch (DatabaseException e) {
LOG.error("Error reading element selector", e);
throw e;
}
}
- public static ElementSelector getSelector(ReadGraph graph, Resource resource) throws DatabaseException {
+ /**
+ * Instantiate an element selector object for an ES.Selection resource.
+ */
+ public static ElementSelector getSelector(RequestProcessor graph, Resource resource) throws DatabaseException {
return graph.syncRequest(new ElementSelectorQuery(resource));
}
+
+ /**
+ * Get an SQL-like textual description of an ES.Selection resource.
+ */
+ public static String getExpression(RequestProcessor graph, Resource resource) throws DatabaseException {
+ return graph.syncRequest(new SelectionExpressionRequest(resource));
+ }
+
+ /**
+ * Get a Java object representation of an ES.Condition resource.
+ */
+ public static Condition getCondition(RequestProcessor graph, Resource condition) throws DatabaseException {
+ return graph.syncRequest(new SelectionConditionRequest(condition));
+ }
+ /**
+ * Get the name of the element selector.
+ */
public String getName() {
return name;
}
+ /**
+ * Get a textual SQL-like description of the element selector.
+ */
public String getExpression() {
return expression;
}
+ /**
+ * Get the resource that this selector represents.
+ */
public Resource getResource() {
return resource;
}
+ /**
+ * Get the generator component. Use {@link #buildSelection(ReadGraph)} to make it available first.
+ */
+ public Generator getGenerator() {
+ return generator;
+ }
+
+ /**
+ * Get the selector component. Use {@link #buildSelection(ReadGraph)} to make it available first.
+ */
+ public Selector getSelector() {
+ return selector;
+ }
+
+ /**
+ * Get the condition component. Use {@link #buildSelection(ReadGraph)} to make it available first.
+ */
+ public Condition getCondition() {
+ return condition;
+ }
+
+ /**
+ *
+ * @param graph
+ * @throws DatabaseException
+ */
+ public void buildSelection(ReadGraph graph) throws DatabaseException {
+ Resource selector = graph.getSingleObject(resource, ES.Selection_HasSelector);
+ Resource generator = graph.getSingleObject(resource, ES.Selection_HasGenerator);
+ Resource condition = graph.getPossibleObject(resource, ES.Selection_HasCondition);
+
+ this.selector = buildSelector(graph, selector);
+ this.generator = buildGenerator(graph, generator);
+ this.condition = buildCondition(graph, condition);
+ }
+
+ public static Map<Resource, String> findDiagrams() {
+ try {
+ return Simantics.getSession().syncRequest(new Read<Map<Resource, String>>() {
+ @Override
+ public Map<Resource, String> perform(ReadGraph graph) throws DatabaseException {
+ Map<Resource, String> result = new HashMap<>();
+ Resource model = graph.syncRequest(new PossibleActiveModel(Simantics.getProjectResource()));
+ List<Resource> composites = QueryIndexUtils.searchByType(graph, model, StructuralResource2.getInstance(graph).Composite);
+ for (Resource r : composites) {
+ // Get diagram
+ Resource diagram = graph.getPossibleObject(r, ModelingResources.getInstance(graph).CompositeToDiagram);
+ if (diagram == null) continue;
+
+ // Filter out user component diagrams
+ Resource parent = graph.getPossibleObject(r, Layer0.getInstance(graph).PartOf);
+ if (parent == null || graph.isInheritedFrom(parent, StructuralResource2.getInstance(graph).Component))
+ continue;
+
+ result.put(r, graph.getRelatedValue(r, Layer0.getInstance(graph).HasName));
+ }
+
+ return result;
+ }
+ });
+ } catch (DatabaseException e) {
+ LOGGER.error("Query for model diagrams failed", e);
+ return Collections.emptyMap();
+ }
+ }
+
+ public static Variable getVariableForElement(ReadGraph graph, Resource element) throws DatabaseException {
+ Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
+ if (component != null) {
+ Variable var = Variables.getVariable(graph, component);
+ RVI realRvi = var.getRVI(graph);
+
+ for (Resource activeModel : graph.syncRequest(new ActiveModels(Simantics.getProjectResource()))) {
+ for (Variable run : graph.syncRequest(new ActiveRuns(activeModel))) {
+ Variable v = realRvi.resolvePossible(graph, run);
+ if (v != null) {
+ return v;
+ }
+ }
+ Variable configuration = Variables.getPossibleConfigurationContext(graph, activeModel);
+ if (configuration != null) {
+ Variable v = realRvi.resolvePossible(graph, configuration);
+ if (v != null) {
+ return v;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static Double getPropertyValue(ReadGraph graph, Resource element, String propertyName) {
+ try {
+ Variable v = getVariableForElement(graph, element);
+ if (v != null) {
+ Number value = v.getPossiblePropertyValue(graph, propertyName);
+ if (value != null)
+ return value.doubleValue();
+ }
+
+ // No property found - try possible mapped element property as well
+ Resource mappedElement = graph.getPossibleObject(element, DN.MappedComponent);
+ if (mappedElement != null)
+ return getPropertyValue(graph, mappedElement, propertyName);
+ }
+ catch (DatabaseException e) {
+ }
+
+ return null;
+ }
+
public List<Resource> selectElementsFrom(ReadGraph graph, Resource model) throws DatabaseException {
if (selector == null) {
buildSelection(graph);
String propertyName = graph.getRelatedValue(resource, ES.PropertyCondition_HasPropertyName);
Double lowerLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasLowerLimit);
Double upperLimit = graph.getPossibleRelatedValue(resource, ES.PropertyCondition_HasUpperLimit);
- cond = new PropertyCondition(propertyName, lowerLimit, upperLimit);
+ cond = new PropertyCondition(resource, propertyName, lowerLimit, upperLimit);
}
else if (graph.isInstanceOf(resource, ES.RegionCondition)) {
DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
- double[] region = graph.getRelatedValue(graph.getSingleObject(resource, ES.RegionCondition_HasRegion), DR.Region_area);
- cond = new RegionCondition(region);
+ Resource regionResource = graph.getSingleObject(resource, ES.RegionCondition_HasRegion);
+ double[] region = graph.getRelatedValue(regionResource, DR.Region_area);
+ cond = new RegionCondition(resource, regionResource, region);
}
else if (graph.isInstanceOf(resource, ES.RouteCondition)) {
- Set<Resource> routePoints = new HashSet<>(ListUtils.toList(graph, graph.getSingleObject(resource, ES.RouteCondition_HasRoute)));
- cond = new RouteCondition(routePoints);
+ Resource routeResource = graph.getSingleObject(resource, ES.RouteCondition_HasRoute);
+ Set<Resource> routePoints = new HashSet<>(ListUtils.toList(graph, routeResource));
+ cond = new RouteCondition(resource, routeResource, routePoints);
}
else if (graph.isInstanceOf(resource, ES.AggregateCondition)) {
- boolean isDisjunction = graph.isInstanceOf(resource, ES.Disjunction);
Collection<Resource> conditionResources = graph.getObjects(resource, ES.HasSubcondition);
List<Condition> conditions = new ArrayList<>(conditionResources.size());
for (Resource c : conditionResources) {
else
throw new IllegalArgumentException("Unknown aggreate condition type " + graph.getURI(graph.getSingleType(resource)));
- cond = new AggregateCondition(type, conditions);
+ cond = new AggregateCondition(resource, type, conditions);
}
else {
throw new IllegalArgumentException("Unknown condition type " + graph.getURI(graph.getSingleType(resource)));
}
- cond.isInverse = graph.hasStatement(resource, ES.Condition_IsInverse, resource);
return cond;
}
private static String buildExpression(ReadGraph graph, Resource r) throws DatabaseException {
if (graph.isInstanceOf(r, ES.Selection)) {
- String exp = "select " + buildExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) +
- " from " + buildExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator));
+ String exp = "select " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasSelector)) +
+ " from " + getExpression(graph, graph.getSingleObject(r, ES.Selection_HasGenerator));
Resource cond = graph.getPossibleObject(r, ES.Selection_HasCondition);
- return cond != null ? exp + " where {" + buildExpression(graph, cond) + "}" : exp;
+ return cond != null ? exp + " where {" + getExpression(graph, cond) + "}" : exp;
}
else if (graph.isInstanceOf(r, ES.Condition)) {
if (graph.isInstanceOf(r, ES.PropertyCondition)) {
List<String> exps = new ArrayList<>();
Collection<Resource> objects = graph.getObjects(r, ES.HasSubcondition);
for (Resource c : objects) {
- String exp = buildExpression(graph, c);
+ String exp = getExpression(graph, c);
exps.add(objects.size() > 1 ? "{" + exp + "}" : exp);
}
String result = String.join(op, exps);
return result;
}
- private void buildSelection(ReadGraph graph) throws DatabaseException {
- Resource selector = graph.getSingleObject(resource, ES.Selection_HasSelector);
- Resource generator = graph.getSingleObject(resource, ES.Selection_HasGenerator);
- Resource condition = graph.getPossibleObject(resource, ES.Selection_HasCondition);
-
- this.selector = buildSelector(graph, selector);
- this.generator = buildGenerator(graph, generator);
- this.condition = buildCondition(graph, condition);
- }
-
private Collection<Resource> filterElementsFrom(ReadGraph graph, Collection<Resource> elements) throws DatabaseException {
if (condition == null) return elements;
return selector.select(graph, filterElementsFrom(graph, generator.generate(graph, model)));
}
- static Variable getVariableForElement(ReadGraph graph, Resource element) throws DatabaseException {
- Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
- if (component != null) {
- Variable var = Variables.getVariable(graph, component);
- RVI realRvi = var.getRVI(graph);
-
- for (Resource activeModel : graph.syncRequest(new ActiveModels(Simantics.getProjectResource()))) {
- for (Variable run : graph.syncRequest(new ActiveRuns(activeModel))) {
- Variable v = realRvi.resolvePossible(graph, run);
- if (v != null) {
- return v;
- }
- }
- Variable configuration = Variables.getPossibleConfigurationContext(graph, activeModel);
- if (configuration != null) {
- Variable v = realRvi.resolvePossible(graph, configuration);
- if (v != null) {
- return v;
- }
- }
- }
- }
-
- return null;
- }
-
- static Double getPropertyValue(ReadGraph graph, Resource element, String propertyName) {
- try {
- Variable v = getVariableForElement(graph, element);
- if (v != null) {
- Number value = v.getPossiblePropertyValue(graph, propertyName);
- if (value != null)
- return value.doubleValue();
- }
-
- // No property found - try possible mapped element property as well
- Resource mappedElement = graph.getPossibleObject(element, DN.MappedComponent);
- if (mappedElement != null)
- return getPropertyValue(graph, mappedElement, propertyName);
- }
- catch (DatabaseException e) {
- }
-
- return null;
- }
-
// Generators
- static abstract class Generator {
+ public static abstract class Generator {
abstract Collection<Resource> generate(ReadGraph graph, Resource model) throws DatabaseException;
}
- static class ModelGenerator extends Generator {
+ public static class ModelGenerator extends Generator {
@Override
Collection<Resource> generate(ReadGraph graph, Resource model) throws DatabaseException {
Resource conf = graph.syncRequest(new Configuration(model));
}
}
- static class DiagramGenerator extends Generator {
- Resource diagram;
+ public static class DiagramGenerator extends Generator {
+ public Resource diagram;
public DiagramGenerator(Resource diagram) {
this.diagram = diagram;
}
}
- static class ExplicitGenerator extends Generator {
+ public static class ExplicitGenerator extends Generator {
public ExplicitGenerator(Collection<Resource> elements) {
this.elements = elements;
}
- Collection<Resource> elements;
+ public Collection<Resource> elements;
@Override
Collection<Resource> generate(ReadGraph graph, Resource model) {
// Selectors
- static abstract class Selector {
+ public static abstract class Selector {
abstract Collection<Resource> select(ReadGraph graph, Collection<Resource> elements);
}
- static class All extends Selector {
+ public static class All extends Selector {
public All() {
}
}
}
- static class PropertySelector extends Selector {
+ public static class PropertySelector extends Selector {
public PropertySelector(boolean smallest, String propertyName, int resultCount) {
this.smallest = smallest;
this.propertyName = propertyName;
this.resultCount = resultCount;
}
- boolean smallest;
- String propertyName;
- int resultCount;
+ public boolean smallest;
+ public String propertyName;
+ public int resultCount;
@SuppressWarnings("unchecked")
@Override
// Conditions
- static abstract class Condition {
- boolean isInverse;
+ public static abstract class Condition {
+ public Resource resource;
+
+ Condition(Resource r) {
+ resource = r;
+ }
+
abstract boolean match(ReadGraph graph, Resource r) throws DatabaseException;
}
- static class PropertyCondition extends Condition {
- public PropertyCondition(String propertyName, Double lowerLimit, Double upperLimit) {
- super();
+ public static class PropertyCondition extends Condition {
+ public PropertyCondition(Resource r, String propertyName, Double lowerLimit, Double upperLimit) {
+ super(r);
+
this.propertyName = propertyName;
this.lowerLimit = lowerLimit;
this.upperLimit = upperLimit;
}
- String propertyName;
- Double lowerLimit;
- Double upperLimit;
+ public String propertyName;
+ public Double lowerLimit;
+ public Double upperLimit;
@Override
boolean match(ReadGraph graph, Resource r) {
}
}
- static class RegionCondition extends Condition {
- public RegionCondition(double[] region) {
- super();
+ public static class RegionCondition extends Condition {
+ public RegionCondition(Resource r, Resource regionResoruce, double[] region) {
+ super(r);
this.region = region;
Path2D path = new Path2D.Double();
path.closePath();
this.path = path;
+ this.regionResource = regionResoruce;
}
+ public Resource regionResource;
double[] region;
Path2D path;
}
}
- static class RouteCondition extends Condition {
- public RouteCondition(Set<Resource> routePoints) {
- super();
+ public static class RouteCondition extends Condition {
+ public RouteCondition(Resource r, Resource routeResource, Set<Resource> routePoints) {
+ super(r);
this.routePoints = routePoints;
+ this.routeResource = routeResource;
}
+ public Resource routeResource;
Set<Resource> routePoints;
@Override
}
}
- static class DiagramCondition extends Condition {
- public DiagramCondition(Resource diagram) {
- super();
- this.diagram = diagram;
- }
-
- Resource diagram;
-
- @Override
- boolean match(ReadGraph graph, Resource r) throws DatabaseException {
- return graph.getSingleObject(r, L0.PartOf).equals(diagram);
- }
- }
-
- static class AggregateCondition extends Condition {
- static enum Type { DISJUNCTION, CONJUNCTION, NEGATION };
+ public static class AggregateCondition extends Condition {
+ public static enum Type { DISJUNCTION, CONJUNCTION, NEGATION };
- public AggregateCondition(Type type, List<Condition> conditions) {
- super();
+ public AggregateCondition(Resource r, Type type, List<Condition> conditions) {
+ super(r);
this.type = type;
this.conditions = conditions;
}
- Type type;
- List<Condition> conditions;
+ public Type type;
+ public List<Condition> conditions;
@Override
boolean match(ReadGraph graph, Resource r) throws DatabaseException {
return new ElementSelector(graph, resource);
}
}
+
+ public final static class SelectionExpressionRequest extends ResourceRead<String> {
+ public SelectionExpressionRequest(Resource condition) {
+ super(condition);
+ }
+
+ @Override
+ public String perform(ReadGraph graph) throws DatabaseException {
+ return ElementSelector.buildExpression(graph, resource);
+ }
+ }
+
+ public static final class SelectionConditionRequest extends ResourceRead<Condition> {
+ public SelectionConditionRequest(Resource resource) {
+ super(resource);
+ }
+
+ @Override
+ public Condition perform(ReadGraph graph) throws DatabaseException {
+ return buildCondition(graph, resource);
+ }
+ }
}
--- /dev/null
+package org.simantics.district.selection;
+
+//import static org.junit.Assert.*;
+//
+//import org.eclipse.core.runtime.NullProgressMonitor;
+//import org.junit.AfterClass;
+//import org.junit.Before;
+//import org.junit.BeforeClass;
+//import org.junit.Test;
+//import org.simantics.Simantics;
+//import org.simantics.db.Resource;
+//import org.simantics.db.WriteGraph;
+//import org.simantics.db.common.request.WriteRequest;
+//import org.simantics.db.exception.DatabaseException;
+//import org.simantics.db.testing.common.AcornTests;
+//import org.simantics.layer0.Layer0;
+//
+//public class ElementSelectorTest {
+//
+// Resource selection;
+// Resource generator;
+// Resource selector;
+//
+// @Before
+// public void setUp() throws DatabaseException {
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// selection = graph.newResource();
+// graph.claim(selection, L0.InstanceOf, ES.Selection);
+// graph.claimLiteral(selection, L0.HasLabel, L0.String, "My Selection");
+// generator = graph.newResource();
+// graph.claim(selection, ES.Selection_HasGenerator, generator);
+// selector = graph.newResource();
+// graph.claim(selection, ES.Selection_HasSelector, selector);
+// }
+// });
+// }
+//
+// @BeforeClass
+// public static void initialize0() throws Exception {
+// AcornTests.newSimanticsWorkspace(null, null);
+// }
+//
+// @AfterClass
+// public static void deinitialize0() throws Exception {
+// Simantics.shutdown(new NullProgressMonitor());
+// }
+//
+// @Test
+// public void testExpressionGeneration1() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_NHighest);
+// graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, "myProperty");
+// graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, 10);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select top 10 of myProperty from model", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration2() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_NLowest);
+// graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, "criteria1");
+// graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, 20);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select bottom 20 of criteria1 from model", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration3() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_All);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select all from model", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration4() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_All);
+// Resource condition = graph.newResource();
+// graph.claim(condition, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition, ES.Selection_HasCondition_Inverse, selection);
+// graph.claimLiteral(condition, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty");
+// graph.claimLiteral(condition, ES.PropertyCondition_HasLowerLimit, L0.Double, 20.0);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select all from model where {20.0 < myProperty}", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration5() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_NLowest);
+// graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, "criteria1");
+// graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, 20);
+// Resource condition = graph.newResource();
+// graph.claim(condition, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition, ES.Selection_HasCondition_Inverse, selection);
+// graph.claimLiteral(condition, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty");
+// graph.claimLiteral(condition, ES.PropertyCondition_HasLowerLimit, L0.Double, 20.0);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select bottom 20 of criteria1 from model where {20.0 < myProperty}", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration6() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_NLowest);
+// graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, "criteria1");
+// graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, 20);
+// Resource condition = graph.newResource();
+// graph.claim(condition, L0.InstanceOf, ES.Disjunction);
+// graph.claim(condition, ES.Selection_HasCondition_Inverse, selection);
+// Resource condition1 = graph.newResource();
+// graph.claim(condition1, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition1, ES.HasSubcondition_Inverse, condition);
+// graph.claimLiteral(condition1, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty1");
+// graph.claimLiteral(condition1, ES.PropertyCondition_HasLowerLimit, L0.Double, 20.0);
+// Resource condition2 = graph.newResource();
+// graph.claim(condition2, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition2, ES.HasSubcondition_Inverse, condition);
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty2");
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasLowerLimit, L0.Double, 0.0);
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasUpperLimit, L0.Double, 100.0);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select bottom 20 of criteria1 from model where {{20.0 < myProperty1} or {0.0 < myProperty2 < 100.0}}", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration7() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Explicit);
+// for (int i = 0; i < 15; i++) {
+// graph.claim(generator, ES.Generator_HasSelectedElement, graph.newResource());
+// }
+// graph.claim(selector, L0.InstanceOf, ES.Selector_All);
+// Resource condition = graph.newResource();
+// graph.claim(condition, L0.InstanceOf, ES.Disjunction);
+// graph.claim(condition, ES.Selection_HasCondition_Inverse, selection);
+// Resource condition1 = graph.newResource();
+// graph.claim(condition1, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition1, ES.HasSubcondition_Inverse, condition);
+// graph.claimLiteral(condition1, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty1");
+// graph.claimLiteral(condition1, ES.PropertyCondition_HasLowerLimit, L0.Double, 20.0);
+// Resource condition2 = graph.newResource();
+// graph.claim(condition2, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition2, ES.HasSubcondition_Inverse, condition);
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty2");
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasLowerLimit, L0.Double, 0.0);
+// graph.claimLiteral(condition2, ES.PropertyCondition_HasUpperLimit, L0.Double, 100.0);
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select all from <list of 15 elements> where {{20.0 < myProperty1} or {0.0 < myProperty2 < 100.0}}", expression);
+// System.err.println(expression);
+// }
+//
+// @Test
+// public void testExpressionGeneration8() throws DatabaseException {
+//
+// Simantics.sync(new WriteRequest() {
+// @Override
+// public void perform(WriteGraph graph) throws DatabaseException {
+// Layer0 L0 = Layer0.getInstance(graph);
+// ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
+//
+// graph.claim(generator, L0.InstanceOf, ES.Generator_Model);
+// graph.claim(selector, L0.InstanceOf, ES.Selector_All);
+// Resource condition = graph.newResource();
+// graph.claim(condition, L0.InstanceOf, ES.Conjunction);
+// graph.claim(condition, ES.Selection_HasCondition_Inverse, selection);
+// Resource condition1 = graph.newResource();
+// graph.claim(condition1, L0.InstanceOf, ES.PropertyCondition);
+// graph.claim(condition1, ES.HasSubcondition_Inverse, condition);
+// graph.claimLiteral(condition1, ES.PropertyCondition_HasPropertyName, L0.String, "myProperty1");
+// Resource condition2 = graph.newResource();
+// graph.claim(condition2, L0.InstanceOf, ES.RegionCondition);
+// graph.claim(condition2, ES.HasSubcondition_Inverse, condition);
+// Resource region = graph.newResource();
+// graph.claim(condition2, ES.RegionCondition_HasRegion, region);
+// graph.claim(region, L0.InstanceOf, L0.Entity);
+// graph.claimLiteral(region, L0.HasLabel, L0.String, "region1");
+// }
+// });
+//
+// ElementSelector sel = Simantics.sync(new ElementSelector.ElementSelectorQuery(selection));
+// assertNotNull(sel);
+// String expression = sel.expression;
+// assertEquals("select all from model where {{has property myProperty1} and {in region region1}}", expression);
+// System.err.println(expression);
+// }
+//}
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.simantics.district.selection.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
<module>org.simantics.district.route.ontology</module>
<module>org.simantics.district.route.ui</module>
<module>org.simantics.district.selection</module>
+ <module>org.simantics.district.selection.ui</module>
<module>org.simantics.maps.server</module>
<module>org.simantics.maps.server.ui</module>