]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.selection.ui/src/org/simantics/district/selection/ui/parts/EditSelectorDialog.java
Manage drop-down menu contents by context in district finder dialog
[simantics/district.git] / org.simantics.district.selection.ui / src / org / simantics / district / selection / ui / parts / EditSelectorDialog.java
index a269d5efe3da4cb483f81492e766aacd465929a5..b708d8e978695dc18919f05a80a824409d2b1564 100644 (file)
@@ -14,10 +14,8 @@ import java.util.function.Consumer;
 
 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.dialogs.MessageDialog;
 import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.layout.RowDataFactory;
@@ -51,7 +49,6 @@ import org.simantics.db.layer0.request.ActiveModels;
 import org.simantics.db.layer0.request.PropertyInfo;
 import org.simantics.db.layer0.request.PropertyInfoRequest;
 import org.simantics.db.layer0.util.Layer0Utils;
-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;
@@ -143,10 +140,18 @@ public class EditSelectorDialog extends Dialog {
 
        private LocalResourceManager resourceManager;
        
+       static class ValidationException extends Exception {
+               private static final long serialVersionUID = 1L;
+
+               public ValidationException(String message) {
+                       super(message);
+               }
+       }
+       
        // Function type for updating condition objects with optional validation
        static interface Updater {
                // If 'validate' is true, a runtime exception may be thrown for invalid values
-               void update(boolean validate);
+               void update(boolean validate) throws ValidationException;
        }
        
        final static Updater NULL_UPDATE = validate -> {};
@@ -186,71 +191,6 @@ public class EditSelectorDialog extends Dialog {
                                diagramNames.add(e.getValue());
                        });
                
-               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()]);
-               
-               try {
-                       Simantics.getSession().syncRequest(new ReadRequest() {
-                               @Override
-                               public void run(ReadGraph graph) throws DatabaseException {
-                                       Layer0 L0 = Layer0.getInstance(graph);
-                                       List<Resource> types = findComponentTypes(graph);
-                                       
-                                       componentTypes = new ArrayList<>(types.size() + 1);
-                                       componentTypeNames = new ArrayList<>(types.size() + 1);
-                                       
-                                       componentTypes.add(null);
-                                       componentTypeNames.add("Any type");
-                                       componentTypes.addAll(types);
-                                       for (Resource t : types) {
-                                               componentTypeNames.add(graph.getValue2(t, L0.HasName));
-                                       }
-                               }
-                       });
-               } catch (DatabaseException e) {
-                       LOGGER.error("Failed to read district component types", e);
-               }
-               
-               componentType = elementSelector.getSelector().componentType;
-               
-               propertyNames = new ArrayList<>();
-               propertyLabels = new ArrayList<>();
-               
-               try {
-                       updatePropertyList();
-               } catch (DatabaseException e) {
-                       LOGGER.error("Failed to read district component properties", e);
-               }
-       
                name = elementSelector != null ? elementSelector.getName() : "";
                propertyName = "";
                numberOfItems = 1;
@@ -290,11 +230,107 @@ public class EditSelectorDialog extends Dialog {
                        }
                        
                        condition = elementSelector.getCondition();
+                       
+                       componentType = elementSelector.getSelector().componentType;
+               }
+               
+               readRegions(diagram);
+               readRoutes();
+               readComponentTypes();
+               updatePropertyList();
+       }
+
+       private void readComponentTypes() {
+               try {
+                       Simantics.getSession().syncRequest(new ReadRequest() {
+                               @Override
+                               public void run(ReadGraph graph) throws DatabaseException {
+                                       Layer0 L0 = Layer0.getInstance(graph);
+                                       List<Resource> types = findComponentTypes(graph);
+                                       
+                                       componentTypes = new ArrayList<>(types.size() + 1);
+                                       componentTypeNames = new ArrayList<>(types.size() + 1);
+                                       
+                                       componentTypes.add(null);
+                                       componentTypeNames.add("Any type");
+                                       componentTypes.addAll(types);
+                                       for (Resource t : types) {
+                                               componentTypeNames.add(graph.getValue2(t, L0.HasName));
+                                       }
+                               }
+                       });
+               } catch (DatabaseException e) {
+                       LOGGER.error("Failed to read district component types", e);
+               }
+       }
+
+       private void readRoutes() {
+               final Map<Resource, String> routes = new HashMap<>();
+               
+               try {
+                       Simantics.getSession().syncRequest(new ReadRequest() {
+                               @Override
+                               public void run(ReadGraph graph) throws DatabaseException {
+                                       Layer0 L0 = Layer0.getInstance(graph);
+                                       RouteResource ROUTE = RouteResource.getInstance(graph);
+                                       
+                                       Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
+                                       List<Resource> routeCollection = QueryIndexUtils.searchByType(graph, model, ROUTE.Route);
+                                       for (Resource r : routeCollection) {
+                                               String name = graph.getRelatedValue(r, L0.HasLabel);
+                                               routes.put(r, name);
+                                       }
+                               }
+                       });
+               } catch (DatabaseException e) {
+                       LOGGER.error("Failed to read routes in the model", e);
+               }
+               
+               routeNames = routes.values().toArray(new String[routes.size()]);
+               routeResources = routes.keySet().toArray(new Resource[routes.size()]);
+       }
+
+       private void readRegions(Resource diagram) {
+               final Map<Resource, String> regions = new HashMap<>();
+               
+               try {
+                       Simantics.getSession().syncRequest(new ReadRequest() {
+                               @Override
+                               public void run(ReadGraph graph) throws DatabaseException {
+                                       Layer0 L0 = Layer0.getInstance(graph);
+                                       ModelingResources MOD = ModelingResources.getInstance(graph);
+                                       DiagramRegionsResource DR = DiagramRegionsResource.getInstance(graph);
+                                       
+                                       // If a specific diagram is given, use that
+                                       Collection<Resource> ds = diagram != null ? Collections.singleton(diagram) : diagrams;
+                                       
+                                       for (Resource composite : ds) {
+                                               Resource diagram = graph.getSingleObject(composite, MOD.CompositeToDiagram);
+                                               for (Resource r : graph.getObjects(diagram, DR.hasRegion)) {
+                                                       if (!graph.isInstanceOf(r, DR.Region))
+                                                               continue;
+                                                       String name = graph.getRelatedValue(r, L0.HasLabel);
+                                                       regions.put(r, name);
+                                               }
+                                       }
+                               }
+                       });
+               } catch (DatabaseException e) {
+                       LOGGER.error("Failed to read regions in the model", e);
                }
+               
+               regionNames = regions.values().toArray(new String[regions.size()]);
+               regionResources = regions.keySet().toArray(new Resource[regions.size()]);
        }
        
        private void updateDialog() {
-               updater.update(false);
+               try {
+                       updater.update(false);
+               } catch (ValidationException e) {
+                       // Should not happend with argument false
+                       assert(false);
+               }
+               
                updater = updateConditionPanel();
                
                content.layout(true, true);
@@ -303,38 +339,53 @@ public class EditSelectorDialog extends Dialog {
 
        @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;
+               try {
+                       generatorIndex = sourceField.getSelectionIndex();
+                       if (generatorIndex == 1) {
+                               int selectionIndex = diagramField.getSelectionIndex();
+                               if (selectionIndex < 0) {
+                                       diagramField.setFocus();
+                                       throw new ValidationException("Please select a diagram");
+                               }
+                               
+                               diagram = diagrams.get(selectionIndex);
                        }
                        
-                       diagram = diagrams.get(selectionIndex);
-               }
-               
-               name = nameField.getText();
-               componentType = componentTypes.get(componentTypeField.getSelectionIndex());
-               selectorIndex = selectorField.getSelectionIndex();
-               int propertyIndex = propertyField.getSelectionIndex();
-               propertyName = propertyIndex >= 0 ? propertyNames.get(propertyIndex) : propertyField.getText();
-               
-               // Try to parse number of items
-               if (useNumberOfItems()) {
-                       try {
-                               numberOfItems = Integer.parseInt(nField.getText());
-                       } catch (RuntimeException e) {
-                               nField.selectAll();
-                               nField.forceFocus();
-                               return;
+                       name = nameField.getText();
+                       if (name.isEmpty()) {
+                               nameField.setFocus();
+                               throw new ValidationException("Please enter a name");
                        }
-               }
-
-               // To to update condition definitions
-               try {
+                       
+                       componentType = componentTypes.get(componentTypeField.getSelectionIndex());
+                       selectorIndex = selectorField.getSelectionIndex();
+                       int propertyIndex = propertyField.getSelectionIndex();
+                       propertyName = propertyIndex >= 0 ? propertyNames.get(propertyIndex) : propertyField.getText();
+                       if (propertyName.isEmpty()) {
+                               propertyField.setFocus();
+                               throw new ValidationException("Please select a property");
+                       }
+                       
+                       // Try to parse number of items
+                       if (useNumberOfItems()) {
+                               try {
+                                       numberOfItems = Integer.parseInt(nField.getText());
+                                       if (numberOfItems <= 0) {
+                                               nField.selectAll();
+                                               nField.setFocus();
+                                               throw new ValidationException("Number of elements must be positive");
+                                       }
+                               } catch (NumberFormatException e) {
+                                       nField.selectAll();
+                                       nField.setFocus();
+                                       throw new ValidationException("Please enter a valid number of elements");
+                               }
+                       }
+       
+                       // To to update condition definitions
                        updater.update(true);
-               } catch (RuntimeException e) {
+               } catch (ValidationException e) {
+                       MessageDialog.openError(this.getShell(), "Missing data", e.getMessage());
                        return;
                }
                
@@ -485,6 +536,19 @@ public class EditSelectorDialog extends Dialog {
                        componentTypeField.select(index >= 0 ? index : 0);
                }
                
+               // Update property selection controls when component type changes
+               componentTypeField.addSelectionListener(new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               int index = componentTypeField.getSelectionIndex();
+                               componentType = index >= 0 ? componentTypes.get(index) : null;
+                               updatePropertyList();
+                               propertyField.setItems(propertyLabels.toArray(new String[] {}));
+                               
+                               updateDialog();
+                       }
+               });
+               
                new Label(selectorComposite, SWT.NONE).setText("with");
                
                selectorField = new Combo(selectorComposite, SWT.BORDER | SWT.READ_ONLY);
@@ -554,6 +618,11 @@ public class EditSelectorDialog extends Dialog {
                                                diagramField.clearSelection();
                                }
                                diagramField.setEnabled(enabled);
+
+                               // Refresh list of regions for current diagram
+                               diagram = enabled ? (diagramIndex >= 0 ? diagrams.get(diagramIndex) : null) : null;
+                               readRegions(diagram);
+                               updateDialog();
                        }
                });
                
@@ -586,7 +655,7 @@ public class EditSelectorDialog extends Dialog {
                Button notCheck = new Button(parent, SWT.CHECK);
                GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.BEGINNING).applyTo(notCheck);
                notCheck.setText("not");
-               notCheck.setSelection(condition.isInverse);
+               notCheck.setSelection(condition != null && condition.isInverse);
                
                Composite conditionComp = new Composite(parent, SWT.NONE);
                GridDataFactory.fillDefaults().applyTo(conditionComp);
@@ -601,6 +670,8 @@ public class EditSelectorDialog extends Dialog {
                                "Any of"
                        );
                
+               typeCombo.addSelectionListener(new ConditionTypeSelectionListener(typeCombo, consumer, condition));
+
                final Updater updater;
                if (condition instanceof PropertyCondition) {
                        typeCombo.select(1);
@@ -619,11 +690,9 @@ public class EditSelectorDialog extends Dialog {
                        ROW_LAYOUT.applyTo(conditionComp);
                        notCheck.setEnabled(false);
                        typeCombo.select(0);
-                       updater = validate -> {};
+                       return NULL_UPDATE;
                }
                
-               typeCombo.addSelectionListener(new ConditionTypeSelectionListener(typeCombo, consumer, condition));
-
                return validate -> {
                        updater.update(validate);
                        condition.isInverse = notCheck.getSelection();
@@ -695,7 +764,7 @@ public class EditSelectorDialog extends Dialog {
                addButton.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
-                               cond.conditions.add(createPropertyCondition("property", null, null));
+                               cond.conditions.add(createPropertyCondition("", null, null));
                                updateDialog();
                        }
                });
@@ -756,6 +825,11 @@ public class EditSelectorDialog extends Dialog {
                // Register update
                return validate -> {
                        int i = routeCombo.getSelectionIndex();
+                       if (validate && i < 0) {
+                               routeCombo.forceFocus();
+                               throw new RuntimeException("Must select a route");
+                       }
+                               
                        condition.routeResource = i >= 0 ? routeResources[i] : null;
                };
        }
@@ -776,6 +850,11 @@ public class EditSelectorDialog extends Dialog {
                // Register update
                return validate -> {
                        int i = regionCombo.getSelectionIndex();
+                       if (validate && i < 0) {
+                               regionCombo.forceFocus();
+                               throw new ValidationException("Please select a region");
+                       }
+                       
                        condition.regionResource = i >= 0 ? regionResources[i] : null;
                };
        }
@@ -813,7 +892,7 @@ public class EditSelectorDialog extends Dialog {
                                if (validate) {
                                        lowerLimitText.selectAll();
                                        lowerLimitText.forceFocus();
-                                       throw e;
+                                       throw new ValidationException("Please enter a valid lower limit");
                                }
                        }
                        
@@ -824,7 +903,7 @@ public class EditSelectorDialog extends Dialog {
                                if (validate) {
                                        upperLimitText.selectAll();
                                        upperLimitText.forceFocus();
-                                       throw e;
+                                       throw new ValidationException("Please enter a valid upper limit");
                                }
                        }
                        
@@ -837,7 +916,7 @@ public class EditSelectorDialog extends Dialog {
                        
                        if (validate && name.isEmpty()) {
                                propertyNameText.forceFocus();
-                               throw new RuntimeException();
+                               throw new ValidationException("Please select a property");
                        } else {
                                condition.propertyName = name;
                        }
@@ -871,49 +950,56 @@ public class EditSelectorDialog extends Dialog {
                return QueryIndexUtils.searchByType(graph, model, DN.Mapping_Base);
        }
        
-       void updatePropertyList() throws DatabaseException {
+       void updatePropertyList() {
+               propertyNames = new ArrayList<>();
+               propertyLabels = new ArrayList<>();
+               
                Collection<Resource> types = componentType != null ? Collections.singleton(componentType) : componentTypes;
                Set<Pair<String, String>> properties = new HashSet<>();
                
-               Simantics.getSession().syncRequest(new ReadRequest() {
-                       @Override
-                       public void run(ReadGraph graph) throws DatabaseException {
-                               Layer0 L0 = Layer0.getInstance(graph);
-                               
-                               for (Resource type : types) {
-                                       if (type == null)
-                                               continue;
-                                       
-                                       Resource ct = graph.getPossibleObject(type, DistrictNetworkResource.getInstance(graph).Mapping_ComponentType);
-                                       if (ct == null)
-                                               continue;
-                                       
-                                       if (graph.isInstanceOf(ct, L0.String)) {
-                                               Resource indexRoot = graph.syncRequest(new IndexRoot(type));
-                                               String name = graph.getValue(ct);
-                                               ct = GraphUtils.getPossibleChild(graph, indexRoot, name);
-                                               if (ct == null)
-                                                       continue;
-                                       }
+               try {
+                       Simantics.getSession().syncRequest(new ReadRequest() {
+                               @Override
+                               public void run(ReadGraph graph) throws DatabaseException {
+                                       Layer0 L0 = Layer0.getInstance(graph);
                                        
-                                       for (Resource prop : graph.getObjects(ct, L0.DomainOf)) {
-                                               if (!graph.isInstanceOf(prop, StructuralResource2.getInstance(graph).Property))
+                                       for (Resource type : types) {
+                                               if (type == null)
                                                        continue;
                                                
-                                               // Filter only numeric properties
-                                               PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(prop));
-                                               if (info != null && info.requiredValueType != null && !isNumericValueType(info.requiredValueType))
+                                               Resource ct = graph.getPossibleObject(type, DistrictNetworkResource.getInstance(graph).Mapping_ComponentType);
+                                               if (ct == null)
                                                        continue;
                                                
-                                               String name = graph.getRelatedValue2(prop, L0.HasName);
-                                               String label = graph.getPossibleRelatedValue2(prop, L0.HasLabel);
-                                               if (label == null) label = name;
+                                               if (graph.isInstanceOf(ct, L0.String)) {
+                                                       Resource indexRoot = graph.syncRequest(new IndexRoot(type));
+                                                       String name = graph.getValue(ct);
+                                                       ct = GraphUtils.getPossibleChild(graph, indexRoot, name);
+                                                       if (ct == null)
+                                                               continue;
+                                               }
                                                
-                                               properties.add(Pair.make(label, name));
+                                               for (Resource prop : graph.getObjects(ct, L0.DomainOf)) {
+                                                       if (!graph.isInstanceOf(prop, StructuralResource2.getInstance(graph).Property))
+                                                               continue;
+                                                       
+                                                       // Filter only numeric properties
+                                                       PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(prop));
+                                                       if (info != null && info.requiredValueType != null && !isNumericValueType(info.requiredValueType))
+                                                               continue;
+                                                       
+                                                       String name = graph.getRelatedValue2(prop, L0.HasName);
+                                                       String label = graph.getPossibleRelatedValue2(prop, L0.HasLabel);
+                                                       if (label == null) label = name;
+                                                       
+                                                       properties.add(Pair.make(label, name));
+                                               }
                                        }
                                }
-                       }
-               });
+                       });
+               } catch (DatabaseException e) {
+                       LOGGER.error("Failed to read district component properties", e);
+               }
                
                propertyNames.clear();
                propertyLabels.clear();