1 package org.simantics.district.selection.ui.parts;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
10 import javax.inject.Inject;
12 import org.eclipse.core.runtime.IStatus;
13 import org.eclipse.core.runtime.Status;
14 import org.eclipse.jface.dialogs.Dialog;
15 import org.eclipse.jface.dialogs.ErrorDialog;
16 import org.eclipse.jface.layout.GridDataFactory;
17 import org.eclipse.jface.layout.GridLayoutFactory;
18 import org.eclipse.jface.layout.RowLayoutFactory;
19 import org.eclipse.jface.window.Window;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.custom.StackLayout;
22 import org.eclipse.swt.events.SelectionAdapter;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.widgets.Button;
25 import org.eclipse.swt.widgets.Combo;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Shell;
30 import org.eclipse.swt.widgets.Text;
31 import org.simantics.Simantics;
32 import org.simantics.db.ReadGraph;
33 import org.simantics.db.Resource;
34 import org.simantics.db.Session;
35 import org.simantics.db.WriteGraph;
36 import org.simantics.db.common.request.ReadRequest;
37 import org.simantics.db.common.request.WriteRequest;
38 import org.simantics.db.exception.DatabaseException;
39 import org.simantics.db.exception.RuntimeDatabaseException;
40 import org.simantics.db.layer0.QueryIndexUtils;
41 import org.simantics.db.layer0.request.ActiveModels;
42 import org.simantics.db.layer0.util.Layer0Utils;
43 import org.simantics.db.request.Read;
44 import org.simantics.db.request.WriteResult;
45 import org.simantics.diagram.stubs.DiagramResource;
46 import org.simantics.district.region.ontology.DiagramRegionsResource;
47 import org.simantics.district.route.ontology.RouteResource;
48 import org.simantics.district.selection.ElementSelectionResource;
49 import org.simantics.district.selection.ElementSelectionUtils;
50 import org.simantics.district.selection.ElementSelector;
51 import org.simantics.district.selection.ElementSelector.AggregateCondition;
52 import org.simantics.district.selection.ElementSelector.AggregateCondition.Type;
53 import org.simantics.district.selection.ElementSelector.All;
54 import org.simantics.district.selection.ElementSelector.Condition;
55 import org.simantics.district.selection.ElementSelector.DiagramGenerator;
56 import org.simantics.district.selection.ElementSelector.ExplicitGenerator;
57 import org.simantics.district.selection.ElementSelector.Generator;
58 import org.simantics.district.selection.ElementSelector.ModelGenerator;
59 import org.simantics.district.selection.ElementSelector.PropertyCondition;
60 import org.simantics.district.selection.ElementSelector.PropertySelector;
61 import org.simantics.district.selection.ElementSelector.RegionCondition;
62 import org.simantics.district.selection.ElementSelector.RouteCondition;
63 import org.simantics.district.selection.ElementSelector.Selector;
64 import org.simantics.layer0.Layer0;
65 import org.simantics.modeling.ModelingResources;
66 import org.simantics.utils.datastructures.Arrays;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class EditSelectorDialog extends Dialog {
72 private static Logger LOGGER = LoggerFactory.getLogger(EditSelectorDialog.class);
74 private ElementSelector elementSelector;
76 // Currently selected elements
77 Collection<Resource> currentSelection;
79 // Data for comboboxes
80 Map<Resource, String> diagrams;
82 private String[] regionNames;
83 private Resource[] regionResources;
85 private String[] routeNames;
86 private Resource[] routeResources;
89 private int generatorIndex;
90 private Combo sourceField;
93 private Text nameField;
95 private Resource diagram;
96 private Combo diagramField;
98 private int selectorIndex;
99 private Combo selectorField;
101 private String propertyName;
102 private Text propertyField;
104 private int numberOfItems;
107 private Condition condition;
108 private Button removeConditionButton;
109 private Text conditionLabel;
111 // Dialog area component
112 private Composite content;
115 public EditSelectorDialog(Shell shell, ElementSelector elementSelector, Collection<Resource> currentSelection) {
118 this.elementSelector = elementSelector;
119 if (elementSelector != null) {
121 Simantics.getSession().sync(new ReadRequest() {
123 public void run(ReadGraph graph) throws DatabaseException {
124 elementSelector.buildSelection(graph);
127 } catch (DatabaseException e1) {
128 LOGGER.error("Failed to read element selector resource " + elementSelector.getResource(), e1);
129 throw new RuntimeDatabaseException(e1);
133 this.currentSelection = currentSelection;
135 final Map<Resource, String> regions = new HashMap<>();
136 final Map<Resource, String> routes = new HashMap<>();
139 Simantics.getSession().syncRequest(new Read<Void>() {
141 public Void perform(ReadGraph graph) throws DatabaseException {
142 Resource model = ActiveModels.getPossibleActiveModel(graph, Simantics.getProjectResource());
143 List<Resource> regionCollection = QueryIndexUtils.searchByType(graph, model, DiagramRegionsResource.getInstance(graph).Region);
144 for (Resource r : regionCollection) {
145 String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
146 regions.put(r, name);
149 List<Resource> routeCollection = QueryIndexUtils.searchByType(graph, model, RouteResource.getInstance(graph).Route);
150 for (Resource r : routeCollection) {
151 String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);
157 } catch (DatabaseException e) {
158 LOGGER.error("Failed to read routes and/or regions in the model", e);
161 regionNames = regions.values().toArray(new String[regions.size()]);
162 regionResources = regions.keySet().toArray(new Resource[regions.size()]);
164 routeNames = routes.values().toArray(new String[routes.size()]);
165 routeResources = routes.keySet().toArray(new Resource[routes.size()]);
167 name = elementSelector != null ? elementSelector.getName() : "";
175 if (elementSelector != null) {
176 Generator generator = elementSelector.getGenerator();
177 if (generator instanceof ModelGenerator) {
180 else if (generator instanceof DiagramGenerator) {
182 diagram = ((DiagramGenerator)generator).diagram;
184 else if (generator instanceof ExplicitGenerator) {
186 // TODO: Management of explicit lists of elements
189 throw new IllegalStateException("Unknown generator type " + generator.getClass().getName());
192 Selector selector = elementSelector.getSelector();
193 if (selector instanceof All) {
196 else if (selector instanceof PropertySelector) {
197 PropertySelector propertySelector = (PropertySelector)selector;
198 selectorIndex = propertySelector.smallest ? 1 : 2;
199 propertyName = propertySelector.propertyName;
200 numberOfItems = propertySelector.resultCount;
203 throw new IllegalStateException("Unknwon selector type " + selector.getClass().getName());
206 condition = elementSelector.getCondition();
211 protected void okPressed() {
212 generatorIndex = sourceField.getSelectionIndex();
213 if (generatorIndex == 1) {
214 int selectionIndex = diagramField.getSelectionIndex();
215 if (selectionIndex < 0) {
216 ErrorDialog.openError(getShell(), "Error", "Please select a diagram", new Status(IStatus.ERROR, "org.simantics.district.selection.ui", "No diagram selected"));
220 diagram = new ArrayList<Resource>(diagrams.keySet()).get(selectionIndex);
223 name = nameField.getText();
225 selectorIndex = selectorField.getSelectionIndex();
227 propertyName = propertyField.getText();
228 String text = nField.getText();
229 numberOfItems = "".equals(text) ? 0 : Integer.parseInt(text);
234 public void writeSelection() throws DatabaseException {
235 Simantics.getSession().syncRequest(new WriteRequest() {
237 public void perform(WriteGraph graph) throws DatabaseException {
238 Layer0 L0 = Layer0.getInstance(graph);
239 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
240 ModelingResources MOD = ModelingResources.getInstance(graph);
241 DiagramResource DIA = DiagramResource.getInstance(graph);
243 graph.markUndoPoint();
244 Layer0Utils.addCommentMetadata(graph, "Created new element selection");
246 Resource lib = ElementSelectionUtils.ensureSelectionLibrary(graph);
250 if (elementSelector != null) {
251 selection = elementSelector.getResource();
252 graph.deny(selection);
255 selection = graph.newResource();
258 graph.claim(selection, L0.InstanceOf, ES.Selection);
259 graph.claimLiteral(selection, L0.HasName, L0.String, UUID.randomUUID().toString());
260 graph.claimLiteral(selection, L0.HasLabel, L0.String, name);
261 graph.claim(selection, L0.PartOf, lib);
264 Resource generator = graph.newResource();
265 Resource generatorType;
266 switch (generatorIndex) {
268 generatorType = ES.Generator_Model;
271 generatorType = ES.Generator_Diagram;
272 Resource composite = graph.getPossibleObject(diagram, MOD.DiagramToComposite);
273 graph.claim(generator, ES.Generator_HasDiagram, composite != null ? composite : diagram);
276 generatorType = ES.Generator_Explicit;
277 for (Resource r : currentSelection) {
279 if (graph.isInstanceOf(r, DIA.Connection))
281 if (!graph.isInstanceOf(r, DIA.Element)) {
282 if (!graph.hasStatement(r, MOD.ComponentToElement))
285 r = graph.getPossibleObject(r, MOD.ComponentToElement);
290 graph.claim(generator, ES.Generator_HasSelectedElement, r);
293 default: throw new IllegalStateException("Invalid source index " + generatorIndex);
295 graph.claim(generator, L0.InstanceOf, generatorType);
296 graph.claim(selection, ES.Selection_HasGenerator, generator);
299 Resource selector = graph.newResource();
300 Resource selectorType;
301 switch (selectorIndex) {
302 case 0: selectorType = ES.Selector_All; break;
303 case 1: selectorType = ES.Selector_NLowest; break;
304 case 2: selectorType = ES.Selector_NHighest; break;
305 default: throw new IllegalStateException("Invalid selector index " + selectorIndex);
307 graph.claim(selector, L0.InstanceOf, selectorType);
308 graph.claim(selection, ES.Selection_HasSelector, selector);
310 if (selectorIndex > 0) {
311 graph.claimLiteral(selector, ES.PropertySelector_HasSelectionPropertyName, L0.String, propertyName);
312 graph.claimLiteral(selector, ES.PropertySelector_HasResultCount, L0.Integer, numberOfItems);
316 if (condition != null) {
317 graph.claim(selection, ES.Selection_HasCondition, condition.resource);
324 protected Control createDialogArea(Composite parent) {
326 getShell().setText("Edit element selector");
328 content = new Composite(parent, SWT.NONE);
329 GridLayoutFactory.swtDefaults().numColumns(3).applyTo(content);
332 Label nameLabel = new Label(content, SWT.NONE);
333 nameLabel.setText("Name");
334 GridDataFactory.swtDefaults().applyTo(nameLabel);
336 nameField = new Text(content, SWT.BORDER);
337 nameField.setEditable(true);
338 nameField.setText(name);
339 GridDataFactory.swtDefaults().span(2, 1).hint(200, SWT.DEFAULT).applyTo(nameField);
342 Label sourceLabel = new Label(content, SWT.NONE);
343 sourceLabel.setText("Source");
344 GridDataFactory.swtDefaults().applyTo(sourceLabel);
346 sourceField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
347 sourceField.setItems("Model", "Diagram", "Current selection");
348 sourceField.select(generatorIndex);
349 GridDataFactory.swtDefaults().span(1, 1).applyTo(sourceField);
351 diagramField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
352 GridDataFactory.swtDefaults().span(1, 1).applyTo(diagramField);
353 diagrams = ElementSelector.findDiagrams();
354 diagramField.setItems(diagrams.values().toArray(new String[diagrams.size()]));
356 int diagramIndex = diagram != null ? new ArrayList<>(diagrams.keySet()).indexOf(diagram) : -1;
357 diagramField.select(diagramIndex);
359 sourceField.addSelectionListener(new SelectionAdapter() {
361 public void widgetSelected(SelectionEvent e) {
362 generatorIndex = sourceField.getSelectionIndex();
363 diagramField.setVisible(isDiagramFieldVisible());
367 sourceField.select(generatorIndex);
368 diagramField.setVisible(isDiagramFieldVisible());
371 Label selectorLabel = new Label(content, SWT.NONE);
372 selectorLabel.setText("Select");
373 GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorLabel);
375 selectorField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
376 selectorField.setItems("All", "N lowest", "N highest");
377 selectorField.select(selectorIndex);
378 GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorField);
380 Composite selectorComposite = new Composite(content, SWT.NONE);
381 GridDataFactory.swtDefaults().span(1, 1).applyTo(selectorComposite);
382 GridLayoutFactory.swtDefaults().numColumns(2).applyTo(selectorComposite);
384 Label propertyLabel = new Label(selectorComposite, SWT.NONE);
385 propertyLabel.setText("Property name");
386 GridDataFactory.swtDefaults().applyTo(propertyLabel);
388 propertyField = new Text(selectorComposite, SWT.BORDER);
389 propertyField.setText(propertyName);
390 GridDataFactory.swtDefaults().hint(80, SWT.DEFAULT).applyTo(propertyField);
392 Label nLabel = new Label(selectorComposite, SWT.NONE);
393 nLabel.setText("Number of elements");
394 GridDataFactory.swtDefaults().applyTo(nLabel);
396 nField = new Text(selectorComposite, SWT.BORDER);
397 nField.setText(Integer.toString(numberOfItems));
398 GridDataFactory.swtDefaults().hint(40, SWT.DEFAULT).applyTo(nField);
400 selectorField.addSelectionListener(new SelectionAdapter() {
402 public void widgetSelected(SelectionEvent e) {
403 selectorIndex = selectorField.getSelectionIndex();
404 selectorComposite.setVisible(isSelectorCompositeVisible());
408 selectorField.select(selectorIndex);
409 selectorComposite.setVisible(isSelectorCompositeVisible());
412 new Label(content, SWT.NONE).setText("Condition");
413 conditionLabel = new Text(content, SWT.READ_ONLY);
414 GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionLabel);
416 new Label(content, SWT.NONE);
417 Composite conditionPanel = new Composite(content, SWT.NONE);
418 GridDataFactory.swtDefaults().span(2, 1).applyTo(conditionPanel);
419 GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(conditionPanel);
420 Button conditionButton = new Button(conditionPanel, SWT.PUSH);
421 conditionButton.setText("Edit...");
422 GridDataFactory.swtDefaults().span(1, 1).applyTo(conditionButton);
423 removeConditionButton = new Button(conditionPanel, SWT.PUSH);
424 removeConditionButton.setText("Remove");
425 GridDataFactory.swtDefaults().span(1, 1).applyTo(removeConditionButton);
429 conditionButton.addSelectionListener(new SelectionAdapter() {
431 public void widgetSelected(SelectionEvent e) {
432 ConditionDialog dialog = new ConditionDialog(getShell(), condition);
433 if (dialog.open() == Window.OK) {
435 condition = dialog.createCondition();
436 } catch (DatabaseException e1) {
437 LOGGER.error("Creating a condition object failed", e1);
445 removeConditionButton.addSelectionListener(new SelectionAdapter() {
447 public void widgetSelected(SelectionEvent e) {
456 private void updateCondition() {
457 if (condition != null) {
458 removeConditionButton.setEnabled(true);
460 conditionLabel.setText(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
461 } catch (DatabaseException e) {
462 LOGGER.error("Error getting expression string for " + condition.resource);
466 conditionLabel.setText("No condition");
467 removeConditionButton.setEnabled(false);
473 private boolean isDiagramFieldVisible() {
474 return generatorIndex == 1;
477 private boolean isSelectorCompositeVisible() {
478 return selectorIndex != 0;
481 class ConditionDialog extends Dialog {
482 // Resource of the edited condition
483 private Resource existingResource;
485 // Inverse condition button
486 private boolean isInverse;
487 private Button inverseField;
490 private int typeIndex;
491 private Combo typeField;
493 // Type-specific control panels under a stack layout
494 private Composite stackPanel;
495 private StackLayout stack;
497 private Composite propertyPanel;
498 private Composite regionPanel;
499 private Composite routePanel;
500 private Composite aggregatePanel;
502 // Property condition
503 private Double lowerLimit;
504 private Double upperLimit;
505 private String propertyName;
507 private Text propertyNameField;
508 private Text lowerLimitField;
509 private Text upperLimitField;
512 private Resource region;
513 private Combo regionField;
516 private Resource route;
517 private Combo routeField;
519 // Aggregate condition
520 private List<Condition> subConditions;
521 private boolean isConjunction;
523 private org.eclipse.swt.widgets.List subConditionField;
524 private Combo operatorField;
526 public ConditionDialog(Shell shell, Condition condition) {
534 subConditions = new ArrayList<>();
536 existingResource = condition != null ? condition.resource : null;
538 if (condition != null) {
539 if (condition instanceof PropertyCondition) {
541 PropertyCondition propertyCondition = (PropertyCondition)condition;
542 propertyName = propertyCondition.propertyName;
543 upperLimit = propertyCondition.upperLimit;
544 lowerLimit = propertyCondition.lowerLimit;
546 else if (condition instanceof RegionCondition) {
548 region = ((RegionCondition)condition).regionResource;
550 else if (condition instanceof RouteCondition) {
552 route = ((RouteCondition)condition).routeResource;
554 else if (condition instanceof AggregateCondition) {
556 subConditions = new ArrayList<>(((AggregateCondition)condition).conditions);
557 isConjunction = ((AggregateCondition)condition).type == Type.CONJUNCTION;
558 isInverse = ((AggregateCondition)condition).type == Type.NEGATION;
564 protected Control createDialogArea(Composite parent) {
565 getShell().setText("Edit selector condition");
567 Composite content = (Composite)super.createDialogArea(parent);
568 GridLayoutFactory.swtDefaults().numColumns(1).applyTo(content);
570 GridDataFactory defaultWidth = GridDataFactory.swtDefaults().hint(200, SWT.DEFAULT);
573 inverseField = new Button(content, SWT.CHECK);
574 inverseField.setText("Is inverse");
575 inverseField.setSelection(isInverse);
578 typeField = new Combo(content, SWT.BORDER | SWT.READ_ONLY);
579 typeField.setItems("Property value", "In region", "On route", "Combination");
580 typeField.select(typeIndex);
582 // Type-dependent stacked panels
583 stackPanel = new Composite(content, SWT.NONE);
584 stack = new StackLayout();
585 stackPanel.setLayout(stack);
587 // Property condition panel
588 propertyPanel = new Composite(stackPanel, SWT.NONE);
589 GridLayoutFactory.swtDefaults().numColumns(2).applyTo(propertyPanel);
591 new Label(propertyPanel, SWT.NONE).setText("Property name");
592 propertyNameField = new Text(propertyPanel, SWT.BORDER);
593 propertyNameField.setText(propertyName);
594 defaultWidth.applyTo(propertyNameField);
596 new Label(propertyPanel, SWT.NONE).setText("Lower limit");
597 lowerLimitField = new Text(propertyPanel, SWT.BORDER);
598 defaultWidth.applyTo(lowerLimitField);
599 if (lowerLimit != null) lowerLimitField.setText(lowerLimit.toString());
601 new Label(propertyPanel, SWT.NONE).setText("Upper limit");
602 upperLimitField = new Text(propertyPanel, SWT.BORDER);
603 defaultWidth.applyTo(upperLimitField);
604 if (upperLimit != null) upperLimitField.setText(upperLimit.toString());
606 // Region condition panel
607 regionPanel = new Composite(stackPanel, SWT.NONE);
608 GridLayoutFactory.swtDefaults().numColumns(2).applyTo(regionPanel);
610 new Label(regionPanel, SWT.NONE).setText("Region");
611 regionField = new Combo(regionPanel, SWT.BORDER | SWT.READ_ONLY);
612 regionField.setItems(regionNames);
613 defaultWidth.applyTo(regionField);
615 if (region != null) {
616 int regionIndex = Arrays.indexOf(regionResources, region);
617 regionField.select(regionIndex);
620 regionField.select(0);
623 // Route condition panel
624 routePanel = new Composite(stackPanel, SWT.NONE);
625 GridLayoutFactory.swtDefaults().numColumns(2).applyTo(routePanel);
627 new Label(routePanel, SWT.NONE).setText("Route");
628 routeField = new Combo(routePanel, SWT.BORDER | SWT.READ_ONLY);
629 routeField.setItems(routeNames);
630 defaultWidth.applyTo(routeField);
633 int routeIndex = Arrays.indexOf(routeResources, route);
634 routeField.select(routeIndex);
637 routeField.select(0);
640 // Aggregate condition panel
641 aggregatePanel = new Composite(stackPanel, SWT.NONE);
642 GridLayoutFactory.swtDefaults().numColumns(2).applyTo(aggregatePanel);
644 new Label(aggregatePanel, SWT.NONE).setText("Operator");
645 operatorField = new Combo(aggregatePanel, SWT.READ_ONLY);
646 operatorField.setItems("And", "Or");
647 operatorField.select(isConjunction ? 0 : 1);
649 new Label(aggregatePanel, SWT.NONE).setText("Sub-conditions");
650 Composite buttons = new Composite(aggregatePanel, SWT.NONE);
651 RowLayoutFactory.swtDefaults().justify(true).fill(true).extendedMargins(0, 0, 0, 0).type(SWT.HORIZONTAL).applyTo(buttons);
653 Button addButton = new Button(buttons, SWT.PUSH);
654 addButton.setText("Add");
655 Button removeButton = new Button(buttons, SWT.PUSH);
656 removeButton.setText("Remove");
657 Button editButton = new Button(buttons, SWT.PUSH);
658 editButton.setText("Edit");
660 new Label(aggregatePanel, SWT.NONE);
661 subConditionField = new org.eclipse.swt.widgets.List(aggregatePanel, SWT.BORDER);
662 GridDataFactory.swtDefaults().hint(200, 150).applyTo(subConditionField);
663 if (subConditions != null) {
664 Session session = Simantics.getSession();
665 List<String> items = new ArrayList<>();
666 for (Condition c : subConditions) {
668 items.add(ElementSelector.getExpression(session, c.resource));
669 } catch (DatabaseException e1) {
670 LOGGER.error("Condition expression read failed", e1);
671 items.add("<Unknown expression>");
675 subConditionField.setItems(items.toArray(new String[items.size()]));
678 addButton.addSelectionListener(new SelectionAdapter() {
680 public void widgetSelected(SelectionEvent e) {
681 ConditionDialog conditionDialog = new ConditionDialog(getShell(), null);
682 if (conditionDialog.open() == Window.OK) {
685 condition = conditionDialog.createCondition();
686 subConditions.add(condition);
689 subConditionField.add(ElementSelector.getExpression(Simantics.getSession(), condition.resource));
690 } catch (DatabaseException e1) {
691 LOGGER.error("Condition expression read failed", e1);
692 subConditionField.add("<Unknown expression>");
694 } catch (DatabaseException e2) {
695 LOGGER.error("Create condition failed", e2);
701 removeButton.addSelectionListener(new SelectionAdapter() {
703 public void widgetSelected(SelectionEvent e) {
704 int index = subConditionField.getSelectionIndex();
706 subConditionField.deselectAll();
707 subConditionField.remove(index);
708 subConditions.remove(index);
710 if (index < subConditions.size())
711 subConditionField.setSelection(index);
714 boolean selected = subConditionField.getSelectionIndex() >= 0;
715 removeButton.setEnabled(selected);
716 editButton.setEnabled(selected);
720 editButton.addSelectionListener(new SelectionAdapter() {
722 public void widgetSelected(SelectionEvent e) {
723 int index = subConditionField.getSelectionIndex();
725 Condition condition = subConditions.get(index);
726 ConditionDialog conditionDialog = new ConditionDialog(getShell(), condition);
727 if (conditionDialog.open() == Window.OK) {
729 condition = conditionDialog.createCondition();
730 subConditions.set(index, condition);
733 subConditionField.setItem(index, ElementSelector.getExpression(Simantics.getSession(), condition.resource));
734 } catch (DatabaseException e1) {
735 LOGGER.error("Condition expression read failed", e1);
736 subConditionField.setItem(index, "<Unknown expression>");
738 } catch (DatabaseException e2) {
739 LOGGER.error("Create condition failed", e2);
746 subConditionField.addSelectionListener(new SelectionAdapter() {
748 public void widgetSelected(SelectionEvent e) {
749 boolean selected = subConditionField.getSelectionIndex() >= 0;
750 removeButton.setEnabled(selected);
751 editButton.setEnabled(selected);
755 // Stack layout update
756 typeField.addSelectionListener(new SelectionAdapter() {
758 public void widgetSelected(SelectionEvent e) {
769 protected void okPressed() {
770 isInverse = inverseField.getSelection();
773 case 0: // Property condition
774 propertyName = propertyNameField.getText();
776 String lowerLimitText = lowerLimitField.getText();
777 lowerLimit = lowerLimitText.equals("") ? null : Double.valueOf(lowerLimitText);
778 String upperLimitText = upperLimitField.getText();
779 upperLimit = upperLimitText.equals("") ? null : Double.valueOf(upperLimitText);
781 catch (NumberFormatException e) {
782 ErrorDialog.openError(getShell(), "Error", "Invalid numeric value: " + e.getMessage(), new Status(OK, "org.simantics.district.selection.ui", e.getMessage()));
786 case 1: { // Region condition
787 int selectionIndex = regionField.getSelectionIndex();
788 if (selectionIndex < 0) {
789 ErrorDialog.openError(getShell(), "Error", "Please select a region", new Status(OK, "org.simantics.district.selection.ui", "No region selection"));
792 region = regionResources[selectionIndex];
795 case 2: // Route condition
796 route = routeResources[routeField.getSelectionIndex()];
798 case 3: // Aggregate condition
799 isConjunction = operatorField.getSelectionIndex() == 0;
806 protected Condition createCondition() throws DatabaseException {
807 if (isInverse && !(typeIndex == 3 && !isConjunction)) {
808 Resource resource0 = createCondition0();
811 Resource resource = Simantics.getSession().syncRequest(new WriteResult<Resource>() {
813 public Resource perform(WriteGraph graph) throws DatabaseException {
814 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
815 Layer0 L0 = Layer0.getInstance(graph);
817 Resource r = graph.newResource();
818 graph.claim(r, L0.InstanceOf, ES.Negation);
819 graph.claim(r, ES.HasSubcondition, resource0);
824 return ElementSelector.getCondition(Simantics.getSession(), resource);
827 return ElementSelector.getCondition(Simantics.getSession(), createCondition0());
831 private Resource createCondition0() throws DatabaseException {
833 case 0: return createPropertyCondition();
834 case 1: return createRegionCondition();
835 case 2: return createRouteCondition();
836 case 3: return createAggregateCondition();
837 default: throw new IllegalStateException("Invalid condition type code " + typeIndex);
841 private Resource createPropertyCondition() throws DatabaseException {
842 return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
844 public Resource perform(WriteGraph graph) throws DatabaseException {
845 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
846 Layer0 L0 = Layer0.getInstance(graph);
848 Resource r = graph.newResource();
849 graph.claim(r, L0.InstanceOf, ES.PropertyCondition);
850 graph.claimLiteral(r, ES.PropertyCondition_HasPropertyName, propertyName);
851 if (lowerLimit != null)
852 graph.claimLiteral(r, ES.PropertyCondition_HasLowerLimit, L0.Double, lowerLimit);
853 if (upperLimit != null)
854 graph.claimLiteral(r, ES.PropertyCondition_HasUpperLimit, L0.Double, upperLimit);
861 private Resource createAggregateCondition() throws DatabaseException {
862 return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
864 public Resource perform(WriteGraph graph) throws DatabaseException {
865 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
866 Layer0 L0 = Layer0.getInstance(graph);
869 if (existingResource != null) {
870 // Reuse existing resource
871 r = existingResource;
872 // Clear any previous statements
873 graph.deny(existingResource);
876 r = graph.newResource();
880 type = isConjunction ? ES.Conjunction : isInverse ? ES.Negation : ES.Disjunction;
882 graph.claim(r, L0.InstanceOf, type);
883 for (Condition c : subConditions) {
884 graph.claim(r, ES.HasSubcondition, c.resource);
892 private Resource createRouteCondition() throws DatabaseException {
893 return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
895 public Resource perform(WriteGraph graph) throws DatabaseException {
896 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
897 Layer0 L0 = Layer0.getInstance(graph);
899 Resource r = graph.newResource();
900 graph.claim(r, L0.InstanceOf, ES.RouteCondition);
901 graph.claim(r, ES.RouteCondition_HasRoute, route);
907 private Resource createRegionCondition() throws DatabaseException {
908 return Simantics.getSession().syncRequest(new WriteResult<Resource>() {
910 public Resource perform(WriteGraph graph) throws DatabaseException {
911 ElementSelectionResource ES = ElementSelectionResource.getInstance(graph);
912 Layer0 L0 = Layer0.getInstance(graph);
914 Resource r = graph.newResource();
915 graph.claim(r, L0.InstanceOf, ES.RegionCondition);
916 graph.claim(r, ES.RegionCondition_HasRegion, region);
922 private void updateStack() {
923 typeIndex = typeField.getSelectionIndex();
925 case 0: stack.topControl = propertyPanel; break;
926 case 1: stack.topControl = regionPanel; break;
927 case 2: stack.topControl = routePanel; break;
928 case 3: stack.topControl = aggregatePanel; break;