]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java
Simulator toolkit enhancements
[simantics/platform.git] / bundles / org.simantics.spreadsheet.graph / src / org / simantics / spreadsheet / graph / function / All.java
index 44f0d4dbbde7b741a1f9e2bd293c36e5e8e1ceea..1439a941dcb53d5a023d894a4615cb8924d469d0 100644 (file)
-package org.simantics.spreadsheet.graph.function;\r
-\r
-import java.io.StringReader;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.function.Consumer;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Databoard;\r
-import org.simantics.databoard.adapter.AdaptException;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.mutable.MutableVariant;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.datatypes.literal.Font;\r
-import org.simantics.datatypes.literal.RGB;\r
-import org.simantics.datatypes.utils.BTreeContentBean;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.StandardRealm;\r
-import org.simantics.db.layer0.exception.MissingVariableException;\r
-import org.simantics.db.layer0.function.StandardChildDomainChildren;\r
-import org.simantics.db.layer0.request.PossibleActiveRun;\r
-import org.simantics.db.layer0.util.Layer0Utils;\r
-import org.simantics.db.layer0.variable.ConstantChildVariable;\r
-import org.simantics.db.layer0.variable.ConstantPropertyVariableBuilder;\r
-import org.simantics.db.layer0.variable.ProxyChildVariable;\r
-import org.simantics.db.layer0.variable.ProxyVariables;\r
-import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;\r
-import org.simantics.db.layer0.variable.ValueAccessor;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.VariableMap;\r
-import org.simantics.db.layer0.variable.VariableMapImpl;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.db.request.Write;\r
-import org.simantics.document.server.io.IColor;\r
-import org.simantics.document.server.io.IFont;\r
-import org.simantics.document.server.io.ITableCell;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.scl.reflection.annotations.SCLValue;\r
-import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
-import org.simantics.spreadsheet.CellEditor;\r
-import org.simantics.spreadsheet.ClientModel;\r
-import org.simantics.spreadsheet.Range;\r
-import org.simantics.spreadsheet.graph.ExcelFormula;\r
-import org.simantics.spreadsheet.graph.SheetNode;\r
-import org.simantics.spreadsheet.graph.SpreadsheetBook;\r
-import org.simantics.spreadsheet.graph.SpreadsheetCell;\r
-import org.simantics.spreadsheet.graph.SpreadsheetCellContent;\r
-import org.simantics.spreadsheet.graph.SpreadsheetFormula;\r
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;\r
-import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant;\r
-import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;\r
-import org.simantics.spreadsheet.graph.SpreadsheetStyle;\r
-import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder;\r
-import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;\r
-import org.simantics.spreadsheet.graph.parser.ParseException;\r
-import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;\r
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;\r
-import org.simantics.spreadsheet.resource.SpreadsheetResource;\r
-import org.simantics.spreadsheet.util.SpreadsheetUtils;\r
-\r
-import gnu.trove.map.TMap;\r
-import gnu.trove.map.hash.THashMap;\r
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;\r
-\r
-public class All {\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> a -> String")\r
-    public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {\r
-       if(context instanceof Resource) {\r
-               return NameUtils.getSafeLabel(graph, ((Resource)context));      \r
-       } else if (context instanceof Variable) {\r
-               Variable parent = ((Variable)context).getParent(graph);\r
-               Variable content =  parent.getPossibleProperty(graph, ClientModel.CONTENT);\r
-               if(content != null) {\r
-               Databoard db = graph.getService(Databoard.class);\r
-                       Variant variant = content.getValue(graph, db.VARIANT);\r
-                       return variant.getValue().toString();\r
-               } else {\r
-                       return parent.getName(graph);\r
-               }\r
-       } else {\r
-               throw new DatabaseException("Unknown context " + context);\r
-       }\r
-    }\r
-\r
-       private static Set<String> CLASSIFICATIONS = new HashSet<String>();\r
-       private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN); \r
-       \r
-       static {\r
-               CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);\r
-       }\r
-\r
-    @SCLValue(type = "ValueAccessor")\r
-       public static ValueAccessor contentValueAccessor = new ValueAccessor() {\r
-               \r
-               @Override\r
-               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {\r
-                   System.out.println("contentValueAccessor.context=" + context.getURI(graph));\r
-                       if(value instanceof String) {\r
-                               \r
-                               // Expressions are given as string\r
-                               String text = (String)value;\r
-                               SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                               if (text.startsWith("==")) {\r
-                       if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {\r
-                           org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);\r
-                           //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);\r
-                           //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);\r
-                       }\r
-                       return;\r
-                               } else {\r
-                                   \r
-                                   Variable cell = context.getParent(graph);\r
-                                   System.out.println("setValue : " + cell.getURI(graph));\r
-                                   \r
-                    String formula = text.substring(1);\r
-                    \r
-                    if (ProxyVariables.isProxy(graph, context)) {\r
-                        try {\r
-                            SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));\r
-                            AstValue v = p.relation();\r
-                            SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);\r
-                            setValueToEngine(graph, cell, context, sformula, binding);\r
-                        } catch (ParseException e) {\r
-                            e.printStackTrace();\r
-                        }\r
-                        return;\r
-                    }\r
-                    \r
-                    Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));\r
-                    graph.claimLiteral(cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);\r
-                               }\r
-                       } else {\r
-                               \r
-                               if(ProxyVariables.isProxy(graph, context)) {\r
-                                       \r
-                                       Variable cell = context.getParent(graph);\r
-                                       setValueToEngine(graph, cell, context, value, binding);\r
-                                       return;\r
-                               }\r
-                               \r
-                               // Values are given as Variant\r
-                               String expression = context.getPossiblePropertyValue(graph, "expression");\r
-                               if(expression != null) {\r
-                                       Object current_ = context.getPossibleValue(graph);\r
-                                       if(current_ instanceof Variable) {\r
-                                               Variable current = (Variable)current_;\r
-                                               Variant variant = (Variant)value;\r
-                                               Datatype dt = current.getDatatype(graph);\r
-                                               if (dt == null) {\r
-                                                       throw new DatabaseException();\r
-                                               }\r
-                                               Binding variableBinding = Bindings.getBinding(dt);\r
-                                               try {\r
-                                                       Object adapted = variant.getValue(variableBinding);\r
-                                                       current.setValue(graph, adapted, variableBinding);\r
-                                               } catch (AdaptException e) {\r
-                                                       Logger.defaultLogError(e);\r
-                                               }\r
-                                               return;\r
-                                       }\r
-                                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                                       Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);\r
-                               }\r
-                               org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);\r
-                               //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);\r
-                       }\r
-               }\r
-               \r
-               private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {\r
-            Variable sheet = cell.getParent(graph);\r
-\r
-            SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-\r
-            while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {\r
-                sheet = sheet.getParent(graph);\r
-            }\r
-            \r
-            Range r = SpreadsheetUtils.decodeCellAbsolute(cell.getName(graph));\r
-            \r
-            Variable root = ProxyVariables.proxyVariableRoot(graph, context);\r
-            \r
-            String sessionName = root.getParent(graph).getURI(graph);\r
-            StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);\r
-            SpreadsheetBook book = realm.getEngine();\r
-            SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);\r
-            sc.setContent(value);\r
-//          book.accept(new InvalidateAll());\r
-            List<SpreadsheetCell> changed = book.invalidate(sc);\r
-            realm.asyncExec(new Runnable() {\r
-\r
-                @Override\r
-                public void run() {\r
-                    try {\r
-                        SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");\r
-                        realm.getNodeManager().setValue(content, value, binding);\r
-//                      for(SpreadsheetCell cell : changed) {\r
-//                          content = (SpreadsheetCellContent)cell.getProperties().get("content");\r
-//                          realm.getNodeManager().setValue(content, value, binding);\r
-//                      }\r
-                    } catch (NodeManagerException e) {\r
-                        Logger.defaultLogError(e);\r
-                    }\r
-                }\r
-            });\r
-               }\r
-               \r
-               @Override\r
-               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {\r
-                       if(value instanceof String) setValue(graph, context, value, Bindings.STRING);\r
-                       else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);\r
-                       else throw new DatabaseException("Unsupported value type " + value);\r
-               }\r
-               \r
-               @Override\r
-               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {\r
-                       return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);\r
-                       //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);\r
-               }\r
-               \r
-               @Override\r
-               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {\r
-                       return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));\r
-//                     return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);\r
-               }\r
-\r
-               @Override\r
-               public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {\r
-                       return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);\r
-//                     return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);\r
-               }\r
-               \r
-       };\r
-\r
-    @SCLValue(type = "ValueAccessor")\r
-       public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {\r
-               \r
-               @Override\r
-               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {\r
-                       if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();\r
-                       if (!(value instanceof String)) throw new IllegalArgumentException();\r
-                       \r
-                       if (((String)value).startsWith("=")) {\r
-                               context.getParent(graph).setValue(graph, value, Bindings.STRING);\r
-                       } else {\r
-                               context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {\r
-                       if (!(value instanceof String)) throw new IllegalArgumentException();\r
-                       \r
-                       if (((String)value).startsWith("=")) {\r
-                               context.getParent(graph).setValue(graph, value, Bindings.STRING);\r
-                       } else {\r
-                               context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {\r
-                       return context.getParent(graph).getValue(graph, binding);\r
-               }\r
-               \r
-               @Override\r
-               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {\r
-                       return context.getParent(graph).getValue(graph);\r
-               }\r
-\r
-               @Override\r
-               public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {\r
-                       return context.getParent(graph).getDatatype(graph);\r
-               }\r
-               \r
-       };\r
-\r
-       @SCLValue(type = "VariableMap")\r
-       public static VariableMap stringArrayChildren = new VariableMapImpl() {\r
-       \r
-               @Override\r
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-                       \r
-                       TMap<String, Variable> map = new THashMap<String, Variable>();\r
-                       getVariables(graph, context, map);\r
-                       return map.get(name);                                   \r
-                       \r
-               }\r
-\r
-               @Override\r
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-                       \r
-                       Resource resource = context.getRepresents(graph);\r
-                       \r
-               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);\r
-               \r
-               String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);\r
-               if(location == null) return map;\r
-               Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);\r
-               if(width == null) return map;\r
-               String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);\r
-               if(array == null) return map;\r
-               \r
-               int rows = array.length / width;\r
-               \r
-               if(map == null) map = new HashMap<String,Variable>();\r
-               \r
-               for(int offset=0,i=0;i<rows;i++) {\r
-                       for(int j=0;j<width;j++) {\r
-                               \r
-                               String value = array[offset++];\r
-                               String valueLocation = SpreadsheetUtils.offset(location, i, j);\r
-\r
-                               ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);\r
-                               ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());\r
-                               \r
-                               map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));\r
-                               \r
-                       }\r
-               }\r
-               \r
-               return map;\r
-               \r
-               }\r
-               \r
-    };\r
-\r
-       @SCLValue(type = "VariableMap")\r
-       public static VariableMap queryRangeChildren = new VariableMapImpl() {\r
-       \r
-               @Override\r
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-                       \r
-                       TMap<String, Variable> map = new THashMap<String, Variable>();\r
-                       getVariables(graph, context, map);\r
-                       return map.get(name);                                   \r
-                       \r
-               }\r
-\r
-               @Override\r
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-                       \r
-               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);\r
-    \r
-               String location = "A1";\r
-               \r
-               try {\r
-                       \r
-                       Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);\r
-                       \r
-                       List<?> data = (List<?>)object;\r
-                       \r
-                       if(map == null) map = new HashMap<String,Variable>();\r
-                       \r
-                       for(Object o : data) {\r
-                               if(o instanceof ITableCell) {\r
-\r
-                                       ITableCell cell = (ITableCell)o;\r
-                                       \r
-                                       String valueLocation = SpreadsheetUtils.offset(location, cell.getRow(), cell.getColumn());\r
-\r
-                                       ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();\r
-                                       \r
-                                       builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));\r
-                                       builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));\r
-                                       \r
-                                       IFont font = cell.getFont();\r
-                                       if(font != null) {\r
-                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));\r
-                                       }\r
-\r
-                                       int align = cell.getAlign();\r
-                                       builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));\r
-                                       \r
-                                       IColor foreground = cell.getFGColor();\r
-                                       if(foreground != null) {\r
-                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));\r
-                                       }\r
-\r
-                                       IColor background = cell.getBGColor();\r
-                                       if(background != null) {\r
-                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));\r
-                                       }\r
-\r
-                                       map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));\r
-\r
-                               }\r
-                       }\r
-                       \r
-               } catch (DatabaseException e) {\r
-                       throw (DatabaseException)e;\r
-               } catch (Throwable t) {\r
-                       throw new DatabaseException(t);\r
-               } finally {\r
-               }\r
-\r
-               return map;\r
-               \r
-               }\r
-               \r
-    };\r
-\r
-       @SCLValue(type = "VariableMap")\r
-       public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {\r
-       \r
-               @Override\r
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-                       \r
-                       if(ProxyVariables.isProxy(graph, context))\r
-                               return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);\r
-                       \r
-                       return super.getVariable(graph, context, name);\r
-                       \r
-//                     TMap<String, Variable> map = new THashMap<String, Variable>();\r
-//                     getVariables(graph, context, map);\r
-//                     return map.get(name);\r
-\r
-               }\r
-\r
-               @Override\r
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-\r
-                       if(ProxyVariables.isProxy(graph, context))\r
-                               return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);\r
-\r
-//             Resource lines = context.getRepresents(graph);\r
-//             \r
-//             BTree bt = new BTree(graph, lines, true);\r
-//             List<Tuple2> entries = bt.entriesOfBTree(graph);\r
-//             for(Tuple2 tuple : entries) {\r
-//                     Variant v = (Variant)tuple.get(0);\r
-//                     Resource line = (Resource)tuple.get(1);\r
-//                     String name = v.getValue().toString();\r
-//                     Variable child = org.simantics.db.layer0.function.All.getStandardChildDomainChildVariable(graph, context, line, name);\r
-//                     if(map == null) map = new THashMap<String,Variable>();\r
-//                     map.put(name, child);\r
-//             }\r
-//    \r
-//             return map;\r
-\r
-//                     return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);\r
-\r
-                       return super.getVariables(graph, context, map);\r
-                       \r
-               }\r
-               \r
-    };\r
-    \r
-    @SCLValue(type = "VariableMap")\r
-       public static VariableMap doubleArrayChildren = new VariableMapImpl() {\r
-       \r
-               @Override\r
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-                       \r
-                       TMap<String, Variable> map = new THashMap<String, Variable>();\r
-                       getVariables(graph, context, map);\r
-                       return map.get(name);                                   \r
-                       \r
-               }\r
-\r
-               @Override\r
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {\r
-                       \r
-                       Resource resource = context.getRepresents(graph);\r
-                       \r
-               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);\r
-               \r
-               String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);\r
-               if(location == null) return map;\r
-               Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);\r
-               if(width == null) return map;\r
-               double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);\r
-               if(array == null) return map;\r
-               \r
-               if(map == null) map = new HashMap<String,Variable>();\r
-               \r
-               int rows = array.length / width;\r
-               \r
-               for(int offset=0,i=0;i<rows;i++) {\r
-                       for(int j=0;j<width;j++) {\r
-                               \r
-                               double value = array[offset++];\r
-                               String valueLocation = SpreadsheetUtils.offset(location, i, j);\r
-\r
-                               ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);\r
-                               ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());\r
-                               \r
-                               map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));\r
-                               \r
-                       }\r
-               }\r
-\r
-               return map;\r
-               \r
-               }\r
-               \r
-    };\r
-\r
-    static class SpreadsheetProxyChildVariable extends ProxyChildVariable {\r
-\r
-        public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {\r
-            super(base, parent, other, name);\r
-        }\r
-    \r
-        @Override\r
-        public Variable create(Variable base, Variable parent, Variable other, String name) {\r
-            return new SpreadsheetProxyChildVariable(base, parent, other, name);\r
-        }\r
-        \r
-        public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {\r
-            \r
-               if(CONTEXT_END.equals(name)) {\r
-               if(other instanceof ProxyChildVariable) {\r
-                       // The context is also a proxy - let it do the job\r
-                    return super.getPossibleChild(graph, name);\r
-               } else {\r
-                       return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);\r
-               }\r
-               }\r
-            \r
-            return super.getPossibleChild(graph, name);\r
-            \r
-        }\r
-        \r
-        public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {\r
-\r
-            Collection<Variable> result = super.getChildren(graph);\r
-            if(!(base instanceof ProxyChildVariable)) {\r
-               Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);\r
-               result.add(root);\r
-            }\r
-            return result;\r
-            \r
-        }       \r
-             \r
-    }\r
-\r
-    @SCLValue(type = "VariableMap")\r
-    public static VariableMap spreadsheetChildren = new VariableMapImpl() {\r
-\r
-        @Override\r
-        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {\r
-               \r
-               if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);\r
-            return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);\r
-            \r
-        }\r
-\r
-        private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {\r
-            Variable root = Variables.getRootVariable(graph);\r
-            return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);\r
-        }\r
-\r
-\r
-        @Override\r
-        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)\r
-                throws DatabaseException {\r
-               \r
-            map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);\r
-            \r
-            if(map == null) map = new HashMap<String,Variable>();\r
-            map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));\r
-            return map;\r
-        }\r
-\r
-    };\r
-\r
-   \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")\r
-    public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {\r
-\r
-       final Variable sheet = context_.getParent(graph);\r
-       \r
-       return new GraphCellEditorAdapter(null) {\r
-\r
-               @Override\r
-               public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {\r
-\r
-                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {\r
-                               \r
-                               @Override\r
-                               public void perform(WriteGraph graph) throws DatabaseException {\r
-                                       CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));\r
-                                       if (editor == null)\r
-                                           return;\r
-                                       editor.edit(transaction, location, property, value, binding, callback);\r
-                               }\r
-                       });\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {\r
-                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {\r
-                               \r
-                               @Override\r
-                               public void perform(WriteGraph graph) throws DatabaseException {\r
-                                   CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);\r
-                                   if (editor == null)\r
-                                       return;\r
-                                       editor.edit(transaction, location, value, callback);\r
-                               }\r
-                       });\r
-                       \r
-               }\r
-               \r
-            private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {\r
-                SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                Range range = SpreadsheetUtils.decodeCellAbsolute(location);\r
-                \r
-                List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);\r
-                if (cells.isEmpty()) {\r
-                    if (value == null) {\r
-                        return null;\r
-                    } else {\r
-                        cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);\r
-                    }\r
-                }\r
-                if (cells.size() != 1)\r
-                    throw new DatabaseException("Can edit only one cell at a time!");\r
-                \r
-                return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);\r
-            }\r
-\r
-               @Override\r
-               public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {\r
-\r
-                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {\r
-\r
-                               @Override\r
-                               public void perform(WriteGraph graph) throws DatabaseException {\r
-\r
-                                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                                       Variable variable = sheet.getPossibleChild(graph, location);\r
-                                       if(variable != null) {\r
-                                                       CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);\r
-                                                       if(editor != null) {\r
-                                                               editor.copy(transaction, location, variant, null);\r
-                                                       }\r
-                                       }\r
-                               }\r
-\r
-                       });\r
-\r
-               }\r
-               \r
-       };\r
-       \r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")\r
-    public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {\r
-\r
-       final Variable cell = context_.getParent(graph);\r
-       \r
-       return new GraphCellEditorAdapter(cell) {\r
-\r
-               @Override\r
-               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {\r
-                       cell.setPropertyValue(graph, property, value, binding);\r
-               }\r
-       };\r
-    }\r
-    \r
-    private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {\r
-       if(r == null) return 0;\r
-       Layer0 L0 = Layer0.getInstance(graph);\r
-               String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);\r
-               if(name.charAt(0) == 'R') {\r
-               return -Integer.parseInt(name.substring(3));\r
-               } else {\r
-                       return Integer.parseInt(name);\r
-               }\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
-    public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {\r
-\r
-       Resource node = context_.getParent(graph).getRepresents(graph);\r
-       BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);\r
-       if(bean == null) return new int[0];\r
-       // There are n keys and n+1 resources\r
-       int[] result = new int[2*bean.n+1];\r
-       for(int i=0;i<bean.n;i++) {\r
-               result[2*i] = encodeLineOrNode(graph, bean.getChild(i));\r
-               result[2*i+1] = (int)bean.getKey(i).getValue();\r
-       }\r
-       result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));\r
-       return result;\r
-       \r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")\r
-    public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {\r
-       \r
-        String contextUri = context_.getURI(graph);\r
-        \r
-       Variable line = context_.getParent(graph);\r
-       \r
-       Collection<Variable> children = line.getChildren(graph);\r
-       ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();\r
-       SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);\r
-       for (Variable child : children) {\r
-           Resource repr = child.getRepresents(graph);\r
-           \r
-           Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);\r
-           Integer styleId = null;\r
-           if (style != null)\r
-               styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);\r
-           if (styleId == null) {\r
-               System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");\r
-               styleId = SpreadsheetStyle.empty().getStyleId();\r
-           }\r
-\r
-               LineContentBeanCell cell = new LineContentBeanCell(styleId);\r
-               \r
-               Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);\r
-               \r
-            if(variant != null) {\r
-                \r
-                Variable var = child.getPossibleProperty(graph, SR.Cell_content);\r
-                String expression = var.getPossiblePropertyValue(graph, "expression");\r
-                if (expression != null) {\r
-                    cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));\r
-                } else {\r
-                    cell.setContent(variant);\r
-                }\r
-                Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));\r
-//                result.add(cell);\r
-                while(result.size() < r.startColumn + 1)\r
-                    result.add(new LineContentBeanCell());\r
-                result.set(r.startColumn, cell);\r
-                    \r
-            }\r
-\r
-       }\r
-       LineContentBean bean = new LineContentBean();\r
-       bean.cells = result.toArray(new LineContentBeanCell[result.size()]);\r
-       return bean;\r
-       \r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")\r
-    public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {\r
-\r
-        System.out.println("Context URI : " + context_.getURI(graph));\r
-       Variable cells = context_.getParent(graph);\r
-       System.out.println("Cell URI : " + cells.getURI(graph));\r
-       \r
-       return new GraphCellEditorAdapter(cells) {\r
-\r
-               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {\r
-                   \r
-                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                       if(ClientModel.CONTENT.equals(property)) {\r
-                               cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);\r
-                    Variable runCell = null;\r
-                    Object transactionContext = transaction.getContext();\r
-                    if (transactionContext != null && transactionContext instanceof Variable) {\r
-                        Variable varContext = (Variable) transactionContext;\r
-                        Variable context = Variables.getContext(graph, varContext);\r
-                        try {\r
-                            runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);\r
-                        } catch (MissingVariableException e) {\r
-                            // Creating new cell, need synchronizing\r
-                            transaction.needSynchronization(cell.getParent(graph));\r
-                        }\r
-                    }\r
-                               if (runCell != null)\r
-                                   runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);\r
-                       } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {\r
-                               cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);\r
-                    Variable runCell = null;\r
-                    Object transactionContext = transaction.getContext();\r
-                    if (transactionContext != null && transactionContext instanceof Variable) {\r
-                        Variable varContext = (Variable) transactionContext;\r
-                        Variable context = Variables.getContext(graph, varContext);\r
-                        try {\r
-                            runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);\r
-                        } catch (MissingVariableException e) {\r
-                            //Creating new cell, need synchronizing\r
-                            transaction.needSynchronization(cell.getParent(graph));\r
-                        }\r
-                    }\r
-                               if (runCell != null)\r
-                                   runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);\r
-                       } else if(ClientModel.BORDER.equals(property)) {\r
-                    Resource textCell = cell.getRepresents(graph);\r
-                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);\r
-                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);\r
-                    builder.border((Integer)value);\r
-                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);\r
-                       } else if(ClientModel.ALIGN.equals(property)) {\r
-                    Resource textCell = cell.getRepresents(graph);\r
-                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);\r
-                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);\r
-                    builder.align((Integer)value);\r
-                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);\r
-                       } else if(ClientModel.LOCKED.equals(property)) {\r
-                               cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);       \r
-                       } else if(ClientModel.ROW_SPAN.equals(property)) {\r
-                               cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);\r
-                       } else if(ClientModel.COLUMN_SPAN.equals(property)) {\r
-                               cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);\r
-                       } else if(ClientModel.FONT.equals(property)) {\r
-                    Resource textCell = cell.getRepresents(graph);\r
-                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);\r
-                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);\r
-                    builder.font((Font)value);\r
-                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);\r
-                       } else if(ClientModel.FOREGROUND.equals(property)) {\r
-                           Resource textCell = cell.getRepresents(graph);\r
-                           Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);\r
-                           SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);\r
-                           builder.foreground((RGB.Integer)value);\r
-                           finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);\r
-                       } else if(ClientModel.BACKGROUND.equals(property)) {\r
-                    Resource textCell = cell.getRepresents(graph);\r
-                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);\r
-                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);\r
-                    builder.background((RGB.Integer)value);\r
-                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);\r
-                       }\r
-               }\r
-               \r
-               private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {\r
-                \r
-                Variable bookVariable = Variables.getContext(graph, cell);\r
-                Resource book = bookVariable.getRepresents(graph);\r
-                Resource createdStyle = null;\r
-                \r
-                SpreadsheetStyle style = builder.build();\r
-                int styleId = style.getStyleId();\r
-\r
-                Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));\r
-                for (Resource eStyle : existingStyles) {\r
-                    int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);\r
-                    if (eStyleId == styleId) {\r
-                        createdStyle = eStyle;\r
-                        break;\r
-                    }\r
-                }\r
-                if (createdStyle == null) {\r
-                       style = builder.name("Style_" + existingStyles.size()).build();\r
-                    createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);\r
-                }\r
-                \r
-                graph.deny(textCell, SHEET.Cell_HasStyle);\r
-                Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);\r
-                if (cellsOfStyle.isEmpty()) {\r
-                    graph.deny(styleContainer);\r
-                }\r
-                graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);\r
-                \r
-//                Variable runCell = null;\r
-//                Object transactionContext = transaction.getContext();\r
-//                if (transactionContext != null && transactionContext instanceof Variable) {\r
-//                    Variable varContext = (Variable) transactionContext;\r
-//                    Variable context = Variables.getContext(graph, varContext);\r
-//                    try {\r
-//                        runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);\r
-//                    } catch (MissingVariableException e) {\r
-//                        //Creating new cell, need synchronizing\r
-//                        transaction.needSynchronization(cell.getParent(graph));\r
-//                    }\r
-//                }\r
-//                if (runCell != null) {\r
-//                    Datatype type = new RecordType();\r
-//                    Binding b = Bindings.getBinding(type);\r
-//                    runCell.setPropertyValue(graph, SHEET.Cell_style, style, b);\r
-//                }\r
-            }\r
-\r
-            private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {\r
-                RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);\r
-                RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);\r
-                Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);\r
-                Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);\r
-                Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);\r
-                \r
-                return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);\r
-            }\r
-\r
-            @Override\r
-               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {\r
-                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                       \r
-                       // Handle possible deletes\r
-                       if (value == null)\r
-                           value = Variant.ofInstance("");\r
-                       \r
-                if (!transaction.isOperationMode()) {\r
-                    cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);\r
-//                    return;\r
-                }\r
-                Variable runCell = null;\r
-                Object transactionContext = transaction.getContext();\r
-                if (transactionContext != null && transactionContext instanceof Variable) {\r
-                    Variable varContext = (Variable) transactionContext;\r
-                    Variable context = Variables.getContext(graph, varContext);\r
-                    try {\r
-                        runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);\r
-                    } catch (MissingVariableException e) {\r
-                        // Creating cell for the first time so no runCell available at this time, needs synchronization\r
-                        transaction.needSynchronization(cell.getParent(graph));\r
-                    }\r
-                    \r
-                }\r
-\r
-                       if (runCell != null) {\r
-                           System.out.println("All.edit " + runCell.getURI(graph));\r
-                           runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {\r
-                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);\r
-                       \r
-                Variable runCell = null;\r
-                Object transactionContext = transaction.getContext();\r
-                if (transactionContext != null && transactionContext instanceof Variable) {\r
-                    Variable varContext = (Variable) transactionContext;\r
-                    Variable context = Variables.getContext(graph, varContext);\r
-                    runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);\r
-                }\r
-                       \r
-                       //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);\r
-                       Object object = cell.getPropertyValue(graph, SHEET.Cell_content);\r
-                       Variant content = null;\r
-                       if (object instanceof Variant) {\r
-                           content = (Variant)object;\r
-                       } else if (object instanceof Double) {\r
-                           content = Variant.ofInstance((Double)object);\r
-                       } else if (object instanceof Float) {\r
-                               content = Variant.ofInstance((Float)object);\r
-                       } else if (object instanceof Integer) {\r
-                           content = Variant.ofInstance((Integer)object);\r
-                       } else if (object instanceof Long) {\r
-                           content = Variant.ofInstance((Long)object);\r
-                       } else if (object instanceof String) {\r
-                           content = Variant.ofInstance((String)object);\r
-                       } else if (object instanceof Variable) {\r
-                           content = Variant.ofInstance((Variable)object);\r
-                       } else {\r
-                           throw new DatabaseException("");\r
-                       }\r
-                       variant.setValue(content);\r
-               }\r
-               \r
-       };\r
-       \r
-    }\r
-    \r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {\r
-               return ProxyVariables.inputVariable(graph, sheet);\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {\r
-               return ProxyVariables.proxySessionVariable(graph, sheet);\r
-    }\r
-\r
-    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")\r
-    public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {\r
-       Resource model = Variables.getModel(graph, property);\r
-       Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));\r
-       if(activeRun != null) return activeRun;\r
-       return Variables.getConfigurationContext(graph, model);\r
-    }\r
-    \r
-       @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")\r
-    public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {\r
-           return CompileSCLValueRequest.compileAndEvaluate(graph, context);\r
-    }\r
-\r
+package org.simantics.spreadsheet.graph.function;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Databoard;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.MutableVariant;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.datatypes.literal.Font;
+import org.simantics.datatypes.literal.RGB;
+import org.simantics.datatypes.utils.BTreeContentBean;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.exception.MissingVariableException;
+import org.simantics.db.layer0.function.StandardChildDomainChildren;
+import org.simantics.db.layer0.request.PossibleActiveRun;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.layer0.variable.ConstantChildVariable;
+import org.simantics.db.layer0.variable.ConstantPropertyVariableBuilder;
+import org.simantics.db.layer0.variable.ProxyChildVariable;
+import org.simantics.db.layer0.variable.ProxyVariables;
+import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
+import org.simantics.db.layer0.variable.ValueAccessor;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.VariableMap;
+import org.simantics.db.layer0.variable.VariableMapImpl;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.db.request.Write;
+import org.simantics.document.server.io.IColor;
+import org.simantics.document.server.io.IFont;
+import org.simantics.document.server.io.ITableCell;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.reflection.annotations.SCLValue;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.spreadsheet.CellEditor;
+import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.graph.ExcelFormula;
+import org.simantics.spreadsheet.graph.SheetNode;
+import org.simantics.spreadsheet.graph.SpreadsheetBook;
+import org.simantics.spreadsheet.graph.SpreadsheetCell;
+import org.simantics.spreadsheet.graph.SpreadsheetCellContent;
+import org.simantics.spreadsheet.graph.SpreadsheetFormula;
+import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
+import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant;
+import org.simantics.spreadsheet.graph.SpreadsheetSessionManager;
+import org.simantics.spreadsheet.graph.SpreadsheetStyle;
+import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder;
+import org.simantics.spreadsheet.graph.celleditor.GraphCellEditorAdapter;
+import org.simantics.spreadsheet.graph.parser.ParseException;
+import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;
+import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.util.SpreadsheetUtils;
+
+import gnu.trove.map.TMap;
+import gnu.trove.map.hash.THashMap;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+
+public class All {
+
+    @SCLValue(type = "ReadGraph -> Resource -> a -> String")
+    public static String cellLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
+       if(context instanceof Resource) {
+               return NameUtils.getSafeLabel(graph, ((Resource)context));      
+       } else if (context instanceof Variable) {
+               Variable parent = ((Variable)context).getParent(graph);
+               Variable content =  parent.getPossibleProperty(graph, ClientModel.CONTENT);
+               if(content != null) {
+               Databoard db = graph.getService(Databoard.class);
+                       Variant variant = content.getValue(graph, db.VARIANT);
+                       return variant.getValue().toString();
+               } else {
+                       return parent.getName(graph);
+               }
+       } else {
+               throw new DatabaseException("Unknown context " + context);
+       }
+    }
+
+       private static Set<String> CLASSIFICATIONS = new HashSet<String>();
+       private static ConstantPropertyVariableBuilder immutableBuilder = new ConstantPropertyVariableBuilder("immutable", true, Bindings.BOOLEAN); 
+       
+       static {
+               CLASSIFICATIONS.add(SpreadsheetResource.URIs.Attribute);
+       }
+
+    @SCLValue(type = "ValueAccessor")
+       public static ValueAccessor contentValueAccessor = new ValueAccessor() {
+               
+               @Override
+               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
+                   System.out.println("contentValueAccessor.context=" + context.getURI(graph));
+                       if(value instanceof String) {
+                               
+                               // Expressions are given as string
+                               String text = (String)value;
+                               SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                               if (text.startsWith("==")) {
+                       if(!Layer0Utils.setOrClearExpression(graph, context, text.substring(1), SHEET.SCLValue)) {
+                           org.simantics.db.layer0.function.All.standardSetValue3(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
+                           //StandardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
+                           //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, Variant.ofInstance(value), Bindings.VARIANT);
+                       }
+                       return;
+                               } else {
+                                   
+                                   Variable cell = context.getParent(graph);
+                                   System.out.println("setValue : " + cell.getURI(graph));
+                                   
+                    String formula = text.substring(1);
+                    
+                    if (ProxyVariables.isProxy(graph, context)) {
+                        try {
+                            SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula));
+                            AstValue v = p.relation();
+                            SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula);
+                            setValueToEngine(graph, cell, context, sformula, binding);
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                        return;
+                    }
+                    
+                    Variant v = new Variant(ExcelFormula.BINDING, new ExcelFormula(formula));
+                    graph.claimLiteral(cell.getRepresents(graph), SHEET.Cell_content, SHEET.Cell_content_Inverse, Layer0.getInstance(graph).Variant, v, Bindings.VARIANT);
+                               }
+                       } else {
+                               
+                               if(ProxyVariables.isProxy(graph, context)) {
+                                       
+                                       Variable cell = context.getParent(graph);
+                                       setValueToEngine(graph, cell, context, value, binding);
+                                       return;
+                               }
+                               
+                               // Values are given as Variant
+                               String expression = context.getPossiblePropertyValue(graph, "expression");
+                               if(expression != null) {
+                                       Object current_ = context.getPossibleValue(graph);
+                                       if(current_ instanceof Variable) {
+                                               Variable current = (Variable)current_;
+                                               Variant variant = (Variant)value;
+                                               Datatype dt = current.getDatatype(graph);
+                                               if (dt == null) {
+                                                       throw new DatabaseException();
+                                               }
+                                               Binding variableBinding = Bindings.getBinding(dt);
+                                               try {
+                                                       Object adapted = variant.getValue(variableBinding);
+                                                       current.setValue(graph, adapted, variableBinding);
+                                               } catch (AdaptException e) {
+                                                       Logger.defaultLogError(e);
+                                               }
+                                               return;
+                                       }
+                                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                                       Layer0Utils.clearExpression(graph, context, SHEET.SCLValue);
+                               }
+                               org.simantics.db.layer0.function.All.standardSetValue3(graph, context, value, binding);
+                               //org.simantics.db.layer0.function.All.standardValueAccessor.setValue(graph, context, value, binding);
+                       }
+               }
+               
+               private void setValueToEngine(WriteGraph graph, Variable cell, Variable context, Object value, Binding binding) throws DatabaseException {
+            Variable sheet = cell.getParent(graph);
+
+            SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+
+            while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
+                sheet = sheet.getParent(graph);
+            }
+            
+            Range r = SpreadsheetUtils.decodeCellAbsolute(cell.getName(graph));
+            
+            Variable root = ProxyVariables.proxyVariableRoot(graph, context);
+            
+            String sessionName = root.getParent(graph).getURI(graph);
+            StandardRealm<SheetNode, SpreadsheetBook> realm = SpreadsheetSessionManager.getInstance().getOrCreateRealm(graph, sessionName);
+            SpreadsheetBook book = realm.getEngine();
+            SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
+            sc.setContent(value);
+//          book.accept(new InvalidateAll());
+            List<SpreadsheetCell> changed = book.invalidate(sc);
+            realm.asyncExec(new Runnable() {
+
+                @Override
+                public void run() {
+                    try {
+                        SpreadsheetCellContent content = (SpreadsheetCellContent)sc.getProperties().get("content");
+                        realm.getNodeManager().setValue(content, value, binding);
+//                      for(SpreadsheetCell cell : changed) {
+//                          content = (SpreadsheetCellContent)cell.getProperties().get("content");
+//                          realm.getNodeManager().setValue(content, value, binding);
+//                      }
+                    } catch (NodeManagerException e) {
+                        Logger.defaultLogError(e);
+                    }
+                }
+            });
+               }
+               
+               @Override
+               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
+                       if(value instanceof String) setValue(graph, context, value, Bindings.STRING);
+                       else if(value instanceof Variant) setValue(graph, context, value, Bindings.VARIANT);
+                       else throw new DatabaseException("Unsupported value type " + value);
+               }
+               
+               @Override
+               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
+                       return org.simantics.db.layer0.function.All.standardGetValue2(graph, context, binding);
+                       //return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context, binding);
+               }
+               
+               @Override
+               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
+                       return org.simantics.db.layer0.function.All.standardGetValue1(graph, ((StandardGraphPropertyVariable)context));
+//                     return org.simantics.db.layer0.function.All.standardValueAccessor.getValue(graph, context);
+               }
+
+               @Override
+               public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
+                       return org.simantics.db.layer0.function.All.standardGetDatatype(graph, context);
+//                     return org.simantics.db.layer0.function.All.standardValueAccessor.getDatatype(graph, context);
+               }
+               
+       };
+
+    @SCLValue(type = "ValueAccessor")
+       public static ValueAccessor contentDisplayValueAccessor = new ValueAccessor() {
+               
+               @Override
+               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
+                       if (!Bindings.STRING.equals(binding)) throw new IllegalArgumentException();
+                       if (!(value instanceof String)) throw new IllegalArgumentException();
+                       
+                       if (((String)value).startsWith("=")) {
+                               context.getParent(graph).setValue(graph, value, Bindings.STRING);
+                       } else {
+                               context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
+                       }
+               }
+               
+               @Override
+               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
+                       if (!(value instanceof String)) throw new IllegalArgumentException();
+                       
+                       if (((String)value).startsWith("=")) {
+                               context.getParent(graph).setValue(graph, value, Bindings.STRING);
+                       } else {
+                               context.getParent(graph).setValue(graph, new Variant(Bindings.STRING, value), Bindings.VARIANT);
+                       }
+               }
+               
+               @Override
+               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
+                       return context.getParent(graph).getValue(graph, binding);
+               }
+               
+               @Override
+               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
+                       return context.getParent(graph).getValue(graph);
+               }
+
+               @Override
+               public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
+                       return context.getParent(graph).getDatatype(graph);
+               }
+               
+       };
+
+       @SCLValue(type = "VariableMap")
+       public static VariableMap stringArrayChildren = new VariableMapImpl() {
+       
+               @Override
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+                       
+                       TMap<String, Variable> map = new THashMap<String, Variable>();
+                       getVariables(graph, context, map);
+                       return map.get(name);                                   
+                       
+               }
+
+               @Override
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+                       
+                       Resource resource = context.getRepresents(graph);
+                       
+               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
+               
+               String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
+               if(location == null) return map;
+               Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
+               if(width == null) return map;
+               String[] array = graph.getPossibleRelatedValue(resource, sr.StringArrayRange_array, Bindings.STRING_ARRAY);
+               if(array == null) return map;
+               
+               int rows = array.length / width;
+               
+               if(map == null) map = new HashMap<String,Variable>();
+               
+               for(int offset=0,i=0;i<rows;i++) {
+                       for(int j=0;j<width;j++) {
+                               
+                               String value = array[offset++];
+                               String valueLocation = SpreadsheetUtils.offset(location, i, j);
+
+                               ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, value, Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
+                               ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
+                               
+                               map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
+                               
+                       }
+               }
+               
+               return map;
+               
+               }
+               
+    };
+
+       @SCLValue(type = "VariableMap")
+       public static VariableMap queryRangeChildren = new VariableMapImpl() {
+       
+               @Override
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+                       
+                       TMap<String, Variable> map = new THashMap<String, Variable>();
+                       getVariables(graph, context, map);
+                       return map.get(name);                                   
+                       
+               }
+
+               @Override
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+                       
+               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
+    
+               String location = "A1";
+               
+               try {
+                       
+                       Object object = context.getPropertyValue(graph, sr.ExpressionRange_cells);
+                       
+                       List<?> data = (List<?>)object;
+                       
+                       if(map == null) map = new HashMap<String,Variable>();
+                       
+                       for(Object o : data) {
+                               if(o instanceof ITableCell) {
+
+                                       ITableCell cell = (ITableCell)o;
+                                       
+                                       String valueLocation = SpreadsheetUtils.offset(location, cell.getRow(), cell.getColumn());
+
+                                       ArrayList<ConstantPropertyVariableBuilder> builders = new ArrayList<ConstantPropertyVariableBuilder>();
+                                       
+                                       builders.add(new ConstantPropertyVariableBuilder(ClientModel.CONTENT, Variant.ofInstance(cell.getText()), Bindings.VARIANT, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
+                                       builders.add(new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet()));
+                                       
+                                       IFont font = cell.getFont();
+                                       if(font != null) {
+                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.FONT, new Font(font.getFamily(), font.getHeight(), font.getStyle()), Font.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
+                                       }
+
+                                       int align = cell.getAlign();
+                                       builders.add(new ConstantPropertyVariableBuilder(ClientModel.ALIGN, align, Bindings.INTEGER, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
+                                       
+                                       IColor foreground = cell.getFGColor();
+                                       if(foreground != null) {
+                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.FOREGROUND, new RGB.Integer(foreground.red(), foreground.green(), foreground.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
+                                       }
+
+                                       IColor background = cell.getBGColor();
+                                       if(background != null) {
+                                               builders.add(new ConstantPropertyVariableBuilder(ClientModel.BACKGROUND, new RGB.Integer(background.red(), background.green(), background.blue()), RGB.Integer.BINDING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS));
+                                       }
+
+                                       map.put(valueLocation, new ConstantChildVariable(context, valueLocation, builders));
+
+                               }
+                       }
+                       
+               } catch (DatabaseException e) {
+                       throw (DatabaseException)e;
+               } catch (Throwable t) {
+                       throw new DatabaseException(t);
+               } finally {
+               }
+
+               return map;
+               
+               }
+               
+    };
+
+       @SCLValue(type = "VariableMap")
+       public static VariableMap spreadsheetLinesChildren = new StandardChildDomainChildren() {
+       
+               @Override
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+                       
+                       if(ProxyVariables.isProxy(graph, context))
+                               return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, null, name);
+                       
+                       return super.getVariable(graph, context, name);
+                       
+//                     TMap<String, Variable> map = new THashMap<String, Variable>();
+//                     getVariables(graph, context, map);
+//                     return map.get(name);
+
+               }
+
+               @Override
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+                       if(ProxyVariables.isProxy(graph, context))
+                               return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), map);
+
+//             Resource lines = context.getRepresents(graph);
+//             
+//             BTree bt = new BTree(graph, lines, true);
+//             List<Tuple2> entries = bt.entriesOfBTree(graph);
+//             for(Tuple2 tuple : entries) {
+//                     Variant v = (Variant)tuple.get(0);
+//                     Resource line = (Resource)tuple.get(1);
+//                     String name = v.getValue().toString();
+//                     Variable child = org.simantics.db.layer0.function.All.getStandardChildDomainChildVariable(graph, context, line, name);
+//                     if(map == null) map = new THashMap<String,Variable>();
+//                     map.put(name, child);
+//             }
+//    
+//             return map;
+
+//                     return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
+
+                       return super.getVariables(graph, context, map);
+                       
+               }
+               
+    };
+    
+    @SCLValue(type = "VariableMap")
+       public static VariableMap doubleArrayChildren = new VariableMapImpl() {
+       
+               @Override
+               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+                       
+                       TMap<String, Variable> map = new THashMap<String, Variable>();
+                       getVariables(graph, context, map);
+                       return map.get(name);                                   
+                       
+               }
+
+               @Override
+               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+                       
+                       Resource resource = context.getRepresents(graph);
+                       
+               SpreadsheetResource sr = SpreadsheetResource.getInstance(graph);
+               
+               String location = graph.getPossibleRelatedValue(resource, sr.Range_location, Bindings.STRING);
+               if(location == null) return map;
+               Integer width = graph.getPossibleRelatedValue(resource, sr.Range_widthBound, Bindings.INTEGER);
+               if(width == null) return map;
+               double[] array = graph.getPossibleRelatedValue(resource, sr.DoubleArrayRange_array, Bindings.DOUBLE_ARRAY);
+               if(array == null) return map;
+               
+               if(map == null) map = new HashMap<String,Variable>();
+               
+               int rows = array.length / width;
+               
+               for(int offset=0,i=0;i<rows;i++) {
+                       for(int j=0;j<width;j++) {
+                               
+                               double value = array[offset++];
+                               String valueLocation = SpreadsheetUtils.offset(location, i, j);
+
+                               ConstantPropertyVariableBuilder labelBuilder = new ConstantPropertyVariableBuilder(ClientModel.LABEL, String.valueOf(value), Bindings.STRING, Collections.<ConstantPropertyVariableBuilder>emptyList(), CLASSIFICATIONS);
+                               ConstantPropertyVariableBuilder typeBuilder = new ConstantPropertyVariableBuilder(Variables.TYPE, sr.Cell, null, Collections.<ConstantPropertyVariableBuilder>emptyList(), Collections.<String>emptySet());
+                               
+                               map.put(valueLocation, new ConstantChildVariable(context, valueLocation, labelBuilder, typeBuilder, immutableBuilder));
+                               
+                       }
+               }
+
+               return map;
+               
+               }
+               
+    };
+
+    static class SpreadsheetProxyChildVariable extends ProxyChildVariable {
+
+        public SpreadsheetProxyChildVariable(Variable base, Variable parent, Variable other, String name) {
+            super(base, parent, other, name);
+        }
+    
+        @Override
+        public Variable create(Variable base, Variable parent, Variable other, String name) {
+            return new SpreadsheetProxyChildVariable(base, parent, other, name);
+        }
+        
+        public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
+            
+               if(CONTEXT_END.equals(name)) {
+               if(other instanceof ProxyChildVariable) {
+                       // The context is also a proxy - let it do the job
+                    return super.getPossibleChild(graph, name);
+               } else {
+                       return org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
+               }
+               }
+            
+            return super.getPossibleChild(graph, name);
+            
+        }
+        
+        public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
+
+            Collection<Variable> result = super.getChildren(graph);
+            if(!(base instanceof ProxyChildVariable)) {
+               Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
+               result.add(root);
+            }
+            return result;
+            
+        }       
+             
+    }
+
+    @SCLValue(type = "VariableMap")
+    public static VariableMap spreadsheetChildren = new VariableMapImpl() {
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+               
+               if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
+            return org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariable(graph, context, name);
+            
+        }
+
+        private Variable getProxy(ReadGraph graph, Variable context) throws DatabaseException {
+            Variable root = Variables.getRootVariable(graph);
+            return new SpreadsheetProxyChildVariable(context, context, root, ProxyChildVariable.CONTEXT_BEGIN);
+        }
+
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map)
+                throws DatabaseException {
+               
+            map = org.simantics.db.layer0.function.All.standardChildDomainChildren.getVariables(graph, context, map);
+            
+            if(map == null) map = new HashMap<String,Variable>();
+            map.put(ProxyChildVariable.CONTEXT_BEGIN, getProxy(graph, context));
+            return map;
+        }
+
+    };
+
+   
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
+    public static CellEditor<Write> defaultSheetCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
+
+       final Variable sheet = context_.getParent(graph);
+       
+       return new GraphCellEditorAdapter(null) {
+
+               @Override
+               public <T> void edit(final Transaction<Write> transaction, final String location, final String property, final T value, final Binding binding, Consumer<?> callback) {
+
+                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {
+                               
+                               @Override
+                               public void perform(WriteGraph graph) throws DatabaseException {
+                                       CellEditor<Write> editor = getPossibleCellEditor(graph, location, value == null ? null : new Variant(binding, value));
+                                       if (editor == null)
+                                           return;
+                                       editor.edit(transaction, location, property, value, binding, callback);
+                               }
+                       });
+                       
+               }
+               
+               @Override
+               public void edit(final Transaction<Write> transaction, final String location, final Variant value, Consumer<?> callback) {
+                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {
+                               
+                               @Override
+                               public void perform(WriteGraph graph) throws DatabaseException {
+                                   CellEditor<Write> editor = getPossibleCellEditor(graph, location, value);
+                                   if (editor == null)
+                                       return;
+                                       editor.edit(transaction, location, value, callback);
+                               }
+                       });
+                       
+               }
+               
+            private CellEditor<Write> getPossibleCellEditor(WriteGraph graph, String location, Variant value) throws DatabaseException {
+                SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                Range range = SpreadsheetUtils.decodeCellAbsolute(location);
+                
+                List<Variable> cells = SpreadsheetGraphUtils.possibleConfigurationCellVariables(graph, sheet, range);
+                if (cells.isEmpty()) {
+                    if (value == null) {
+                        return null;
+                    } else {
+                        cells = SpreadsheetGraphUtils.getOrCreateConfigurationCellVariables(graph, sheet, range);
+                    }
+                }
+                if (cells.size() != 1)
+                    throw new DatabaseException("Can edit only one cell at a time!");
+                
+                return cells.iterator().next().getPropertyValue(graph, SHEET.cellEditor);
+            }
+
+               @Override
+               public void copy(final Transaction<Write> transaction, final String location, final MutableVariant variant, Consumer<?> callback) {
+
+                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {
+
+                               @Override
+                               public void perform(WriteGraph graph) throws DatabaseException {
+
+                                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                                       Variable variable = sheet.getPossibleChild(graph, location);
+                                       if(variable != null) {
+                                                       CellEditor<Write> editor = variable.getPossiblePropertyValue(graph, SHEET.cellEditor);
+                                                       if(editor != null) {
+                                                               editor.copy(transaction, location, variant, null);
+                                                       }
+                                       }
+                               }
+
+                       });
+
+               }
+               
+       };
+       
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
+    public static CellEditor<Write> variableCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
+
+       final Variable cell = context_.getParent(graph);
+       
+       return new GraphCellEditorAdapter(cell) {
+
+               @Override
+               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
+                       cell.setPropertyValue(graph, property, value, binding);
+               }
+       };
+    }
+    
+    private static int encodeLineOrNode(ReadGraph graph, Resource r) throws DatabaseException {
+       if(r == null) return 0;
+       Layer0 L0 = Layer0.getInstance(graph);
+               String name = graph.getRelatedValue(r, L0.HasName, Bindings.STRING);
+               if(name.charAt(0) == 'R') {
+               return -Integer.parseInt(name.substring(3));
+               } else {
+                       return Integer.parseInt(name);
+               }
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+    public static int[] lineNodeKeys(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
+
+       Resource node = context_.getParent(graph).getRepresents(graph);
+       BTreeContentBean bean = BTreeContentBean.readPossible(graph, node);
+       if(bean == null) return new int[0];
+       // There are n keys and n+1 resources
+       int[] result = new int[2*bean.n+1];
+       for(int i=0;i<bean.n;i++) {
+               result[2*i] = encodeLineOrNode(graph, bean.getChild(i));
+               result[2*i+1] = (int)bean.getKey(i).getValue();
+       }
+       result[2*bean.n] = encodeLineOrNode(graph, bean.getChild(bean.n));
+       return result;
+       
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> LineContentBean")
+    public static LineContentBean defaultLineCells(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
+       
+        String contextUri = context_.getURI(graph);
+        
+       Variable line = context_.getParent(graph);
+       
+       Collection<Variable> children = line.getChildren(graph);
+       ObjectArrayList<LineContentBeanCell> result = new ObjectArrayList<>();
+       SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
+       for (Variable child : children) {
+           Resource repr = child.getRepresents(graph);
+           
+           Resource style = graph.getPossibleObject(repr, SR.Cell_HasStyle);
+           Integer styleId = null;
+           if (style != null)
+               styleId = graph.getPossibleRelatedValue(style, SR.Style_id, Bindings.INTEGER);
+           if (styleId == null) {
+               System.err.println("Style " + style + " has no ID or either cell "+ repr + " has no style attached to it !!");
+               styleId = SpreadsheetStyle.empty().getStyleId();
+           }
+
+               LineContentBeanCell cell = new LineContentBeanCell(styleId);
+               
+               Variant variant = child.getPossiblePropertyValue(graph, SR.Cell_content);
+               
+            if(variant != null) {
+                
+                Variable var = child.getPossibleProperty(graph, SR.Cell_content);
+                String expression = var.getPossiblePropertyValue(graph, "expression");
+                if (expression != null) {
+                    cell.setContent(new Variant(SpreadsheetSCLConstant.BINDING, new SpreadsheetSCLConstant(expression, variant.getValue())));
+                } else {
+                    cell.setContent(variant);
+                }
+                Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));
+//                result.add(cell);
+                while(result.size() < r.startColumn + 1)
+                    result.add(new LineContentBeanCell());
+                result.set(r.startColumn, cell);
+                    
+            }
+
+       }
+       LineContentBean bean = new LineContentBean();
+       bean.cells = result.toArray(new LineContentBeanCell[result.size()]);
+       return bean;
+       
+    }
+    
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> CellEditor")
+    public static CellEditor<Write> textCellEditor(ReadGraph graph, Resource resource, final Variable context_) throws DatabaseException {
+
+        System.out.println("Context URI : " + context_.getURI(graph));
+       Variable cells = context_.getParent(graph);
+       System.out.println("Cell URI : " + cells.getURI(graph));
+       
+       return new GraphCellEditorAdapter(cells) {
+
+               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, String property, T value, Binding binding) throws DatabaseException {
+                   
+                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                       if(ClientModel.CONTENT.equals(property)) {
+                               cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
+                    Variable runCell = null;
+                    Object transactionContext = transaction.getContext();
+                    if (transactionContext != null && transactionContext instanceof Variable) {
+                        Variable varContext = (Variable) transactionContext;
+                        Variable context = Variables.getContext(graph, varContext);
+                        try {
+                            runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
+                        } catch (MissingVariableException e) {
+                            // Creating new cell, need synchronizing
+                            transaction.needSynchronization(cell.getParent(graph));
+                        }
+                    }
+                               if (runCell != null)
+                                   runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
+                       } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
+                               cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
+                    Variable runCell = null;
+                    Object transactionContext = transaction.getContext();
+                    if (transactionContext != null && transactionContext instanceof Variable) {
+                        Variable varContext = (Variable) transactionContext;
+                        Variable context = Variables.getContext(graph, varContext);
+                        try {
+                            runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
+                        } catch (MissingVariableException e) {
+                            //Creating new cell, need synchronizing
+                            transaction.needSynchronization(cell.getParent(graph));
+                        }
+                    }
+                               if (runCell != null)
+                                   runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
+                       } else if(ClientModel.BORDER.equals(property)) {
+                    Resource textCell = cell.getRepresents(graph);
+                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
+                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
+                    builder.border((Integer)value);
+                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
+                       } else if(ClientModel.ALIGN.equals(property)) {
+                    Resource textCell = cell.getRepresents(graph);
+                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
+                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
+                    builder.align((Integer)value);
+                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
+                       } else if(ClientModel.LOCKED.equals(property)) {
+                               cell.setPropertyValue(graph, SHEET.Cell_locked, value, Bindings.BOOLEAN);       
+                       } else if(ClientModel.ROW_SPAN.equals(property)) {
+                               cell.setPropertyValue(graph, SHEET.Cell_rowSpan, value, Bindings.INTEGER);
+                       } else if(ClientModel.COLUMN_SPAN.equals(property)) {
+                               cell.setPropertyValue(graph, SHEET.Cell_columnSpan, value, Bindings.INTEGER);
+                       } else if(ClientModel.FONT.equals(property)) {
+                    Resource textCell = cell.getRepresents(graph);
+                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
+                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
+                    builder.font((Font)value);
+                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
+                       } else if(ClientModel.FOREGROUND.equals(property)) {
+                           Resource textCell = cell.getRepresents(graph);
+                           Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
+                           SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
+                           builder.foreground((RGB.Integer)value);
+                           finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
+                       } else if(ClientModel.BACKGROUND.equals(property)) {
+                    Resource textCell = cell.getRepresents(graph);
+                    Resource styleContainer = graph.getSingleObject(textCell, SHEET.Cell_HasStyle);
+                    SpreadsheetStyleBuilder builder = computeStyleBuilder(SHEET, graph, styleContainer);
+                    builder.background((RGB.Integer)value);
+                    finishStyleUpdate(graph, SHEET, styleContainer, textCell, builder, transaction);
+                       }
+               }
+               
+               private void finishStyleUpdate(WriteGraph graph, SpreadsheetResource SHEET, Resource styleContainer, Resource textCell, SpreadsheetStyleBuilder builder, Transaction<?> transaction) throws DatabaseException {
+                
+                Variable bookVariable = Variables.getContext(graph, cell);
+                Resource book = bookVariable.getRepresents(graph);
+                Resource createdStyle = null;
+                
+                SpreadsheetStyle style = builder.build();
+                int styleId = style.getStyleId();
+
+                Collection<Resource> existingStyles = graph.syncRequest(new ObjectsWithType(book, Layer0.getInstance(graph).ConsistsOf, SHEET.Style));
+                for (Resource eStyle : existingStyles) {
+                    int eStyleId = graph.getRelatedValue2(eStyle, SHEET.Style_id, Bindings.INTEGER);
+                    if (eStyleId == styleId) {
+                        createdStyle = eStyle;
+                        break;
+                    }
+                }
+                if (createdStyle == null) {
+                       style = builder.name("Style_" + existingStyles.size()).build();
+                    createdStyle = SpreadsheetGraphUtils.createStyle(graph, book, style);
+                }
+                
+                graph.deny(textCell, SHEET.Cell_HasStyle);
+                Collection<Resource> cellsOfStyle = graph.getObjects(styleContainer, SHEET.Cell_StyleOf);
+                if (cellsOfStyle.isEmpty()) {
+                    graph.deny(styleContainer);
+                }
+                graph.claim(textCell, SHEET.Cell_HasStyle, createdStyle);
+                
+//                Variable runCell = null;
+//                Object transactionContext = transaction.getContext();
+//                if (transactionContext != null && transactionContext instanceof Variable) {
+//                    Variable varContext = (Variable) transactionContext;
+//                    Variable context = Variables.getContext(graph, varContext);
+//                    try {
+//                        runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
+//                    } catch (MissingVariableException e) {
+//                        //Creating new cell, need synchronizing
+//                        transaction.needSynchronization(cell.getParent(graph));
+//                    }
+//                }
+//                if (runCell != null) {
+//                    Datatype type = new RecordType();
+//                    Binding b = Bindings.getBinding(type);
+//                    runCell.setPropertyValue(graph, SHEET.Cell_style, style, b);
+//                }
+            }
+
+            private SpreadsheetStyleBuilder computeStyleBuilder(SpreadsheetResource SHEET, WriteGraph graph, Resource styleContainer) throws DatabaseException {
+                RGB.Integer foreground = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_foreground, RGB.Integer.BINDING);
+                RGB.Integer background = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_background, RGB.Integer.BINDING);
+                Font font = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_font, Font.BINDING);
+                Integer align = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_align, Bindings.INTEGER);
+                Integer border = graph.getPossibleRelatedValue2(styleContainer, SHEET.Cell_border, Bindings.INTEGER);
+                
+                return SpreadsheetStyle.newInstace().foreground(foreground).background(background).font(font).align(align).border(border);
+            }
+
+            @Override
+               public <T> void edit(WriteGraph graph, Transaction<Write> transaction, String location, Variant value) throws DatabaseException {
+                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                       
+                       // Handle possible deletes
+                       if (value == null)
+                           value = Variant.ofInstance("");
+                       
+                if (!transaction.isOperationMode()) {
+                    cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
+//                    return;
+                }
+                Variable runCell = null;
+                Object transactionContext = transaction.getContext();
+                if (transactionContext != null && transactionContext instanceof Variable) {
+                    Variable varContext = (Variable) transactionContext;
+                    Variable context = Variables.getContext(graph, varContext);
+                    try {
+                        runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
+                    } catch (MissingVariableException e) {
+                        // Creating cell for the first time so no runCell available at this time, needs synchronization
+                        transaction.needSynchronization(cell.getParent(graph));
+                    }
+                    
+                }
+
+                       if (runCell != null) {
+                           System.out.println("All.edit " + runCell.getURI(graph));
+                           runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
+                       }
+               }
+               
+               @Override
+               public <T> void copy(WriteGraph graph, Transaction<Write> transaction, String location, MutableVariant variant) throws DatabaseException {
+                       SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
+                       
+                Variable runCell = null;
+                Object transactionContext = transaction.getContext();
+                if (transactionContext != null && transactionContext instanceof Variable) {
+                    Variable varContext = (Variable) transactionContext;
+                    Variable context = Variables.getContext(graph, varContext);
+                    runCell = Variables.switchRealization(graph, cell, context.getRepresents(graph), context);
+                }
+                       
+                       //Variant content = cell.getPropertyValue(graph, SHEET.Cell_content, Bindings.VARIANT);
+                       Object object = cell.getPropertyValue(graph, SHEET.Cell_content);
+                       Variant content = null;
+                       if (object instanceof Variant) {
+                           content = (Variant)object;
+                       } else if (object instanceof Double) {
+                           content = Variant.ofInstance((Double)object);
+                       } else if (object instanceof Float) {
+                               content = Variant.ofInstance((Float)object);
+                       } else if (object instanceof Integer) {
+                           content = Variant.ofInstance((Integer)object);
+                       } else if (object instanceof Long) {
+                           content = Variant.ofInstance((Long)object);
+                       } else if (object instanceof String) {
+                           content = Variant.ofInstance((String)object);
+                       } else if (object instanceof Variable) {
+                           content = Variant.ofInstance((Variable)object);
+                       } else {
+                           throw new DatabaseException("");
+                       }
+                       variant.setValue(content);
+               }
+               
+       };
+       
+    }
+    
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable spreadsheetInput(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
+               return ProxyVariables.inputVariable(graph, sheet);
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable spreadsheetSession(ReadGraph graph, Resource converter, Variable sheet) throws DatabaseException {
+               return ProxyVariables.proxySessionVariable(graph, sheet);
+    }
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> Variable")
+    public static Variable spreadsheetRunInput(ReadGraph graph, Resource converter, Variable property) throws DatabaseException {
+       Resource model = Variables.getModel(graph, property);
+       Variable activeRun = graph.syncRequest(new PossibleActiveRun(model));
+       if(activeRun != null) return activeRun;
+       return Variables.getConfigurationContext(graph, model);
+    }
+    
+       @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
+    public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+           return CompileSCLValueRequest.compileAndEvaluate(graph, context);
+    }
+
 }
\ No newline at end of file