]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram/src/org/simantics/diagram/function/All.java
Fix NPE from flagTransform
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / function / All.java
index b15aa060bf884bf073c9f302b072da13efe32cef..5bb793f7df39b6147ce72511d48664d9ba94ec95 100644 (file)
-package org.simantics.diagram.function;\r
-\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Point2D;\r
-import java.util.Arrays;\r
-import java.util.Collection;\r
-import java.util.List;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.PossibleIndexRoot;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.exception.MissingVariableException;\r
-import org.simantics.db.layer0.request.PossibleConfiguration;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.diagram.content.ElementContext;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.diagram.stubs.G2DResource;\r
-import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
-import org.simantics.issues.common.IssueUtils;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.template2d.ontology.Template2dResource;\r
-import org.simantics.scenegraph.loader.SceneGraphContext;\r
-import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;\r
-import org.simantics.scl.reflection.annotations.SCLValue;\r
-\r
-\r
-public class All {\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable defaultRuntimeVariable(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-\r
-        SceneGraphContext vc = ScenegraphLoaderUtils.getContext(graph, context);\r
-        if(vc == null) return null;\r
-\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        String uri = graph.getRelatedValue(vc.getRuntime(), DIA.RuntimeDiagram_HasVariable, Bindings.STRING);\r
-        return Variables.getVariable(graph, uri);\r
-\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
-    public static String referenceText(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-\r
-        //DiagramResource DIA = DiagramResource.getInstance(graph);\r
-\r
-        //Resource runtime = ScenegraphLoaderUtils.getRuntime(graph, context);\r
-        String path = context.getParent(graph).getPropertyValue(graph, "reference", Bindings.STRING);\r
-\r
-        // diagram uri and diagram variable\r
-//        String diagramURI = graph.getRelatedValue(runtime, DIA.RuntimeDiagram_HasVariable, Bindings.STRING);\r
-//        Variable diagramVariable = org.simantics.db.layer0.variable.Variables.getVariable(graph, diagramURI);\r
-\r
-//        Variable property = diagramVariable.browse(graph, path);\r
-\r
-        try {\r
-            Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);\r
-               PredefinedVariables vars = PredefinedVariables.getInstance();\r
-               Variable property = vars.getVariable(graph, path, converter, selection);\r
-               if (property  != null)\r
-                       return property.getValue(graph).toString();\r
-        } catch (MissingVariableException e){\r
-               return "Invalid path.";\r
-        }\r
-        return null;\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> ElementContext -> a")\r
-    public static Object modelledTransform(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {\r
-        return graph.getRelatedValue(context.element, G2DResource.getInstance(graph).HasTransform, Bindings.DOUBLE_ARRAY);\r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> ElementContext -> a")\r
-    public static Object flagTransform(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {\r
-               Layer0 L0 = Layer0.getInstance(graph);\r
-               DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        Template2dResource TEMPLATE2D = Template2dResource.getInstance(graph);\r
-\r
-               Resource flag = context.element;\r
-               Resource runtimeDiagram = context.runtime;\r
-\r
-               Resource diagram = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);\r
-               if (diagram == null)\r
-                       return flagTransformImpl(graph, converter, context);\r
-\r
-               Resource template = getTemplateFromDiagram(graph, diagram);\r
-               if (template == null)\r
-                       return flagTransformImpl(graph, converter, context);\r
-               \r
-               double gridSize = DiagramGraphUtil.getGridSize(graph, diagram, 0.0);\r
-\r
-               String tableName = graph.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING);\r
-               Integer rowIndex = graph.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER);\r
-//        double[] mat = graph.getRelatedValue(flag, DIA.HasTransform, Bindings.DOUBLE_ARRAY);\r
-        \r
-        \r
-        Collection<Resource> slotTables = graph.getObjects(template, L0.ConsistsOf);\r
-        for (Resource slotTable:slotTables){\r
-               if (!graph.isInstanceOf(slotTable, TEMPLATE2D.FlagTable))\r
-                       continue;\r
-               String name = graph.getPossibleRelatedValue(slotTable, L0.HasName, Bindings.STRING);\r
-               if (!name.equals(tableName))\r
-                       continue;\r
-               \r
-            double[] transform = graph.getPossibleRelatedValue2(slotTable, DIA.Scenegraph_Composite_transform, Bindings.getBindingUnchecked(double[].class));\r
-               Resource align = graph.getPossibleObject(slotTable, TEMPLATE2D.FlagTable_HasAlignment);\r
-               boolean isRightAlignment = false;\r
-               if (align.equals(TEMPLATE2D.FlagTable_Alignment_Right))\r
-                       isRightAlignment = true;\r
-               Float width = graph.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasWidth, Bindings.FLOAT);\r
-               Float rowHeight = graph.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasRowHeigth, Bindings.FLOAT);\r
-               //Integer rowCount = g.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasRowCount, Bindings.INTEGER);\r
-               \r
-//                     Rectangle2D rowBounds = new Rectangle2D.Double(0, rowHeight*rowIndex, width, rowHeight);\r
-//                     rowBounds = GeometryUtils.transformShape(rowBounds, new AffineTransform(transform)).getBounds2D();\r
-//            e.setHint(FlagClass.KEY_FLAG_BOUNDS, rowBounds);\r
-            \r
-            double[] flagTransform = graph.getRelatedValue(flag, DIA.HasTransform, Bindings.DOUBLE_ARRAY);\r
-            return calcTransform(transform, flagTransform, rowHeight, width, isRightAlignment, rowIndex, gridSize);\r
-        }\r
-\r
-        return flagTransformImpl(graph, converter, context);\r
-    }\r
-\r
-    private static Object flagTransformImpl(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {\r
-        double[] mat = graph.getRelatedValue(context.element, G2DResource.getInstance(graph).HasTransform, Bindings.DOUBLE_ARRAY);\r
-        return mat;\r
-    }\r
-\r
-       private static double[] calcTransform(double[] tableTransform, double[] flagTransform, Float rowHeight, Float tableWidth, boolean isRightAlignment, Integer flagRowIndex, double gridSize) {\r
-               double scale = tableTransform[3];\r
-               double scaledRowHeigth = scale*rowHeight;\r
-\r
-               // move to coordinate system of parent of iotable\r
-               double rowMiddleY = tableTransform[5]+(flagRowIndex+0.5F)*scaledRowHeigth;\r
-               if (gridSize != 0.0) {\r
-                       double modulo = rowMiddleY%gridSize;\r
-                       int count =(int) (rowMiddleY/gridSize);\r
-                       double gridOnRow = (modulo > (gridSize/2))?gridSize*(1+count):gridSize*count;\r
-                       double diff = (gridOnRow > rowMiddleY)? gridOnRow - rowMiddleY:rowMiddleY-gridOnRow;\r
-                       if (diff < (scaledRowHeigth/2))\r
-                               rowMiddleY = gridOnRow; \r
-               }\r
-               // move back to iotable coordinate system\r
-               rowMiddleY = (rowMiddleY-tableTransform[5])/scale;\r
-\r
-               double xx = isRightAlignment ? tableWidth : 0.0; \r
-\r
-               AffineTransform trans = new AffineTransform(new double[]{tableTransform[0],tableTransform[1],tableTransform[2],tableTransform[3],0.0,0.0});\r
-               Point2D point = new Point2D.Double(xx, rowMiddleY);\r
-               trans.transform(point, point);\r
-\r
-               double[] copy = Arrays.copyOf(flagTransform, flagTransform.length);\r
-               copy[4] = tableTransform[4] + point.getX();\r
-               copy[5] = tableTransform[5] + point.getY();\r
-               return copy;\r
-       }\r
-\r
-    public static Resource getTemplate(ReadGraph graph, Resource runtimeDiagram) throws DatabaseException {\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        Resource diagram = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);\r
-        if (diagram == null)\r
-            return null;\r
-        return getTemplateFromDiagram(graph, diagram);\r
-    }\r
-\r
-    public static Resource getTemplateFromDiagram(ReadGraph graph, Resource diagram) throws DatabaseException {\r
-        Template2dResource TEMPLATE2D = Template2dResource.getInstance(graph);\r
-        Resource template = graph.getPossibleObject(diagram, TEMPLATE2D.HasDrawingTemplate);\r
-        return template;\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")\r
-    public static String diagramElementIssuePath(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-\r
-        List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);\r
-        if(contexts.isEmpty()) return "";\r
-\r
-        Resource context = contexts.get(0);\r
-\r
-        Resource mapped = graph.getPossibleObject(context, MOD.ComponentToElement);\r
-        if(mapped != null) context = mapped;\r
-        mapped = graph.getPossibleObject(context, MOD.ConnectionToDiagramConnection);\r
-        if(mapped != null) context = mapped;\r
-\r
-        if(!graph.isInstanceOf(context, DIA.Element)) return "";\r
-\r
-        Resource configuration = graph.sync(new PossibleConfiguration(context));\r
-        if(configuration == null) return "";\r
-\r
-        Resource diagram = graph.getPossibleObject(context, L0.PartOf);\r
-        if(diagram == null) return "";\r
-\r
-        Resource composite = graph.getPossibleObject(diagram, MOD.DiagramToComposite);\r
-        if(composite == null) return "";\r
-\r
-        Resource issueRoot = Variables.getPossibleIndexRoot(graph, property);\r
-        if(issueRoot == null) return "";\r
-        Resource contextRoot = graph.sync(new PossibleIndexRoot(composite));\r
-        if(contextRoot == null) return "";\r
-        if(issueRoot.equals(contextRoot)) {\r
-            String uri = graph.getURI(composite);\r
-            String modelURI = graph.getURI(contextRoot);\r
-            return IssueUtils.pathString(uri, modelURI.length()+1);\r
-        } else {\r
-            String uri = graph.getURI(composite);\r
-            String modelURI = graph.getURI(graph.getRootLibrary());\r
-            return IssueUtils.pathString(uri, modelURI.length()+1);\r
-        }\r
-    }\r
-\r
-}\r
+package org.simantics.diagram.function;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FontDialog;
+import org.simantics.Simantics;
+import org.simantics.browsing.ui.NodeContext;
+import org.simantics.browsing.ui.content.Labeler.DialogModifier;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.PossibleIndexRoot;
+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.exception.MissingVariableException;
+import org.simantics.db.layer0.request.PossibleConfiguration;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.diagram.content.ElementContext;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.stubs.G2DResource;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.issues.common.IssueUtils;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.template2d.ontology.Template2dResource;
+import org.simantics.scenegraph.loader.SceneGraphContext;
+import org.simantics.scenegraph.loader.ScenegraphLoaderUtils;
+import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.ui.fonts.Fonts;
+import org.simantics.utils.ui.AdaptionUtils;
+import org.simantics.utils.ui.ErrorLogger;
+
+
+public class All {
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable defaultRuntimeVariable(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+
+        SceneGraphContext vc = ScenegraphLoaderUtils.getContext(graph, context);
+        if(vc == null) return null;
+
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+        String uri = graph.getRelatedValue(vc.getRuntime(), DIA.RuntimeDiagram_HasVariable, Bindings.STRING);
+        return Variables.getVariable(graph, uri);
+
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
+    public static String referenceText(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+
+        //DiagramResource DIA = DiagramResource.getInstance(graph);
+
+        //Resource runtime = ScenegraphLoaderUtils.getRuntime(graph, context);
+        String path = context.getParent(graph).getPropertyValue(graph, "reference", Bindings.STRING);
+
+        // diagram uri and diagram variable
+//        String diagramURI = graph.getRelatedValue(runtime, DIA.RuntimeDiagram_HasVariable, Bindings.STRING);
+//        Variable diagramVariable = org.simantics.db.layer0.variable.Variables.getVariable(graph, diagramURI);
+
+//        Variable property = diagramVariable.browse(graph, path);
+
+        try {
+            Variable selection = ScenegraphLoaderUtils.getPossibleVariableSelection(graph, context);
+               PredefinedVariables vars = PredefinedVariables.getInstance();
+               Variable property = vars.getVariable(graph, path, converter, selection);
+               if (property  != null)
+                       return property.getValue(graph).toString();
+        } catch (MissingVariableException e){
+               return "Invalid path.";
+        }
+        return null;
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> ElementContext -> a")
+    public static Object modelledTransform(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {
+        return graph.getRelatedValue(context.element, G2DResource.getInstance(graph).HasTransform, Bindings.DOUBLE_ARRAY);
+    }
+    
+    @SCLValue(type = "ReadGraph -> Resource -> ElementContext -> a")
+    public static Object flagTransform(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {
+               Layer0 L0 = Layer0.getInstance(graph);
+               DiagramResource DIA = DiagramResource.getInstance(graph);
+        Template2dResource TEMPLATE2D = Template2dResource.getInstance(graph);
+
+               Resource flag = context.element;
+               Resource runtimeDiagram = context.runtime;
+               if (runtimeDiagram == null)
+                       return flagTransformImpl(graph, converter, context);
+
+               Resource diagram = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);
+               if (diagram == null)
+                       return flagTransformImpl(graph, converter, context);
+
+               Resource template = getTemplateFromDiagram(graph, diagram);
+               if (template == null)
+                       return flagTransformImpl(graph, converter, context);
+               
+               double gridSize = DiagramGraphUtil.getGridSize(graph, diagram, 0.0);
+
+               String tableName = graph.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING);
+               Integer rowIndex = graph.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableRowIndex, Bindings.INTEGER);
+//        double[] mat = graph.getRelatedValue(flag, DIA.HasTransform, Bindings.DOUBLE_ARRAY);
+        
+        
+        Collection<Resource> slotTables = graph.getObjects(template, L0.ConsistsOf);
+        for (Resource slotTable:slotTables){
+               if (!graph.isInstanceOf(slotTable, TEMPLATE2D.FlagTable))
+                       continue;
+               String name = graph.getPossibleRelatedValue(slotTable, L0.HasName, Bindings.STRING);
+               if (!name.equals(tableName))
+                       continue;
+               
+            double[] transform = graph.getPossibleRelatedValue2(slotTable, DIA.Scenegraph_Composite_transform, Bindings.getBindingUnchecked(double[].class));
+               Resource align = graph.getPossibleObject(slotTable, TEMPLATE2D.FlagTable_HasAlignment);
+               boolean isRightAlignment = false;
+               if (align.equals(TEMPLATE2D.FlagTable_Alignment_Right))
+                       isRightAlignment = true;
+               Float width = graph.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasWidth, Bindings.FLOAT);
+               Float rowHeight = graph.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasRowHeigth, Bindings.FLOAT);
+               //Integer rowCount = g.getPossibleRelatedValue(slotTable, TEMPLATE2D.FlagTable_HasRowCount, Bindings.INTEGER);
+               
+//                     Rectangle2D rowBounds = new Rectangle2D.Double(0, rowHeight*rowIndex, width, rowHeight);
+//                     rowBounds = GeometryUtils.transformShape(rowBounds, new AffineTransform(transform)).getBounds2D();
+//            e.setHint(FlagClass.KEY_FLAG_BOUNDS, rowBounds);
+            
+            double[] flagTransform = graph.getRelatedValue(flag, DIA.HasTransform, Bindings.DOUBLE_ARRAY);
+            return calcTransform(transform, flagTransform, rowHeight, width, isRightAlignment, rowIndex, gridSize);
+        }
+
+        return flagTransformImpl(graph, converter, context);
+    }
+
+    private static Object flagTransformImpl(ReadGraph graph, Resource converter, ElementContext context) throws DatabaseException {
+        double[] mat = graph.getRelatedValue(context.element, G2DResource.getInstance(graph).HasTransform, Bindings.DOUBLE_ARRAY);
+        return mat;
+    }
+
+       private static double[] calcTransform(double[] tableTransform, double[] flagTransform, Float rowHeight, Float tableWidth, boolean isRightAlignment, Integer flagRowIndex, double gridSize) {
+               double scale = tableTransform[3];
+               double scaledRowHeigth = scale*rowHeight;
+
+               // move to coordinate system of parent of iotable
+               double rowMiddleY = tableTransform[5]+(flagRowIndex+0.5F)*scaledRowHeigth;
+               if (gridSize != 0.0) {
+                       double modulo = rowMiddleY%gridSize;
+                       int count =(int) (rowMiddleY/gridSize);
+                       double gridOnRow = (modulo > (gridSize/2))?gridSize*(1+count):gridSize*count;
+                       double diff = (gridOnRow > rowMiddleY)? gridOnRow - rowMiddleY:rowMiddleY-gridOnRow;
+                       if (diff < (scaledRowHeigth/2))
+                               rowMiddleY = gridOnRow; 
+               }
+               // move back to iotable coordinate system
+               rowMiddleY = (rowMiddleY-tableTransform[5])/scale;
+
+               double xx = isRightAlignment ? tableWidth : 0.0; 
+
+               AffineTransform trans = new AffineTransform(new double[]{tableTransform[0],tableTransform[1],tableTransform[2],tableTransform[3],0.0,0.0});
+               Point2D point = new Point2D.Double(xx, rowMiddleY);
+               trans.transform(point, point);
+
+               double[] copy = Arrays.copyOf(flagTransform, flagTransform.length);
+               copy[4] = tableTransform[4] + point.getX();
+               copy[5] = tableTransform[5] + point.getY();
+               return copy;
+       }
+
+    public static Resource getTemplate(ReadGraph graph, Resource runtimeDiagram) throws DatabaseException {
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+        Resource diagram = graph.getPossibleObject(runtimeDiagram, DIA.RuntimeDiagram_HasConfiguration);
+        if (diagram == null)
+            return null;
+        return getTemplateFromDiagram(graph, diagram);
+    }
+
+    public static Resource getTemplateFromDiagram(ReadGraph graph, Resource diagram) throws DatabaseException {
+        Template2dResource TEMPLATE2D = Template2dResource.getInstance(graph);
+        Resource template = graph.getPossibleObject(diagram, TEMPLATE2D.HasDrawingTemplate);
+        return template;
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> String")
+    public static String diagramElementIssuePath(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+
+        List<Resource> contexts = IssueUtils.getContextsForProperty(graph, property);
+        if(contexts.isEmpty()) return "";
+
+        Resource context = contexts.get(0);
+
+        Resource mapped = graph.getPossibleObject(context, MOD.ComponentToElement);
+        if(mapped != null) context = mapped;
+        mapped = graph.getPossibleObject(context, MOD.ConnectionToDiagramConnection);
+        if(mapped != null) context = mapped;
+
+        if(!graph.isInstanceOf(context, DIA.Element)) return "";
+
+        Resource configuration = graph.sync(new PossibleConfiguration(context));
+        if(configuration == null) return "";
+
+        Resource diagram = graph.getPossibleObject(context, L0.PartOf);
+        if(diagram == null) return "";
+
+        Resource composite = graph.getPossibleObject(diagram, MOD.DiagramToComposite);
+        if(composite == null) return "";
+
+        Resource issueRoot = Variables.getPossibleIndexRoot(graph, property);
+        if(issueRoot == null) return "";
+        Resource contextRoot = graph.sync(new PossibleIndexRoot(composite));
+        if(contextRoot == null) return "";
+        if(issueRoot.equals(contextRoot)) {
+            String uri = graph.getURI(composite);
+            String modelURI = graph.getURI(contextRoot);
+            return IssueUtils.pathString(uri, modelURI.length()+1);
+        } else {
+            String uri = graph.getURI(composite);
+            String modelURI = graph.getURI(graph.getRootLibrary());
+            return IssueUtils.pathString(uri, modelURI.length()+1);
+        }
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+    public static Object fontModifier(ReadGraph graph, Resource r, final Variable variable) throws DatabaseException {
+       return new DialogModifier() {
+
+               @Override
+               public String getValue() {
+                       return null;
+               }
+
+               @Override
+               public String isValid(String label) {
+                       return null;
+               }
+
+               @Override
+               public void modify(final String label) {
+                       Simantics.getSession().async(new WriteRequest() {
+
+                               @Override
+                               public void perform(WriteGraph graph) throws DatabaseException {
+                                       Variable displayValue = variable.getParent(graph);
+                                       displayValue.setValue(graph, label, Bindings.STRING);
+                               }
+
+                       });
+               }
+
+               public String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer<String> applyCallback) {
+                       
+                       Control ctrl = (Control) parentControl;
+                       FontData[] initialValue = null;
+                       
+                       try {
+                               String font = Simantics.getSession().syncRequest(new UniqueRead<String>() {
+                                       @Override
+                                       public String perform(ReadGraph graph) throws DatabaseException {
+                                               Variable v = AdaptionUtils.adaptToSingle(context, Variable.class);
+                                               if(v == null) return null;
+                                               String displayValue = v.getPossiblePropertyValue(graph, "HasDisplayValue", Bindings.STRING);
+                                               return displayValue;
+                                       }
+                               });
+                               if (font != null) {
+                                       String[] fields = font.split(",");
+                                       if (fields.length == 3) {
+                                               int size = 14;
+                                               try {
+                                                       size = Integer.parseInt(fields[1]);
+                                               } catch (NumberFormatException e) {
+                                                       ErrorLogger.defaultLogError(e);
+                                               }
+                                               int style = SWT.NORMAL;
+                                               try {
+                                                       style = Fonts.swtStyle(fields[2]);
+                                               } catch (RuntimeException e) {
+                                                       ErrorLogger.defaultLogError(e);
+                                               }
+                                               initialValue = new FontData[] { new FontData(fields[0], size, style) };
+                                       }
+                               }
+                       } catch (DatabaseException e) {
+                               ErrorLogger.defaultLogError(e);
+                       }
+
+                       FontDialog dialog = new FontDialog(ctrl.getShell());
+                       if (initialValue != null)
+                               dialog.setFontList(initialValue);
+                       FontData font = dialog.open();
+                       if (font != null)
+                               applyCallback.accept(font.getName() + "," + font.getHeight() + "," + Fonts.fromSwtStyle(font.getStyle()));
+                       return null;
+               }
+
+       };
+       
+    }
+    
+}