]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java
Red background color & tooltip for invalid derived property expression
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / componentTypeEditor / DerivedPropertiesSection.java
index 1fa503515b4e840c8bd5c55a7b1ae8729fa2626b..23777604d35e43e6d221a60f7b2908e01566f777 100644 (file)
@@ -9,6 +9,8 @@ import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.layout.TableColumnLayout;
 import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.window.DefaultToolTip;
+import org.eclipse.jface.window.ToolTip;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.TableEditor;
 import org.eclipse.swt.events.MouseAdapter;
@@ -16,11 +18,13 @@ import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
@@ -32,22 +36,39 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.RequestProcessor;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
-import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
 import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.PropertyInfoRequest;
+import org.simantics.db.layer0.variable.StandardGraphChildVariable;
+import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
+import org.simantics.db.layer0.variable.Variable;
 import org.simantics.layer0.Layer0;
+import org.simantics.modeling.scl.CompileProceduralSCLMonitorRequest;
+import org.simantics.modeling.scl.CompileSCLMonitorRequest;
 import org.simantics.modeling.userComponent.ComponentTypeCommands;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
 import org.simantics.scl.runtime.function.Function4;
 import org.simantics.structural.stubs.StructuralResource2;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class DerivedPropertiesSection implements ComponentTypeViewerSection {
-    private static final String[] COLUMN_NAMES = 
-            new String[] {"Name", "Type", "Expression", "Label", "Description"};
+    private static final String[] COLUMN_NAMES = {
+            Messages.DerivedPropertiesSection_Name,
+            Messages.DerivedPropertiesSection_Type,
+            Messages.DerivedPropertiesSection_Expression,
+            Messages.DerivedPropertiesSection_Unit,
+            Messages.DerivedPropertiesSection_Label,
+            Messages.DerivedPropertiesSection_Description
+    };
     private static final int[] COLUMN_LENGTHS =
-            new int[] { 120, 100, 100, 100, 100 };
+            new int[] { 120, 100, 100, 70, 100, 100 };
     private static final int[] COLUMN_WEIGHTS =
-            new int[] { 0, 0, 100, 0, 0 };
+            new int[] { 0, 0, 100, 0, 0, 0 };
     private static Function4<RequestProcessor, Resource, Resource, String, String> VALIDATE_MONITOR_EXPRESSION =
             new Function4<RequestProcessor, Resource, Resource, String, String>() {
         @Override
@@ -56,6 +77,8 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
         }
     };
     
+    private static final Logger LOGGER = LoggerFactory.getLogger(DerivedPropertiesSection.class);
+    
     ComponentTypeViewerData data;
     Table table;
     TableColumn[] columns;
@@ -71,7 +94,7 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
         Form form = data.form;
         section = tk.createSection(form.getBody(), Section.TITLE_BAR | Section.EXPANDED);
         section.setLayout(new FillLayout());
-        section.setText("Derived properties");
+        section.setText(Messages.DerivedPropertiesSection_DerivedProperties);
 
         Composite sectionBody = tk.createComposite(section);
         GridLayoutFactory.fillDefaults().numColumns(2).applyTo(sectionBody);
@@ -143,7 +166,7 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
                     break;
 
                 case 1:
-                    data.editType(table, editor, propertyInfo, selectedItem, column, false);
+                    data.editType(table, editor, propertyInfo, selectedItem, column, null, false);
                     break;
 
                 case 2:
@@ -155,11 +178,11 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
                     }, VALIDATE_MONITOR_EXPRESSION);
                     break;
 
-//                case 3:
-//                    editUnit(table2, editor2, propertyInfo, selectedItem, column);
-//                    break;
-
                 case 3:
+                    data.editUnit(table, editor, propertyInfo, selectedItem, column);
+                    break;
+
+                case 4:
                     data.editValue(table, editor, propertyInfo, selectedItem, column, propertyInfo.immutable ? null : new StringWriter() {
                         @Override
                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {
@@ -170,7 +193,7 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
                     }, null);
                     break;
 
-                case 4:
+                case 5:
                     data.editMultilineText(table, editor, propertyInfo, selectedItem, selectedItemBounds, column, new StringWriter() {
                         @Override
                         public void perform(WriteGraph graph, String newValue) throws DatabaseException {
@@ -191,9 +214,9 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
         GridDataFactory.fillDefaults().applyTo(buttons);
         GridLayoutFactory.fillDefaults().applyTo(buttons);
 
-        newProperty = tk.createButton(buttons, "New property", SWT.PUSH);
+        newProperty = tk.createButton(buttons, Messages.DerivedPropertiesSection_NewProperty, SWT.PUSH);
         GridDataFactory.fillDefaults().applyTo(newProperty);
-        removeProperty = tk.createButton(buttons, "Remove property", SWT.PUSH);
+        removeProperty = tk.createButton(buttons, Messages.DerivedPropertiesSection_RemoveProperty, SWT.PUSH);
         GridDataFactory.fillDefaults().applyTo(removeProperty);
 
         // Actions
@@ -247,11 +270,11 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
     public static String validateMonitorExpression(final RequestProcessor processor, final Resource componentType, final Resource relation, final String expression) {
 
         if (expression.trim().isEmpty()) {
-            return "Expression is empty.";
+            return Messages.DerivedPropertiesSection_ExpressionIsEmpty;
         }
 
         if (expression.trim().isEmpty()) {
-            return "Expression is empty.";
+            return Messages.DerivedPropertiesSection_ExpressionIsEmpty;
         }
         try {
             return processor.sync(new UniqueRead<String>() {
@@ -261,47 +284,69 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
 
                     StructuralResource2 STR = StructuralResource2.getInstance(graph);
 
-                    Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(componentType));
-
+                    // TODO: this is a bit hackish but should get the job done in most parts and
+                    // importantly indicates something for the user
+                    PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheAsyncListener.<PropertyInfo>instance());
+                    Variable parent = new StandardGraphChildVariable(null, null, componentType) {
+                        
+                        public Resource getType(ReadGraph graph) throws DatabaseException {
+                            return componentType;
+                        };
+                        
+                        public Variable getPossibleProperty(ReadGraph graph, String name) throws DatabaseException {
+                            Variable prop = super.getPossibleProperty(graph, name);
+                            if (prop != null) {
+                                return prop;
+                            } else {
+                                return getChild(graph, name);
+                            }
+                        };
+                    };
+                    
                     for(Resource literal : graph.getAssertedObjects(componentType, relation)) {
 
                         try {
-                            // TODO validation
+                            Variable context = new StandardGraphPropertyVariable(parent, null, null, info, literal);
                             if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) {
-                                //Layer0 L0 = Layer0.getInstance(graph);
-                                //Resource environment = graph.getPossibleObject(literal, L0.SCLValue_environment); 
-                                //ContextModule context = graph.sync(new TypeMonitorContextRequest(componentType));
-                                //String SCLMain = graph.syncRequest(new SCLMainModuleRequest(indexRoot));
-                                //CompilationContext cc = new CompilationContext(environment, context, SCLMain);
-                                //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.<CompiledExpression>instance());
+                                CompileProceduralSCLMonitorRequest.compileAndEvaluate(graph, context);
                             } else {
-                                //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph);
-                                //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.<CompiledExpression>instance());
-                                //graph.syncRequest(new CompileSCLMonitorRequest(graph, context));
+                                compileAndEvaluate(graph, context, expression);
                             }
                             
                         } catch (Exception e) {
                             String msg = e.getMessage();
-                            int index = msg.indexOf(":");
+                            int index = msg.indexOf(":"); //$NON-NLS-1$
                             if(index > 0) msg = msg.substring(index);
                             return msg;
                         }
-                        
                     }
-                    
                     return null;
-                    
                 }
                 
             });
         } catch (DatabaseException e) {
-            e.printStackTrace();
+            LOGGER.error("Could not validate ", e);
         }
-
         return null;
-
     }
 
+    public static void compileAndEvaluate(ReadGraph graph, Variable context, String expression) throws DatabaseException {
+        SCLContext sclContext = SCLContext.getCurrent();
+        Object oldGraph = sclContext.get("graph");
+        try {
+            CompileSCLMonitorRequest compileSCLMonitorRequest = new ValidationCompilationRequest(graph, context, expression);
+            Function1<Variable,Object> exp = graph.syncRequest(compileSCLMonitorRequest);
+            sclContext.put("graph", graph);
+            //return exp.apply(context.getParent(graph));
+        } catch (DatabaseException e) {
+            throw (DatabaseException)e;
+        } catch (Throwable t) {
+            throw new DatabaseException(t);
+        } finally {
+            sclContext.put("graph", oldGraph);
+        }
+    }
+    
     @Override
     public void update(ComponentTypePropertiesResult result) {
         if (table.isDisposed())
@@ -327,13 +372,16 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
 
             TableItem item = new TableItem(table, SWT.NONE);
 
-            item.setText(0, info.valid != null ? info.name + " (!)" : info.name);
+            item.setText(0, info.valid != null ? info.name + " (!)" : info.name); //$NON-NLS-1$
             item.setText(1, info.type);
             item.setText(2, info.expression);
-            //item.setText(3, unitStr(info));
-            item.setText(3, info.label);
-            item.setText(4, info.description);
+            item.setText(3, info.unitString());
+            item.setText(4, info.label);
+            item.setText(5, info.description);
 
+            if (info.valid != null)
+                item.setBackground(table.getDisplay().getSystemColor(SWT.COLOR_RED));
+            
             item.setForeground(fg);
 
             item.setData(info);
@@ -342,6 +390,29 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
                 selectedItems.add(item);
         }
         
+        new DefaultToolTip(table, ToolTip.NO_RECREATE, false) {
+
+            @Override
+            protected boolean shouldCreateToolTip(Event event) {
+                TableItem item = table.getItem(new Point(event.x, event.y));
+                if (item != null) {
+                    ComponentTypeViewerPropertyInfo info = (ComponentTypeViewerPropertyInfo) item.getData();
+                    return info.valid != null;
+                }
+                return false;
+            }
+
+            @Override
+            protected String getText(Event event) {
+                TableItem item = table.getItem(new Point(event.x, event.y));
+                if (item != null) {
+                    ComponentTypeViewerPropertyInfo info = (ComponentTypeViewerPropertyInfo) item.getData();
+                    return info.valid.replaceAll("\n", "");
+                }
+                return super.getText(event);
+            }
+        };
+        
         table.setTopIndex(topIndex);
         table.setSelection(selectedItems.toArray(new TableItem[selectedItems.size()]));
         table.redraw();
@@ -376,4 +447,29 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection {
         return 100.0;
     }
 
-}
+    private static final class ValidationCompilationRequest extends CompileSCLMonitorRequest {
+        private final String expression;
+    
+        private ValidationCompilationRequest(ReadGraph graph, Variable context, String expression)
+                throws DatabaseException {
+            super(graph, context);
+            this.expression = expression;
+        }
+    
+        @Override
+        protected String getExpressionText(ReadGraph graph) throws DatabaseException {
+            return expression;
+        }
+    
+        @Override
+        public int hashCode() {
+            return super.hashCode() + 37 * expression.hashCode();
+        }
+    
+        @Override
+        public boolean equals(Object obj) {
+            return super.equals(obj) && ((ValidationCompilationRequest)obj).expression.equals(expression);
+        }
+    }
+
+}
\ No newline at end of file