]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java
Merge changes I78c3a258,I7bf72f04
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / componentTypeEditor / ComponentTypeViewerData.java
index d6b312426253fa33226aeb13f36505455ddea238..01c799d45832b824835b1a477c20c3ecd3dfce16 100644 (file)
@@ -1,14 +1,21 @@
 package org.simantics.modeling.ui.componentTypeEditor;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.IMessageProvider;
 import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StyledText;
 import org.eclipse.swt.custom.TableEditor;
@@ -29,6 +36,7 @@ import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.forms.widgets.Form;
 import org.eclipse.ui.forms.widgets.FormToolkit;
 import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
 import org.simantics.databoard.type.NumberType;
 import org.simantics.databoard.units.internal.library.UnitLibrary;
 import org.simantics.databoard.util.Limit;
@@ -36,14 +44,21 @@ import org.simantics.databoard.util.Range;
 import org.simantics.databoard.util.RangeException;
 import org.simantics.db.RequestProcessor;
 import org.simantics.db.Resource;
+import org.simantics.db.Statement;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.NamedResource;
+import org.simantics.db.common.request.IndexRoot;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.function.DbConsumer;
+import org.simantics.db.layer0.QueryIndexUtils;
+import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.layer0.Layer0;
 import org.simantics.modeling.userComponent.ComponentTypeCommands;
 import org.simantics.scl.runtime.function.Function2;
 import org.simantics.scl.runtime.function.Function4;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.threads.ThreadUtils;
 import org.simantics.utils.ui.ErrorLogger;
 
 public class ComponentTypeViewerData {
@@ -51,29 +66,29 @@ public class ComponentTypeViewerData {
      * Used to validate property names.
      */
     public static final Pattern PROPERTY_NAME_PATTERN =
-            Pattern.compile("([a-z]|_[0-9a-zA-Z_])[0-9a-zA-Z_]*");
+            Pattern.compile("([a-z]|_[0-9a-zA-Z_])[0-9a-zA-Z_]*"); //$NON-NLS-1$
 
     public static final String[] PROPERTY_TYPE_SUGGESTIONS = new String[] {
-        "Double",
-        "Integer",
-        "Float",
-        "String",
-        "Boolean",
-        "Long",
-        "[Double]",
-        "[Integer]",
-        "[Float]",
-        "[String]",
-        "[Boolean]",
-        "[Long]",
-        "Vector Double",
-        "Vector Integer",
-        "Vector Float",
-        "Vector String",
-        "Vector Boolean",
-        "Vector Long"        
+        "Double", //$NON-NLS-1$
+        "Integer", //$NON-NLS-1$
+        "Float", //$NON-NLS-1$
+        "String", //$NON-NLS-1$
+        "Boolean", //$NON-NLS-1$
+        "Long", //$NON-NLS-1$
+        "[Double]", //$NON-NLS-1$
+        "[Integer]", //$NON-NLS-1$
+        "[Float]", //$NON-NLS-1$
+        "[String]", //$NON-NLS-1$
+        "[Boolean]", //$NON-NLS-1$
+        "[Long]", //$NON-NLS-1$
+        "Vector Double", //$NON-NLS-1$
+        "Vector Integer", //$NON-NLS-1$
+        "Vector Float", //$NON-NLS-1$
+        "Vector String", //$NON-NLS-1$
+        "Vector Boolean", //$NON-NLS-1$
+        "Vector Long" //$NON-NLS-1$
     };
-    
+
     public Resource componentType;
     public FormToolkit tk;
     public Form form;
@@ -90,12 +105,44 @@ public class ComponentTypeViewerData {
 
     public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
             Pattern namePattern) {
+        editName(table, editor, propertyInfo, selectedItem, column, namePattern, null);
+    }
+
+    public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
+            Pattern namePattern, DbConsumer<WriteGraph> extraWriter) {
         editName(table, editor, propertyInfo, selectedItem, column,
-                (pInfo, name) -> validatePropertyName(pInfo, name, namePattern));
+                null,
+                (pInfo, name) -> validatePropertyName(pInfo, name, namePattern),
+                extraWriter);
     }
 
     public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
-            Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator) {
+            Function2<ComponentTypeViewerPropertyInfo, String, String> nameFilter, Pattern namePattern, DbConsumer<WriteGraph> extraWriter) {
+        editName(table, editor, propertyInfo, selectedItem, column, nameFilter,
+                (pInfo, name) -> validatePropertyName(pInfo, name, namePattern),
+                extraWriter);
+    }
+
+    public void editName(Table table, TableEditor editor, ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
+            Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator)
+    {
+        editName(table, editor, propertyInfo, selectedItem, column, nameValidator, null);
+    }
+
+    public void editName(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column,
+            Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator, DbConsumer<WriteGraph> extraWriter) {
+        editName(table, editor, propertyInfo, selectedItem, column, null, nameValidator, extraWriter);
+    }
+
+    public void editName(
+            Table table,
+            TableEditor editor,
+            final ComponentTypeViewerPropertyInfo propertyInfo,
+            TableItem selectedItem,
+            int column,
+            Function2<ComponentTypeViewerPropertyInfo, String, String> nameFilter,
+            Function2<ComponentTypeViewerPropertyInfo, String, String> nameValidator,
+            DbConsumer<WriteGraph> extraWriter) {
         int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
         final Text text = new Text(table, SWT.NONE | extraStyle);
         org.eclipse.swt.widgets.Listener listener = 
@@ -105,9 +152,11 @@ public class ComponentTypeViewerData {
                 if (e.type == SWT.Dispose) {
                     form.setMessage(null);
                     return;
-                }
-
-                if (e.type == SWT.Modify) {
+                } else if (e.type == SWT.Verify) {
+                    // Filter input if necessary
+                    e.text = nameFilter != null ? nameFilter.apply(propertyInfo, e.text) : e.text;
+                    return;
+                } else if (e.type == SWT.Modify) {
                     // validate current name
                     String error = nameValidator.apply(propertyInfo, text.getText());
                     if (error != null) {
@@ -118,9 +167,7 @@ public class ComponentTypeViewerData {
                         form.setMessage(null);
                     }
                     return;
-                }
-
-                if (e.type == SWT.Traverse) {
+                } else if (e.type == SWT.Traverse) {
                     if (e.detail == SWT.TRAVERSE_ESCAPE) {
                         text.dispose();
                         e.doit = false;
@@ -147,7 +194,7 @@ public class ComponentTypeViewerData {
                         graph.markUndoPoint();
                         Layer0 L0 = Layer0.getInstance(graph);
                         String prevName = graph.getPossibleRelatedValue2(propertyInfo.resource, L0.HasName);
-                        String oldCamelCasedLabel = prevName != null ? ComponentTypeCommands.camelCaseNameToLabel(prevName) : "";
+                        String oldCamelCasedLabel = prevName != null ? ComponentTypeCommands.camelCaseNameToLabel(prevName) : ""; //$NON-NLS-1$
                         String oldLabel = graph.getPossibleRelatedValue(propertyInfo.resource, L0.HasLabel);
                         boolean setLabel = oldLabel == null
                                 || oldLabel.isEmpty()
@@ -157,10 +204,15 @@ public class ComponentTypeViewerData {
                         ComponentTypeCommands.rename(graph, propertyInfo.resource, newValue);
                         if (setLabel)
                             ComponentTypeCommands.setLabel(graph, propertyInfo.resource, ComponentTypeCommands.camelCaseNameToLabel(newValue));
+
+                        if (extraWriter != null)
+                            extraWriter.accept(graph);
                     }
                 });
             }
         };
+        if (nameFilter != null)
+            text.addListener(SWT.Verify, listener);
         text.addListener(SWT.Modify, listener);
         text.addListener(SWT.Deactivate, listener);
         text.addListener(SWT.Traverse, listener);
@@ -173,7 +225,7 @@ public class ComponentTypeViewerData {
         editor.setEditor(text, selectedItem, column);
     }
 
-    public void editType(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column, final boolean convertDefaultValue) {
+    public void editType(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column, String range, final boolean convertDefaultValue) {
         int extraStyle = propertyInfo.immutable ? SWT.READ_ONLY : 0;
         final Combo combo = new Combo(table, SWT.NONE | extraStyle);
         combo.setText(selectedItem.getText(column));
@@ -203,12 +255,48 @@ public class ComponentTypeViewerData {
                 if (propertyInfo.immutable)
                     return;
 
+                
                 Simantics.getSession().async(new WriteRequest() {
                     @Override
                     public void perform(WriteGraph graph)
                             throws DatabaseException {
                         graph.markUndoPoint();
-                        ComponentTypeCommands.editType(graph, componentType, propertyInfo.resource, convertDefaultValue, newValue);
+
+                        String newValue2 = newValue;
+
+                        Resource possibleGraphType = null;
+                        Resource root = graph.syncRequest(new IndexRoot(componentType));
+
+                        Resource L0Res = graph.getResource("http://www.simantics.org/Layer0-1.1");
+                        Layer0 L0 = Layer0.getInstance(graph);
+
+                        Collection<Resource> graphTypes1 = QueryIndexUtils.searchByTypeAndName(graph, L0Res, L0.ValueType, newValue);
+                        Collection<Resource> graphTypes2 = QueryIndexUtils.searchByTypeAndName(graph, root, L0.ValueType, newValue);
+
+                        Collection<Resource> graphTypes = new HashSet<>(graphTypes1);
+                        graphTypes.addAll(graphTypes2);
+
+                        Set<Pair<Resource, String>> candidates = new HashSet<>();
+                        for (Resource graphType : graphTypes) {
+                            Collection<Statement> stms = graph.getAssertedStatements(graphType, L0.HasValueType);
+                            if(stms.size() == 1) {
+                                // Only accept valueType if it asserts HasValueType with the same name
+                                String hasValueType = graph.getValue(stms.iterator().next().getObject(), Bindings.STRING);
+                                if (hasValueType.equals(newValue)) {
+                                    candidates.add(new Pair<>(graphType, hasValueType));
+                                }
+                            }
+                        }
+
+                        // We support only graph types with unique name at this point. Later we could implement UI to let the user to select from multiple graph types.
+                        if (candidates.size() == 1) {
+                            Pair<Resource, String> result = candidates.iterator().next();
+                            possibleGraphType = result.first;
+                            newValue2 = result.second;
+                        }
+
+                        ComponentTypeCommands.editType(graph, componentType, propertyInfo.resource, convertDefaultValue, newValue2, possibleGraphType);
+                        if (range != null) ComponentTypeCommands.setRange(graph, componentType, propertyInfo.resource, range);
                     }
                 });
             }
@@ -219,7 +307,7 @@ public class ComponentTypeViewerData {
         combo.addListener(SWT.Traverse, listener);
     }
 
-    protected void editUnit(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column) {
+    public void editUnit(Table table, TableEditor editor, final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem, int column) {
         // Disallow unit editing for non-numeric configuration properties
         if (propertyInfo.numberType == null && propertyInfo.sectionSpecificData == null)
             return;
@@ -333,18 +421,32 @@ public class ComponentTypeViewerData {
 
         if (validator != null) {
             org.eclipse.swt.widgets.Listener validationListener = new org.eclipse.swt.widgets.Listener() {
+                
+                private ScheduledFuture<?> future;
+                
                 @Override
                 public void handleEvent(Event e) {
                     final String newValue = text.getText();
-                    String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue);
-                    if (error != null) {
-                        text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
-                        text.setToolTipText(error);
-                        return;
-                    } else {
-                        text.setBackground(null);
-                        text.setToolTipText(null);
-                    }
+                    if (future != null && !future.isCancelled())
+                        future.cancel(true);
+                    future = ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> {
+                        String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue);
+                        if (!text.isDisposed()) {
+                            text.getDisplay().asyncExec(() -> {
+                                if (!text.isDisposed()) {
+                                    if (error != null) {
+                                        text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
+                                        text.setToolTipText(error);
+                                        return;
+                                    } else {
+                                        text.setBackground(null);
+                                        text.setToolTipText(null);
+                                    }
+                                }
+                                
+                            });
+                        }
+                    }, 500, TimeUnit.MILLISECONDS);
                 }
             };
             text.addListener(SWT.Modify, validationListener);
@@ -353,7 +455,7 @@ public class ComponentTypeViewerData {
 
     private Range parseRange(NumberType numberType, String minStr, String maxStr, boolean lowInclusive, boolean highInclusive) throws RangeException {
         try {
-            String rangeStr = (lowInclusive ? "[" : "(")  + minStr + ".." + maxStr + (highInclusive ? "]" : ")");
+            String rangeStr = (lowInclusive ? "[" : "(")  + minStr + ".." + maxStr + (highInclusive ? "]" : ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
             return Range.valueOf(rangeStr);
         } catch (IllegalArgumentException e) {
             // Limits are invalid
@@ -363,8 +465,8 @@ public class ComponentTypeViewerData {
     
     private static Combo createRangeInclusionCombo(Composite parent, boolean inclusive) {
         Combo rng = new Combo(parent, SWT.READ_ONLY);
-        rng.add("Inclusive");
-        rng.add("Exclusive");
+        rng.add(Messages.ComponentTypeViewerData_Inclusive);
+        rng.add(Messages.ComponentTypeViewerData_Exclusive);
         rng.select(inclusive ? 0 : 1);
         return rng;
     }
@@ -393,12 +495,12 @@ public class ComponentTypeViewerData {
         GridLayoutFactory.swtDefaults().numColumns(3).applyTo(composite);
 
         Label low = new Label(composite, SWT.NONE);
-        low.setText("Minimum Value:");
+        low.setText(Messages.ComponentTypeViewerData_MinimumValue);
         final Text lowText = new Text(composite, SWT.BORDER | extraTextStyle);
         GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(lowText);
         final Combo lowSelector = createRangeInclusionCombo(composite, !range.getLower().isExclusive());
         Label high = new Label(composite, SWT.NONE);
-        high.setText("Maximum Value:");
+        high.setText(Messages.ComponentTypeViewerData_MaximumValue);
         final Text highText = new Text(composite, SWT.BORDER | extraTextStyle);
         GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).applyTo(highText);
         final Combo highSelector = createRangeInclusionCombo(composite, !range.getUpper().isExclusive());
@@ -408,10 +510,10 @@ public class ComponentTypeViewerData {
         GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).applyTo(buttonComposite);
 
         Button ok = new Button(buttonComposite, SWT.NONE);
-        ok.setText("&OK");
+        ok.setText(IDialogConstants.OK_LABEL);
         GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);
         Button cancel = new Button(buttonComposite, SWT.NONE);
-        cancel.setText("&Cancel");
+        cancel.setText(IDialogConstants.CANCEL_LABEL);
         GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(ok);
 
         if (range.getLower().getValue() != null)
@@ -481,7 +583,7 @@ public class ComponentTypeViewerData {
         shell.open();
     }
 
-    protected void editMultilineText(Table table, TableEditor editor,
+    public void editMultilineText(Table table, TableEditor editor,
             final ComponentTypeViewerPropertyInfo propertyInfo, TableItem selectedItem,
             Rectangle selectedItemBounds, int column, final StringWriter writer)
     {
@@ -527,10 +629,10 @@ public class ComponentTypeViewerData {
             }
         };
 
-        String helpText = propertyInfo.immutable ? "ESC to close." : "Ctrl+Enter to apply changes, ESC to cancel.";
+        String helpText = propertyInfo.immutable ? Messages.ComponentTypeViewerData_ESCToClose : Messages.ComponentTypeViewerData_CtrlEnterApplyChanges;
         Label help = tk.createLabel(shell, helpText, SWT.BORDER | SWT.FLAT);
         GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(help);
-        help.setForeground( tk.getColors().createColor( "fg", tk.getColors().getSystemColor(SWT.COLOR_LIST_SELECTION) ) );
+        help.setForeground( tk.getColors().createColor( "fg", tk.getColors().getSystemColor(SWT.COLOR_LIST_SELECTION) ) ); //$NON-NLS-1$
 
         Display display = table.getDisplay();
         Rectangle clientArea = display.getClientArea();
@@ -561,16 +663,15 @@ public class ComponentTypeViewerData {
             return null;
         for (ComponentTypeViewerPropertyInfo info : properties) {
             if (propertyName.equals(info.name))
-                return "Property name '" + propertyName + "' is already in use.";
+                return NLS.bind(Messages.ComponentTypeViewerData_PropertyNameInUse, propertyName); 
         }
         for (NamedResource cp : connectionPoints) {
             if (propertyName.equals(cp.getName()))
-                return "Name '" + propertyName + "' is already used for a terminal.";
+                return NLS.bind(Messages.ComponentTypeViewerData_NameInUse, propertyName ); 
         }
         Matcher m = namePattern.matcher(propertyName);
         if (!m.matches())
-            return "Property name '" + propertyName + "' contains invalid characters, does not match pattern "
-                    + namePattern.pattern() + ".";
+            return NLS.bind(Messages.ComponentTypeViewerData_ContainsInvalidCharacters, propertyName, namePattern.pattern());
         return null;
     }