]> gerrit.simantics Code Review - simantics/district.git/commitdiff
Change selection logic for n lowest/highest value queries 14/3314/1
authorReino Ruusu <reino.ruusu@semantum.fi>
Fri, 4 Oct 2019 11:55:00 +0000 (14:55 +0300)
committerReino Ruusu <reino.ruusu@semantum.fi>
Fri, 4 Oct 2019 11:55:00 +0000 (14:55 +0300)
gitlab #62

Change-Id: I2dce7f429c112fcf028edfebd110bd13a0f8ed26

org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/ElementSelectorTableUI.java
org.simantics.district.selection/src/org/simantics/district/selection/ElementSelector.java

index 09f34609497f5e0b792597932848edf541355e5c..001c8730970895461b67ffba3e766c9a4be5dae8 100644 (file)
@@ -6,6 +6,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
 import org.eclipse.jface.viewers.DoubleClickEvent;
@@ -21,6 +22,7 @@ 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.Display;
 import org.eclipse.swt.widgets.Tree;
 import org.simantics.Simantics;
 import org.simantics.browsing.ui.common.AdaptableHintContext;
@@ -39,9 +41,9 @@ import org.simantics.district.selection.ElementSelectionResource;
 import org.simantics.district.selection.ElementSelector;
 import org.simantics.district.selection.ElementSelector.DiagramGenerator;
 import org.simantics.district.selection.ElementSelector.ExplicitGenerator;
+import org.simantics.district.selection.ElementSelector.PropertySelector;
+import org.simantics.district.selection.ElementSelector.SelectionResult;
 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;
@@ -233,13 +235,13 @@ public class ElementSelectorTableUI extends Composite {
                        TreeSelection selection = (TreeSelection) event.getViewer().getSelection();
                        ElementSelector query = (ElementSelector) selection.getFirstElement();
                        try {
-                               List<Resource> result = Simantics.getSession().syncRequest(new Read<List<Resource>>() {
+                               SelectionResult result = Simantics.getSession().syncRequest(new Read<SelectionResult>() {
                                        @Override
-                                       public List<Resource> perform(ReadGraph graph) throws DatabaseException {
+                                       public SelectionResult perform(ReadGraph graph) throws DatabaseException {
                                                model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
                                                if (model == null) {
                                                        LOGGER.warn("No active model");
-                                                       return Collections.emptyList();
+                                                       return new SelectionResult(Collections.emptyList(), 0, 0);
                                                }
                                                
                                                return query.selectElementsFrom(graph, model);
@@ -247,17 +249,24 @@ public class ElementSelectorTableUI extends Composite {
                                });
                                
                                if (query.getGenerator() instanceof DiagramGenerator || query.getGenerator() instanceof ExplicitGenerator) {
-                                       DistrictNetworkUIUtil.openDNDiagramWithSelection(event.getViewer().getControl().getDisplay(), result);
+                                       DistrictNetworkUIUtil.openDNDiagramWithSelection(event.getViewer().getControl().getDisplay(), new ArrayList<>(result.elements));
                                }
                                else {
-                                       selectionService.setPostSelection(new StructuredSelection(Lists.map(new FunctionImpl1<Resource, AdaptableHintContext>() {
-                                               public AdaptableHintContext apply(Resource p0) {
-                                                       AdaptableHintContext selectionElement = new SelectionElement(SelectionHints.STD_KEYS);
-                                                       selectionElement.setHint(SelectionHints.KEY_MAIN, p0);
-                                                       selectionElement.setHint(SelectionHints.KEY_MODEL, model);
-                                                       return selectionElement;
-                                               }
-                                       }, result)));
+                                       selectionService.setPostSelection(new StructuredSelection(result.elements.stream()
+                                                       .map(p0 -> {
+                                                               AdaptableHintContext selectionElement = new SelectionElement(SelectionHints.STD_KEYS);
+                                                               selectionElement.setHint(SelectionHints.KEY_MAIN, p0);
+                                                               selectionElement.setHint(SelectionHints.KEY_MODEL, model);
+                                                               return selectionElement;
+                                                       })
+                                                       .toArray()));
+                               }
+                               
+                               if (result.tailCount != result.tailSize) {
+                                       String name = query.getSelector() != null && query.getSelector() instanceof PropertySelector ? ((PropertySelector)query.getSelector()).propertyName : null;
+                                       String msg = "Last " + result.tailCount + " of the " + result.elements.size() + " selected elements are an arbitraty subset of " + result.tailSize + " elements with equal values" +
+                                                       (name != null ? " for " + name : "");
+                                       MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Note", msg);
                                }
                        } catch (DatabaseException e) {
                                LOGGER.error("Element selection query failed", e);
index bf051b4c9828e3f9d4d0b08a3e8409a3d4d3c091..f0cbf4b1af9d02bfe0bee56b9eea098561e499be 100644 (file)
@@ -4,11 +4,13 @@ import java.awt.geom.Path2D;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.simantics.Simantics;
 import org.simantics.db.ReadGraph;
@@ -32,10 +34,8 @@ import org.simantics.district.region.ontology.DiagramRegionsResource;
 import org.simantics.district.selection.ElementSelector.AggregateCondition.Type;
 import org.simantics.layer0.Layer0;
 import org.simantics.modeling.ModelingResources;
-import org.simantics.scl.runtime.Lists;
-import org.simantics.scl.runtime.function.FunctionImpl1;
-import org.simantics.scl.runtime.tuple.Tuple2;
 import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.utils.datastructures.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -234,13 +234,12 @@ public class ElementSelector {
                return null;
        }
 
-       public List<Resource> selectElementsFrom(ReadGraph graph, Resource model) throws DatabaseException {
+       public SelectionResult selectElementsFrom(ReadGraph graph, Resource model) throws DatabaseException {
                if (selector == null) {
                        buildSelection(graph);
                }
                
-               Collection<Resource> result = gather(graph, model);
-               return result instanceof List ? (List<Resource>) result : new ArrayList<>(result);
+               return gather(graph, model);
        }
 
        private static Generator buildGenerator(ReadGraph graph, Resource resource) throws DatabaseException {
@@ -458,7 +457,7 @@ public class ElementSelector {
                return result;
        }
        
-       private Collection<Resource> gather(ReadGraph graph, Resource model) throws DatabaseException {
+       private SelectionResult gather(ReadGraph graph, Resource model) throws DatabaseException {
                return selector.select(graph, filterElementsFrom(graph, generator.generate(graph, model)));
        }
        
@@ -473,17 +472,28 @@ public class ElementSelector {
                Collection<Resource> generate(ReadGraph graph, Resource model) throws DatabaseException {
                        Resource conf = graph.syncRequest(new Configuration(model));
                        
-                       ArrayList<Resource> result = new ArrayList<>();
+                       HashMap<Resource, Resource> fromMapped = new HashMap<Resource, Resource>();
                        
                        // Iterate over diagrams
+                       // Each model element is represented by the corresponding mapping element, if present
                        for (Resource comp : graph.getObjects(conf, L0.ConsistsOf)) {
                                if (!graph.isInstanceOf(comp, STR.Composite)) continue;
                                
                                Resource diagram = graph.getPossibleObject(comp, MOD.CompositeToDiagram);
-                               if (diagram != null) result.addAll(elementsOfDiagram(graph, diagram));
+                               if (diagram != null) {
+                                       for (Resource elem : elementsOfDiagram(graph, diagram)) {
+                                               Resource mapped = graph.getPossibleObject(elem, DN.MappedComponent);
+                                               if (mapped != null) {
+                                                       fromMapped.put(mapped, elem);
+                                               }
+                                               else if (!fromMapped.containsKey(elem)) {
+                                                       fromMapped.put(elem, elem);
+                                               }
+                                       }
+                               }
                        }
                        
-                       return result;
+                       return new ArrayList<>(fromMapped.values());
                }
        }
        
@@ -515,8 +525,20 @@ public class ElementSelector {
        
        // Selectors
        
+       public static class SelectionResult {
+               public final Collection<Resource> elements;
+               public final int tailCount;
+               public final int tailSize;
+               
+               public SelectionResult(Collection<Resource> elements, int tailCount, int tailSize) {
+                       this.elements = elements;
+                       this.tailCount = tailCount;
+                       this.tailSize = tailSize;
+               }
+       }
+
        public static abstract class Selector {
-               abstract Collection<Resource> select(ReadGraph graph, Collection<Resource> elements);
+               abstract SelectionResult select(ReadGraph graph, Collection<Resource> elements);
        }
        
        public static class All extends Selector {
@@ -524,8 +546,8 @@ public class ElementSelector {
                }
 
                @Override
-               Collection<Resource> select(ReadGraph graph, Collection<Resource> elements) {
-                       return elements;
+               SelectionResult select(ReadGraph graph, Collection<Resource> elements) {
+                       return new SelectionResult(elements, 0, 0);
                }
        }
        
@@ -540,40 +562,48 @@ public class ElementSelector {
                public String propertyName;
                public int resultCount;
                
-               @SuppressWarnings("unchecked")
                @Override
-               Collection<Resource> select(ReadGraph graph, Collection<Resource> elements) {
-                       List<Tuple2> result2 = Lists.map(new FunctionImpl1<Resource, Tuple2>() {
-                               @Override
-                               public Tuple2 apply(Resource r) {
-                                       return new Tuple2(r, getPropertyValue(graph, r, propertyName));
-                               }
-                       }, new ArrayList<>(elements));
+               SelectionResult select(ReadGraph graph, Collection<Resource> elements) {
+                       // Select sorting direction
+                       Comparator<Pair<Resource, Double>> comparator = smallest ?
+                                       (p1, p2) -> Double.compare(p1.second, p2.second) :
+                                       (p1, p2) -> Double.compare(p1.second, p2.second);
                        
-                       result2 = Lists.filter(new FunctionImpl1<Tuple2, Boolean>() {
-                               @Override
-                               public Boolean apply(Tuple2 t) {
-                                       return t.c1 != null;
-                               }
-                       }, result2);
+                       // Get association list to property values
+                       List<Pair<Resource, Double>> result2 = elements.stream()
+                                       .map(r -> Pair.make(r, getPropertyValue(graph, r, propertyName)))
+                                       .filter(t -> t.second != null)
+                                       .sorted(comparator)
+                                       .collect(Collectors.toList());
+                       int count = Math.min(resultCount, result2.size());
                        
-                       result2.sort((t1, t2) -> smallest ? Double.compare((Double) t1.c1, (Double) t2.c1) : Double.compare((Double) t2.c1, (Double) t1.c1));
+                       // Count number of equal values at the end of the list
+                       int tailCount = 0;
+                       double tailValue = count > 0 ? result2.get(count-1).second : 0.0;
+                       for (int i = count-1; i >= 0; i--) {
+                               if (result2.get(i).second == tailValue)
+                                       tailCount++;
+                               else
+                                       break;
+                       }
                        
-                       if (resultCount < result2.size()) {
-                               double limitValue = (double) result2.get(resultCount-1).c1;
-                               
-                               // Expand selection to contain all items with the same value as the nth one
-                               int count = resultCount;
-                               while (count < result2.size() && (double)result2.get(count).c1 == limitValue) count++;
-                               result2 = result2.subList(0, count);
+                       // Count number of elements with value equal to the end of the list
+                       int tailSize = tailCount;
+                       for (int i = count; i < result2.size(); i++) {
+                               if (result2.get(i).second == tailValue)
+                                       tailSize++;
+                               else
+                                       break;
                        }
                        
-                       return (List<Resource>) Lists.map(new FunctionImpl1<Tuple2, Resource>() {
-                               @Override
-                               public Resource apply(Tuple2 p0) {
-                                       return (Resource) p0.c0;
-                               }
-                       }, result2);
+                       // Take first n items
+                       if (count < result2.size()) {
+                               result2 = result2.subList(0, resultCount);
+                       }
+                       
+                       // Map to list or resources
+                       List<Resource> selection = result2.stream().map(p -> p.first).collect(Collectors.toList());
+                       return new SelectionResult(selection, tailCount, tailSize);
                }
        }