]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Spreadsheet changes
authorAntti Villberg <antti.villberg@semantum.fi>
Fri, 16 Nov 2018 13:11:27 +0000 (15:11 +0200)
committerAntti Villberg <antti.villberg@semantum.fi>
Sun, 18 Nov 2018 05:09:12 +0000 (07:09 +0200)
Change-Id: Iecb754032ab998491bd91d88b4a9d7d8b1eef873

162 files changed:
bundles/org.simantics.spreadsheet.common/META-INF/MANIFEST.MF
bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/util/SpreadsheetUtils.java
bundles/org.simantics.spreadsheet.graph/plugin.xml
bundles/org.simantics.spreadsheet.graph/scl/Spreadsheet/All.scl
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/EvaluateAll.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelArrayFormula.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelFormula.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelImport.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/GraphUI.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/InvalidateAll.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/PrintVisitor.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetGraphUtils.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetNodeManager.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetRealm.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetReferenceResolver.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSessionManager.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetTypeNode.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitable.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitor.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/adapter/DoubleArrayCellVariable.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/adapter/DoubleArrayCells.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/adapter/SpreadsheetVariable.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/adapter/StringArrayCells.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/All.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/SpreadsheetRootVariable.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/request/SpreadsheetExpressionVisitor.java
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java [deleted file]
bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SpreadsheetSynchronizationEventHandler.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientModelImpl.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ClientTableModel.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/DeleteHandler.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExcelAdapter.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/ExpressionTextListener.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SelectionListener.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/SpreadsheetModel.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TextTableCellEditor.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/CommandCellTab.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/ExcelLink.java
bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/editor/SpreadsheetSelectionProcessor.java
bundles/org.simantics.spreadsheet/.classpath
bundles/org.simantics.spreadsheet/META-INF/MANIFEST.MF
bundles/org.simantics.spreadsheet/build.properties
bundles/org.simantics.spreadsheet/lib/commons-math3-3.6.1.jar [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Adaptable.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellEditor.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellModifier.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellParseException.java [moved from bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/exception/CellParseException.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ClientModel.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CommandCellExecutor.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Disposable.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Matrix.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Range.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SheetVariables.java
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetCellStyle.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellStyle.java with 83% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitable.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitor.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Spreadsheets.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetNode.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SheetNode.java with 53% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContent.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContent.java with 53% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContentExpression.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContentExpression.java with 61% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellEditable.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellEditable.java with 73% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetElement.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetElement.java with 78% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetFormula.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetFormula.java with 62% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetSCLConstant.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSCLConstant.java with 96% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetStyle.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetStyle.java with 81% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetTypeNode.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AndFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CountifFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfErrorFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfErrorFormulaFunction.java with 63% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfFormulaFunction.java with 51% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IsErrorFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IsErrorFormulaFunction.java with 50% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/LinestFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/LinestFormulaFunction.java with 82% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/MatchFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PiFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/PiFormulaFunction.java with 53% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundFormulaFunction.java with 62% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundupFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundupFormulaFunction.java with 62% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SpreadsheetEvaluationEnvironment.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SpreadsheetEvaluationEnvironment.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SqrtFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SqrtFormulaFunction.java with 54% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumFormulaFunction.java with 52% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumifFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumifFormulaFunction.java with 65% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/TodayFormulaFunction.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/TodayFormulaFunction.java with 66% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ParseException.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ParseException.java with 99% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.java with 99% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.jj [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.jj with 100% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserConstants.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserConstants.java with 97% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParserTokenManager.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParserTokenManager.java with 99% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetParserUtils.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetParserUtils.java with 96% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SimpleCharStream.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SimpleCharStream.java with 99% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/Token.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/Token.java with 98% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/TokenMgrError.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/TokenMgrError.java with 98% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstApply.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstApply.java with 89% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArgList.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArgList.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArithmeticExpression.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArithmeticExpression.java with 90% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArray.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArray.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArrayFormulaReference.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArrayFormulaReference.java with 94% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstBoolean.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstBoolean.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstDouble.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstDouble.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstFactor.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstFactor.java with 88% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstIdentifier.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstIdentifier.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstInteger.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstInteger.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstList.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstList.java with 92% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNothing.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNothing.java with 94% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNull.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNull.java with 92% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRange.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRange.java with 92% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRelation.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRelation.java with 94% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstString.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstString.java with 93% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstTerm.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstTerm.java with 88% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValue.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValue.java with 92% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValueVisitor.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValueVisitor.java with 94% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBean.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBean.java with 66% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBeanCell.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBeanCell.java with 78% similarity]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java [new file with mode: 0644]
bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/StyleUpdater.java [moved from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/StyleUpdater.java with 96% similarity]

index eab319b3a0419348ecdfe24c5c466cccb71f43ed..8d195df0cd1206f9d2a764b41c37899566783365 100644 (file)
@@ -18,7 +18,6 @@ Export-Package: org.simantics.spreadsheet.common,
  org.simantics.spreadsheet.common.cell,
  org.simantics.spreadsheet.common.cell.handler,
  org.simantics.spreadsheet.common.client,
- org.simantics.spreadsheet.common.exception,
  org.simantics.spreadsheet.common.expression.analysis,
  org.simantics.spreadsheet.common.expression.lexer,
  org.simantics.spreadsheet.common.expression.node,
index 4d6715dc5d57fd0635ed27e7cccd7d9f3db58767..dcd88cf61306f80730fc047441c940e87bde2ea2 100644 (file)
@@ -51,286 +51,14 @@ import org.simantics.spreadsheet.CellEditor.Transaction;
 import org.simantics.spreadsheet.ClientModel;
 import org.simantics.spreadsheet.ClientModel.OperationMode;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.TableCell;
 import org.simantics.spreadsheet.common.cell.StringCellParser;
-import org.simantics.spreadsheet.common.exception.CellParseException;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.synchronization.LineContentBean;
 import org.simantics.utils.datastructures.Pair;
 
 public class SpreadsheetUtils {
-    
-    public static final int SPREADSHEET_BTREE_SIZE = 100;
-       
-       public static String offset(String location, int rowOffset, int columnOffset) {
-
-               Range range = decodeCellAbsolute(location);
-               String result = cellName(range.startRow + rowOffset, range.startColumn + columnOffset); 
-               //      System.err.println("offset " + location + "(" + rowOffset + " " + columnOffset + ") = >" + result);
-               return result;
-
-       }
-
-       public static Object extract(Object object, int row, int column) {
-               if(object instanceof List) {
-                       List list = (List)object;
-                       if(list.size() <= row) return null;
-                       Object item = list.get(row);
-                       if(item instanceof Tuple) {
-                               Tuple tuple = (Tuple)item;
-                               if(tuple.length() <= column) return null;
-                               return tuple.get(column);
-                       }
-               }
-               return null;
-       }
-
-       //      1 kirjain, 'A' + column
-       //      2 kirjainta, 'A' + column % 26 , 'A' + int((column-26)/26)
-       //      3 kirjainta 'A' + column % 26 , 'A' + int(column-(26*(26+1)) / 26) % 26
-
-       //    0              26
-       //    26             26 + 26*26
-       //    26 + 26*26     26 + 26*26 + 26*26*26
-
-       public static String columnName(int column, int current, int limit, int chars) {
-
-               if(column < limit) {
-
-                       char[] buf = new char[chars];
-                       column -= current;
-                       for(int i=chars-1;i>=0;i--) {
-                               char rem = (char)(column % 26);
-                               column = (column / 26);
-                               buf[i] = (char)('A' + rem); 
-                       }
-                       return new String(buf);
-
-               } else return columnName(column, limit, 26*(limit+1), chars+1);
-
-       }
-
-       public static String columnName(int column) {
-               return columnName(column, 0, 26, 1);
-       }    
-
-       public static String cellName(int row, int column) {
-
-               String result = columnName(column);
-               result += (row+1);
-               return result;
-
-       }    
-
-       public static Range decodeCellAbsolute(String identifier) {
-               long l = decodeCellCoded(identifier);
-               int row = (int)(l & 0xffffffff) - 1;
-               int column = (int)((l>>32) & 0xffffffff);
-               return new Range(row, row, column, column);
-       }
-
-       public static Range decodePossibleCellAbsolute(String identifier) {
-           try {
-               return decodeCellAbsolute(identifier);
-           } catch (CellParseException e) {
-               return null;
-           }
-       }
-
-       public static long decodeCellCoded(String identifier) {
-
-           //        System.out.println("decodecellabsolute " + identifier);
-
-           int row = 0;
-               int column = 0;
-               
-//             identifier.
-               
-               int position = 0;
-               
-               // We skip $ here
-               if(identifier.charAt(position) == '$') position++;
-               
-               int length = identifier.length();
-               
-               while(position < length) {
-                       char b = identifier.charAt(position);
-                       if(b >= 'A' && b <= 'Z') column = column * 26 + (b-'A' + 1);
-                       else break;
-                       position++;
-               }
-
-               // We skip $ here
-               if(position < length)
-                       if(identifier.charAt(position) == '$')
-                               position++;
-
-               while(position < length) {
-                       char b = identifier.charAt(position);
-                       if(b >= '0' && b <= '9'){
-                               row = row * 10 + b-'0';
-                       }
-                       else if(b=='-' && position < (length-1)){//identify use of full row range here.
-                               position++;
-                               char b2 = identifier.charAt(position);
-                               if(b2=='1'){
-                                       row = 0;
-                                       position++;
-                                       break;
-                               }
-                       }
-                       else {
-                               break;
-                       }
-                       position++;
-               }
-
-               if(position == length) {
-
-                       // We need to be able to express -1 in row => report row + 1 here
-                       column--;
-                       //            System.err.println("ra " + identifier + " => " + row + " " + column);
-                       return row + (((long)column)<<32);
-
-               } else {
-
-                       throw new CellParseException("Cell identifier '" + identifier + "' is not a valid cell reference.");
-
-               }
-
-       }
-
-       public static Range decodeCellRelative(String identifier, int row, int column) {
-
-               int offset = Integer.valueOf(identifier.substring(1).trim());
-               //        System.out.println("offset=" + offset);
-
-               if(identifier.startsWith("L") || identifier.startsWith("l")) {
-                       return new Range(row, row, column-offset, column-offset);
-               } else if(identifier.startsWith("R") || identifier.startsWith("r")) {
-                       return new Range(row, row, column+offset, column+offset);
-               } else if(identifier.startsWith("U") || identifier.startsWith("u")) {
-                       return new Range(row-offset, row-offset, column, column);
-               } else if(identifier.startsWith("D") || identifier.startsWith("d")) {
-                       return new Range(row+offset, row+offset, column, column);
-               } else {
-                       throw new CellParseException("Relative cell syntax must begin with L|R|U|D.");
-               }
-
-       }
-
-       public static Range decodeCell(String identifier, int row, int column) {
-
-               if(identifier.startsWith("_")) {
-                       return decodeCellRelative(identifier.substring(1), row, column);
-               } else {
-                       return decodeCellAbsolute(identifier);
-               }
-
-       }
-
-       public static Range decodeReference(String identifier, int row, int column) {
-               if(!identifier.startsWith("&")) throw new CellParseException("A reference cell was expected.");
-               return decodeRange(identifier.substring(1), row, column);
-       }
-
-       public static List<Range> decodeRanges(String ranges){
-               String[] splitted = ranges.split(",");
-               List<Range> result = new ArrayList<>();
-               for(String split : splitted){
-                       result.add(decodeRange(split));
-               }
-               return result;
-       }
-       
-       public static int startRow(List<Range> ranges){
-               int s = -1;
-               for(Range r : ranges){
-                       if(r.startRow<s || s==-1){
-                               s = r.startRow;
-                       }
-               }
-               return s;
-       }
-       
-       public static int startColumn(List<Range> ranges){
-               int s = -1;
-               for(Range r : ranges){
-                       if(r.startColumn<s || s==-1){
-                               s = r.startColumn;
-                       }
-               }
-               return s;
-       }
-       
-       public static int amountOfRows(Range r){
-               int endRow = -2;
-               int startRow = -2;
-               if(r.isFullRows()){
-                       return Range.MAXROWSPEC;
-               }
-               if(endRow == -2 && startRow == -2){
-                       endRow = r.endRow;
-                       startRow = r.startRow;
-               }
-               if(r.startRow<startRow){
-                       startRow = r.startRow;
-               }
-               if(r.endRow>endRow){
-                       endRow = r.endRow;
-               }
-               return endRow - startRow +1;
-       }
-       
-       public static int amountOfColumns(Range r){
-               int endColumn = -2;
-               int startColumn = -2;
-               if(r.isFullColumns()){
-                       return Range.MAXCOLUMNSPEC;
-               }
-               if(endColumn == -2 && startColumn == -2){
-                       endColumn = r.endColumn; 
-                       startColumn = r.startColumn;
-               }
-               if(r.startColumn<startColumn){
-                       startColumn = r.startColumn;
-               }
-               if(r.endColumn>endColumn){
-                       endColumn = r.endColumn;
-               }
-               return endColumn - startColumn +1;
-       }
-       
-       public static Range decodeRange(String rangeOrCell) {
-               if(rangeOrCell.isEmpty()) return fullRange();
-               return decodeRange(rangeOrCell, 0, 0);
-       }
-       
-       public static Range fullRange() {
-               return new Range(0, -1, 0, -1);
-       }
-
-       public static Range decodeRange(String rangeOrCell, int row, int column) {
-       
-               String[] parts = rangeOrCell.split(":");
-               if(parts.length == 1) {
-
-                       return decodeCell(rangeOrCell, row, column);
-
-               } else if (parts.length == 2) {
-
-                       Range from = decodeCell(parts[0].trim(), row, column);
-                       //            System.out.println("decodefrom=" + from);
-                       Range to = decodeCell(parts[1].trim(), row, column);
-                       //            System.out.println("decodeto=" + to);
-                       return Range.combine(from, to);
-
-               } else {
-
-                       throw new CellParseException("The reference cell syntax was invalid. At most 1 occurrence of ':' is expected.");
-
-               }
-
-       }
 
        public static Pair<String, Collection<PropertyCreationData>> parse(String text, StringCellParser[] parsers) {
 
@@ -410,15 +138,15 @@ public class SpreadsheetUtils {
 
        public static void main(String[] args) {
                for(int i=0;i<16384;i++) {
-                       String name = columnName(i);
-                       Range r = decodeCellAbsolute(name + "1");
+                       String name = Spreadsheets.columnName(i);
+                       Range r = Spreadsheets.decodeCellAbsolute(name + "1");
                        System.err.println(i + " " + name + " " + r);
                }
        }
 
        public static String getLabel(ClientModel model, int row, int column) {
                try {
-                       String location = SpreadsheetUtils.cellName(row, column);
+                       String location = Spreadsheets.cellName(row, column);
                        String label = model.getPropertyAt(location, ClientModel.LABEL);
                        if(label != null) return label;
                        Variant content = SpreadsheetUtils.getSafeClientVariant(model, location, ClientModel.CONTENT);
@@ -435,8 +163,8 @@ public class SpreadsheetUtils {
        }
 
        public static boolean isInBounds(String base, String location, int wBounds, int hBounds) {
-               Range baseRange = decodeCellAbsolute(base);
-               Range locationRange = decodeCellAbsolute(location);
+               Range baseRange = Spreadsheets.decodeCellAbsolute(base);
+               Range locationRange = Spreadsheets.decodeCellAbsolute(location);
                if(locationRange.startColumn < baseRange.startColumn) return false;
                if(locationRange.startRow < baseRange.startRow) return false;
                int wb = wBounds == -1 ? (Integer.MAX_VALUE / 3) : wBounds;
@@ -577,7 +305,7 @@ public class SpreadsheetUtils {
 //            graph.claim(result, L0.ConsistsOf, L0.PartOf, newCell);
 //            BTree bt = new BTree(graph, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, SR.Lines, SR.LineNode, L0.PartOf, true);
         
-        BTree bt = new BTree(graph, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, sr.Lines, sr.LineNode, L0.PartOf, false);
+        BTree bt = new BTree(graph, Spreadsheets.SPREADSHEET_BTREE_SIZE, sr.Lines, sr.LineNode, L0.PartOf, false);
 //        BTree bt = BTreeUtils.create(graph, sr.Lines, sr.LineNode, L0.PartOf, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, false);
         Resource lines = bt.rootOfBTree();
         
@@ -807,7 +535,7 @@ public class SpreadsheetUtils {
         if (formatString == null)
             return getLabel(model, row, column); 
         try {
-            String location = SpreadsheetUtils.cellName(row, column);
+            String location = Spreadsheets.cellName(row, column);
             Variant content = SpreadsheetUtils.getSafeClientVariant(model, location, ClientModel.CONTENT);
             if(content != null) {
                 
index 18738892970d05ecb16e5538d46bdf1f73263e03..6088f678d02e649376f456b10a670dca2cd9aeac 100644 (file)
@@ -12,7 +12,7 @@
          <externalClass className="org.simantics.db.layer0.variable.ValueAccessor"/>
          <externalClass className="org.simantics.db.layer0.variable.VariableMap"/>
          <externalClass className="org.simantics.spreadsheet.CellEditor"/>
-         <externalClass className="org.simantics.spreadsheet.graph.function.LineContentBean"/>
+         <externalClass className="org.simantics.spreadsheet.synchronization.LineContentBean"/>
          <class className="org.simantics.spreadsheet.graph.function.All"/>
       </namespace>
    </extension>
index 8898ce10a9a306d58b0ea796e6d96653987fd132..9ca65f8d100da2d9c9586a7d795df80133fa99be 100644 (file)
@@ -4,6 +4,9 @@ include "Simantics/SCL"
 include "Document/All"
 include "File"
 
+importJava "org.simantics.spreadsheet.graph.ExternalRef" where
+    data ExternalRef
+
 importJava "org.simantics.spreadsheet.common.TableCell" where
     data TableCell
 
@@ -41,6 +44,8 @@ importJava "org.simantics.spreadsheet.graph.SpreadsheetGraphUtils" where
     saveInitialCondition :: Variable -> Resource -> String -> <WriteGraph> Resource
     findCell :: Variable -> String -> <ReadGraph> Maybe Variable
     invalidateAll :: Variable -> <ReadGraph> ()
+    extRefVariable :: Variable -> <ReadGraph> Variant
+    extRefActiveVariable :: Variable -> <ReadGraph> Variant
 
 importJava "org.simantics.spreadsheet.util.SpreadsheetUtils" where
     createSheet :: Resource -> String -> <WriteGraph> Resource
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellFormulaFunction.java
deleted file mode 100644 (file)
index 8880085..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public interface CellFormulaFunction<T> {
-
-       T evaluate(CellValueVisitor visitor, AstArgList args);
-       
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/CellValueVisitor.java
deleted file mode 100644 (file)
index 8150b4d..0000000
+++ /dev/null
@@ -1,478 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.Range;
-import org.simantics.spreadsheet.graph.formula.FormulaError2;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.parser.ast.AstApply;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstArithmeticExpression;
-import org.simantics.spreadsheet.graph.parser.ast.AstArray;
-import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference;
-import org.simantics.spreadsheet.graph.parser.ast.AstBoolean;
-import org.simantics.spreadsheet.graph.parser.ast.AstDouble;
-import org.simantics.spreadsheet.graph.parser.ast.AstFactor;
-import org.simantics.spreadsheet.graph.parser.ast.AstIdentifier;
-import org.simantics.spreadsheet.graph.parser.ast.AstInteger;
-import org.simantics.spreadsheet.graph.parser.ast.AstNothing;
-import org.simantics.spreadsheet.graph.parser.ast.AstNull;
-import org.simantics.spreadsheet.graph.parser.ast.AstRange;
-import org.simantics.spreadsheet.graph.parser.ast.AstRelation;
-import org.simantics.spreadsheet.graph.parser.ast.AstString;
-import org.simantics.spreadsheet.graph.parser.ast.AstTerm;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-import org.simantics.spreadsheet.graph.parser.ast.AstValueVisitor;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
-
-import it.unimi.dsi.fastutil.longs.AbstractLongList;
-import it.unimi.dsi.fastutil.longs.LongArrayList;
-
-public class CellValueVisitor implements AstValueVisitor<Object> {
-
-       final public SpreadsheetBook book;
-       final private SpreadsheetEvaluationEnvironment env;
-       final private SpreadsheetCell thisCell;
-       final private LongArrayList references = new LongArrayList();
-       
-       public CellValueVisitor(SpreadsheetEvaluationEnvironment env, SpreadsheetCell thisCell) {
-               this.book = env.getBook();
-               this.env = env;
-               this.thisCell = thisCell;
-       }
-       
-       public void addReference(long ref) {
-               references.add(ref);
-       }
-       
-       public AbstractLongList getReferences() {
-               return references;
-       }
-       
-       @Override
-       public Object visit(AstBoolean astBoolean) {
-               return astBoolean.value;
-       }
-
-       @Override
-       public Object visit(AstDouble astFloat) {
-               return astFloat.value;
-       }
-
-       @Override
-       public Object visit(AstInteger astInteger) {
-               return astInteger.value;
-       }
-
-       @Override
-       public Object visit(AstNull astNull) {
-               throw new IllegalStateException();
-       }
-
-       @Override
-       public Object visit(AstString astString) {
-               return astString.value;
-       }
-
-       @Override
-       public Object visit(AstRange astRange) {
-               
-               if(astRange.isRef()){
-                       return FormulaError2.REF.getString();
-               }
-               
-               if(astRange.isCell()) {
-                       String ref = astRange.first;
-                       Range r = SpreadsheetUtils.decodeCell(ref, 0, 0);
-                       String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
-                       SpreadsheetCell cell = thisCell.getBook().get(sheetName, r.startRow, r.startColumn);
-                       if(cell == null) {
-                           SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
-                           SpreadsheetLine line = eng.getLine(r.startRow);
-                           
-                           if (line == null) {
-                               line = new SpreadsheetLine(eng.lines, r.startRow);
-                               eng.lines.lines.put(-r.startRow, line);
-                           }
-                           cell = SpreadsheetCell.empty(line, r.startColumn);
-                       }
-                       return cell.evaluate(env, this);
-                       
-               } else {
-                       
-                       Object cached = thisCell.getEngine().getCachedRange(astRange);
-                       if(cached != null) {
-                               
-                               Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second);
-                               String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
-                               SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
-                               Range r = eng.actualRange(r_);
-                               for(int row=0; row < r.height();row++) {
-                                       SpreadsheetLine line = eng.getLine(r.startRow + row);
-                                       if(line != null) {
-                                               for(int column=0; column < r.width();column++) {
-                                                       int col = r.startColumn + column;
-                                                       if(line.cells.size() > col) {
-                                                               SpreadsheetCell cell = line.cells.get(r.startColumn + column);
-                                                               //Add references, but do not evaluate if there exists a cached range.
-                                                               addReference(cell.makeReferenceKey());
-                                                       }
-                                               }
-                                       }
-                               }       
-                               return cached;
-                       }
-                       
-                       Range r_ = SpreadsheetUtils.decodeRange(astRange.first + ":" + astRange.second);
-                       String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
-                       SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
-                       // Full ranges are resolved here
-                       Range r = eng.actualRange(r_);
-                       SpreadsheetMatrix result = new SpreadsheetMatrix(r.width(), r.height());
-                       for(int row=0; row < r.height();row++) {
-                               SpreadsheetLine line = eng.getLine(r.startRow + row);
-                               if(line != null) {
-                                       for(int column=0; column < r.width();column++) {
-                                               int col = r.startColumn + column;
-                                               if(line.cells.size() > col) {
-                                                       SpreadsheetCell cell = line.cells.get(r.startColumn + column);
-                                                       result.values[r.width()*row + column] = cell.evaluate(env, this);
-                                               }
-                                       }
-                               }
-                       }
-                       thisCell.getEngine().cacheRange(astRange, result);
-                       return result;
-               }
-       }
-
-       @Override
-       public Object visit(AstArgList astArgList) {
-               throw new IllegalStateException();
-       }
-
-       @Override
-       public Object visit(AstApply astApply) {
-               CellFormulaFunction<?> fn = env.getFunction(astApply.value);
-               if(fn != null) {
-                       return fn.evaluate(this, astApply.args);
-               } else {
-                       return FormulaError2.NAME.getString();
-               }
-       }
-
-       @Override
-       public Object visit(AstRelation astRelation) {
-
-               Object leftResult = astRelation.left.accept(this);
-               Object rightResult = astRelation.right.accept(this);
-               
-               FormulaError2 err = FormulaError2.forObject(leftResult);
-               if(err!=null) return err.getString();
-               FormulaError2 err2 = FormulaError2.forObject(rightResult);
-               if(err2!=null) return err2.getString();
-               
-               if(leftResult instanceof Variant){
-                       Object leftTemp = ((Variant)leftResult).getValue();
-                       Double leftVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftTemp);
-                       if(leftVal==null) leftResult = leftTemp.toString();
-                       else leftResult = leftVal;
-               }
-               if(rightResult instanceof Variant){
-                       Object rightTemp = ((Variant)rightResult).getValue();
-                       Double rightVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightTemp);
-                       if(rightVal==null) rightResult = rightTemp.toString();
-                       else rightResult = rightVal;
-               }
-               if ((leftResult instanceof String) && (rightResult instanceof String)) {
-                       String leftString = (leftResult.toString()).toLowerCase();
-                       String rightString = (rightResult.toString()).toLowerCase();
-                       if("<".equals(astRelation.op.trim())) return leftString.compareTo(rightString) < 0;
-                       else if(">".equals(astRelation.op.trim())) return leftString.compareTo(rightString) > 0;
-                       else if("=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) == 0;
-                       else if("<>".equals(astRelation.op.trim())) return leftString.compareTo(rightString) != 0 ;
-                       else if("<=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) <= 0 ;
-                       else if(">=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) >= 0 ;
-                       else throw new IllegalStateException();
-               } else {
-                       Number leftNumber = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftResult);
-                       Number rightNumber = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightResult);
-                       if(leftNumber==null || rightNumber==null) return false;
-                       if("<".equals(astRelation.op.trim())) return leftNumber.doubleValue() < rightNumber.doubleValue();
-                       else if(">".equals(astRelation.op.trim())) return leftNumber.doubleValue() > rightNumber.doubleValue();
-                       else if("=".equals(astRelation.op.trim())) return leftNumber.doubleValue() == rightNumber.doubleValue();
-                       else if("<>".equals(astRelation.op.trim())) return leftNumber.doubleValue() != rightNumber.doubleValue();
-                       else if("<=".equals(astRelation.op.trim())) return leftNumber.doubleValue() <= rightNumber.doubleValue();
-                       else if(">=".equals(astRelation.op.trim())) return leftNumber.doubleValue() >= rightNumber.doubleValue();
-                       else throw new IllegalStateException();
-               }
-       }
-       
-       Object leftValueWithPrefix(Object result, AstValue value, String prefix, boolean forceNumber) {
-               if(result == null) {
-                       Object obj = value.accept(this);
-                       FormulaError2 err = FormulaError2.forObject(obj);
-                       if(err!=null) return err.getString();
-                       
-                       if("-".equals(prefix)) {
-                               result = SpreadsheetGraphUtils.asNumber(obj);
-                               return -((Number)result).doubleValue();
-                       } else {
-                               if(forceNumber) return SpreadsheetGraphUtils.asNumber(obj);
-                               else return obj;
-                       }
-               }
-               try{
-                       return (Number)Double.parseDouble(result.toString());
-               } catch (NumberFormatException e){
-                       return result;
-               }
-       }
-
-       @Override
-       public Object visit(AstArithmeticExpression exp) {
-               Object result = null;
-               Object other = null;
-               AstValue value = null;
-               Object acceptedValue = null;
-               
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       value = exp.rightValue(i);
-                       acceptedValue = value.accept(this);
-                       if("+".equals(op)) {
-                               result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
-                               
-                               if(!(result instanceof Number)) {
-                                       FormulaError2 err = FormulaError2.forObject(result);
-                                       if(err!=null) return err.getString();
-                                       
-                                       if(result instanceof String && !((String) result).isEmpty()){
-                                               Number num = SpreadsheetGraphUtils.asValidNumber(result);
-                                               if(num == null) {
-                                                       return FormulaError2.VALUE.getString();
-                                               } else {
-                                                       result = num;
-                                               }
-                                       } 
-                                       else if(result instanceof Variant){
-                                               Object val = ((Variant)result).getValue();
-                                               if(val instanceof String && (val.toString().isEmpty())){
-                                                       result = 0.0;
-                                               } else {
-                                                       Number resNum = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(val);
-                                                       if(resNum==null) return FormulaError2.VALUE.getString();
-                                                       else result = resNum;
-                                               }
-                                       } else {
-                                               result = 0.0;
-                                       }
-                               }
-                               
-                               FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
-                               if(err2!=null) return err2.getString();
-                               
-                               other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(acceptedValue);
-                               if(other==null)
-                                       return FormulaError2.handleErrorCall(acceptedValue);
-                               
-                               result = ((Number)result).doubleValue() + ((Number)other).doubleValue();
-                               
-                       } else if("-".equals(op)) {
-                               result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
-                               
-                               if(!(result instanceof Number)) {
-                                       FormulaError2 err = FormulaError2.forObject(result);
-                                       if(err!=null) return err.getString();
-                                       
-                                       if(result instanceof String && !((String) result).isEmpty()){
-                                               Number num = SpreadsheetGraphUtils.asValidNumber(result);
-                                               if(num == null) {
-                                                       return FormulaError2.VALUE.getString();
-                                               } else {
-                                                       result = num;
-                                               }
-                                       } 
-                                       else if(result instanceof Variant){
-                                               Object val = ((Variant)result).getValue();
-                                               if(val instanceof String && (val.toString().isEmpty())){
-                                                       result = 0.0;
-                                               } else {
-                                                       Number resNum = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(val);
-                                                       if(resNum==null)
-                                                               return FormulaError2.VALUE.getString();
-                                                       else result = resNum;
-                                               }
-                                       } else {
-                                               result = 0.0;
-                                       }
-                               }
-                               FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
-                               if(err2!=null) return err2.getString();
-                               
-                               other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(acceptedValue);
-                               if(other==null)
-                                       return FormulaError2.handleErrorCall(acceptedValue);
-                               
-                               result = ((Number)result).doubleValue() - ((Number)other).doubleValue();
-                               
-                       } else if("&".equals(op)) {
-                               result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
-                               FormulaError2 err = FormulaError2.forObject(result);
-                               if(err!=null) return err.getString();
-                               FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
-                               if(err2!=null) return err2.getString();
-                               
-                               result = SpreadsheetGraphUtils.asString(result);
-                               other = SpreadsheetGraphUtils.asString(acceptedValue);
-
-                               result += (String)other;
-                       }
-               }
-               return leftValueWithPrefix(result, exp.left, exp.prefix, false);
-               
-       }
-
-       @Override
-       public Object visit(AstTerm exp) {
-               Number result = null;
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       AstValue value = exp.rightValue(i);
-                       Object leftValue = exp.left.accept(this);
-                       Object rightValue = value.accept(this);
-                       if("*".equals(op)) {
-                               if(result == null) {
-                                       result = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftValue);
-                                       if(result == null)
-                                               return FormulaError2.handleErrorCall(leftValue);
-                               }
-                               Number other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightValue);
-                               if(other==null) return FormulaError2.handleErrorCall(rightValue);
-                               
-                               result = new Double(result.doubleValue() * other.doubleValue());
-                               
-                       } else if("/".equals(op)) {
-                               if(result == null) {
-                                       result = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftValue);
-                                       if(result == null)
-                                               return FormulaError2.handleErrorCall(leftValue);
-                               }
-                               Number other = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(rightValue);
-                               if(other==null) return FormulaError2.handleErrorCall(rightValue);
-                               if(other.doubleValue()==0.0) return FormulaError2.DIV0.getString();
-                               
-                               result = new Double(result.doubleValue() / other.doubleValue());        
-                       }
-               }
-               if(result == null) result = SpreadsheetGraphUtils.asNumber(exp.left.accept(this));
-               return result;
-       }
-
-       @Override
-       public Object visit(AstFactor exp) {
-               Object result = null;
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       AstValue value = exp.rightValue(i);
-                       if("^".equals(op)) {
-                               if(result == null) {
-                                       Object leftValue = exp.left.accept(this);
-
-                                       FormulaError2 err = FormulaError2.forObject(leftValue);
-                                       if(err!=null) return err.getString();
-                                       
-                                       if(leftValue instanceof Variant){
-                                               Object leftTemp = ((Variant)leftValue).getValue();
-                                               Double leftV = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(leftTemp);
-                                               if(leftV==null) leftValue = leftTemp.toString();
-                                               else leftValue = leftV;
-                                       }
-                                       
-                                       if(leftValue instanceof String){
-                                               if((leftValue.toString()).isEmpty())
-                                                       result = 0;
-                                                else 
-                                                       return FormulaError2.VALUE.getString();
-                                       }
-                                       else if(leftValue instanceof SpreadsheetMatrix) 
-                                               result = leftValue;
-                                       else 
-                                               result = SpreadsheetGraphUtils.asNumber(leftValue);
-                               }
-                               Object otherValue = value.accept(this);
-                               
-                               FormulaError2 err2 = FormulaError2.forObject(otherValue);
-                               if(err2!=null) return err2.getString();
-                               
-                               if(otherValue instanceof Variant){
-                                       Object otherTemp = ((Variant)otherValue).getValue();
-                                       Double otherV = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(otherTemp);
-                                       if(otherV==null) otherValue = otherTemp.toString();
-                                       else otherValue = otherV;
-                               }
-                               
-                               if(otherValue instanceof String){
-                                       if((otherValue.toString()).isEmpty())
-                                               otherValue = 0;
-                                       else 
-                                               return FormulaError2.VALUE.getString();
-                               }
-                               
-                               if(result instanceof SpreadsheetMatrix) {
-                                       result = ((SpreadsheetMatrix)result).pow(otherValue);
-                               } else {
-                                       if(otherValue instanceof SpreadsheetMatrix) {
-                                               throw new IllegalStateException();
-                                       } else {
-                                               Double base = ((Number)result).doubleValue();
-                                               Double exponent = SpreadsheetGraphUtils.asNumber(otherValue);
-                                               if(exponent==0 && base==0)
-                                                       return FormulaError2.NUM.getString();
-                                               if(exponent<0 && base==0)
-                                                       return FormulaError2.DIV0.getString();
-                                               result = Math.pow(base, exponent);
-                                               if(result instanceof Double && Double.isInfinite((Double)result)){
-                                                       return FormulaError2.NUM.getString();
-                                               }
-                                       }
-                               }
-                       }
-               }
-               if(result == null) result = SpreadsheetGraphUtils.asNumber(exp.left.accept(this));
-               return result;
-       }
-
-       @Override
-       public Object visit(AstIdentifier id) {
-               return FormulaError2.NAME.getString();
-               //throw new IllegalStateException();
-       }
-       
-       @Override
-       public Object visit(AstArray array) {
-               SpreadsheetMatrix m = new SpreadsheetMatrix(array.values.size(), 1);
-               for(int i=0;i<array.values.size();i++) {
-                       m.values[i] = array.values.get(i).accept(this);
-               }
-               return m; 
-       }
-       
-       @Override
-       public Object visit(AstNothing array) {
-               return AstNothing.NOTHING;
-       }
-       
-       @Override
-       public Object visit(AstArrayFormulaReference ref) {
-               
-               Range thisRange = SpreadsheetUtils.decodeRange(thisCell.getName());
-               Range arrayRange = SpreadsheetUtils.decodeRange(ref.range);
-               int x = thisRange.startColumn - arrayRange.startColumn;
-               int y = thisRange.startRow - arrayRange.startRow;
-               
-               SpreadsheetMatrix m = (SpreadsheetMatrix)ref.value.accept(this);
-               return m.get(y, x);
-               
-       }
-
-}
index fa629bbc4ecb0aaa938a2c64aa94fc7940858f6a..1d55203ff2da5ac1c0222c2b1bf7a1c4b4681f3b 100644 (file)
@@ -1,6 +1,12 @@
 package org.simantics.spreadsheet.graph;
 
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetEngine;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.SpreadsheetLines;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
 
 public class EvaluateAll implements SpreadsheetVisitor {
        
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelArrayFormula.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelArrayFormula.java
deleted file mode 100644 (file)
index da9dd5f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.binding.Binding;
-
-public class ExcelArrayFormula {
-       
-       public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelArrayFormula.class);
-
-       public String range;
-       public String expression;
-       
-       public ExcelArrayFormula(String range, String expression) {
-               this.range = range;
-               this.expression = expression;
-       }
-       
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelFormula.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/ExcelFormula.java
deleted file mode 100644 (file)
index bad4fd0..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.binding.Binding;
-
-public class ExcelFormula {
-       
-       public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelFormula.class);
-
-       public String expression;
-       
-       public ExcelFormula(String expression) {
-               this.expression = expression;
-       }
-       
-}
index 8b2d9af4f520530f2686ee34dadf6b2415ce4233..24a0a85d0ce15c204e14da3eb7b9ddef85daba48 100644 (file)
@@ -39,12 +39,17 @@ import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.service.XSupport;
 import org.simantics.layer0.Layer0;
 import org.simantics.operation.Layer0X;
-import org.simantics.spreadsheet.graph.SpreadsheetStyle.SpreadsheetStyleBuilder;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
+import org.simantics.spreadsheet.solver.formula.CellValueVisitor;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.spreadsheet.synchronization.ExcelArrayFormula;
+import org.simantics.spreadsheet.synchronization.ExcelFormula;
 import org.simantics.utils.DataContainer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -124,7 +129,7 @@ public class ExcelImport {
                                 graph.claim(sheet, L0.ConsistsOf, L0.PartOf, newCell);
                             }
 
-                            BTree bt = new BTree(graph, SpreadsheetUtils.SPREADSHEET_BTREE_SIZE, SR.Lines, SR.LineNode, L0.PartOf, true);
+                            BTree bt = new BTree(graph, Spreadsheets.SPREADSHEET_BTREE_SIZE, SR.Lines, SR.LineNode, L0.PartOf, true);
                             result.add(bt);
                             Resource lines = bt.rootOfBTree();
 
@@ -172,7 +177,7 @@ public class ExcelImport {
                                     Cell val = row.getCell(i, Row.RETURN_BLANK_AS_NULL);
                                     if(val != null) {
                                        
-                                        String cellName = SpreadsheetUtils.cellName(rowN, i);
+                                        String cellName = Spreadsheets.cellName(rowN, i);
                                         
                                         int ccIndx = val.getColumnIndex();
                                         if(columnWidths.size()<=ccIndx){
@@ -590,7 +595,7 @@ public class ExcelImport {
             SheetFormulaParser p = new SheetFormulaParser(new StringReader("(-(0.2/2)+SQRT((0.2/2)^2-4*((0.2/2)^2-(3*0.17625)/(PI()*4.7))))"));
             AstValue v = p.relation();
             System.err.println("v="+v);
-            SpreadsheetBook book = new SpreadsheetBook();
+            SpreadsheetBook book = new SpreadsheetBook("http:/");
             Object o = v.accept(new CellValueVisitor(SpreadsheetEvaluationEnvironment.getInstance(book), null));
             System.err.println("o="+o);
         }
index 03df2dd0a8eb8f99af62ee7d6cfb31b012dfd660..0f0175bfc86dad3be7ad410242a973a2c9ac080d 100644 (file)
@@ -63,6 +63,8 @@ import org.simantics.spreadsheet.ClientModel.OperationMode;
 import org.simantics.spreadsheet.SheetCommands;
 import org.simantics.spreadsheet.event.model.RemoveCellHandler;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
 import org.simantics.ui.selection.WorkbenchSelectionUtils;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.strings.AlphanumComparator;
index 97290dacbf38b5491df247757179d0ae814749d0..9a7a23703e094507f7ce4d04bf8f69ec15f278f2 100644 (file)
@@ -1,5 +1,12 @@
 package org.simantics.spreadsheet.graph;
 
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetEngine;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.SpreadsheetLines;
+
 public class InvalidateAll implements SpreadsheetVisitor {
        
        public InvalidateAll() {
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/PrintVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/PrintVisitor.java
deleted file mode 100644 (file)
index 1e36a69..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.simantics.spreadsheet.Range;
-import org.simantics.spreadsheet.graph.parser.ast.AstApply;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstArithmeticExpression;
-import org.simantics.spreadsheet.graph.parser.ast.AstArray;
-import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference;
-import org.simantics.spreadsheet.graph.parser.ast.AstBoolean;
-import org.simantics.spreadsheet.graph.parser.ast.AstDouble;
-import org.simantics.spreadsheet.graph.parser.ast.AstFactor;
-import org.simantics.spreadsheet.graph.parser.ast.AstIdentifier;
-import org.simantics.spreadsheet.graph.parser.ast.AstInteger;
-import org.simantics.spreadsheet.graph.parser.ast.AstNothing;
-import org.simantics.spreadsheet.graph.parser.ast.AstNull;
-import org.simantics.spreadsheet.graph.parser.ast.AstRange;
-import org.simantics.spreadsheet.graph.parser.ast.AstRelation;
-import org.simantics.spreadsheet.graph.parser.ast.AstString;
-import org.simantics.spreadsheet.graph.parser.ast.AstTerm;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-import org.simantics.spreadsheet.graph.parser.ast.AstValueVisitor;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
-
-public class PrintVisitor implements AstValueVisitor<String> {
-
-       @Override
-       public String visit(AstBoolean astBoolean) {
-               return "" + astBoolean.value;
-       }
-
-       @Override
-       public String visit(AstDouble astFloat) {
-               return "" + astFloat.value;
-       }
-
-       @Override
-       public String visit(AstInteger astInteger) {
-               return "" + astInteger.value;
-       }
-
-       @Override
-       public String visit(AstNull astNull) {
-               return "AstNull";
-       }
-
-       @Override
-       public String visit(AstString astString) {
-               return "\"" + astString.value + "\"";  
-       }
-
-       @Override
-       public String visit(AstRange astRange) {
-               if(astRange.isCell()) {
-                       return astRange.first;
-               } else {
-                       return astRange.first + ":" + astRange.second;
-               }
-       }
-
-       @Override
-       public String visit(AstArgList astArgList) {
-               StringBuilder b = new StringBuilder();
-               for(int i=0;i<astArgList.values.size();i++) {
-                       if(i > 0) b.append(";");
-                       b.append(astArgList.values.get(i).accept(this));
-               }
-               return b.toString();
-       }
-
-       @Override
-       public String visit(AstApply astApply) {
-               if(astApply.args == null) {
-                       return astApply.value + "()";
-               } else {
-                       return astApply.value + "(" + astApply.args.accept(this) + ")";
-               }
-       }
-
-       @Override
-       public String visit(AstRelation astRelation) {
-
-               StringBuilder b = new StringBuilder();
-               b.append(astRelation.left.accept(this));
-               b.append(astRelation.op.trim());
-               b.append(astRelation.right.accept(this));
-               return b.toString();
-               
-       }
-       
-       @Override
-       public String visit(AstArithmeticExpression exp) {
-               
-               StringBuilder b = new StringBuilder();
-               if(exp.prefix != null) b.append(exp.prefix);
-               
-               b.append(exp.left.accept(this));
-
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       b.append(op);
-                       AstValue value = exp.rightValue(i);
-                       b.append(value.accept(this));
-               }
-               
-               return b.toString();
-               
-       }
-
-       @Override
-       public String visit(AstTerm exp) {
-               
-               StringBuilder b = new StringBuilder();
-               
-               b.append(exp.left.accept(this));
-
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       b.append(op);
-                       AstValue value = exp.rightValue(i);
-                       b.append(value.accept(this));
-               }
-               
-               return b.toString();
-               
-       }
-
-       @Override
-       public String visit(AstFactor exp) {
-               
-               StringBuilder b = new StringBuilder();
-               
-               b.append(exp.left.accept(this));
-
-               for(int i=0;i<exp.rightCount();i++) {
-                       String op = exp.rightOp(i);
-                       b.append(op);
-                       AstValue value = exp.rightValue(i);
-                       b.append(value.accept(this));
-               }
-               
-               return b.toString();
-               
-       }
-
-       @Override
-       public String visit(AstIdentifier id) {
-               return "AstIdentifier";
-       }
-       
-       @Override
-       public String visit(AstArray array) {
-               StringBuilder b = new StringBuilder();
-               for(int i=0;i<array.values.size();i++) {
-                       if(i > 0) b.append(";");
-                       b.append(array.values.get(i).accept(this));
-               }
-               return b.toString();
-       }
-       
-       @Override
-       public String visit(AstNothing array) {
-               return "AstNothing";
-       }
-       
-       @Override
-       public String visit(AstArrayFormulaReference ref) {
-               return "{" + ref.value.accept(this) + "}";
-       }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetBook.java
deleted file mode 100644 (file)
index 88fea35..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-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.Optional;
-import java.util.Set;
-
-import org.simantics.databoard.Bindings;
-import org.simantics.databoard.binding.Binding;
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.db.exception.DatabaseException;
-import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
-import org.simantics.simulator.variable.exceptions.NodeManagerException;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.synchronization.LineNodeUpdater;
-import org.simantics.spreadsheet.graph.synchronization.LineUpdater;
-import org.simantics.spreadsheet.graph.synchronization.NullUpdater;
-import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent;
-import org.simantics.spreadsheet.graph.synchronization.StyleUpdater;
-import org.simantics.structural.synchronization.utils.ComponentFactory;
-import org.simantics.structural.synchronization.utils.MappingBase;
-import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
-import org.simantics.structural.synchronization.utils.ModuleUpdaterFactoryBase;
-import org.simantics.structural.synchronization.utils.Solver;
-import org.simantics.structural.synchronization.utils.SolverNameUtil;
-
-import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
-import it.unimi.dsi.fastutil.longs.AbstractLongList;
-import it.unimi.dsi.fastutil.longs.AbstractLongSet;
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import it.unimi.dsi.fastutil.longs.LongArraySet;
-import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
-
-public class SpreadsheetBook implements StandardNodeManagerSupport<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
-
-       private static final long serialVersionUID = 7417208688311691396L;
-       
-       public Serializable NotAvailableError = new Serializable() {
-               private static final long serialVersionUID = 2535371785498129460L;
-       };
-       
-       public Long2ObjectOpenHashMap<AbstractLongSet> referenceMap = new Long2ObjectOpenHashMap<>();
-       
-       private Int2ObjectArrayMap<SpreadsheetStyle> styles = new Int2ObjectArrayMap<>();
-//     public ObjectArrayList<SpreadsheetStyle> styles = new ObjectArrayList<SpreadsheetStyle>();
-       public ArrayList<SpreadsheetEngine> sheets = new ArrayList<SpreadsheetEngine>();
-       
-       private SpreadsheetMapping mapping;
-       
-       
-       private int idCounter = 1;
-       
-       public SpreadsheetBook() {
-               getNewId(this);
-               mapping = new SpreadsheetMapping(new SheetLineComponent(""));
-       }
-       
-       public Map<Integer, SpreadsheetElement> children = new HashMap<>();
-
-       private boolean iterationEnabled;
-
-       public int getNewId(SpreadsheetElement element) {
-               int result = idCounter++;
-               children.put(result, element);
-               return result; 
-       }
-       
-       public long getEngineIndex(SpreadsheetEngine engine) {
-               for(int i=0;i<sheets.size();i++)
-                       if(sheets.get(i) == engine) return i;
-               throw new IllegalStateException("Did not find sheet " + engine.getName());
-       }
-       
-       public void registerReferences(long cell, AbstractLongList refs) {
-               for(int i=0;i<refs.size();i++) {
-                       long key = refs.getLong(i);
-                       AbstractLongSet set = referenceMap.get(key);
-                       if(set == null) {
-                               set = new LongArraySet();
-                               referenceMap.put(key, set);
-                       }
-                       if(set.size() == 5) {
-                               AbstractLongSet newSet = new LongLinkedOpenHashSet();
-                               newSet.addAll(set);
-                               set = newSet;
-                               referenceMap.put(key, set);
-                       }
-                       set.add(cell);
-               }
-       }
-       
-       @Override
-       public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
-               Object value = getEngineValue(node);
-               if(value instanceof Variant) return Bindings.VARIANT;
-               if(value instanceof String) return Bindings.STRING;
-               if(value instanceof Boolean) return Bindings.BOOLEAN;
-               else return Bindings.VOID;
-               
-       }
-       
-       @Override
-       public Object getEngineValue(SheetNode node) {
-               if(node instanceof SpreadsheetCellContent) {
-                       try {
-                               SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
-                               Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
-                               if(content == null) return Variant.ofInstance("");
-                               if(content instanceof Variant) return content;
-                               else return Variant.ofInstance(content);
-                       } catch (Throwable t) {
-                               t.printStackTrace();
-                               return Variant.ofInstance(t.toString());
-                       }
-               } else if (node instanceof SpreadsheetCellContentExpression) {
-                       SpreadsheetCellContentExpression scce = (SpreadsheetCellContentExpression)node;
-                       if (scce.cell.content instanceof SpreadsheetFormula) {
-                       SpreadsheetFormula formula = (SpreadsheetFormula)scce.cell.content; 
-                       return formula.expression;
-                       } else if (scce.cell.content instanceof SpreadsheetSCLConstant) {
-                           SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) scce.cell.content;
-                           return "=" + sclConstant.expression;
-                       } else {
-                           System.out.println("Broken SpreadsheetCellContentExpression possibly due to overwriting an existing expression with a constant or something else (current content is " + scce.cell.content + ")");
-                           if (scce.cell.content instanceof Variant) {
-                               return scce.cell.content;
-                           } else {
-                               return Variant.ofInstance(scce.cell.content);
-                           }
-                       }
-               } else if (node instanceof SpreadsheetTypeNode) {
-                       SpreadsheetTypeNode stn = (SpreadsheetTypeNode)node;
-                       return stn.uri;
-               } else if (node instanceof SpreadsheetCellStyle) {
-                   int styleId = ((SpreadsheetCellStyle) node).cell.style;
-                   SpreadsheetStyle style = getStyle(styleId);
-                   if (style == null) {
-                       style = SpreadsheetStyle.empty();
-                       if (styleId != style.getStyleId())
-                           new Exception("different style ids!" + styleId + "  " + style.getStyleId()).printStackTrace();
-                       addStyle(style);
-                   }
-                   return style;
-               } else if (node instanceof SpreadsheetCellEditable) {
-                   boolean editable = ((SpreadsheetCellEditable) node).editable();
-                   return editable;
-               }
-               return null;
-       }
-
-       @Override
-       public void setEngineValue(SheetNode node, Object value) {
-       }
-
-       @Override
-       public String getName(SheetNode node) {
-               return node.getName();
-       }
-
-       @Override
-       public Map<String, SheetNode> getChildren(SheetNode node) {
-               return node.getChildren();
-       }
-
-       @Override
-       public Map<String, SheetNode> getProperties(SheetNode node) {
-               return node.getProperties();
-       }
-
-       @Override
-       public String getName() {
-               return "";
-       }
-
-       @Override
-       public Map<String, SpreadsheetEngine> getChildren() {
-               Map<String,SpreadsheetEngine> result = new HashMap<String,SpreadsheetEngine>();
-               for(SpreadsheetEngine engine : sheets)
-                       result.put(engine.getName(), engine);
-               return result;
-       }
-
-       @Override
-       public Map<String, SheetNode> getProperties() {
-               return Collections.emptyMap();
-       }
-       
-       public SpreadsheetCell get(String sheet, int row, int column) {
-               SpreadsheetEngine engine = getEngine(sheet);
-               if(engine == null) return null;
-               SpreadsheetLine line = engine.getLine(row);
-               if(line == null) return null;
-               if(line.cells.size() <= column) return null;
-               return line.cells.get(column);
-       }
-
-       public SpreadsheetCell get(SpreadsheetEngine engine, int row, int column) {
-               SpreadsheetLine line = engine.getLine(row);
-               if(line == null) return null;
-               if(line.cells.size() <= column) return null;
-               return line.cells.get(column);
-       }
-
-       public SpreadsheetEngine getEngine(String sheet) {
-               for(SpreadsheetEngine engine : sheets)
-                       if(sheet.equals(engine.getName())) return engine;
-               return null;
-       }
-
-       @Override
-       public ModuleUpdaterBase<SheetLineComponent> createUpdater(String id) throws DatabaseException {
-               if("http://www.simantics.org/Spreadsheet-1.2/Line".equals(id))
-                       return new LineUpdater(id);
-               else if("http://www.simantics.org/Spreadsheet-1.2/LineNode".equals(id))
-                       return new LineNodeUpdater(id);
-               else if ("http://www.simantics.org/Spreadsheet-1.2/Style".equals(id))
-                   return new StyleUpdater(id);
-               else if("http://www.simantics.org/Spreadsheet-1.2/Lines".equals(id))
-                       return new NullUpdater(id);
-               else if("http://www.simantics.org/Spreadsheet-1.2/Spreadsheet".equals(id))
-                       return new NullUpdater(id);
-               else if("http://www.simantics.org/Spreadsheet-1.2/Book".equals(id))
-                       return new NullUpdater(id);
-               else
-                       throw new IllegalStateException("createUpdater " + id);
-       }
-
-       @Override
-       public SheetLineComponent create(String uid) {
-               return new SheetLineComponent(uid);
-       }
-
-       @Override
-       public String getFreshName(String parentName, String name) {
-               return parentName + "/" + name;
-       }
-
-       @Override
-       public String ensureNameIsVariationOf(String parentName, int id, String name) {
-           if (parentName.isEmpty())
-               return name;
-               return parentName + "/" + name;
-       }
-
-       final static int COMP_ROOT_POS = "COMP_ROOT/".length();
-       
-       @Override
-       public int getId(String name) {
-               
-               if("COMP_ROOT".equals(name)) return 1;
-
-               String path = name.substring(COMP_ROOT_POS);
-               String[] parts = path.split("/");
-               Object o = resolve(parts, 0);
-               if(o instanceof SpreadsheetLines) {
-                       return ((SpreadsheetLines)o).getId();
-               } else if(o instanceof SpreadsheetLine) {
-                       return ((SpreadsheetLine)o).getId();
-               } else if(o instanceof SpreadsheetEngine) {
-                       return ((SpreadsheetEngine)o).getId();
-               } else if (o instanceof SpreadsheetStyle) {
-                   return ((SpreadsheetStyle) o).getId();
-               }
-               
-               throw new IllegalStateException("Resolved object for parts " + Arrays.toString(parts) + " is not the right type! It is " + o);
-               
-       }
-       
-       Object resolve(String[] parts, int index) {
-               String part = parts[index];
-               if (part.startsWith("Style")) {
-                   for (SpreadsheetStyle style : styles.values()) {
-                       if (style.name.equals(part)) {
-                           return style;
-                       }
-                   }
-               }
-               SpreadsheetEngine engine = getEngine(part);
-               if(engine == null) return 0;
-               if(index == parts.length-1) return engine;
-               else return engine.resolve(parts, index+1);
-       }
-
-       @Override
-       public String getName(int id) {
-               if(id == -2) return "http://www.simantics.org/Spreadsheet-1.2/Book";
-               else if(id == -3) return "http://www.simantics.org/Spreadsheet-1.2/Spreadsheet";
-               else if(id == -4) return "http://www.simantics.org/Spreadsheet-1.2/Lines";
-               else if(id == -5)
-                   return "http://www.simantics.org/Spreadsheet-1.2/LineNode";
-               else if (id == -6)
-                   return "http://www.simantics.org/Spreadsheet-1.2/Line";
-               else if(id == -7)
-                   return "http://www.simantics.org/Spreadsheet-1.2/Style";
-               else return "" + id;
-       }
-
-       @Override
-       public int getModuleType(int id) {
-               Serializable s = children.get(id);
-               if(s instanceof SpreadsheetBook) return -2;
-               else if(s instanceof SpreadsheetEngine) return -3;
-               else if(s instanceof SpreadsheetLines) {
-                       if("Lines".equals(((SpreadsheetLines) s).getName()))
-                               return -4;
-                       else
-                               return -5;
-               }
-               else if(s instanceof SpreadsheetLine)
-                   return -6;
-               else if (s instanceof SpreadsheetStyle)
-                   return -7;
-               else throw new IllegalStateException();
-       }
-
-       @Override
-       public void remove(int id) {
-           
-           SpreadsheetElement child = children.get(id);
-           Optional<SpreadsheetElement> parent = child.getParent();
-           
-           if (parent.isPresent()) {
-               parent.get().remove(child);
-               children.remove(id);
-           }
-       }
-
-       @Override
-       public void addSubprocess(String name, String subprocessType) {
-               ensureSubprocess(name);
-       }
-       
-       public <T> T ensureSubprocess(String name) {
-               String[] parts = name.split("/");
-               if(parts.length == 2) {
-                       SpreadsheetEngine engine = getEngine(parts[1]);
-                       if(engine == null) {
-                               engine = new SpreadsheetEngine(this, parts[1]);
-                               sheets.add(engine);
-                       }
-                       return (T)engine;
-               } else if (parts.length > 2) {
-                       SpreadsheetEngine engine = getEngine(parts[1]);
-                       return (T)engine.ensureSubprocess(parts, 2);
-               }
-               throw new IllegalStateException();
-       }
-       
-
-       @Override
-       public void includeSubprocess(String parentName, String subprocessName) {
-               // Nop
-       }
-
-       @Override
-       public <T> T getConcreteSolver() {
-               return (T)this;
-       }
-       
-       @Override
-       public void accept(SpreadsheetVisitor v) {
-               v.visit(this);
-       }
-       
-       //Recursively find all SpreadsheetCells, invalidate them and return them all as a set
-       public Set<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
-               Set<SpreadsheetCell> result = new HashSet<>();
-               result.add(cell);
-               cell.invalidate();
-               long refKey = cell.makeReferenceKey();
-               AbstractLongSet refs = referenceMap.remove(refKey);
-               if(refs == null) return result;
-               for(long ref : refs) {
-                       long sheet = ref >> 40;
-                       long row = (ref >> 20) & 0xFFFFF;
-                       long col = (ref) & 0xFFFFF;
-                       SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col);
-                       result.addAll(invalidate(referer));
-               }
-               return result;
-       }
-       
-       @Deprecated
-       public List<SpreadsheetCell> invalidateShallow(SpreadsheetCell cell) {
-               ArrayList<SpreadsheetCell> result = new ArrayList<>();
-               result.add(cell);
-               cell.invalidate();
-               long refKey = cell.makeReferenceKey();
-               AbstractLongSet refs = referenceMap.remove(refKey);
-               if(refs == null) return result;
-               for(long ref : refs) {
-                       long sheet = ref >> 40;
-                       long row = (ref >> 20) & 0xFFFFF;
-                       long col = (ref) & 0xFFFFF;
-                       SpreadsheetCell referer = get(sheets.get((int)sheet), (int)row, (int)col);
-                       invalidate(referer);
-                       result.add(referer);
-               }
-               return result;
-       }
-
-    public void addStyle(SpreadsheetStyle style) {
-        if (style.name == null) {
-            new Exception("Trying to add style to book without name!!").printStackTrace();
-            return;
-        }
-        style.setSynchronizationId(getNewId(style));
-        styles.put(style.getStyleId(), style);
-    }
-
-    public SpreadsheetStyle getStyle(int styleId) {
-        return styles.get(styleId);
-    }
-
-    public MappingBase<SheetLineComponent> getMapping() {
-        return mapping;
-    }
-
-    @Override
-    public Optional<SpreadsheetElement> getParent() {
-        return Optional.empty();
-    }
-
-    @Override
-    public Collection<SpreadsheetElement> getSpreadsheetChildren() {
-        return children.values();
-    }
-
-    @Override
-    public void remove(SpreadsheetElement child) {
-        // TODO Auto-generated method stub
-        
-    }
-
-       public void setIterationEnabled(boolean value) {
-               this.iterationEnabled = value;
-       }
-       
-       public boolean isIterationEnabled() {
-               return iterationEnabled;
-       }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java
deleted file mode 100644 (file)
index 0ee66cf..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.simantics.spreadsheet.graph.formula.FormulaError2;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
-
-public class SpreadsheetCell implements SpreadsheetElement, SheetNode {
-
-       private static final long serialVersionUID = 6616793596542239339L;
-
-       public static SpreadsheetCell EMPTY;
-       
-       static {
-           EMPTY = new SpreadsheetCell(null, -1);
-           EMPTY.setContent("");
-           EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId());
-       }
-       
-       private boolean inProgress = false;
-       private int iterations = 0;
-       
-       final private SpreadsheetLine line;
-       final private int column;
-       int style;
-       Object content;
-       final private Map<String, SheetNode> properties;
-       
-       public SpreadsheetCell(SpreadsheetLine line, int column) {
-               this.properties = createProperties();
-               this.line = line;
-               this.column = column;
-       }
-
-       //All SpreadsheetCells have these properties - create them when object is created
-       private Map<String, SheetNode> createProperties() {
-           Map<String, SheetNode> p = new HashMap<>();     
-           p.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell));
-           p.put("content", new SpreadsheetCellContent(this));
-        p.put("style", new SpreadsheetCellStyle(this));
-        p.put("editable", new SpreadsheetCellEditable(this));
-        return p;
-       }
-       
-    public boolean hasExpression() {
-               return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; 
-       }
-       
-       public void setContent(Object newContent) {
-//       if(newContent != null) {
-//            if (!(newContent instanceof Serializable)) {
-//                throw new AssertionError("content not instanceof Serializable but it is " + newContent.getClass().getSimpleName());
-//            }
-//        }
-           if (GraphUI.DEBUG)
-               System.out.println("SpreadsheetCell.setContent "+ this + " " + newContent);
-               this.content = newContent;
-       }
-
-       @Override
-       public String getName() {
-               return SpreadsheetUtils.cellName(line.row, column);
-       }
-
-       @Override
-       public Map<?, ?> getChildren() {
-               return Collections.emptyMap();
-       }
-       
-       private static String[] keys = { "typeURI", "content" };
-       
-       @Override
-       public Map<String, SheetNode> getProperties() {
-           if (GraphUI.DEBUG)
-               System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style);
-           return properties; //Return this SpreadsheetCells's properties, rather than a new HashMap
-       }
-       
-       public SpreadsheetBook getBook() {
-               return line.getEngine().getBook();
-       }
-
-       public SpreadsheetEngine getEngine() {
-               return line.getEngine();
-       }
-
-       public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {
-               return evaluate(env, null);
-       }
-
-       public <T> T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) {
-//         System.err.println(getEngine().getName() + ":" + getName() + ": evaluate");
-               if(caller != null)
-                       caller.addReference(makeReferenceKey());
-               if(content instanceof SpreadsheetFormula) {
-                       SpreadsheetFormula f = (SpreadsheetFormula)content;
-                       if(f.result == null) {
-                               CellValueVisitor visitor = new CellValueVisitor(env, this);
-                               AstValue value = ((SpreadsheetFormula)content).value;
-                               if(this.inProgress == true) this.iterations++;
-                               
-                               if(!env.getBook().isIterationEnabled()){
-                                       if(this.inProgress == false){
-                                               this.inProgress = true;
-                                               f.result = value.accept(visitor);
-                                       }
-                                       else f.result = FormulaError2.CIRCULAR_REF.getString();
-                               }
-                               else if(this.iterations<env.iterationLimit){
-                                       this.inProgress = true;
-                                       f.result = value.accept(visitor);
-                               }
-                               else {
-                                       if(f.result==null)
-                                               f.result = 0.0;
-                               }
-                               
-                               env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
-                       }
-                       this.inProgress = false;
-                       this.iterations = 0;
-                       return (T)f.result;
-               } else if (content instanceof SpreadsheetSCLConstant) {
-                   SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
-                   return (T) sclConstant.content;
-               } else {
-                       this.inProgress = false;
-                       return (T)content;
-               }
-       }
-       
-       public long makeReferenceKey() {
-               SpreadsheetBook book = getBook();
-               SpreadsheetEngine engine = getEngine();
-               long engineIndex = book.getEngineIndex(engine);
-               long row = line.row;
-               long col = column;
-               return (engineIndex << 40) + (row << 20) + col; 
-       }
-       
-       public void invalidate() {
-               getEngine().rangeCache = null;
-               if(content instanceof SpreadsheetFormula) {
-                       SpreadsheetFormula f = (SpreadsheetFormula)content;
-                       f.result = null;
-               }
-       }
-
-       @Override
-       public void accept(SpreadsheetVisitor v) {
-               v.visit(this);
-       }
-
-    @Override
-    public Optional<SpreadsheetElement> getParent() {
-        return Optional.of(line);
-    }
-
-    @Override
-    public List<SpreadsheetElement> getSpreadsheetChildren() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public void remove(SpreadsheetElement child) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + column;
-        result = prime * result + ((line == null) ? 0 : line.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        SpreadsheetCell other = (SpreadsheetCell) obj;
-        if (column != other.column)
-            return false;
-        if (line == null) {
-            if (other.line != null)
-                return false;
-        } else if (!line.equals(other.line))
-            return false;
-        return true;
-    }
-
-    public void setStyle(int styleId) {
-        this.style = styleId;
-    }
-
-    public int getStyle() {
-        return style;
-    }
-
-    public Object getContent() {
-        return content;
-    }
-    
-    public static SpreadsheetCell empty(SpreadsheetLine line, int column) {
-        SpreadsheetCell cell =  new SpreadsheetCell(line, column);
-        cell.setContent("");
-        cell.setStyle(SpreadsheetStyle.empty().getStyleId());
-        return cell;
-    }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetEngine.java
deleted file mode 100644 (file)
index 364e926..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.simantics.spreadsheet.Range;
-import org.simantics.spreadsheet.graph.parser.ast.AstRange;
-
-@SuppressWarnings("rawtypes")
-public class SpreadsheetEngine implements SpreadsheetElement, SheetNode {
-
-       private static final long serialVersionUID = -5246063647558595642L;
-       
-       private static final String LINES = "Lines";
-       
-       private final SpreadsheetBook book;
-       private final String name;
-       private final int id;
-
-       public SpreadsheetLines lines;
-       
-       transient public Map<String,Object> rangeCache;
-
-       public Map<String,Object> getRangeCache() {
-               if(rangeCache == null) rangeCache = new HashMap<String,Object>();
-               return rangeCache;
-       }
-       
-       public Object getCachedRange(AstRange range) {
-               if(range.sheetName != null) return null;
-               return getRangeCache().get(range.first + ":" + range.second); 
-       }
-       
-       public void cacheRange(AstRange range, Object value) {
-               if(range.sheetName != null) return;
-               getRangeCache().put(range.first + ":" + range.second, value);
-       }
-
-       public SpreadsheetEngine(SpreadsheetBook book, String name) {
-               this.book = book;
-               this.name = name;
-               this.id = book.getNewId(this);
-               this.lines = new SpreadsheetLines(this, LINES);
-       }
-       
-       public SpreadsheetBook getBook() {
-               return book;
-       }
-       
-       public int getId() {
-               return id;
-       }
-       
-       Object resolve(String[] parts, int index) {
-               
-               String part = parts[index];
-               if(!part.equals(LINES)) return null;
-               
-               if(index == parts.length-1) return lines;
-               
-               return lines.resolve(parts, index+1);
-
-       }
-       
-       @Override
-       public String getName() {
-               return name;
-       }
-       
-       @Override
-       public Map<String, SheetNode> getChildren() {
-               return Collections.singletonMap(LINES, lines);
-       }
-       
-       @Override
-       public Map<String, SheetNode> getProperties() {
-               return Collections.emptyMap();
-       } 
-       
-       public Object ensureSubprocess(String[] path, int index) {
-               
-               String name = path[index];
-               if(!LINES.equals(name)) throw new IllegalStateException();
-               if(index == path.length - 1) return lines;
-               return lines.ensureSubprocess(path, index+1);
-               
-       }
-       
-       public SpreadsheetLine getLine(int row) {
-               assert(lines.nodes.size() == 1);
-               SpreadsheetLines root = lines.nodes.values().iterator().next();
-               return root.getLine(row);
-       }
-
-       @Override
-       public void accept(SpreadsheetVisitor v) {
-               v.visit(this);
-       }
-       
-       public Range actualRange(Range r) {
-               if(r.isFullRows()) {
-                       SpreadsheetLines root = lines.nodes.values().iterator().next();
-                       Range result = new Range(r);
-                       result.startRow = 0;
-                       result.endRow = root.getMaxRow(); 
-                       return result;
-               } else {
-                       return r;
-               }
-       }
-
-    @Override
-    public Optional<SpreadsheetElement> getParent() {
-        return Optional.of(book);
-    }
-
-    @Override
-    public List<SpreadsheetElement> getSpreadsheetChildren() {
-        return Collections.singletonList(lines);
-    }
-
-    @Override
-    public void remove(SpreadsheetElement child) {
-        
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((book == null) ? 0 : book.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        SpreadsheetEngine other = (SpreadsheetEngine) obj;
-        if (book == null) {
-            if (other.book != null)
-                return false;
-        } else if (!book.equals(other.book))
-            return false;
-        if (name == null) {
-            if (other.name != null)
-                return false;
-        } else if (!name.equals(other.name))
-            return false;
-        return true;
-    }
-       
-       
-}
\ No newline at end of file
index 032acfcfce722809848b8fceeeac10bb9bd19800..976f2aa07c57ae0dfac018b3507c3ffad4b3a03c 100644 (file)
@@ -23,28 +23,42 @@ import org.simantics.datatypes.utils.BTree;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.BinaryRead;
 import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.UnaryRead;
 import org.simantics.db.common.utils.LiteralFileUtil;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ServiceException;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
+import org.simantics.db.procedure.Listener;
 import org.simantics.db.service.ClusteringSupport;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.runtime.tuple.Tuple2;
 import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.spreadsheet.ExternalRef;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetEngine;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.structural.synchronization.client.Synchronizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.iterator.TObjectIntIterator;
 import gnu.trove.map.hash.TObjectIntHashMap;
 
 public class SpreadsheetGraphUtils {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(SpreadsheetGraphUtils.class);
+
     public static File extractInitialCondition(ReadGraph graph, Resource ic) throws DatabaseException, IOException {
 
        SpreadsheetResource SR = SpreadsheetResource.getInstance(graph);
@@ -218,7 +232,7 @@ public class SpreadsheetGraphUtils {
        SpreadsheetEngine engine = book.getEngine(sheetName);
        if(engine == null) return null;
        
-       Range r = SpreadsheetUtils.decodeCellAbsolute(cellName);
+       Range r = Spreadsheets.decodeCellAbsolute(cellName);
        SpreadsheetLine line = engine.getLine(r.startRow);
        if(line == null) return null;
        
@@ -233,200 +247,6 @@ public class SpreadsheetGraphUtils {
     }
 
     
-    public static boolean asBoolean(Object object) {
-       if(object instanceof Boolean) return (Boolean)object;
-       else if(object instanceof Number) return ((Number)object).doubleValue() != 0;
-       else if(object instanceof Variant) return asBoolean(((Variant)object).getValue());
-       else if(object instanceof String) {
-               Double d = asDoubleWhereEmptyStringIsZero((String)object);
-               if(d==null) return false;
-               else return d != 0;
-       }
-       return false;
-    }
-    
-    public static String asString(Object object) {
-       if(object == null) return "";
-       if(object instanceof String) return (String)object;
-       if(object instanceof Number) {
-               double dVal = ((Number)object).doubleValue();
-               if(dVal == Math.floor(dVal)){
-                       return ""+((Number)object).intValue();
-               } else {
-                       return object.toString();
-               }
-       }
-       else if(object instanceof Variant) {
-               Object o = ((Variant) object).getValue();
-               if(o instanceof String) return (String)o;
-               else if(o instanceof Number) asString((Number)o);
-               else return o.toString();
-       }
-       return object.toString();
-    }
-    
-    public static Double asDoubleWhereEmptyStringIsZero(Object object){
-       if(object instanceof Number)
-               return ((Number)object).doubleValue();
-       else if(object instanceof String) {
-               try {
-                       if(((String)object).isEmpty())
-                               return 0.0;
-                       return Double.parseDouble((String)object);
-                       } catch (NumberFormatException e) {
-                               return null;
-                       }
-       } else if(object instanceof Variant) {
-               Object o = ((Variant) object).getValue();
-               return asDoubleWhereEmptyStringIsZero(o);
-       } else if (SpreadsheetCell.EMPTY == object) {
-               return null;
-       }
-       return null;
-    }
-    
-    public static double asNumber(Object object) {
-       if(object instanceof Number) {
-               return ((Number)object).doubleValue();
-       } else if(object instanceof String) {
-               try {
-                       String str = (String)object;
-                       if(str.isEmpty()) return 0;
-                       return Double.parseDouble((String)object);
-                       } catch (NumberFormatException e) {
-                       return 0;
-                       }
-       } else if(object instanceof Variant) {
-               Object o = ((Variant) object).getValue();
-               return asNumber(o);
-       } else if (SpreadsheetCell.EMPTY == object) {
-               return 0.0;
-       }
-               
-       return 0.0;
-       
-    }
-    
-    public static Number asValidNumber(Object object) {
-       if(object instanceof Number) {
-               return (Number)object;
-       } else if(object instanceof String) {
-               try {
-                       return Double.parseDouble((String)object);
-                       } catch (NumberFormatException e) {
-                       return null;
-                       }
-       } else if(object instanceof Variant) {
-               Object o = ((Variant) object).getValue();
-               return asNumber(o);
-       } else if (SpreadsheetCell.EMPTY == object) {
-               return null;
-       }
-               
-       return null;
-       
-    }
-    
-    public static boolean matchCriteria(Object value, Object criteria) {
-       if(value==null || criteria==null) return false;
-       
-       if(value instanceof Variant){
-               Double dVal = asDoubleWhereEmptyStringIsZero(value);
-               if(dVal==null) value = ((Variant)value).getValue();
-               else value = dVal;
-       }
-       if(criteria instanceof Variant){
-               Double dVal = asDoubleWhereEmptyStringIsZero(criteria);
-               if(dVal==null) criteria = ((Variant)criteria).getValue();
-               else criteria = dVal;
-       }
-       
-       if(criteria instanceof Number && value instanceof Number) {
-               Number nc = (asNumber(criteria));
-               Number nv = (asNumber(value));
-               return nc.equals(nv);
-       }
-       if(criteria instanceof String){
-               boolean nums = false;
-               Object valueObj = null;
-                       if(value instanceof Number){
-                               valueObj = ((Number)value).doubleValue();
-                               nums = true;
-                       }
-                       else valueObj = value.toString();
-                       
-               String sc = criteria.toString();
-                       if(sc.length() >= 3){
-                               String oper = sc.substring(0, 2);
-                               String criteriaStr = sc.substring(2);
-                               Double criteriaNum = null;
-                               try {
-                                       criteriaNum = Double.parseDouble(criteriaStr);
-                                       if(oper.equals("<>")){
-                                               if(!nums) return true;
-                                       }
-                                       else if(!nums) return false;
-                                       nums = true;
-                               } catch (NumberFormatException e){
-                                       if(oper.equals("<>")){
-                                               if(nums) return true;
-                                       }
-                                       else if(nums) return false;
-                                       nums = false;
-                               }
-                               
-                               if(oper.equals(">=")){
-                                       if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) >= 0 ;
-                                       else return ((Number)valueObj).doubleValue() >= criteriaNum;
-                               } else if(oper.equals("<=")){
-                                       if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) <= 0 ;
-                                       else return ((Number)valueObj).doubleValue() <= criteriaNum;
-                               } else if(oper.equals("<>")){
-                                       if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) != 0 ;
-                                       else return ((Number)valueObj).doubleValue() != criteriaNum;
-                               }
-                       }
-               if(sc.length() >= 2){
-                       String oper = sc.substring(0, 1);
-                       String criteriaStr = sc.substring(1);
-                       Double criteriaNum = null;
-                       
-                       try {
-                                       criteriaNum = Double.parseDouble(criteriaStr);
-                                       if(!nums) return false;
-                                       nums = true;
-                               } catch (NumberFormatException e){
-                                       if(nums) return false;
-                                       nums = false;
-                               }
-                       if(oper.equals("<")){
-                               if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) < 0;
-                               else return ((Number)valueObj).doubleValue() < criteriaNum;
-                       } else if(oper.equals(">")){
-                               if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) > 0;
-                               else return ((Number)valueObj).doubleValue() > criteriaNum;
-                       } else if(oper.equals("=")){
-                               if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) == 0;
-                               else return ((Number)valueObj).doubleValue() == criteriaNum;
-                       }
-               }
-               return sc.equals(valueObj);
-       }
-       else if (criteria instanceof Number){
-               return false;
-       }
-       throw new IllegalStateException();
-    }
-
-    public static boolean excelEquals(Object left, Object right) {
-       if(left instanceof String) {
-               if(right instanceof String) {
-                       return ((String) left).toLowerCase().equals(((String) right).toLowerCase());
-               }
-       }
-       return left.equals(right);
-    }
-    
 
     public static List<Variable> possibleConfigurationCellVariables(ReadGraph graph, Variable sheet, Range range) throws DatabaseException {
         List<Variable> rowVariables = possibleConfigurationLineVariables(graph, sheet, range);
@@ -521,7 +341,7 @@ public class SpreadsheetGraphUtils {
     
     private static boolean variableInRange(ReadGraph graph, Variable child, Range range) throws DatabaseException {
         String name = child.getName(graph);
-        Range childRange = SpreadsheetUtils.decodeCellAbsolute(name);
+        Range childRange = Spreadsheets.decodeCellAbsolute(name);
 //        System.out.print(" and range " + childRange);
         if (childRange != null && range.contains(childRange)) {
 //             System.out.println(" => range.contains(childRange) = true");
@@ -566,7 +386,7 @@ public class SpreadsheetGraphUtils {
             for (int rowNumber = range.startRow; rowNumber <= range.endRow; rowNumber++) {
                 Variable row = rowIterator.next();
                 for (int colNumber = range.startColumn; colNumber <= range.endColumn; colNumber++) {
-                    String location = SpreadsheetUtils.cellName(rowNumber, colNumber);
+                    String location = Spreadsheets.cellName(rowNumber, colNumber);
                     defaultCreateCell(graph, row, location, new Variant(Bindings.STRING, ""));
                 }
             }
@@ -670,5 +490,104 @@ public class SpreadsheetGraphUtils {
         SpreadsheetGraphUtils.saveInitialCondition(graph, run, root, "Initial");
         return run;
     }
+    
+    public static Variant extRefVariable(ReadGraph graph, Variable var) throws DatabaseException {
+        System.err.println("extRefVariable " + var.getURI(graph));
+        return new Variant(Bindings.VOID, new ExternalRefVariable(graph, var));
+    }
+    
+    static class ExternalRefVariable implements ExternalRef {
+
+        final private String uri;
+        
+        public ExternalRefVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+            this.uri = variable.getURI(graph);
+        }
+        
+        @Override
+        public void listen(Object context, ExternalRefListener listener) {
+            System.err.println("listen " + listener);
+            Simantics.getSession().asyncRequest(new UnaryRead<String, Variant>(uri) {
+
+                @Override
+                public Variant perform(ReadGraph graph) throws DatabaseException {
+                    Variable variable = Variables.getVariable(graph, parameter);
+                    System.err.println("ExternalRef value for " + variable.getURI(graph));
+                    return variable.getVariantValue(graph);
+                }
+                
+            }, new Listener<Variant>() {
+
+                @Override
+                public void execute(Variant result) {
+                    System.err.println("execute " + result);
+                    listener.newValue(result);
+                }
+
+                @Override
+                public void exception(Throwable t) {
+                    LOGGER.error("Error while evaluating variable value", t);
+                }
+
+                @Override
+                public boolean isDisposed() {
+                    return listener.isDisposed();
+                }
+                
+            });
+        }
+        
+    }
 
+    public static Variant extRefActiveVariable(ReadGraph graph, Variable var) throws DatabaseException {
+        System.err.println("extRefActiveVariable " + var.getURI(graph));
+        return new Variant(Bindings.VOID, new ExternalRefActiveVariable(graph, var));
+    }
+    
+    static class ExternalRefActiveVariable implements ExternalRef {
+
+        final private String uri;
+        
+        public ExternalRefActiveVariable(ReadGraph graph, Variable variable) throws DatabaseException {
+            this.uri = variable.getURI(graph);
+        }
+        
+        @Override
+        public void listen(Object context, ExternalRefListener listener) {
+            System.err.println("listen " + context + " " + listener);
+            Simantics.getSession().asyncRequest(new BinaryRead<String, String, Variant>((String)context, uri) {
+
+                @Override
+                public Variant perform(ReadGraph graph) throws DatabaseException {
+                    Variable contextVariable = Variables.getVariable(graph, parameter);
+                    System.err.println("extref1 " + contextVariable.getURI(graph));
+                    Variable configVariable = Variables.getVariable(graph, parameter2);
+                    System.err.println("extref2 " + configVariable.getURI(graph));
+                    Variable activeVariable = Variables.switchPossibleContext(graph, configVariable, contextVariable.getRepresents(graph));
+                    System.err.println("ExternalRef value for " + activeVariable.getURI(graph));
+                    return activeVariable.getVariantValue(graph);
+                }
+            }, new Listener<Variant>() {
+
+                @Override
+                public void execute(Variant result) {
+                    System.err.println("execute " + result);
+                    listener.newValue(result);
+                }
+
+                @Override
+                public void exception(Throwable t) {
+                    LOGGER.error("Error while evaluating variable value", t);
+                }
+
+                @Override
+                public boolean isDisposed() {
+                    return listener.isDisposed();
+                }
+                
+            });
+        }
+        
+    }
+    
 }
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLine.java
deleted file mode 100644 (file)
index ef6937f..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.simantics.spreadsheet.Range;
-import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
-
-import it.unimi.dsi.fastutil.objects.ObjectArrayList;
-
-public class SpreadsheetLine implements SpreadsheetElement<SpreadsheetCell, SpreadsheetLines>, SheetNode {
-
-       private static final long serialVersionUID = -304574098117404663L;
-       
-       final private SpreadsheetLines parent;
-       final public int row;
-       int id;
-       
-       public ObjectArrayList<SpreadsheetCell> cells = new ObjectArrayList<>();
-       
-       public SpreadsheetLine(SpreadsheetLines parent, int row) {
-               this.parent = parent;
-               this.row = row;
-               this.id = getEngine().getBook().getNewId(this);
-//             getEngine().registerRow(row, this);
-       }
-       
-       public int getId() {
-               return id;
-       }
-       
-       public SpreadsheetEngine getEngine() {
-//             if(parent instanceof SpreadsheetEngine)
-//                 return (SpreadsheetEngine)parent;
-               return ((SpreadsheetLines)parent).getEngine();
-       }
-
-       @Override
-       public String getName() {
-               return "Row"+row;
-       }
-
-       @Override
-       public Map getChildren() {
-               String rowName = ""+row;
-               Map<String,SpreadsheetCell> result = new HashMap<>();
-               for(int i=0;i<cells.size();i++) {
-                       SpreadsheetCell cell = cells.get(i);
-                       if(SpreadsheetCell.EMPTY == cell) continue;
-                       String name = "Row"+SpreadsheetUtils.columnName(i) + rowName;
-                       result.put(name, cell);
-               }
-               return result;
-       }
-
-       @Override
-       public Map getProperties() {
-               return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Line));
-       }
-       
-       Object resolve(String[] parts, int index) {
-               
-               if(index == parts.length) return this;
-               
-               Range r = SpreadsheetUtils.decodeCellAbsolute(parts[index]);
-               return cells.get(r.startColumn);
-               
-       }
-
-       public void accept(SpreadsheetVisitor v) {
-               v.visit(this);
-       }
-       
-       public String getPath() {
-               return ((SpreadsheetLines)parent).getPath() + "/" + getName();
-       }
-
-    @Override
-    public Optional<SpreadsheetLines> getParent() {
-        return Optional.of(parent);
-    }
-
-    @Override
-    public List<SpreadsheetCell> getSpreadsheetChildren() {
-        return cells;
-    }
-
-    @Override
-    public void remove(SpreadsheetCell child) {
-        
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
-        result = prime * result + row;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        SpreadsheetLine other = (SpreadsheetLine) obj;
-        if (parent == null) {
-            if (other.parent != null)
-                return false;
-        } else if (!parent.equals(other.parent))
-            return false;
-        if (row != other.row)
-            return false;
-        return true;
-    }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetLines.java
deleted file mode 100644 (file)
index b3d6f09..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Optional;
-
-import org.simantics.spreadsheet.resource.SpreadsheetResource;
-
-import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
-
-public class SpreadsheetLines implements SpreadsheetElement<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
-
-       private static final long serialVersionUID = -3615335969248723486L;
-       
-       private final int id;
-       private SpreadsheetEngine parent;
-       private String name;
-       public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
-       public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
-       public int[] keys;
-
-       public SpreadsheetLines(SpreadsheetEngine parent, String name) {
-               this.parent = parent;
-               this.name = name;
-               id = getEngine().getBook().getNewId(this);
-       }
-
-       public SpreadsheetEngine getEngine() {
-               return parent;
-       }
-
-       public int getId() {
-               return id;
-       }
-       
-       @Override
-       public String getName() {
-               return name;
-       }
-
-       @Override
-       public Map getChildren() {
-               Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap();
-               result.putAll(nodes);
-               result.putAll(lines);
-               return result;
-       }
-
-       @Override
-       public Map getProperties() {
-               return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Lines));
-       } 
-       
-       Object resolve(String[] parts, int index) {
-               
-               String part = parts[index];
-               if(part.charAt(0) == 'R') {
-                       int indx = Integer.parseInt(part.substring(3));
-                       SpreadsheetLine line = lines.get(-indx);
-                       if(line != null) {
-                               if(index == parts.length-1) return line;
-                               else return line.resolve(parts, index+1);
-                       }
-               } else {
-                       int indx = Integer.parseInt(part);
-                       SpreadsheetLines node = nodes.get(indx);
-                       if(node != null) {
-                               if(index == parts.length-1) return node;
-                               else return node.resolve(parts, index+1);
-                       }
-               }
-               
-               return null;
-
-       }
-
-       public Object ensureSubprocess(String[] path, int index) {
-               
-               String name = path[index];
-
-               int i = Integer.parseInt(name);
-               SpreadsheetLines line = nodes.get(i);
-               if(line == null) {
-                       line = new SpreadsheetLines(parent, "" + i);
-                       nodes.put(i, line);
-               }
-
-               if(index == path.length - 1) {
-                       return line;
-               } else {
-                       return line.ensureSubprocess(path, index+1);
-               }
-               
-       }
-       
-       public void setKeys(int[] keys) {
-               this.keys = keys;
-       }
-       
-       @Override
-       public void accept(SpreadsheetVisitor v) {
-               v.visit(this);
-       }
-
-       public String getPath() {
-                       return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName();
-       }
-
-       private int getKey(int index) {
-               return keys[2*index+1];
-       }
-
-       private int getChild(int index) {
-               return keys[2*index];
-       }
-
-       /*
-        *  [(child,key),...,key)
-        * 
-        */
-       public SpreadsheetLine getLine(int k) {
-               
-               int i=1;
-               int n = (keys.length - 1) / 2;
-               
-               while(i <= n && k > getKey(i-1)) i++;
-               
-               if(i <= n && k == getKey(i-1)) {
-                       return lines.get(-k);
-               }
-
-               int nodeName = getChild(i-1);
-               SpreadsheetLines node = nodes.get(nodeName);
-               if(node == null) return null;
-               return node.getLine(k);
-               
-       }
-       
-       public int getMaxRow() {
-               // if keys == null then this is the root of BTree which has only one child 
-               if (keys == null) {
-                       int maxRow = 0;
-                       for (SpreadsheetLines node : nodes.values()) {
-                               int row = node.getMaxRow();
-                               if (row > maxRow)
-                                       maxRow = row;
-                       }
-                       return maxRow;
-               }
-               int largestChild = keys[keys.length-1]; 
-               if(largestChild > 0) {
-                       SpreadsheetLines child = nodes.get(largestChild);
-                       return child.getMaxRow();
-               } else {
-                       return keys[keys.length-2];
-               }
-       }
-
-    @Override
-    public Optional<SpreadsheetEngine> getParent() {
-        return Optional.of(parent);
-    }
-
-    @Override
-    public Collection<SpreadsheetLine> getSpreadsheetChildren() {
-        return lines.values();
-    }
-
-    @Override
-    public void remove(SpreadsheetLine child) {
-        lines.remove(-child.row);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        SpreadsheetLines other = (SpreadsheetLines) obj;
-        if (name == null) {
-            if (other.name != null)
-                return false;
-        } else if (!name.equals(other.name))
-            return false;
-        if (parent == null) {
-            if (other.parent != null)
-                return false;
-        } else if (!parent.equals(other.parent))
-            return false;
-        return true;
-    }
-       
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMapping.java
deleted file mode 100644 (file)
index 64079d2..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.io.Serializable;
-
-import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent;
-import org.simantics.structural.synchronization.utils.ComponentFactory;
-import org.simantics.structural.synchronization.utils.MappingBase;
-import org.simantics.structural.synchronization.utils.Solver;
-import org.simantics.structural.synchronization.utils.StateUndoContextBase;
-
-public class SpreadsheetMapping extends MappingBase<SheetLineComponent> implements Serializable {
-       
-    private static final long serialVersionUID = -7556699663877911393L;
-    
-    final SheetLineComponent configuration;
-       
-       public SpreadsheetMapping(SheetLineComponent configuration) {
-           super(configuration, true);
-               this.configuration = configuration;
-       }
-
-       @Override
-       public SheetLineComponent getConfiguration() {
-               return configuration;
-       }
-
-       @Override
-       public StateUndoContextBase createUndoContext() {
-               return new StateUndoContextBase() {
-                       
-                       @Override
-                       public void saveState(Solver solver, int componentId, String uid) {
-                       }
-                       
-                       @Override
-                       public boolean loadState(Solver solver, int componentId, String uid) {
-                               return false;
-                       }
-               };
-       }
-
-       @Override
-       public ComponentFactory<SheetLineComponent> createComponentFactory() {
-               return new ComponentFactory<SheetLineComponent>() {
-
-                       @Override
-                       public SheetLineComponent create(String uid) {
-                               return new SheetLineComponent(uid);
-                       }
-                       
-               };
-       }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetMatrix.java
deleted file mode 100644 (file)
index b9a4f95..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.io.Serializable;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.formula.FormulaError2;
-
-public class SpreadsheetMatrix implements Serializable {
-
-       private static final long serialVersionUID = 5729700370527844640L;
-       
-       private int w;
-       private int h;
-       public Object[] values;
-       
-       public SpreadsheetMatrix(int w, int h) {
-               this.w = w;
-               this.h = h;
-               this.values = new Object[w*h];
-       }
-       
-       public Object get(int row, int column) {
-               return values[w*row+column];
-       }
-       
-       public void set(int row, int column, Object value) {
-               values[w*row+column] = value;
-       }
-
-       public int getWidth() {
-               return w;
-       }
-
-       public int getHeight() {
-               return h;
-       }
-       
-       public double sum() {
-               double result = 0;
-               for(int i=0;i<values.length;i++) {
-                       Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
-                       if(n != null) result += n.doubleValue();
-               }
-               return result;
-       }
-       
-       public Object sumWithFormulaError(){
-               Double result = 0.0;
-               for(int i = 0; i < values.length; i++){
-                       Object obj = values[i];
-                       if(obj != null){
-                               FormulaError2 error = FormulaError2.forObject(obj);
-                if(error!=null) return error.getString();
-                    
-                Number n = SpreadsheetGraphUtils.asValidNumber(obj);
-                               if(n != null) result += n.doubleValue();
-                       }
-               }
-               return result;
-       }
-
-       public double average() {
-               double result = 0;
-               double count = 0;
-               for(int i=0;i<values.length;i++) {
-                       Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
-                       if(n != null) {
-                               result += n.doubleValue();
-                               count++;
-                       }
-               }
-               if(count == 0) return result;
-               return result / count;
-       }
-       
-       public double countOfActualDoubleValues(){
-               double count = 0.0;
-               for(int i = 0; i < values.length; i++){
-                       Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
-                       if(n!=null) count++;
-               }
-               return count;
-       }
-       
-       public Object productWithFormulaError(){
-               Double result = 1.0;
-               boolean atLeastOne = false;
-               for(int i = 0; i < values.length; i++){
-                       Object obj = values[i];
-                       if(obj != null){
-                               FormulaError2 error = FormulaError2.forObject(obj);
-                       if(error!=null) return error.getString();
-                       
-                               Number n = SpreadsheetGraphUtils.asValidNumber(values[i]);
-                               if(n != null) {
-                                       double dval = n.doubleValue();
-                                       if(dval<=0) return FormulaError2.NUM.getString();
-                                       result = result*dval;
-                                       atLeastOne = true;
-                               }
-                       }
-               }
-               if(atLeastOne) return result;
-               else return 0.0;
-       }
-       
-       public SpreadsheetMatrix pow(Object exponent_) {
-               if(exponent_ instanceof SpreadsheetMatrix) {
-                       SpreadsheetMatrix exponent = (SpreadsheetMatrix)exponent_;
-                       SpreadsheetMatrix result = new SpreadsheetMatrix(exponent.w, h);
-                       for(int i=0;i<h;i++) {
-                               for(int j=0;j<exponent.w;j++) {
-                                       result.set(i,j, Math.pow(SpreadsheetGraphUtils.asNumber(get(i, 0)),
-                                                       SpreadsheetGraphUtils.asNumber(exponent.get(0, j))));
-                               }
-                       }
-                       return result;
-               } else {
-                       double n = SpreadsheetGraphUtils.asNumber(exponent_);
-                       SpreadsheetMatrix result = new SpreadsheetMatrix(w, h);
-                       for(int i=0;i<result.values.length;i++) {
-                               result.values[i] = Math.pow(SpreadsheetGraphUtils.asNumber(values[i]), n);
-                       }
-                       return result;
-               }
-       }
-       
-       
-}
\ No newline at end of file
index caa6dc23f4602d10589187018c99f66a9f1f9a24..b86544c0dfed7a7e42328334622a84d21c568dbb 100644 (file)
@@ -1,22 +1,45 @@
 package org.simantics.spreadsheet.graph;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
 import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.layer0.Layer0;
-import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.db.StandardVariableNodeManager;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.spreadsheet.SpreadsheetCellStyle;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetBook.SpreadsheetBookListener;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
+import org.simantics.spreadsheet.solver.SpreadsheetCellContentExpression;
+import org.simantics.spreadsheet.solver.SpreadsheetCellEditable;
+import org.simantics.spreadsheet.solver.SpreadsheetFormula;
+import org.simantics.spreadsheet.solver.SpreadsheetTypeNode;
 import org.simantics.structural.stubs.StructuralResource2;
 
 @SuppressWarnings("rawtypes")
-public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, SpreadsheetBook> {
+public class SpreadsheetNodeManager extends StandardVariableNodeManager<SheetNode, SpreadsheetBook> {
 
     public SpreadsheetNodeManager(SpreadsheetRealm realm) {
         super(realm, realm.getEngine());
+        realm.getEngine().registerListener(new SpreadsheetBookListener() {
+            
+            @Override
+            public void cellsChanged(Collection<SpreadsheetCell> cells) {
+                for(SpreadsheetCell cell : cells) {
+                    System.err.println("Modification in cell " + cell);
+                    refreshVariable(new SpreadsheetCellContent(cell));
+                    refreshVariable(new SpreadsheetCellContentExpression(cell));
+                }
+            }
+        });
     }
 
     static final Set<String> COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component);
@@ -52,6 +75,12 @@ public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, Sprea
     public void setValue(SheetNode node, Object value, Binding binding) throws NodeManagerException {
        Set<SheetNode> dirtyNodeContents = findDirtyNodeContents(node);
        super.setValueAndFireSelectedListeners(node, value, binding, dirtyNodeContents);
+       if(value instanceof SpreadsheetFormula) {
+           SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
+           SpreadsheetCellContentExpression scce = new SpreadsheetCellContentExpression(scc.cell);
+           // We need to also refresh the expression variable in this case
+           refreshVariable(scce);
+       }
     }
     
     //Find the cells that are used by this cell and their SpreadsheetContents, so that they can be marked as dirty later
@@ -78,4 +107,18 @@ public class SpreadsheetNodeManager extends StandardNodeManager<SheetNode, Sprea
        
        return dirtyNodeContents;
     }
+    
+    
+    @Override
+    protected Variant getEngineVariantOrCached(SheetNode node) throws NodeManagerException {
+        Variant variant = valueCache.get(node);
+        if(variant == null) {
+            Object value = realm.getEngine().getEngineValue(node);
+            Binding binding = realm.getEngine().getEngineBinding(node);
+            variant = new Variant(binding, value);
+            valueCache.put(node, variant);
+        }
+        return variant;
+    }
+    
 }
index 5ec73b1e5729ddea5eaa870c59c052a9a929308e..8812c847de0dc26130d66c76d7301fa0118d5114 100644 (file)
@@ -2,6 +2,8 @@ package org.simantics.spreadsheet.graph;
 
 import org.simantics.simulator.toolkit.StandardNodeManager;
 import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index 8bb3a9b9b34a5b6cb00cff5c114363413ea6fa47..af5e36d369f9fa738cd582a965e738af5fd48014 100644 (file)
@@ -1,6 +1,6 @@
 package org.simantics.spreadsheet.graph;
 
-import org.simantics.spreadsheet.graph.synchronization.SheetLineComponent;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
 import org.simantics.structural.synchronization.utils.ReferenceResolverBase;
 import org.simantics.structural.synchronization.utils.Solver;
 import org.slf4j.Logger;
index ec8935f285ced8713f9614c9fca87f6ecdce9329..936bee76e55db2033edbdb60336d6d89ba3a88f3 100644 (file)
@@ -20,9 +20,11 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.simulator.toolkit.StandardRealm;
 import org.simantics.simulator.toolkit.db.StandardVariableSessionManager;
-import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
 import org.simantics.spreadsheet.graph.synchronization.SpreadsheetSynchronizationEventHandler;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
 import org.simantics.structural.synchronization.client.Synchronizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -136,7 +138,7 @@ public class SpreadsheetSessionManager extends StandardVariableSessionManager<Sh
                 return ic;
         }
 
-        SpreadsheetBook book = new SpreadsheetBook();
+        SpreadsheetBook book = new SpreadsheetBook(context.getURI(graph));
         
         Variable base = ProxyVariables.proxyVariableBase(graph, run);
         Resource bookResource = base.getRepresents(graph);
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetTypeNode.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetTypeNode.java
deleted file mode 100644 (file)
index b982f19..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-import java.util.Collections;
-import java.util.Map;
-
-public class SpreadsheetTypeNode implements SheetNode {
-
-       public final String uri;
-       
-       public SpreadsheetTypeNode(String uri) {
-               this.uri = uri;
-       }
-       
-       @Override
-       public String getName() {
-               return "typeURI";
-       }
-
-       @Override
-       public Map getChildren() {
-               return Collections.emptyMap();
-       }
-
-       @Override
-       public Map getProperties() {
-               return Collections.emptyMap();
-       }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitable.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitable.java
deleted file mode 100644 (file)
index 192c7e2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-public interface SpreadsheetVisitable {
-       void accept(SpreadsheetVisitor v);
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitor.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetVisitor.java
deleted file mode 100644 (file)
index ff11703..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.simantics.spreadsheet.graph;
-
-public interface SpreadsheetVisitor {
-
-       void visit(SpreadsheetBook book);
-       void visit(SpreadsheetEngine engine);
-       void visit(SpreadsheetLines node);
-       void visit(SpreadsheetLine line);
-       void visit(SpreadsheetCell cell);
-
-}
index 22695e52d7f4781c2ac88c1628209707b450808c..8650fc8f91fdc8e87dd205f1dd34e6fa10a7183e 100644 (file)
@@ -10,9 +10,9 @@ import org.simantics.db.layer0.variable.ConstantChildVariable;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.cell.VariableCellEditor;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 public class DoubleArrayCellVariable extends ConstantChildVariable {
 
@@ -38,8 +38,8 @@ public class DoubleArrayCellVariable extends ConstantChildVariable {
                                        if(baseLocation == null) return;
                                        String editLocation = cell.getPossiblePropertyValue(graph, Variables.NAME);
                                        
-                                       Range baseRange = SpreadsheetUtils.decodeCellAbsolute(baseLocation);
-                                       Range editRange = SpreadsheetUtils.decodeCellAbsolute(editLocation);
+                                       Range baseRange = Spreadsheets.decodeCellAbsolute(baseLocation);
+                                       Range editRange = Spreadsheets.decodeCellAbsolute(editLocation);
                                        
                                        int x = editRange.startColumn - baseRange.startColumn;
                                        int y = editRange.startRow - baseRange.startRow;
index 896fd6602cdaa39ff7721639b9a39d7765555d29..a6db85a5e45db34cfe8f9b74a4bf64460ded52e0 100644 (file)
@@ -5,7 +5,6 @@ import java.util.Collection;
 import java.util.Collections;
 
 import org.simantics.databoard.Bindings;
-import org.simantics.databoard.Datatypes;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.db.ReadGraph;
@@ -16,8 +15,8 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.VariableFactory;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.spreadsheet.SheetVariables;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.utils.datastructures.datatype.RGBInt8;
 
 public class DoubleArrayCells implements VariableFactory {
@@ -49,7 +48,7 @@ public class DoubleArrayCells implements VariableFactory {
                for(int offset=0,i=0;i<rows;i++) {
                        for(int j=0;j<width;j++) {
                                double value = data[offset++];
-                               String valueLocation = SpreadsheetUtils.offset(location, i, j);
+                               String valueLocation = Spreadsheets.offset(location, i, j);
                                result.add(new DoubleArrayCellVariable(variable, valueLocation, propertyNames, bindings, new Object[] { Variant.ofInstance(value), fore, back, configuration, String.valueOf(value), false }));
                        }
                }
index 0244d5c07949fc897b01f9fc37f7ddf3dbe675a1..f3d8c1c2bbe961e7c774e04b24d5b64dfc40e544 100644 (file)
@@ -15,8 +15,8 @@ import org.simantics.db.layer0.variable.Variables;
 import org.simantics.layer0.Layer0;
 import org.simantics.spreadsheet.Range;
 import org.simantics.spreadsheet.SheetVariables;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.matrix.VariantMatrix;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 public class SpreadsheetVariable extends ExtendedGraphChildVariable {
 
@@ -90,13 +90,13 @@ public class SpreadsheetVariable extends ExtendedGraphChildVariable {
        @Override
        public Variable getPossibleSpecialChild(ReadGraph graph, String name) throws DatabaseException {
                if(name.contains(":")) {
-                       Range range = SpreadsheetUtils.decodeRange(name, 0, 0);
+                       Range range = Spreadsheets.decodeRange(name, 0, 0);
                        
                        VariantMatrix matrix = new VariantMatrix(range.height(),range.width());
                        
                        for(int x=range.startColumn;x<=range.endColumn;x++) {
                                for(int y=range.startRow;y<=range.endRow;y++) {
-                                       String location = SpreadsheetUtils.cellName(y,x);
+                                       String location = Spreadsheets.cellName(y,x);
                                        Variable child = getPossibleChild(graph, location);
                                        Variant value = null;
                                        if(child != null)
index b75142b3462c262ed5bd0f884ee06f7794b158f2..041332451a5624a9097e5aa253882ee165f50d27 100644 (file)
@@ -13,8 +13,8 @@ import org.simantics.db.layer0.variable.ConstantChildVariable;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.VariableFactory;
 import org.simantics.db.layer0.variable.Variables;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 public class StringArrayCells implements VariableFactory {
 
@@ -39,7 +39,7 @@ public class StringArrayCells implements VariableFactory {
                for(int offset=0,i=0;i<rows;i++) {
                        for(int j=0;j<width;j++) {
                                String value = data[offset++];
-                               String valueLocation = SpreadsheetUtils.offset(location, i, j);
+                               String valueLocation = Spreadsheets.offset(location, i, j);
                                result.add(new ConstantChildVariable(variable, valueLocation, propertyNames, bindings, new Object[] { value, true }));
                        }
                }
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AndFormulaFunction.java
deleted file mode 100644 (file)
index 4152188..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public class AndFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() == 0)
-            throw new IllegalStateException();
-        Boolean finalResult = Boolean.TRUE;
-        for (int i = 0; i < args.values.size(); i++) {
-               Object res = (args.values.get(i).accept(visitor));
-               FormulaError2 err = FormulaError2.forObject(res);
-               if(err!=null) return err.getString();
-               
-            if ((res instanceof Boolean && !((Boolean)res)) || !SpreadsheetGraphUtils.asBoolean(res))
-                finalResult = Boolean.FALSE;
-        }
-        return finalResult;
-    }
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/AverageFormulaFunction.java
deleted file mode 100644 (file)
index b8ca32e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-
-public class AverageFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() == 0)
-            throw new IllegalStateException();
-        Double sum = 0.0;
-        double count = 0.0;
-        for(AstValue value : args.values){
-               Object res = value.accept(visitor);
-               if (res instanceof SpreadsheetMatrix) {
-              Object value2 = ((SpreadsheetMatrix) res).sumWithFormulaError();
-              if(value2 instanceof String) return value2;
-              
-              sum += ((Number)value2).doubleValue();
-              count += ((SpreadsheetMatrix) res).countOfActualDoubleValues();
-               } else {
-                       FormulaError2 err = FormulaError2.forObject(res);
-                       if(err!=null) return err.getString();
-                       
-                       if(res instanceof Variant){
-                               Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res);
-                               if(dVal==null) res = ((Variant)res).toString();
-                               else res = dVal;
-                       }
-                       
-                       Double v = null;
-               if(res instanceof String && !res.equals("")){
-                       v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res);
-               }
-               else if(res instanceof Number)
-                       v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(res);
-               
-                       if(v!=null){
-                               sum += v;
-                               count++;
-                       }
-               }
-        }
-        if(count==0.0) return FormulaError2.DIV0.getString();
-        return sum/count;
-    }
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/CountifFormulaFunction.java
deleted file mode 100644 (file)
index f34b89f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstRange;
-
-public class CountifFormulaFunction implements CellFormulaFunction<Integer> {
-
-    @Override
-    public Integer evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() != 2) throw new IllegalStateException();
-        
-        AstRange range = (AstRange) args.values.get(0);
-        SpreadsheetMatrix matrix = (SpreadsheetMatrix) range.accept(visitor);
-        Object crit = null;
-        try {
-               crit = args.values.get(1).accept(visitor);
-        } catch (IllegalStateException e){
-               return 0;
-        }
-        
-        String criteria = SpreadsheetGraphUtils.asString(crit);
-        int result = 0;
-        for (Object value : matrix.values) {
-            if (SpreadsheetGraphUtils.matchCriteria(value, criteria))
-                result++;
-        }
-        return Integer.valueOf(result);
-    }
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/FormulaError2.java
deleted file mode 100644 (file)
index e47cbe8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.poi.util.Internal;
-import org.simantics.databoard.binding.mutable.Variant;
-
-public enum FormulaError2{
-       @Internal
-       _NO_ERROR(-1, "(no error)"),NULL(0x00, "#NULL"),DIV0(0x07,"#DIV/0!"),VALUE(0x0F,
-       "#VALUE!"),REF(0x17,"#REF!"),NAME(0x1D,"#NAME?"),NUM(0x24,"#NUM!"),NA(0x2A, "#N/A"),
-       CIRCULAR_REF(0xFFFFFFC4, "~CIRCULAR~REF~"),FUNCTION_NOT_IMPLEMENTED(0xFFFFFFE2,"~FUNCTION~NOT~IMPLEMENTED~");
-       
-       private final String text;
-       //private final Integer longType;
-       //private final byte shortType;
-       
-       private static Map<String, FormulaError2> smap = new HashMap<String, FormulaError2>();
-       
-       private FormulaError2(int type, String text){
-               //this.longType = type;
-               //this.shortType = (byte)type;
-               this.text = text;
-       }
-       
-       static {
-               for(FormulaError2 error : values()) {
-                       smap.put(error.getString(), error);
-               }
-       }
-       
-       public String getString(){
-               return this.text;
-       }
-       
-       public static FormulaError2 forString(String errorName){
-        FormulaError2 err = smap.get(errorName);
-        return err;
-    }
-       
-       public static FormulaError2 forObject(Object errorObj){
-               if(errorObj instanceof Variant)
-                       return forString(((Variant)errorObj).getValue().toString());
-               else
-                       return forString(errorObj.toString());
-       }
-       
-       public static String handleErrorCall(Object value){
-               if(value==null) return VALUE.getString();
-               FormulaError2 error = FormulaError2.forObject(value);
-               if(error!=null) return error.getString();
-               return VALUE.getString();
-       }
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/GeomeanFormulaFunction.java
deleted file mode 100644 (file)
index 8868985..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-
-public class GeomeanFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() == 0)
-            throw new IllegalStateException();
-        double result = 1.0;
-        double count = 0.0;
-        for (AstValue value : args.values){
-               Object r = value.accept(visitor);
-               if (r instanceof SpreadsheetMatrix) {
-              Object v = ((SpreadsheetMatrix) r).productWithFormulaError();
-              if(v instanceof String) return v;
-              double dval = ((Number)v).doubleValue();
-              if(dval!=0.0){
-                  result = result*dval;
-                  count += ((SpreadsheetMatrix) r).countOfActualDoubleValues();
-              }
-               } else {
-                               FormulaError2 error = FormulaError2.forObject(r);
-                               if(error!=null) return error.getString();
-                       
-                               Number vNum = SpreadsheetGraphUtils.asValidNumber(r);
-                               Double v = null;
-                               if(vNum!=null) v = vNum.doubleValue();
-                               
-                       if(v!=null){
-                               if(v<=0) return FormulaError2.NUM.getString();
-                               result = result*v;
-                               count++;
-                       }
-               }
-        }
-        if(result==0.0 || count==0.0) return FormulaError2.NUM.getString();
-        return Double.valueOf(Math.pow(result, (1.0/count)));
-    }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/HlookupFormulaFunction.java
deleted file mode 100644 (file)
index 409ae8b..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public class HlookupFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException();
-
-        Object lookupValue = args.values.get(0).accept(visitor);
-        boolean lookupIsString = lookupValue instanceof String;
-
-        FormulaError2 error = FormulaError2.forObject(lookupValue);
-        if(error!=null) return error.getString();
-        
-        if(lookupValue instanceof Variant){
-               Object varVal = ((Variant)lookupValue).getValue();
-               Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(varVal);
-               if(dVal==null) {
-                       lookupValue = varVal.toString();
-                       lookupIsString = true;
-               }
-               else lookupValue = dVal;
-        }
-        
-        SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
-        
-        boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true;
-
-               if(array.values.length != 0){
-                       if(lookupIsString){
-                               Object obj = array.values[0];
-                               if(obj instanceof Variant)
-                                       obj = ((Variant)obj).getValue();
-                               if(SpreadsheetGraphUtils.asValidNumber(obj)!=null)
-                                       return FormulaError2.NA.getString();
-                               obj = obj.toString();
-                               String valStr = ((String)obj).toLowerCase();
-                               if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 )
-                                       return FormulaError2.NA.getString();
-                       }
-                       else if(lookupValue instanceof Number){
-                               Double d = ((Number)lookupValue).doubleValue();
-                               Number d2 = SpreadsheetGraphUtils.asValidNumber(array.values[0]);
-                               if(d2==null || d<(d2.doubleValue()))
-                                       return FormulaError2.NA.getString();
-                       }
-               }
-
-        Number rowIndexN = (Number) SpreadsheetGraphUtils.asValidNumber(args.values.get(2).accept(visitor));
-        if(rowIndexN==null) return FormulaError2.REF.getString();
-        int rowIndexNum = rowIndexN.intValue();
-               if(rowIndexNum>array.getHeight()) return FormulaError2.REF.getString();
-               
-        if (approximateMatch) {
-               Integer colPosOfLargestValSmallerThanLookUp = null;
-               if(lookupIsString){
-                       String largestValSmallerThanLookUp = null;
-                       String ref = lookupValue.toString();
-                       String previousValue = null;
-                       for(int i = 0; i < array.getWidth(); i++){
-                               Object val = array.get(0, i);
-                               if(val instanceof Variant)
-                                       val = ((Variant)val).getValue();
-                               String currValue = val.toString();
-                               int currCompedToRef = currValue.compareTo(ref);
-                               if(currCompedToRef>=0){
-                                       if(i==0)
-                                               return array.get(rowIndexNum-1, i);
-                                       else if(previousValue.compareTo(ref) > currCompedToRef )
-                                               return array.get(rowIndexNum-1, i);
-                                       else 
-                                               return array.get(rowIndexNum - 1, i - 1);
-                               }
-                               if(colPosOfLargestValSmallerThanLookUp==null){
-                                       colPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = currValue;
-                               } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){
-                                       colPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = currValue;
-                               }
-                               previousValue = currValue;
-                       }
-                       
-               } else {
-                       double ref = SpreadsheetGraphUtils.asNumber(lookupValue);
-                       double lastDiff = Double.MIN_VALUE;
-                       Double largestValSmallerThanLookUp = null;
-               for (int i = 0; i < array.getWidth(); i++) {
-                       Object value = array.get(0, i);
-                       double n = SpreadsheetGraphUtils.asNumber(value);
-                       double diff = n - ref;
-                       if (diff >= 0) {
-                       if (i == 0)
-                               return array.get(rowIndexNum - 1, i);
-                       else if (diff < -lastDiff)
-                               return array.get(rowIndexNum - 1, i);
-                       else
-                               return array.get(rowIndexNum - 1, i - 1);
-                       }
-                               if(colPosOfLargestValSmallerThanLookUp==null){
-                                       colPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = n;
-                               } else if(largestValSmallerThanLookUp < n){
-                                       colPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = n;
-                               }
-                       lastDiff = diff;
-               }
-               }
-               if(colPosOfLargestValSmallerThanLookUp!=null) return array.get(rowIndexNum - 1, colPosOfLargestValSmallerThanLookUp);
-               
-        } else {
-
-            for (int i = 0; i < array.getWidth(); i++) {
-                Object value = array.get(0, i);
-                if(value instanceof Variant){
-                       if(lookupIsString)
-                               value = ((Variant)value).getValue().toString();
-                       else 
-                               value = SpreadsheetGraphUtils.asNumber(value);
-                }
-                if (SpreadsheetGraphUtils.excelEquals(lookupValue, value)) {
-                    return array.get(rowIndexNum - 1, i);
-                }
-            }
-
-        }
-
-        return FormulaError2.NA.getString();
-    }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/MatchFormulaFunction.java
deleted file mode 100644 (file)
index e9b7c7b..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public class MatchFormulaFunction implements CellFormulaFunction<Object>{
-       
-       @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() < 2 || args.values.size() > 3) throw new IllegalStateException();
-        
-        SpreadsheetMatrix lookup_array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
-        if(lookup_array.getWidth()!=1 && lookup_array.getHeight()!=1) return FormulaError2.NA.getString();
-        
-        Object lookup_value = args.values.get(0).accept(visitor);
-        
-        int match_type = 1;
-        try{
-               if(args.values.size()==3){
-                       int matchArg = ((Number)args.values.get(2).accept(visitor)).intValue();
-                       if(matchArg<0)
-                               match_type = -1;
-                       else if(matchArg>0)
-                               match_type = 1;
-                       else
-                               match_type = 0;
-               }
-        } catch(Exception e) {
-               return FormulaError2.NA.getString();
-        }
-
-        boolean useHeight = false;
-        if(lookup_array.getWidth()==1) useHeight = true;
-        
-        int max = 0;
-        if(useHeight) max = lookup_array.getHeight();
-        else max = lookup_array.getWidth();
-
-        Integer pos = null;
-        if(lookup_value instanceof Variant){
-               Object obj = ((Variant)lookup_value).getValue();
-               Number nVal = SpreadsheetGraphUtils.asValidNumber(obj);
-               if(nVal!=null) obj = nVal;
-               else obj = obj.toString();
-        }
-        
-        if(lookup_value instanceof Number){
-               Double previousValue = null;
-               Double closestMatch = null;
-            Double lookup = ((Number)lookup_value).doubleValue();
-            int indexWhereCorrectOrderStartsAt = 0;
-            
-            if(match_type!=0) {
-               for(int i = 0; i < max;i++){
-                       Double currValue = null;
-                       Number currNum;
-                               if(useHeight){
-                                       currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(i,0));
-                               } else {
-                                       currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(0,i));
-                               }
-                               if(currNum!=null){
-                                       currValue = currNum.doubleValue();
-                               if(currValue != null){
-                                       if(previousValue!=null){
-                                               if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue))
-                                                       indexWhereCorrectOrderStartsAt = i;
-                                               else
-                                                       break;
-                                       }
-                                       previousValue = currValue;
-                               }
-                       }
-               }
-            }
-            int begin = indexWhereCorrectOrderStartsAt;
-            
-            for(int i = begin; i < max;i++){
-                Double currValue = null;
-                Number currNum;
-                       if(useHeight){
-                               currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(i,0));
-                       } else {
-                               currNum = SpreadsheetGraphUtils.asValidNumber(lookup_array.get(0,i));
-                       }
-                       if(currNum!=null){
-                               currValue = currNum.doubleValue();
-                       if(currValue != null){
-                               if(previousValue==null) previousValue = currValue;
-                               if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue)){
-                                       if(pos!=null)
-                                               return pos+1;
-                               previousValue = currValue;
-                               }
-                                       int comp = lookup.compareTo(currValue);
-                                       if(comp == 0){
-                                               closestMatch = currValue;
-                                               pos = i;
-                                       }
-                                       else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){
-                                               if(closestMatch==null && pos==null){
-                                                       closestMatch = currValue;
-                                                       pos = i;
-                                               }
-                                               else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){
-                                                       closestMatch = currValue;
-                                                       pos = i;
-                                               }
-                                       }
-                               previousValue = currValue;
-                       }
-                }
-            }
-        }
-            
-        else if(lookup_value instanceof String){
-               String previousValue = null;
-               String closestMatch = null;
-            String lookup = (String)lookup_value;
-            int indexWhereCorrectOrderStartsAt = 0;
-            
-            if(match_type!=0) {
-               for(int i = 0; i < max;i++){
-                       String currValue = null;
-                       Object obj;
-                       if(useHeight){
-                               obj = lookup_array.get(i,0);
-                       } else {
-                               obj = lookup_array.get(0,i);
-                       }
-                       if(obj instanceof Variant){
-                               obj = ((Variant)obj).getValue();
-                       }
-                       if(obj!=null && !(obj instanceof Number)){
-                               currValue = obj.toString();
-                               currValue = currValue.toLowerCase();
-                       }
-                       if(currValue != null && !currValue.equals("")){
-                               if(previousValue!=null){
-                                       if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0))
-                                               indexWhereCorrectOrderStartsAt = i;
-                                       else
-                                               break;
-                               }
-                               previousValue = currValue;
-                       }
-               }
-            }
-            
-            int begin = indexWhereCorrectOrderStartsAt;
-
-            for(int i = begin; i < max;i++){
-               String currValue = null;
-                       Object obj;
-                       if(useHeight){
-                               obj = lookup_array.get(i,0);
-                       } else {
-                               obj = lookup_array.get(0,i);
-                       }
-                       if(obj instanceof Variant){
-                               obj = ((Variant)obj).getValue();
-                       }
-                       if(obj!=null && !(obj instanceof Number)){
-                               currValue = obj.toString();
-                               currValue = currValue.toLowerCase();
-                       }
-
-                if(currValue != null && !currValue.equals("")){
-                       if(previousValue==null) previousValue = currValue;
-                       if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)){
-                               if(pos!=null)
-                                       return pos+1;
-                           previousValue = currValue;
-                       }
-                       int comp = lookup.compareTo(currValue);
-                       if(comp == 0){
-                               closestMatch = currValue;
-                               pos = i;
-                       }
-                               else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){
-                                       if(closestMatch==null && pos==null){
-                                               closestMatch = currValue;
-                                               pos = i;
-                                       }
-                                       else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){
-                                               closestMatch = currValue;
-                                               pos = i;
-                                       }
-                               }
-                       previousValue = currValue;
-                }
-            }
-        }
-
-        if(pos==null)return FormulaError2.NA.getString();
-        return pos+1;
-    }
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/OrFormulaFunction.java
deleted file mode 100644 (file)
index 9422211..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public class OrFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() == 0) throw new IllegalStateException();
-        
-        for (int i = 0; i < args.values.size(); i++) {
-               Object obj = null;
-               try {
-                       obj = args.values.get(i).accept(visitor);
-               } catch (IllegalStateException e){
-                       return FormulaError2.NAME.getString();
-               }
-               FormulaError2 error = FormulaError2.forObject(obj);
-               if(error!=null) return error.getString();
-               
-            if (SpreadsheetGraphUtils.asBoolean(obj))
-                return Boolean.TRUE;
-        }
-        return Boolean.FALSE;
-    }
-
-}
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/VlookupFormulaFunction.java
deleted file mode 100644 (file)
index 5f99cfc..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.simantics.spreadsheet.graph.formula;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-
-public class VlookupFormulaFunction implements CellFormulaFunction<Object> {
-
-    @Override
-    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-        if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException();
-
-        Object lookupValue = args.values.get(0).accept(visitor);
-        boolean lookupIsString = lookupValue instanceof String;
-
-        FormulaError2 error = FormulaError2.forObject(lookupValue);
-        if(error!=null) return error.getString();
-        
-        if(lookupValue instanceof Variant){
-               Object varVal = ((Variant)lookupValue).getValue();
-               Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(varVal);
-               if(dVal==null) {
-                       lookupValue = varVal.toString();
-                       lookupIsString = true;
-               }
-               else lookupValue = dVal;
-        }
-
-        
-        SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
-
-        boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true;
-
-        boolean valueExists = false;
-               if(array.values.length != 0){
-                       for(int i = 0; i < array.getHeight(); i++){
-                               if(lookupIsString){
-                                       Object obj = array.get(i,0);
-                                       if(obj instanceof Variant)
-                                               obj = ((Variant)obj).getValue();
-                                       if(obj!=null && SpreadsheetGraphUtils.asValidNumber(obj)==null){
-                                               obj = obj.toString();
-                                               String valStr = ((String)obj).toLowerCase();
-                                               if((lookupValue.toString().toLowerCase()).compareTo(valStr)>=0 ){
-                                                       valueExists = true;
-                                                       break;
-                                               }
-                                       }
-                               }
-                               else if(lookupValue instanceof Number){
-                                       Double d = ((Number)lookupValue).doubleValue();
-                                       Number d2 = SpreadsheetGraphUtils.asValidNumber(array.get(i,0));
-                                       if(d2!=null && d>=(d2.doubleValue())){
-                                               valueExists = true;
-                                               break;
-                                       }
-                               }
-                       }
-//                     if(lookupIsString){
-//                             Object obj = array.values[0];
-//                             if(obj instanceof Variant)
-//                                     obj = ((Variant)obj).getValue();
-//                             if(SpreadsheetGraphUtils.asValidNumber(obj)!=null)
-//                                     return FormulaError2.NA.getString();
-//                             obj = obj.toString();
-//                             String valStr = ((String)obj).toLowerCase();
-//                             if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 )
-//                                     return FormulaError2.NA.getString();
-//                     }
-//                     else if(lookupValue instanceof Number){
-//                             Double d = ((Number)lookupValue).doubleValue();
-//                             Number d2 = SpreadsheetGraphUtils.asValidNumber(array.values[0]);
-//                             if(d2==null || d<(d2.doubleValue()))
-//                                     return FormulaError2.NA.getString();
-//                     }
-               }
-               if(!valueExists) return FormulaError2.NA.getString();
-               
-               Number colIndexN = SpreadsheetGraphUtils.asValidNumber(args.values.get(2).accept(visitor));
-               if(colIndexN==null) return FormulaError2.REF.getString();
-               int colIndexNum = colIndexN.intValue();
-        if(colIndexNum>array.getWidth()) return FormulaError2.REF.getString();
-        
-        if (approximateMatch) {
-               Integer rowPosOfLargestValSmallerThanLookUp = null;
-               if(lookupIsString){
-                       String ref = lookupValue.toString().toLowerCase();
-                       String previousValue = null;
-                       String largestValSmallerThanLookUp = null;
-                       for(int i = 0; i < array.getHeight(); i++){
-                               Object val = array.get(i, 0);
-                               if(val instanceof Variant)
-                                       val = ((Variant)val).getValue();
-                               String currValue = val.toString().toLowerCase();
-                               if(currValue.compareTo(ref)>0){
-                                       if(i==0)
-                                               return array.get(i, colIndexNum-1);
-                                       else if(previousValue.compareTo(ref) > currValue.compareTo(ref))
-                                               return array.get(i, colIndexNum-1);
-                                       else 
-                                               return array.get(i - 1, colIndexNum - 1);
-                               }
-                               if(rowPosOfLargestValSmallerThanLookUp==null){
-                                       rowPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = currValue;
-                               } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){
-                                       rowPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = currValue;
-                               }
-                               previousValue = currValue;
-                       }
-                       
-               } else {
-                       double ref = SpreadsheetGraphUtils.asNumber(lookupValue);
-               double lastDiff = Double.MIN_VALUE;
-               Double largestValSmallerThanLookUp = null;
-               for (int i = 0; i < array.getHeight(); i++) {
-                       Object value = array.get(i, 0);
-                       double n = SpreadsheetGraphUtils.asNumber(value);
-                       double diff = n - ref;
-                       if (diff > 0) {
-                       if (i == 0)
-                               return array.get(i, colIndexNum - 1);
-                       else if (diff < -lastDiff)
-                               return array.get(i, colIndexNum - 1);
-                       else
-                               return array.get(i - 1, colIndexNum - 1);
-                       }
-                               if(rowPosOfLargestValSmallerThanLookUp==null){
-                                       rowPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = n;
-                               } else if(largestValSmallerThanLookUp < n){
-                                       rowPosOfLargestValSmallerThanLookUp = i;
-                                       largestValSmallerThanLookUp = n;
-                               }
-                       lastDiff = diff;
-               }
-               }
-               
-               if(rowPosOfLargestValSmallerThanLookUp!=null) return array.get(rowPosOfLargestValSmallerThanLookUp, colIndexNum - 1);
-        
-        } else {
-            for (int i = 0; i < array.getHeight(); i++) {
-                Object value = array.get(i, 0);
-                if(value instanceof Variant){
-                       if(lookupIsString)
-                               value = ((Variant)value).getValue().toString();
-                       else 
-                               value = SpreadsheetGraphUtils.asNumber(value);
-                }
-                if (SpreadsheetGraphUtils.excelEquals(lookupValue, value)) {
-                    return array.get(i, colIndexNum - 1);
-                }
-            }
-        }
-
-        return FormulaError2.NA.getString();
-    }
-
-}
index 98ef90231fc6be36999667b377ad46fe1cd5b516..9b0f708df8c11628fbb1c13af1dabf76bf46b669 100644 (file)
@@ -54,22 +54,26 @@ 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.Spreadsheets;
 import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant;
+import org.simantics.spreadsheet.graph.SpreadsheetNodeManager;
 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.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetCellContent;
+import org.simantics.spreadsheet.solver.SpreadsheetFormula;
+import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle.SpreadsheetStyleBuilder;
+import org.simantics.spreadsheet.solver.formula.parser.ParseException;
+import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.spreadsheet.synchronization.ExcelFormula;
+import org.simantics.spreadsheet.synchronization.LineContentBean;
+import org.simantics.spreadsheet.synchronization.LineContentBeanCell;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 import gnu.trove.map.TMap;
@@ -80,127 +84,135 @@ 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);
-       }
+        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);
-       }
+    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));
-                                   
+    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(ProxyVariables.isProxy(graph, context))
+                        // SCL expressions are not supported in solver
+                        return;
+
+                    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);
+                            setValueToEngine(graph, cell, context, sformula, SpreadsheetFormula.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 {
+                    Layer0Utils.claimLiteral(graph, 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);
 
+            if(Bindings.STRING.equals(binding) && !(value instanceof String))
+                System.err.println("asd");
+
             SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
 
             while(!sheet.getType(graph).equals(SHEET.Spreadsheet)) {
                 sheet = sheet.getParent(graph);
             }
-            
-            Range r = SpreadsheetUtils.decodeCellAbsolute(cell.getName(graph));
-            
+
+            Range r = Spreadsheets.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); //Invalidation handled by SpreadsheetNodeManager
             realm.asyncExec(new Runnable() {
 
                 @Override
@@ -208,306 +220,287 @@ public class All {
                     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));
+        }
+
+        @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);
+        @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;
-               
-               }
-               
+    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 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 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 = Spreadsheets.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 = Spreadsheets.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);
-                       
+    @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);
-                       
-               }
-               
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+            System.err.println("getVariables " + context.getURI(graph));
+
+            if(ProxyVariables.isProxy(graph, context))
+                return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, Collections.emptyMap(), 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;
-               
-               }
-               
+    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 = Spreadsheets.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 {
@@ -515,38 +508,38 @@ public class All {
         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
+
+            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);
-               }
-               }
-            
+                } 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);
+                Variable root = org.simantics.db.layer0.function.All.buildChildVariable(graph, this, base.getRepresents(graph), null);
+                result.add(root);
             }
             return result;
-            
+
         }       
-             
+
     }
 
     @SCLValue(type = "VariableMap")
@@ -554,10 +547,10 @@ public class All {
 
         @Override
         public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-               
-               if(ProxyChildVariable.CONTEXT_BEGIN.equals(name)) return getProxy(graph, context);
+
+            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 {
@@ -569,9 +562,9 @@ public class All {
         @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;
@@ -579,160 +572,160 @@ public class All {
 
     };
 
-   
+
     @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);
-                               }
-                       });
-                       
-               }
-               
+        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.decodePossibleCellAbsolute(location);
-                   if(range == null) return null; //No editor found
-                   
-                   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);
+                Range range = Spreadsheets.decodePossibleCellAbsolute(location);
+                if(range == null) return null; //No editor found
+
+                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) {
+            @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 {
 
-                       SpreadsheetUtils.schedule(transaction, new WriteRequest() {
+                        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);
+                            }
+                        }
+                    }
 
-                               @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) {
+        final Variable cell = context_.getParent(graph);
 
-               @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);
-               }
-       };
+        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);
-               }
+        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;
-       
+        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);
-               
+
+        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) {
@@ -740,35 +733,35 @@ public class All {
                 } else {
                     cell.setContent(variant);
                 }
-                Range r = SpreadsheetUtils.decodeCellAbsolute(child.getName(graph));
+                Range r = Spreadsheets.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;
-       
+        }
+        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 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) {
@@ -781,10 +774,11 @@ public class All {
                             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);
+                    if (runCell != null)
+                        runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.VARIANT);
+                } else if(ClientModel.CONTENT_EXPRESSION.equals(property)) {
+                    System.err.println("cell: " + cell.getURI(graph));
+                    cell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
                     Variable runCell = null;
                     Object transactionContext = transaction.getContext();
                     if (transactionContext != null && transactionContext instanceof Variable) {
@@ -797,53 +791,56 @@ public class All {
                             transaction.needSynchronization(cell.getParent(graph));
                         }
                     }
-                               if (runCell != null)
-                                   runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
-                       } else if(ClientModel.BORDER.equals(property)) {
+                    if (runCell != null)
+                        runCell.setPropertyValue(graph, SHEET.Cell_content, value, Bindings.STRING);
+                    // SCL expressions always require synchronization
+                    if(value.toString().startsWith("=="))
+                        transaction.needSynchronization(cell.getParent(graph));
+                } 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)) {
+                } 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)) {
+                } 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)) {
+                } 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 {
-                
+                }
+            }
+
+            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();
 
@@ -856,34 +853,17 @@ public class All {
                     }
                 }
                 if (createdStyle == null) {
-                       style = builder.name("Style_" + existingStyles.size()).build();
+                    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 {
@@ -892,18 +872,18 @@ public class All {
                 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("");
-                       
+            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;
@@ -919,19 +899,19 @@ public class All {
                         // 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);
-                       
+                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) {
@@ -939,55 +919,55 @@ public class All {
                     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);
-               }
-               
-       };
-       
+
+                //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);
+        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);
+        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);
+        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")
+
+    @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
     public static Object sclValue(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
-           return CompileSCLValueRequest.compileAndEvaluate(graph, context);
+        return CompileSCLValueRequest.compileAndEvaluate(graph, context);
     }
 
 }
\ No newline at end of file
index 5327d9b7cb389363fa9d88cc6e79963f04921657..aad988fb94cbe10c9f6926730ebc04bf7d0ffa75 100644 (file)
@@ -20,6 +20,7 @@ import org.simantics.db.layer0.variable.VariableNode;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.spreadsheet.Range;
 import org.simantics.spreadsheet.SheetVariables;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.matrix.VariantMatrix;
 import org.simantics.spreadsheet.graph.Ranges;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
@@ -77,7 +78,7 @@ public class SpreadsheetRootVariable extends StandardGraphChildVariable {
         
         if(name.contains(":")) {
                
-            Range range = SpreadsheetUtils.decodeRange(name, 0, 0);
+            Range range = Spreadsheets.decodeRange(name, 0, 0);
             
             VariantMatrix matrix = new VariantMatrix(range.height(),range.width());
             String rangeNames[][] = new String[range.height()][range.width()];
@@ -85,7 +86,7 @@ public class SpreadsheetRootVariable extends StandardGraphChildVariable {
             
             for(int x=range.startColumn;x<=range.endColumn;x++) {
                 for(int y=range.startRow;y<=range.endRow;y++) {
-                    String location = SpreadsheetUtils.cellName(y,x);
+                    String location = Spreadsheets.cellName(y,x);
                     Variable child = context.getPossibleChild(graph, location);
                     Variant value = null;
                     if(child != null)
index be73a741cdb633532055ff67ccd6878b13dece54..71466070ef099d03bbfc947570d43980b98f117a 100644 (file)
@@ -29,7 +29,7 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.layer0.Layer0;
 import org.simantics.spreadsheet.Range;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.Spreadsheets;
 
 public class SpreadsheetExpressionVisitor extends DepthFirstAdapter {
 
@@ -220,13 +220,13 @@ public class SpreadsheetExpressionVisitor extends DepthFirstAdapter {
                
                String identifier = node.toString().trim();
 
-               Range range = SpreadsheetUtils.decodeRange(identifier, row, column);
+               Range range = Spreadsheets.decodeRange(identifier, row, column);
                if (range.size() != 1) {
                        ArrayList<Object> value = new ArrayList<Object>();
                        for (int c = range.startColumn; c <= range.endColumn; c++) {
                                for (int r = range.startRow; r <= range.endRow; r++) {
                                        try {
-                                               String location = SpreadsheetUtils.cellName(r, c);
+                                               String location = Spreadsheets.cellName(r, c);
                                                Variable cell = cellVariable.getChild(graph, location);
                                                System.out.println("cell=" + cell.getURI(graph));
                                                String label = cell.getPossiblePropertyValue(graph, "Label");
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineCommandBuilder.java
deleted file mode 100644 (file)
index a7e5f87..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import java.io.StringReader;
-
-import org.simantics.databoard.adapter.AdaptException;
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.ExcelArrayFormula;
-import org.simantics.spreadsheet.graph.ExcelFormula;
-import org.simantics.spreadsheet.graph.SpreadsheetBook;
-import org.simantics.spreadsheet.graph.SpreadsheetCell;
-import org.simantics.spreadsheet.graph.SpreadsheetFormula;
-import org.simantics.spreadsheet.graph.SpreadsheetLine;
-import org.simantics.spreadsheet.graph.SpreadsheetLines;
-import org.simantics.spreadsheet.graph.SpreadsheetSCLConstant;
-import org.simantics.spreadsheet.graph.function.LineContentBean;
-import org.simantics.spreadsheet.graph.function.LineContentBeanCell;
-import org.simantics.spreadsheet.graph.parser.SheetFormulaParser;
-import org.simantics.spreadsheet.graph.parser.ast.AstArrayFormulaReference;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.Solver;
-
-public class LineCommandBuilder implements CommandBuilder {
-       
-       private String name;
-//     private boolean update;
-       LineContentBean bean;
-       
-       public LineCommandBuilder(String name, boolean update) {
-               this.name = name;
-//             this.update = update;
-       }
-
-       @Override
-       public void apply(Solver solver) {
-               
-               SpreadsheetBook book = solver.getConcreteSolver();
-               
-               String path = name.substring(0, name.lastIndexOf("/"));
-               String lineName = name.substring(name.lastIndexOf("/")+1);
-               int row = Integer.parseInt(lineName.substring(3));
-               
-               SpreadsheetLines node = book.ensureSubprocess(path);
-               SpreadsheetLine line = node.lines.get(-row);
-               if(line == null) {
-                       line = new SpreadsheetLine(node, row);
-                       node.lines.put(-row, line);
-               }
-               
-//             line.cells.clear();
-               for(int i=0;i<bean.cells.length;i++) {
-                       
-                   SpreadsheetCell currentCell;
-                   if (line.cells.size() > i) {
-                       currentCell = line.cells.get(i);
-                   } else {
-                       currentCell = new SpreadsheetCell(line, i);
-                       line.cells.add(currentCell);
-                   }
-                   
-                       LineContentBeanCell cell = bean.cells[i];
-                       
-                       try {
-                               Object content = cell.getContent();
-                               if (content instanceof Variant) {
-                                   Variant cellVariant = (Variant) content;
-                                   if (cellVariant == LineContentBeanCell.EMPTY) {
-                                       currentCell.setStyle(cell.getStyleId());
-                                       // Empty content
-                                       currentCell.setContent("");
-//                                     if (currentCell != SpreadsheetCell.EMPTY) {
-//                                         line.cells.remove(i);
-//                                         line.cells.add(i, SpreadsheetCell.EMPTY);
-//                                     }
-                                   } else if(ExcelFormula.BINDING.type().equals(cellVariant.getBinding().type())) {
-                           ExcelFormula formula = (ExcelFormula)cellVariant.getValue(ExcelFormula.BINDING);
-                           SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
-                           AstValue v = p.relation();
-                        currentCell.setStyle(cell.getStyleId());
-                        SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression);
-                        currentCell.setContent(sformula);
-                       } else if (ExcelArrayFormula.BINDING.type().equals(cellVariant.getBinding().type())) {
-                           ExcelArrayFormula formula = (ExcelArrayFormula)cellVariant.getValue(ExcelArrayFormula.BINDING);
-                           SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
-                           AstArrayFormulaReference v = new AstArrayFormulaReference(formula.range, p.relation());
-                        currentCell.setStyle(cell.getStyleId());
-                        SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression);
-                        currentCell.setContent(sformula);
-                       } else {
-                        currentCell.setStyle(cell.getStyleId());
-                        // DO not update constant values during update
-                        currentCell.setContent(cellVariant.getValue());
-                       }
-                               } else if (content instanceof SpreadsheetSCLConstant){
-                    currentCell.setStyle(cell.getStyleId());
-                    currentCell.setContent(content);
-                               }
-                       } catch (Throwable e) {
-                           Object content = cell.getContent();
-                if (content instanceof Variant) {
-                    Variant cellVariant = (Variant) content;
-                    currentCell.setStyle(cell.getStyleId());
-                    currentCell.setContent(content);
-                    try {
-                        new Exception("failed: " + ((ExcelFormula)(cellVariant.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace();
-                    } catch (AdaptException e1) {
-                        e1.printStackTrace();
-                    }
-                } else {
-                    currentCell.setStyle(cell.getStyleId());
-                    currentCell.setContent("LCB error happened");
-                }
-                       }
-               }
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public <T> T getConcrete() {
-               return (T)this;
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineNodeUpdater.java
deleted file mode 100644 (file)
index c731c44..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import java.util.Collection;
-import java.util.Map;
-
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.ModuleUpdateContext;
-import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
-import org.simantics.structural.synchronization.utils.PropertyUpdateRule;
-
-public class LineNodeUpdater extends ModuleUpdaterBase<SheetLineComponent> {
-       
-       public LineNodeUpdater(String id) {
-               
-               super(id);
-               
-               isComposite = true;
-               
-               addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
-                       
-                       @Override
-                       public String getPropertyName() {
-                               return "keys";
-                       }
-                       
-                       @Override
-                       public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
-                                       Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
-                               
-                               LinesCommandBuilder builder = context.<LinesCommandBuilder>getConcreteCommand();
-                               Variant v = propertyMap.get("keys");
-                               if (v != null & v.getValue() != null)
-                                   builder.keys = (int[])v.getValue();
-                               
-                       }
-                       
-               });
-               
-       }
-
-       @Override
-       public CommandBuilder createAddCommandBuilder(String name) {
-               return new LinesCommandBuilder(name, false);
-       }
-
-       @Override
-       public CommandBuilder createUpdateCommandBuilder(String name) {
-               return new LinesCommandBuilder(name, true);
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LineUpdater.java
deleted file mode 100644 (file)
index 66acdce..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import java.util.Collection;
-import java.util.Map;
-
-import org.simantics.databoard.adapter.AdaptException;
-import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.function.LineContentBean;
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.ModuleUpdateContext;
-import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
-import org.simantics.structural.synchronization.utils.PropertyUpdateRule;
-
-public class LineUpdater extends ModuleUpdaterBase<SheetLineComponent> {
-       
-       public LineUpdater(String id) {
-               super(id);
-               addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
-                       
-                       @Override
-                       public String getPropertyName() {
-                               return "content";
-                       }
-                       
-                       @Override
-                       public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
-                                       Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
-                               
-                               LineCommandBuilder builder = context.<LineCommandBuilder>getConcreteCommand();
-                try {
-                    LineContentBean valuee = (LineContentBean) value.getValue(LineContentBean.BINDING);
-                    builder.bean = valuee;
-                } catch (AdaptException e) {
-                    e.printStackTrace();
-                } catch (ClassCastException e) {
-                    e.printStackTrace();
-                }
-//                             if (valuee instanceof LineContentBean)
-//                         
-//                     else
-//                         System.err.println("valuee is instanceof " + valuee.getClass().getSimpleName() + " " + valuee);
-                       
-                       }
-                       
-               });
-       }
-
-       @Override
-       public CommandBuilder createAddCommandBuilder(String name) {
-               return new LineCommandBuilder(name, false);
-       }
-
-       @Override
-       public CommandBuilder createUpdateCommandBuilder(String name) {
-               return new LineCommandBuilder(name, true);
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/LinesCommandBuilder.java
deleted file mode 100644 (file)
index cd1a6f3..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import org.simantics.spreadsheet.graph.SpreadsheetBook;
-import org.simantics.spreadsheet.graph.SpreadsheetLines;
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.Solver;
-
-public class LinesCommandBuilder implements CommandBuilder {
-       
-       private final boolean update;
-    private String name;
-       int[] keys;
-       
-       public LinesCommandBuilder(String name, boolean update) {
-               this.name = name;
-               this.update = update;
-       }
-
-       @Override
-       public void apply(Solver solver) {
-//         if (update)
-//             return;
-               
-               SpreadsheetBook book = solver.getConcreteSolver();
-               SpreadsheetLines node = book.ensureSubprocess(name);
-               node.setKeys(keys);
-               
-//             String path = name.substring(0, name.lastIndexOf("/"));
-//             String lineName = name.substring(name.lastIndexOf("/")+1);
-//             int row = Integer.parseInt(lineName.substring(3));
-//             
-               
-//             SpreadsheetLine line = node.lines.get(-row);
-//             if(line == null) {
-//                     line = new SpreadsheetLine(node, row);
-//                     node.lines.put(-row, line);
-//             }
-//             
-//             for(int i=0;i<bean.cells.length;i++) {
-//                     
-//                     LineContentBeanCell cell = bean.cells[i];
-//                     
-//                     try {
-//                             
-//                             if(ExcelFormula.BINDING.type().equals(cell.content.getBinding().type())) {
-//                                     ExcelFormula formula = (ExcelFormula)cell.content.getValue(ExcelFormula.BINDING);
-//                                     SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
-//                                     AstValue v = p.relation();
-//                                     line.cells.add(new SpreadsheetCell(line, i, new SpreadsheetFormula(v, formula.expression), 0));
-//                             } else {
-//                                     line.cells.add(new SpreadsheetCell(line, i, cell.content.getValue(), 0));
-//                             }
-//                     } catch (Throwable e) {
-//                             line.cells.add(new SpreadsheetCell(line, i, cell.content.getValue(), 0));
-//                             try {
-//                                     new Exception("failed: " + ((ExcelFormula)(cell.content.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace();
-//                             } catch (AdaptException e1) {
-//                                     e1.printStackTrace();
-//                             }
-//                     }
-//                     
-//             }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public <T> T getConcrete() {
-               return (T)this;
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullCommandBuilder.java
deleted file mode 100644 (file)
index ea37490..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.Solver;
-
-public class NullCommandBuilder implements CommandBuilder {
-       
-       @Override
-       public void apply(Solver solver) {
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public <T> T getConcrete() {
-               return (T)this;
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/NullUpdater.java
deleted file mode 100644 (file)
index 3fa3379..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import org.simantics.structural.synchronization.utils.CommandBuilder;
-import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
-
-public class NullUpdater extends ModuleUpdaterBase<SheetLineComponent> {
-       
-       public NullUpdater(String typeId) {
-               super(typeId);
-               isComposite = true;
-       }
-
-       @Override
-       public CommandBuilder createAddCommandBuilder(String name) {
-               return new NullCommandBuilder();
-       }
-
-       @Override
-       public CommandBuilder createUpdateCommandBuilder(String name) {
-               return new NullCommandBuilder();
-       }
-       
-}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java b/bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/SheetLineComponent.java
deleted file mode 100644 (file)
index 5edea56..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.simantics.spreadsheet.graph.synchronization;
-
-import java.io.Serializable;
-
-import org.simantics.structural.synchronization.utils.ComponentBase;
-
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.procedure.TObjectProcedure;
-
-public class SheetLineComponent extends ComponentBase<SheetLineComponent> implements Serializable {
-
-    private static final long serialVersionUID = 1777515716175831266L;
-    
-       private THashMap<String, SheetLineComponent> childMap = new THashMap<>();
-       
-       public SheetLineComponent(String uid) {
-           super(uid, 0);
-       }
-       
-//     public SheetLineComponent(String uid, String solverComponentName, int componentId) {
-//             this.uid = uid;
-//             this.solverComponentName = solverComponentName;
-//             this.componentId = componentId;
-//     }
-       
-       @Override
-       public THashMap<String, SheetLineComponent> getChildMap() {
-               return childMap;
-       }
-
-       @Override
-       public void setChildMap(THashMap<String, SheetLineComponent> newChildMap) {
-               childMap = newChildMap;
-               if(childMap != null) {
-                       childMap.forEachValue(new TObjectProcedure<SheetLineComponent>() {
-                               @Override
-                               public boolean execute(SheetLineComponent component) {
-                                       component.parent = SheetLineComponent.this;
-                                       return true;
-                               }
-                       });
-               }
-       }
-       
-       @Override
-       public String toString() {
-           return solverComponentName + " (" + super.toString() + ")";
-       }
-
-}
index 4d943fb342b8d22615873ed48ef890372945b5e8..7deacb3d7f6c4c42dfbf03d86c3ea83b0debc9ca 100644 (file)
@@ -1,8 +1,9 @@
 package org.simantics.spreadsheet.graph.synchronization;
 
 import org.simantics.db.ReadGraph;
-import org.simantics.spreadsheet.graph.SpreadsheetBook;
 import org.simantics.spreadsheet.graph.SpreadsheetReferenceResolver;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
 import org.simantics.structural.synchronization.utils.SynchronizationEventHandlerBase;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 86fda3d5a7634933efff640a2690ba99de19773b..98335a529126d1e3c784dec6ea4665a5d2a3d617 100644 (file)
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.simantics.spreadsheet.ui;
 
-import gnu.trove.map.hash.THashMap;
-
 import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -23,10 +21,12 @@ import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.simantics.spreadsheet.ClientModel;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.collections.CollectionUtils;
 
+import gnu.trove.map.hash.THashMap;
+
 public class ClientModelImpl implements ClientModel {
        
        final private Map<String, Map<String, Object>> properties = new THashMap<String, Map<String, Object>>();
@@ -226,7 +226,7 @@ public class ClientModelImpl implements ClientModel {
                        Map<String, Object> cls = cells.remove(location);
                        if(cls == null) return;
                        
-                       long l = SpreadsheetUtils.decodeCellCoded(location);
+                       long l = Spreadsheets.decodeCellCoded(location);
                        int row = (int)(l & 0xffffffff) - 1;
                        int column = (int)((l>>32) & 0xffffffff);
                        
@@ -280,7 +280,7 @@ public class ClientModelImpl implements ClientModel {
 
                                cls.put(property, value);
 
-                               long l = SpreadsheetUtils.decodeCellCoded(location);
+                               long l = Spreadsheets.decodeCellCoded(location);
                                int row = (int)(l & 0xffffffff) - 1;
                                int column = (int)((l>>32) & 0xffffffff);
 
index 395fcbdd73e536555cd6336b8f02b52e4e35afe0..08a1b0ef6f898a5796b2e48017176f297236e75b 100644 (file)
@@ -19,7 +19,8 @@ import javax.swing.table.DefaultTableModel;
 import org.simantics.spreadsheet.ClientModel;
 import org.simantics.spreadsheet.ClientModel.ClientModelListener;
 import org.simantics.spreadsheet.ClientModel.OperationMode;
-import org.simantics.spreadsheet.graph.SpreadsheetStyle;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.ui.colors.Colors;
 import org.simantics.ui.fonts.Fonts;
@@ -142,7 +143,7 @@ final public class ClientTableModel extends DefaultTableModel {
        
        @Override
        public Object getValueAt(int row, int column) {
-               String location = SpreadsheetUtils.cellName(row, column);
+               String location = Spreadsheets.cellName(row, column);
                
 //             System.out.println("CellValue for location " + location);
                
index 44c2b219a756bc00645cf9cf644b722cce5b887d..6ac032259799ea294e077aa0cdd80976adb6309a 100644 (file)
@@ -16,8 +16,8 @@ import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.ui.handlers.HandlerUtil;
 import org.simantics.spreadsheet.CellEditor;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.graph.GraphUI;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 
 public class DeleteHandler extends AbstractHandler {
@@ -39,7 +39,7 @@ public class DeleteHandler extends AbstractHandler {
        
        for(int row : rows) {
                for(int col : cols) {
-                       ce.edit(null, SpreadsheetUtils.cellName(row, col), null, null);
+                       ce.edit(null, Spreadsheets.cellName(row, col), null, null);
                }
        }
        
index b21a22500eddf2898fdee4febf1f6ecb6f22b559..a51b32a0fc1f14bc90ea06a2836c0c5636570c37 100644 (file)
@@ -25,9 +25,10 @@ import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.spreadsheet.Adaptable;
 import org.simantics.spreadsheet.CellEditor;
 import org.simantics.spreadsheet.CellEditor.Transaction;
-import org.simantics.spreadsheet.ClientModel.OperationMode;
 import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.ClientModel.OperationMode;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.cell.StringCellParser;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.utils.threads.logger.ITask;
@@ -196,7 +197,7 @@ public class ExcelAdapter implements ActionListener {
 
                                                        CellValue cell = (CellValue)table.getValueAt(startRow+i, startCol+j);
                                                        if(cell.label != null) {
-                                                               String location = SpreadsheetUtils.cellName(startRow+i, startCol+j);
+                                                               String location = Spreadsheets.cellName(startRow+i, startCol+j);
                                                                Boolean computed = model.getPropertyAt(location, ClientModel.COMPUTED);
                                                                if(computed != null && computed) return;
                                                                removals.add(location);
@@ -221,9 +222,9 @@ public class ExcelAdapter implements ActionListener {
                                                                startCol+j< table.getColumnCount()) {
 
                                                        if (value.startsWith("=")) {
-                                                               editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null);
+                                                               editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), ClientModel.CONTENT_EXPRESSION, value, Bindings.STRING, null);
                                                        } else {
-                                                               editor.edit(tr, SpreadsheetUtils.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null);
+                                                               editor.edit(tr, Spreadsheets.cellName(startRow+i, startCol+j), Variant.ofInstance(value), null);
                                                        }
 
                                                }
@@ -243,8 +244,8 @@ public class ExcelAdapter implements ActionListener {
 
                                for(int i=0;i<from.height();i++) {
                                        for(int j=0;j<from.width();j++) {
-                                               String fromCell = SpreadsheetUtils.cellName(from.startRow+i, from.startColumn+j);
-                                               String toCell = SpreadsheetUtils.cellName(to.startRow+i, to.startColumn+j);
+                                               String fromCell = Spreadsheets.cellName(from.startRow+i, from.startColumn+j);
+                                               String toCell = Spreadsheets.cellName(to.startRow+i, to.startColumn+j);
                                                Object obj = model.getPropertyAt(fromCell, "content");
                                                if (obj == null)
                                                    continue;
index 881cdad0dfd4faf3e6f982f7a1c625009f551337..1d9a90eabebd92a5e30d3aaf31ad9d8998918274 100644 (file)
@@ -11,7 +11,7 @@ import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.spreadsheet.CellEditor;
 import org.simantics.spreadsheet.ClientModel;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
+import org.simantics.spreadsheet.Spreadsheets;
 
 public class ExpressionTextListener implements FocusListener, KeyListener {
 
@@ -44,9 +44,9 @@ public class ExpressionTextListener implements FocusListener, KeyListener {
                if(currentRow == -1 || currentColumn == -1) return;
                
                if (current.startsWith("=")) {
-                   editor.edit(null, SpreadsheetUtils.cellName(currentRow, currentColumn), ClientModel.CONTENT_EXPRESSION, current, Bindings.STRING, null);
+                   editor.edit(null, Spreadsheets.cellName(currentRow, currentColumn), ClientModel.CONTENT_EXPRESSION, current, Bindings.STRING, null);
                } else {
-                   editor.edit(null, SpreadsheetUtils.cellName(currentRow, currentColumn), Variant.ofInstance(current), null);
+                   editor.edit(null, Spreadsheets.cellName(currentRow, currentColumn), Variant.ofInstance(current), null);
                }
                undoPoint = current;
                
index 8a8da732b3e121c082dd8ac3aab4cd22d65ba31c..500d8cd7f6bf1bad8adac4967699caee6309d41a 100644 (file)
@@ -11,9 +11,10 @@ import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.db.layer0.variable.Variable;
 import org.simantics.spreadsheet.Adaptable;
 import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
-import org.simantics.utils.ui.jface.ActiveSelectionProvider;
 import org.simantics.ui.selection.VariableWorkbenchSelectionElement;
+import org.simantics.utils.ui.jface.ActiveSelectionProvider;
 
 public class SelectionListener implements ListSelectionListener {
 
@@ -65,7 +66,7 @@ public class SelectionListener implements ListSelectionListener {
 
                                String expression = "";
 
-                               Object expressionO = clientModel.getPossiblePropertyAt(SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
+                               Object expressionO = clientModel.getPossiblePropertyAt(Spreadsheets.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
                                if(expressionO instanceof String) {
                                        expression = (String)expressionO;
                                } else if(expressionO instanceof Variant) {
@@ -73,7 +74,7 @@ public class SelectionListener implements ListSelectionListener {
                                }
 
                                if(expression == null) {
-                                       Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT);
+                                       Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, Spreadsheets.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT);
                                        if(content != null)
                                                expression =  content.getValue().toString();
                                        else
index 5940cfbe0224a7e73ce495e3c18b196361db65af..7d60519470116eb066866dc1ba0e48d452c9c38e 100644 (file)
@@ -72,16 +72,16 @@ import org.simantics.spreadsheet.CellEditor.Transaction;
 import org.simantics.spreadsheet.ClientModel;
 import org.simantics.spreadsheet.ClientModel.OperationMode;
 import org.simantics.spreadsheet.SheetCommands;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.cell.Parsers;
 import org.simantics.spreadsheet.common.cell.StringCellParser;
 import org.simantics.spreadsheet.event.model.RemoveCellHandler;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.ui.colors.Colors;
 import org.simantics.ui.dnd.LocalObjectTransfer;
 import org.simantics.ui.dnd.LocalObjectTransferable;
 import org.simantics.ui.fonts.Fonts;
-import org.simantics.utils.ui.dialogs.ShowMessage;
 import org.simantics.utils.ui.awt.WrapLayout;
+import org.simantics.utils.ui.dialogs.ShowMessage;
 import org.simantics.utils.ui.jface.ActiveSelectionProvider;
 
 @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -409,16 +409,16 @@ public class SpreadsheetModel {
                                        for(int col : selectedColumns) {
                                                for(int row : selectedRows) {
                                                        
-                                                       String location = SpreadsheetUtils.cellName(row, col);
+                                                       String location = Spreadsheets.cellName(row, col);
                                                        
                                                        // No
                                                        if(index == 0) {
                                                                if(col > 0) {
-                                                                       String left = SpreadsheetUtils.cellName(row, col-1);
+                                                                       String left = Spreadsheets.cellName(row, col-1);
                                                                        setCurrent(left, getCurrent(left, row, col-1) & 2);
                                                                }
                                                                if(row > 0) {
-                                                                       String up = SpreadsheetUtils.cellName(row-1, col);
+                                                                       String up = Spreadsheets.cellName(row-1, col);
                                                                        setCurrent(up, getCurrent(up, row-1, col) & 1);
                                                                }
                                                                setCurrent(location, 0);
@@ -430,14 +430,14 @@ public class SpreadsheetModel {
                                                        // Top
                                                        else if(index == 2) {
                                                                if(row > 0) {
-                                                                       String up = SpreadsheetUtils.cellName(row-1, col);
+                                                                       String up = Spreadsheets.cellName(row-1, col);
                                                                        setCurrent(up, getCurrent(up, row-1, col) | 2);
                                                                }
                                                        }
                                                        // Left
                                                        else if(index == 3) {
                                                                if(col > 0) {
-                                                                       String left = SpreadsheetUtils.cellName(row, col-1);
+                                                                       String left = Spreadsheets.cellName(row, col-1);
                                                                        setCurrent(left, getCurrent(left, row, col-1) | 1);
                                                                }
                                                        }
@@ -530,7 +530,7 @@ public class SpreadsheetModel {
                                                                if (selection.intersects(span)) {
                                                                        selection = selection.union(span);
                                                                        found = true;
-                                                                       String location = SpreadsheetUtils.cellName(span.y, span.x);
+                                                                       String location = Spreadsheets.cellName(span.y, span.x);
                                                                        editor.edit(transaction, location, ClientModel.ROW_SPAN, 1, Bindings.INTEGER, null);
                                                                        editor.edit(transaction, location, ClientModel.COLUMN_SPAN, 1, Bindings.INTEGER, null);
                                                                        iter.remove();
@@ -538,7 +538,7 @@ public class SpreadsheetModel {
                                                        }
                                                }
                                                
-                                               String location = SpreadsheetUtils.cellName(selection.y, selection.x);
+                                               String location = Spreadsheets.cellName(selection.y, selection.x);
                                                if (selection.height > 1) {
                                                        editor.edit(transaction, location, ClientModel.ROW_SPAN, selection.height, Bindings.INTEGER, null);
                                                }
@@ -1042,7 +1042,7 @@ public class SpreadsheetModel {
        private void editSelection(CellEditor editor, Transaction transaction, String property, Object value, Binding binding) { 
                for(int col : table.getSelectedColumns()) {
                        for(int row : table.getSelectedRows()) {
-                               String location = SpreadsheetUtils.cellName(row, col);
+                               String location = Spreadsheets.cellName(row, col);
                                editor.edit(transaction, location, property, value, binding, null);
                        }
                }
@@ -1059,7 +1059,7 @@ public class SpreadsheetModel {
 //             Transaction transaction = editor.startTransaction(); 
                for(int col : selectedColumns) {
                        for(int row : selectedRows) {
-                               String location = SpreadsheetUtils.cellName(row, col);
+                               String location = Spreadsheets.cellName(row, col);
                                
                                CellValue value = (CellValue)table.getValueAt(row, col);
                                int align = value != null ? value.align : 0;
index 24fade56ae6a839b93195f7e723a699c42475256..f84e0ef84747e402696c6fa6af2a0000a471231d 100644 (file)
@@ -27,6 +27,7 @@ import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.spreadsheet.CellEditor;
 import org.simantics.spreadsheet.ClientModel;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEditor {
@@ -135,7 +136,7 @@ class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEd
         
        String str = (String)getCellEditorValue();
 
-       String cellName = SpreadsheetUtils.cellName(row, column);
+       String cellName = Spreadsheets.cellName(row, column);
        Object expressionO = clientModel.getPossiblePropertyAt(cellName, ClientModel.CONTENT_EXPRESSION);
        String expression = null;
        if(expressionO instanceof String) {
@@ -158,11 +159,11 @@ class TextTableCellEditor extends DefaultCellEditor implements SpreadsheetCellEd
                return;
         
         if (str.startsWith("=")) {
-                       editor.edit(null, SpreadsheetUtils.cellName(row, column), ClientModel.CONTENT_EXPRESSION, str, Bindings.STRING, null);
+                       editor.edit(null, Spreadsheets.cellName(row, column), ClientModel.CONTENT_EXPRESSION, str, Bindings.STRING, null);
                //Update cell expression
                        clientModel.setProperty(cellName, ClientModel.CONTENT_EXPRESSION, str);
                } else {
-                       editor.edit(null, SpreadsheetUtils.cellName(row, column), Variant.ofInstance(str), null);
+                       editor.edit(null, Spreadsheets.cellName(row, column), Variant.ofInstance(str), null);
                        //Update cell expression
                        clientModel.setProperty(cellName, ClientModel.CONTENT_EXPRESSION, null); //If not an expression, then the expression property is null
                }
index 74a539c73a0d85a82094fdf0bd3a5776377bd4bd..f0b9c8c0f2feddd682d4149ee5943653d14c32c1 100644 (file)
@@ -24,8 +24,8 @@ import org.simantics.db.management.ISessionContext;
 import org.simantics.selectionview.PropertyTabContributorImpl;
 import org.simantics.spreadsheet.CommandCellExecutor;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.graph.GraphUI;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 public class CommandCellTab extends PropertyTabContributorImpl {
 
@@ -89,7 +89,7 @@ public class CommandCellTab extends PropertyTabContributorImpl {
                                if(ui != null) {
                                        CommandCellExecutor executor = (CommandCellExecutor)ui.getAdapter(CommandCellExecutor.class);
                                        String location = variable.getPossiblePropertyValue(graph, "HasName");
-                                       Range range = SpreadsheetUtils.decodeCellAbsolute(location);
+                                       Range range = Spreadsheets.decodeCellAbsolute(location);
                                        executor.execute(range.startRow, range.startColumn);
                                        System.out.println("uiui");
                                }
index 03467d6f67ff86f48ee12bd1da7ef37e38c8a39b..e68f115adf642b8663c11179d3f8a6fe0d48694f 100644 (file)
@@ -29,10 +29,11 @@ import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.excel.Excel;
 import org.simantics.excel.ExcelException;
 import org.simantics.layer0.Layer0;
+import org.simantics.spreadsheet.CellParseException;
 import org.simantics.spreadsheet.ClientModel;
 import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.common.client.ClientModelListenerAdapter;
-import org.simantics.spreadsheet.common.exception.CellParseException;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
 import org.simantics.spreadsheet.util.SpreadsheetUtils;
 import org.simantics.utils.FileUtils;
@@ -148,7 +149,7 @@ public class ExcelLink extends ClientModelListenerAdapter {
                if(ClientModel.CONTENT.equals(property) && value != null && value instanceof Variant) {
                        
                        if(handle == 0) return;
-                       Range range = SpreadsheetUtils.decodeCellAbsolute(location);
+                       Range range = Spreadsheets.decodeCellAbsolute(location);
                        excel.setString_(handle, range.startRow, range.startColumn, ((Variant)value).getValue().toString());
                        final String modis = excel.getModifications_(handle);
 
@@ -159,7 +160,7 @@ public class ExcelLink extends ClientModelListenerAdapter {
 
                                        String[] parts = (modis+"0").split("#");
                                        
-                                       Range range = SpreadsheetUtils.decodeRange(parts[0]);
+                                       Range range = Spreadsheets.decodeRange(parts[0]);
                                        
                                Layer0 L0 = Layer0.getInstance(graph);
                                SpreadsheetResource SHEET = SpreadsheetResource.getInstance(graph);
@@ -168,7 +169,7 @@ public class ExcelLink extends ClientModelListenerAdapter {
                                        for(int i=0;i<range.height();i++) {
                                                for(int j=0;j<range.width();j++) {
                                                        
-                                                       String addr = SpreadsheetUtils.cellName(range.startRow + i, range.startColumn + j);
+                                                       String addr = Spreadsheets.cellName(range.startRow + i, range.startColumn + j);
                                                        String content = parts[index++];
                                                        
                                                        Resource cell = Layer0Utils.getPossibleChild(graph, container, addr);
@@ -247,7 +248,7 @@ public class ExcelLink extends ClientModelListenerAdapter {
                                        
                                                for(Pair<String, Object> label : model.listAll(ClientModel.LABEL)) {
                                                        try {
-                                                               Range range = SpreadsheetUtils.decodeCellAbsolute(label.first);
+                                                               Range range = Spreadsheets.decodeCellAbsolute(label.first);
                                                                excel.setString_(handle, range.startRow, range.startColumn, (String)label.second);
 //                                                             System.err.println("excel.setString " + label.second);
                                                        } catch (CellParseException e) {
@@ -255,7 +256,7 @@ public class ExcelLink extends ClientModelListenerAdapter {
                                                }
                                                for(Pair<String, Object> label : model.listAll(ClientModel.CONTENT)) {
                                                        try {
-                                                               Range range = SpreadsheetUtils.decodeCellAbsolute(label.first);
+                                                               Range range = Spreadsheets.decodeCellAbsolute(label.first);
                                                                //excel.setString_(handle, range.startRow, range.startColumn, (String)label.second);
                                                                
                                                                String uri = (String)label.second;
index 11da9ac7b1779a22c59e4f6c0dd33195dad72aa0..ea54d631949ebda8ae96dfd7a0b351b35f9dd80f 100644 (file)
@@ -11,10 +11,10 @@ import org.simantics.db.layer0.variable.Variable;
 import org.simantics.db.layer0.variable.Variables;
 import org.simantics.selectionview.ComparableTabContributor;
 import org.simantics.selectionview.SelectionProcessor;
+import org.simantics.spreadsheet.Spreadsheets;
 import org.simantics.spreadsheet.resource.SpreadsheetResource;
 import org.simantics.spreadsheet.ui.TableSelection;
 import org.simantics.spreadsheet.ui.editor.NoCellTab.NoCellInput;
-import org.simantics.spreadsheet.util.SpreadsheetUtils;
 
 /**
  * @author Tuukka Lehtonen
@@ -32,7 +32,7 @@ public class SpreadsheetSelectionProcessor implements SelectionProcessor<Collect
                final TableSelection sel = (TableSelection)it.next();
                int row = sel.getRows()[0];
                int column = sel.getColumns()[0];
-               String location = SpreadsheetUtils.cellName(row, column);
+               String location = Spreadsheets.cellName(row, column);
                ArrayList<ComparableTabContributor> result = new ArrayList<ComparableTabContributor>(); 
                final Variable cell = variable.getPossibleChild(graph, location);
                if(cell != null) {
index eca7bdba8f03f22510b7980a94dbfe10c16c0901..2b095890ee91f878640e4a80cd0787a8e744367b 100644 (file)
@@ -1,7 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="lib" path="lib/commons-math3-3.6.1.jar"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
index ce6f47de20859ca56d951eccab673e7622618172..6c49df22c90a7e604af19eb19abfbef2208151bc 100644 (file)
@@ -6,8 +6,21 @@ Bundle-Version: 1.1.0.qualifier
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.simantics.spreadsheet,
  org.simantics.spreadsheet.cell.handler,
- org.simantics.spreadsheet.event.model
+ org.simantics.spreadsheet.event.model,
+ org.simantics.spreadsheet.solver,
+ org.simantics.spreadsheet.solver.formula,
+ org.simantics.spreadsheet.solver.formula.parser,
+ org.simantics.spreadsheet.solver.formula.parser.ast,
+ org.simantics.spreadsheet.synchronization
 Require-Bundle: org.simantics.utils.datastructures;bundle-version="1.0.0",
- org.simantics.databoard;bundle-version="0.6.1"
+ org.simantics.databoard;bundle-version="0.6.1",
+ it.unimi.dsi.fastutil;bundle-version="7.2.1",
+ gnu.trove3,
+ org.simantics.scl.runtime,
+ org.simantics.datatypes;bundle-version="1.0.0",
+ org.simantics.common;bundle-version="1.0.0",
+ org.simantics.simulator.toolkit;bundle-version="1.0.0",
+ org.simantics.structural.synchronization;bundle-version="1.0.0",
+ org.apache.poi
 Bundle-Vendor: VTT Technical Research Centre of Finland
 Automatic-Module-Name: org.simantics.spreadsheet
index dfa46571bba26df766d0c2656b9133051b8a9ca5..a1c21d247965fc14d7d9b35e138d12c3e4a766a7 100644 (file)
@@ -12,4 +12,5 @@
 source.. = src/
 output.. = bin/
 bin.includes = META-INF/,\
-               .
+               .,\
+               lib/
diff --git a/bundles/org.simantics.spreadsheet/lib/commons-math3-3.6.1.jar b/bundles/org.simantics.spreadsheet/lib/commons-math3-3.6.1.jar
new file mode 100644 (file)
index 0000000..0ff582c
Binary files /dev/null and b/bundles/org.simantics.spreadsheet/lib/commons-math3-3.6.1.jar differ
index a1c38ee4767d3e8d93a4ca9452c61f05e3050035..7865ed84eadb4262e34a3c8f1d72306a5e0b7356 100644 (file)
@@ -14,7 +14,7 @@ package org.simantics.spreadsheet;
 
 
 public interface Adaptable {
-       
-       <T> T getAdapter(Class<T> clazz);
-       
+
+    <T> T getAdapter(Class<T> clazz);
+
 }
index b322335a1c0bcd8d36d908526d17daced932fc92..a90cf51466127cd0c378a9eef616247dae943a08 100644 (file)
@@ -20,53 +20,53 @@ import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.spreadsheet.ClientModel.OperationMode;
 
 public interface CellEditor<O> {
-    
-       public interface Transaction<O> {
-           
-           void setContext(Object context);
-           
-           Object getContext();
-           
-           void add(O operation);
-           
-               /*
-                * Applies the operations collected with this transaction
-                
-                */
-           void commit();
-           
-           boolean isOperationMode();
-        
+
+    public interface Transaction<O> {
+
+        void setContext(Object context);
+
+        Object getContext();
+
+        void add(O operation);
+
+        /*
+         * Applies the operations collected with this transaction
+         * 
+         */
+        void commit();
+
+        boolean isOperationMode();
+
         List<Object> needSynchronization();
 
         void needSynchronization(Object synchronizable);
-       }
-       
-       /*
-        * Sets the given property of the given cell
-        
-        * @param transaction a combined transaction, null for immediate change
-        * @param location a cell location e.g. 'A1'
-        * @param property the name of the property
-        * @param value the property value
-        * @param binding used for serializing the value 
-        */
-       <T> void edit(Transaction<O> transaction, String location, String property, T value, Binding binding, Consumer<?> callback);
-       /*
-        * Edits the given cell using the given textual input
-        
-        * @param transaction a combined transaction, null for immediate change
-        * @param location a cell location e.g. 'A1'
-        * @param value a text describing the change
-        */
+    }
+
+    /*
+     * Sets the given property of the given cell
+     * 
+     * @param transaction a combined transaction, null for immediate change
+     * @param location a cell location e.g. 'A1'
+     * @param property the name of the property
+     * @param value the property value
+     * @param binding used for serializing the value 
+     */
+    <T> void edit(Transaction<O> transaction, String location, String property, T value, Binding binding, Consumer<?> callback);
+    /*
+     * Edits the given cell using the given textual input
+     * 
+     * @param transaction a combined transaction, null for immediate change
+     * @param location a cell location e.g. 'A1'
+     * @param value a text describing the change
+     */
     void edit(Transaction<O> transaction, String location, Variant variant, Consumer<?> callback);
 
     void copy(Transaction<O> transaction, String location, MutableVariant variant, Consumer<?> callback);
-    
-       /*
-        * Creates a new transaction object
-        
-        */
+
+    /*
+     * Creates a new transaction object
+     * 
+     */
     Transaction<O> startTransaction(OperationMode mode);
-    
+
 }
index ca15766c591c29613c074d755841efd95f9f5e51..45c1fdf1a87d79efd65ede1ee1deb4b79e623523 100644 (file)
@@ -15,8 +15,8 @@ package org.simantics.spreadsheet;
  * An interface for updating a client spreadsheet model
  */
 public interface CellModifier {
-       void setProperty(String location, String property, Object value);
-       void clear(String location);
-       void clearAll();
-       void flush();
+    void setProperty(String location, String property, Object value);
+    void clear(String location);
+    void clearAll();
+    void flush();
 }
similarity index 93%
rename from bundles/org.simantics.spreadsheet.common/src/org/simantics/spreadsheet/common/exception/CellParseException.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/CellParseException.java
index 055c002acda00b05a020bfbe52ef640aa174b56c..d5025bed5832e9da2c042e9dd370c229146a7604 100644 (file)
@@ -9,7 +9,7 @@
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.common.exception;
+package org.simantics.spreadsheet;
 
 public class CellParseException extends RuntimeException {
 
@@ -18,5 +18,5 @@ public class CellParseException extends RuntimeException {
     public CellParseException(String message) {
         super(message);
     }
-    
+
 }
index 55cfa1f5e6d57689855448f17388a3c27f3db5e3..7304419d17db9cdb07286ade159a5a9b0beb8f48 100644 (file)
@@ -18,112 +18,112 @@ import org.simantics.utils.datastructures.Pair;
 
 
 public interface ClientModel extends CellModifier {
-    
+
     public enum OperationMode {
         OPERATION,
         EDIT_MODE
     }
 
-       public interface ClientModelListener {
-               
-               public void rows(int amount);
-               public void columns(int amount);
-
-               public void columnLabels(String[] labels);
-               public void rowLabels(String[] labels);
-               public void columnWidths(int[] widths);
-               
-               public void sources(String[] available, String current);
-               
-               public void propertyChange(String location, String property, Object value);
-               public void cleared(String location);
-               public void flush();
-               
-       }
-
-       public static final String EXCEL = "Excel";
-       public static final String EXCEL_VISIBLE = "Visible";
-
-       /**
-        * The location argument to use for setting header properties.
-        * @see #HEADERS_COL_LABELS
-        * @see #HEADERS_COL_WIDTHS
-        * @see #HEADERS_ROW_HEIGHTS
-        * @see #HEADERS_ROW_LABELS
-        */
-       public static final String HEADERS = "Headers";
-       public static final String HEADERS_COL_WIDTHS = "columnWidths";
-       public static final String HEADERS_ROW_HEIGHTS = "rowHeights";
-       public static final String HEADERS_COL_LABELS = "columnLabels";
-       public static final String HEADERS_ROW_LABELS = "rowLabels";
-       
-       /**
-        * The location argument to use for setting dimension properties.
-        * @see #DIMENSIONS_COL_COUNT
-        * @see #DIMENSIONS_FIT_COLS
-        * @see #DIMENSIONS_FIT_ROWS
-        * @see #DIMENSIONS_ROW_COUNT
-        */
-       public static final String DIMENSIONS = "Dimensions";
-       public static final String DIMENSIONS_FIT_ROWS = "fitRows";
-       public static final String DIMENSIONS_FIT_COLS = "fitColumns";
-       public static final String DIMENSIONS_COL_COUNT = "columnCount";
-       public static final String DIMENSIONS_ROW_COUNT = "rowCount";
-
-       public static final String SOURCES = "Sources";
-       public static final String SOURCES_AVAILABLE = "available";
-       public static final String SOURCES_CURRENT = "current";
-
-       public static final String SHEETS = "Sheets";
-       public static final String SHEETS_AVAILABLE = "available";
-       public static final String SHEETS_CURRENT = "current";
-       
-       public static final String CONTEXT = "Context";
-       public static final String CONTEXT_CURRENT = "current";
-       
-       public static final String MODE = "Mode";
-       public static final String MODE_CURRENT = "current";
-       
-       public static final String STATES = "States";
-       public static final String STATES_AVAILABLE = "available";
-       public static final String STATES_CURRENT = "current";
-
-       public static final String FONT = "font";
-       public static final String FOREGROUND = "foreground";
-       public static final String BACKGROUND = "background";
-       public static final String BORDER = "border";
-       public static final String ALIGN = "align";
-       public static final String LABEL = "label";
-       public static final String CONTENT = "content";
-       public static final String CONTENT_EXPRESSION = "content#expression";
-       public static final String COMPUTED = "Computed";
-       public static final String LOCKED = "locked";
-       public static final String ROW_SPAN = "rowSpan";
-       public static final String COLUMN_SPAN = "columnSpan";
-       
+    public interface ClientModelListener {
+
+        public void rows(int amount);
+        public void columns(int amount);
+
+        public void columnLabels(String[] labels);
+        public void rowLabels(String[] labels);
+        public void columnWidths(int[] widths);
+
+        public void sources(String[] available, String current);
+
+        public void propertyChange(String location, String property, Object value);
+        public void cleared(String location);
+        public void flush();
+
+    }
+
+    public static final String EXCEL = "Excel";
+    public static final String EXCEL_VISIBLE = "Visible";
+
+    /**
+     * The location argument to use for setting header properties.
+     * @see #HEADERS_COL_LABELS
+     * @see #HEADERS_COL_WIDTHS
+     * @see #HEADERS_ROW_HEIGHTS
+     * @see #HEADERS_ROW_LABELS
+     */
+    public static final String HEADERS = "Headers";
+    public static final String HEADERS_COL_WIDTHS = "columnWidths";
+    public static final String HEADERS_ROW_HEIGHTS = "rowHeights";
+    public static final String HEADERS_COL_LABELS = "columnLabels";
+    public static final String HEADERS_ROW_LABELS = "rowLabels";
+
+    /**
+     * The location argument to use for setting dimension properties.
+     * @see #DIMENSIONS_COL_COUNT
+     * @see #DIMENSIONS_FIT_COLS
+     * @see #DIMENSIONS_FIT_ROWS
+     * @see #DIMENSIONS_ROW_COUNT
+     */
+    public static final String DIMENSIONS = "Dimensions";
+    public static final String DIMENSIONS_FIT_ROWS = "fitRows";
+    public static final String DIMENSIONS_FIT_COLS = "fitColumns";
+    public static final String DIMENSIONS_COL_COUNT = "columnCount";
+    public static final String DIMENSIONS_ROW_COUNT = "rowCount";
+
+    public static final String SOURCES = "Sources";
+    public static final String SOURCES_AVAILABLE = "available";
+    public static final String SOURCES_CURRENT = "current";
+
+    public static final String SHEETS = "Sheets";
+    public static final String SHEETS_AVAILABLE = "available";
+    public static final String SHEETS_CURRENT = "current";
+
+    public static final String CONTEXT = "Context";
+    public static final String CONTEXT_CURRENT = "current";
+
+    public static final String MODE = "Mode";
+    public static final String MODE_CURRENT = "current";
+
+    public static final String STATES = "States";
+    public static final String STATES_AVAILABLE = "available";
+    public static final String STATES_CURRENT = "current";
+
+    public static final String FONT = "font";
+    public static final String FOREGROUND = "foreground";
+    public static final String BACKGROUND = "background";
+    public static final String BORDER = "border";
+    public static final String ALIGN = "align";
+    public static final String LABEL = "label";
+    public static final String CONTENT = "content";
+    public static final String CONTENT_EXPRESSION = "content#expression";
+    public static final String COMPUTED = "Computed";
+    public static final String LOCKED = "locked";
+    public static final String ROW_SPAN = "rowSpan";
+    public static final String COLUMN_SPAN = "columnSpan";
+
     public static final String ITERATION_ENABLED = "iterationEnabled";
-       
+
     void addListener(ClientModelListener listener);
     void removeListener(ClientModelListener listener);
     <T> T getPropertyAt(String location, String property);
     <T> T getPossiblePropertyAt(String location, String property);
-    
+
     int[] getColumnWidths();
     int[] getRowHeights();
-    
+
     int getRows();
     int getColumns();
 
-       public Collection<Pair<String, Object>> listAll(String property);
-       
-       /*
-        * Returns a copy of the span. Null if not found.
-        */
-       public Rectangle getSpan(int row, int column);
-
-       /*
-        * Returns a copy of the span list.
-        */     
-       public List<Rectangle> getSpans();
-       
+    public Collection<Pair<String, Object>> listAll(String property);
+
+    /*
+     * Returns a copy of the span. Null if not found.
+     */
+    public Rectangle getSpan(int row, int column);
+
+    /*
+     * Returns a copy of the span list.
+     */        
+    public List<Rectangle> getSpans();
+
 }
index 2287c1f616f112c650877d6764d0270ef7b83f5b..84eaa00b50e4c734c3fb09d20c19aa1cae7a1b50 100644 (file)
@@ -14,7 +14,7 @@ package org.simantics.spreadsheet;
 
 
 public interface CommandCellExecutor {
-    
+
     void execute(int row, int column);
-    
+
 }
index e49ce181f3a8f8ef698f2d7fdbebf77615ecfa83..bd055461b7234eece315668cda4bae6d028b06bb 100644 (file)
@@ -14,6 +14,6 @@ package org.simantics.spreadsheet;
 
 public interface Disposable {
 
-       void dispose();
-       
+    void dispose();
+
 }
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/ExternalRef.java
new file mode 100644 (file)
index 0000000..70486d9
--- /dev/null
@@ -0,0 +1,16 @@
+package org.simantics.spreadsheet;
+
+import org.simantics.databoard.binding.mutable.Variant;
+
+public interface ExternalRef {
+
+    public interface ExternalRefListener {
+
+        public void newValue(Variant value);
+        public boolean isDisposed();
+
+    }
+
+    public void listen(Object context, ExternalRefListener listener);
+
+}
index 9dfe56e9563d829fdf7b13d9f5ee50161ab32462..8288cb6f38e6d46c8db875e1e93eddf2d00e84e1 100644 (file)
@@ -15,11 +15,11 @@ import java.util.Collection;
 
 
 public interface Matrix {
-       
-       int getColumnCount();
-       int getRowCount();
-       Object get(int row, int column);
-       Collection<Object> getColumn(int column);
-       Collection<Object> getRow(int column);
-       
+
+    int getColumnCount();
+    int getRowCount();
+    Object get(int row, int column);
+    Collection<Object> getColumn(int column);
+    Collection<Object> getRow(int column);
+
 }
index 3c9d4b87e4d6bd62cf949e6371489f7351fd3122..b4a31c316f65a794614ec197e93a7172401472d3 100644 (file)
@@ -13,26 +13,26 @@ package org.simantics.spreadsheet;
 
 
 public class Range {
-       public static final int MAXROWSPEC = Integer.MAX_VALUE;//1048576;//
-       public static final int MAXCOLUMNSPEC = Integer.MAX_VALUE;//16384;//
-       
+    public static final int MAXROWSPEC = Integer.MAX_VALUE;//1048576;//
+    public static final int MAXCOLUMNSPEC = Integer.MAX_VALUE;//16384;//
+
     public int startRow;
     public int endRow;
     public int startColumn;
     public int endColumn;
-    
+
     public Range(int startRow, int endRow, int startColumn, int endColumn) {
         this.startRow = startRow;
         this.endRow = endRow;
         this.startColumn = startColumn;
         this.endColumn = endColumn;
-        
+
         if(startRow == -1) this.startRow = MAXROWSPEC;
-       if(endRow == -1) this.endRow = MAXROWSPEC;
-       if(startColumn == -1) this.startColumn = MAXCOLUMNSPEC;
-       if(endColumn == -1) this.endColumn = MAXCOLUMNSPEC;
+        if(endRow == -1) this.endRow = MAXROWSPEC;
+        if(startColumn == -1) this.startColumn = MAXCOLUMNSPEC;
+        if(endColumn == -1) this.endColumn = MAXCOLUMNSPEC;
     }
-    
+
     public Range(Range copy) {
         this.startRow = copy.startRow;
         this.endRow = copy.endRow;
@@ -43,46 +43,46 @@ public class Range {
     public static Range combine(Range from, Range to) {
         return new Range(from.startRow, to.endRow, from.startColumn, to.endColumn);
     }
-    
+
     public boolean isFull() {
-       return endRow == MAXROWSPEC && endColumn == MAXCOLUMNSPEC;
+        return endRow == MAXROWSPEC && endColumn == MAXCOLUMNSPEC;
     }
 
     public boolean isFullRows() {
-       return endRow == MAXROWSPEC;
+        return endRow == MAXROWSPEC;
     }
 
     public boolean isFullColumns() {
-       return endColumn == MAXCOLUMNSPEC;
+        return endColumn == MAXCOLUMNSPEC;
     }
 
     public int size() {
         return (endRow-startRow + 1) * (endColumn - startColumn + 1);
     }
-    
+
     public int width() {
-       return (endColumn - startColumn + 1);
+        return (endColumn - startColumn + 1);
     }
-    
+
     public int height() {
-       return (endRow-startRow + 1);
+        return (endRow-startRow + 1);
     }
-    
+
     public boolean contains(Range r) {
-       if(endRow >= 0) {
-               if(r.endRow > endRow) return false;
-               if(r.startRow < startRow) return false;
-       }
-       if(endColumn >= 0) {
-               if(r.startColumn < startColumn) return false;
-               if(r.endColumn > endColumn) return false;
-       }
-       return true;
+        if(endRow >= 0) {
+            if(r.endRow > endRow) return false;
+            if(r.startRow < startRow) return false;
+        }
+        if(endColumn >= 0) {
+            if(r.startColumn < startColumn) return false;
+            if(r.endColumn > endColumn) return false;
+        }
+        return true;
     }
-    
+
     @Override
     public String toString() {
         return "Range[(" + startRow + "," + startColumn + ")-(" + endRow + "," + endColumn + ")]";
     }
-    
+
 }
index 6877ba80ee0b95e9199a9717dc65f84e300925fd..b79910facb42b1cf3eb952d9dc1ff830002fce41 100644 (file)
@@ -2,9 +2,9 @@ package org.simantics.spreadsheet;
 
 public class SheetVariables {
 
-       public static final String CONTENT = "content";
-       public static final String FOREGROUND = "foreground";
-       public static final String BACKGROUND = "background";
-       public static final String RANGE_CELL_NAMES = "rangeCellNames";
+    public static final String CONTENT = "content";
+    public static final String FOREGROUND = "foreground";
+    public static final String BACKGROUND = "background";
+    public static final String RANGE_CELL_NAMES = "rangeCellNames";
 
 }
similarity index 83%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellStyle.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetCellStyle.java
index a8dd3732d7f929089aec33b98b289f931e76d09f..3056e8cfc48424fa48d9f04647937b5ab4aeaf69 100644 (file)
@@ -1,12 +1,18 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet;
 
 import java.util.Collections;
 import java.util.Map;
 
+import org.simantics.spreadsheet.solver.SheetNode;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+
+@SuppressWarnings("rawtypes")
 public class SpreadsheetCellStyle implements SheetNode {
 
-    public final SpreadsheetCell cell;
+    private static final long serialVersionUID = -219628109106298874L;
     
+    public final SpreadsheetCell cell;
+
     public SpreadsheetCellStyle(SpreadsheetCell spreadsheetCell) {
         this.cell = spreadsheetCell;
     }
@@ -25,7 +31,7 @@ public class SpreadsheetCellStyle implements SheetNode {
     public Map getProperties() {
         return Collections.emptyMap();
     }
-    
+
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetMatrix.java
new file mode 100644 (file)
index 0000000..b6896d5
--- /dev/null
@@ -0,0 +1,128 @@
+package org.simantics.spreadsheet;
+
+import java.io.Serializable;
+
+import org.simantics.spreadsheet.solver.formula.FormulaError2;
+
+public class SpreadsheetMatrix implements Serializable {
+
+    private static final long serialVersionUID = 5729700370527844640L;
+
+    private int w;
+    private int h;
+    public Object[] values;
+
+    public SpreadsheetMatrix(int w, int h) {
+        this.w = w;
+        this.h = h;
+        this.values = new Object[w*h];
+    }
+
+    public Object get(int row, int column) {
+        return values[w*row+column];
+    }
+
+    public void set(int row, int column, Object value) {
+        values[w*row+column] = value;
+    }
+
+    public int getWidth() {
+        return w;
+    }
+
+    public int getHeight() {
+        return h;
+    }
+
+    public double sum() {
+        double result = 0;
+        for(int i=0;i<values.length;i++) {
+            Number n = Spreadsheets.asValidNumber(values[i]);
+            if(n != null) result += n.doubleValue();
+        }
+        return result;
+    }
+
+    public Object sumWithFormulaError(){
+        Double result = 0.0;
+        for(int i = 0; i < values.length; i++){
+            Object obj = values[i];
+            if(obj != null){
+                FormulaError2 error = FormulaError2.forObject(obj);
+                if(error!=null) return error.getString();
+
+                Number n = Spreadsheets.asValidNumber(obj);
+                if(n != null) result += n.doubleValue();
+            }
+        }
+        return result;
+    }
+
+    public double average() {
+        double result = 0;
+        double count = 0;
+        for(int i=0;i<values.length;i++) {
+            Number n = Spreadsheets.asValidNumber(values[i]);
+            if(n != null) {
+                result += n.doubleValue();
+                count++;
+            }
+        }
+        if(count == 0) return result;
+        return result / count;
+    }
+
+    public double countOfActualDoubleValues(){
+        double count = 0.0;
+        for(int i = 0; i < values.length; i++){
+            Number n = Spreadsheets.asValidNumber(values[i]);
+            if(n!=null) count++;
+        }
+        return count;
+    }
+
+    public Object productWithFormulaError(){
+        Double result = 1.0;
+        boolean atLeastOne = false;
+        for(int i = 0; i < values.length; i++){
+            Object obj = values[i];
+            if(obj != null){
+                FormulaError2 error = FormulaError2.forObject(obj);
+                if(error!=null) return error.getString();
+
+                Number n = Spreadsheets.asValidNumber(values[i]);
+                if(n != null) {
+                    double dval = n.doubleValue();
+                    if(dval<=0) return FormulaError2.NUM.getString();
+                    result = result*dval;
+                    atLeastOne = true;
+                }
+            }
+        }
+        if(atLeastOne) return result;
+        else return 0.0;
+    }
+
+    public SpreadsheetMatrix pow(Object exponent_) {
+        if(exponent_ instanceof SpreadsheetMatrix) {
+            SpreadsheetMatrix exponent = (SpreadsheetMatrix)exponent_;
+            SpreadsheetMatrix result = new SpreadsheetMatrix(exponent.w, h);
+            for(int i=0;i<h;i++) {
+                for(int j=0;j<exponent.w;j++) {
+                    result.set(i,j, Math.pow(Spreadsheets.asNumber(get(i, 0)),
+                            Spreadsheets.asNumber(exponent.get(0, j))));
+                }
+            }
+            return result;
+        } else {
+            double n = Spreadsheets.asNumber(exponent_);
+            SpreadsheetMatrix result = new SpreadsheetMatrix(w, h);
+            for(int i=0;i<result.values.length;i++) {
+                result.values[i] = Math.pow(Spreadsheets.asNumber(values[i]), n);
+            }
+            return result;
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitable.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitable.java
new file mode 100644 (file)
index 0000000..11a793b
--- /dev/null
@@ -0,0 +1,5 @@
+package org.simantics.spreadsheet;
+
+public interface SpreadsheetVisitable {
+    void accept(SpreadsheetVisitor v);
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/SpreadsheetVisitor.java
new file mode 100644 (file)
index 0000000..69ded35
--- /dev/null
@@ -0,0 +1,17 @@
+package org.simantics.spreadsheet;
+
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetEngine;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.SpreadsheetLines;
+
+public interface SpreadsheetVisitor {
+
+    void visit(SpreadsheetBook book);
+    void visit(SpreadsheetEngine engine);
+    void visit(SpreadsheetLines node);
+    void visit(SpreadsheetLine line);
+    void visit(SpreadsheetCell cell);
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Spreadsheets.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/Spreadsheets.java
new file mode 100644 (file)
index 0000000..db9237e
--- /dev/null
@@ -0,0 +1,486 @@
+package org.simantics.spreadsheet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.scl.runtime.tuple.Tuple;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+
+public class Spreadsheets {
+
+    public static final int SPREADSHEET_BTREE_SIZE = 100;
+    public static final String CELL_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Cell";
+    public static final String LINE_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Line";
+    public static final String LINES_TYPE_URI = "http://www.simantics.org/Spreadsheet-1.2/Lines";
+
+    public static boolean asBoolean(Object object) {
+        if(object instanceof Boolean) return (Boolean)object;
+        else if(object instanceof Number) return ((Number)object).doubleValue() != 0;
+        else if(object instanceof Variant) return asBoolean(((Variant)object).getValue());
+        else if(object instanceof String) {
+            Double d = asDoubleWhereEmptyStringIsZero((String)object);
+            if(d==null) return false;
+            else return d != 0;
+        }
+        return false;
+    }
+
+    public static String asString(Object object) {
+        if(object == null) return "";
+        if(object instanceof String) return (String)object;
+        if(object instanceof Number) {
+            double dVal = ((Number)object).doubleValue();
+            if(dVal == Math.floor(dVal)){
+                return ""+((Number)object).intValue();
+            } else {
+                return object.toString();
+            }
+        }
+        else if(object instanceof Variant) {
+            Object o = ((Variant) object).getValue();
+            if(o instanceof String) return (String)o;
+            else if(o instanceof Number) asString((Number)o);
+            else return o.toString();
+        }
+        return object.toString();
+    }
+
+    public static Double asDoubleWhereEmptyStringIsZero(Object object){
+        if(object instanceof Number)
+            return ((Number)object).doubleValue();
+        else if(object instanceof String) {
+            try {
+                if(((String)object).isEmpty())
+                    return 0.0;
+                return Double.parseDouble((String)object);
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        } else if(object instanceof Variant) {
+            Object o = ((Variant) object).getValue();
+            return asDoubleWhereEmptyStringIsZero(o);
+        } else if (SpreadsheetCell.EMPTY == object) {
+            return null;
+        }
+        return null;
+    }
+
+    public static double asNumber(Object object) {
+        if(object instanceof Number) {
+            return ((Number)object).doubleValue();
+        } else if(object instanceof String) {
+            try {
+                String str = (String)object;
+                if(str.isEmpty()) return 0;
+                return Double.parseDouble((String)object);
+            } catch (NumberFormatException e) {
+                return 0;
+            }
+        } else if(object instanceof Variant) {
+            Object o = ((Variant) object).getValue();
+            return asNumber(o);
+        } else if (SpreadsheetCell.EMPTY == object) {
+            return 0.0;
+        }
+
+        return 0.0;
+
+    }
+
+    public static Number asValidNumber(Object object) {
+        if(object instanceof Number) {
+            return (Number)object;
+        } else if(object instanceof String) {
+            try {
+                return Double.parseDouble((String)object);
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        } else if(object instanceof Variant) {
+            Object o = ((Variant) object).getValue();
+            return asNumber(o);
+        } else if (SpreadsheetCell.EMPTY == object) {
+            return null;
+        }
+
+        return null;
+
+    }
+
+    public static boolean matchCriteria(Object value, Object criteria) {
+        if(value==null || criteria==null) return false;
+
+        if(value instanceof Variant){
+            Double dVal = asDoubleWhereEmptyStringIsZero(value);
+            if(dVal==null) value = ((Variant)value).getValue();
+            else value = dVal;
+        }
+        if(criteria instanceof Variant){
+            Double dVal = asDoubleWhereEmptyStringIsZero(criteria);
+            if(dVal==null) criteria = ((Variant)criteria).getValue();
+            else criteria = dVal;
+        }
+
+        if(criteria instanceof Number && value instanceof Number) {
+            Number nc = (asNumber(criteria));
+            Number nv = (asNumber(value));
+            return nc.equals(nv);
+        }
+        if(criteria instanceof String){
+            boolean nums = false;
+            Object valueObj = null;
+            if(value instanceof Number){
+                valueObj = ((Number)value).doubleValue();
+                nums = true;
+            }
+            else valueObj = value.toString();
+
+            String sc = criteria.toString();
+            if(sc.length() >= 3){
+                String oper = sc.substring(0, 2);
+                String criteriaStr = sc.substring(2);
+                Double criteriaNum = null;
+                try {
+                    criteriaNum = Double.parseDouble(criteriaStr);
+                    if(oper.equals("<>")){
+                        if(!nums) return true;
+                    }
+                    else if(!nums) return false;
+                    nums = true;
+                } catch (NumberFormatException e){
+                    if(oper.equals("<>")){
+                        if(nums) return true;
+                    }
+                    else if(nums) return false;
+                    nums = false;
+                }
+
+                if(oper.equals(">=")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) >= 0 ;
+                    else return ((Number)valueObj).doubleValue() >= criteriaNum;
+                } else if(oper.equals("<=")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) <= 0 ;
+                    else return ((Number)valueObj).doubleValue() <= criteriaNum;
+                } else if(oper.equals("<>")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) != 0 ;
+                    else return ((Number)valueObj).doubleValue() != criteriaNum;
+                }
+            }
+            if(sc.length() >= 2){
+                String oper = sc.substring(0, 1);
+                String criteriaStr = sc.substring(1);
+                Double criteriaNum = null;
+
+                try {
+                    criteriaNum = Double.parseDouble(criteriaStr);
+                    if(!nums) return false;
+                    nums = true;
+                } catch (NumberFormatException e){
+                    if(nums) return false;
+                    nums = false;
+                }
+                if(oper.equals("<")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) < 0;
+                    else return ((Number)valueObj).doubleValue() < criteriaNum;
+                } else if(oper.equals(">")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) > 0;
+                    else return ((Number)valueObj).doubleValue() > criteriaNum;
+                } else if(oper.equals("=")){
+                    if(!nums) return (valueObj.toString().toLowerCase()).compareTo(criteriaStr.toLowerCase()) == 0;
+                    else return ((Number)valueObj).doubleValue() == criteriaNum;
+                }
+            }
+            return sc.equals(valueObj);
+        }
+        else if (criteria instanceof Number){
+            return false;
+        }
+        throw new IllegalStateException();
+    }
+
+    public static boolean excelEquals(Object left, Object right) {
+        if(left instanceof String) {
+            if(right instanceof String) {
+                return ((String) left).toLowerCase().equals(((String) right).toLowerCase());
+            }
+        }
+        return left.equals(right);
+    }
+
+
+    //  1 kirjain, 'A' + column
+    //  2 kirjainta, 'A' + column % 26 , 'A' + int((column-26)/26)
+    //  3 kirjainta 'A' + column % 26 , 'A' + int(column-(26*(26+1)) / 26) % 26
+
+    //    0              26
+    //    26             26 + 26*26
+    //    26 + 26*26     26 + 26*26 + 26*26*26
+
+    public static String columnName(int column, int current, int limit, int chars) {
+
+        if(column < limit) {
+
+            char[] buf = new char[chars];
+            column -= current;
+            for(int i=chars-1;i>=0;i--) {
+                char rem = (char)(column % 26);
+                column = (column / 26);
+                buf[i] = (char)('A' + rem); 
+            }
+            return new String(buf);
+
+        } else return columnName(column, limit, 26*(limit+1), chars+1);
+
+    }
+
+    public static String columnName(int column) {
+        return columnName(column, 0, 26, 1);
+    }    
+
+    public static String cellName(int row, int column) {
+
+        String result = columnName(column);
+        result += (row+1);
+        return result;
+
+    }    
+
+    public static String offset(String location, int rowOffset, int columnOffset) {
+
+        Range range = decodeCellAbsolute(location);
+        String result = cellName(range.startRow + rowOffset, range.startColumn + columnOffset); 
+        //      System.err.println("offset " + location + "(" + rowOffset + " " + columnOffset + ") = >" + result);
+        return result;
+
+    }
+
+    public static Range decodeCellAbsolute(String identifier) {
+        long l = decodeCellCoded(identifier);
+        int row = (int)(l & 0xffffffff) - 1;
+        int column = (int)((l>>32) & 0xffffffff);
+        return new Range(row, row, column, column);
+    }
+
+    public static Range decodePossibleCellAbsolute(String identifier) {
+        try {
+            return decodeCellAbsolute(identifier);
+        } catch (CellParseException e) {
+            return null;
+        }
+    }
+
+    public static long decodeCellCoded(String identifier) {
+
+        //        System.out.println("decodecellabsolute " + identifier);
+
+        int row = 0;
+        int column = 0;
+
+//      identifier.
+
+        int position = 0;
+
+        // We skip $ here
+        if(identifier.charAt(position) == '$') position++;
+
+        int length = identifier.length();
+
+        while(position < length) {
+            char b = identifier.charAt(position);
+            if(b >= 'A' && b <= 'Z') column = column * 26 + (b-'A' + 1);
+            else break;
+            position++;
+        }
+
+        // We skip $ here
+        if(position < length)
+            if(identifier.charAt(position) == '$')
+                position++;
+
+        while(position < length) {
+            char b = identifier.charAt(position);
+            if(b >= '0' && b <= '9'){
+                row = row * 10 + b-'0';
+            }
+            else if(b=='-' && position < (length-1)){//identify use of full row range here.
+                position++;
+                char b2 = identifier.charAt(position);
+                if(b2=='1'){
+                    row = 0;
+                    position++;
+                    break;
+                }
+            }
+            else {
+                break;
+            }
+            position++;
+        }
+
+        if(position == length) {
+
+            // We need to be able to express -1 in row => report row + 1 here
+            column--;
+            //            System.err.println("ra " + identifier + " => " + row + " " + column);
+            return row + (((long)column)<<32);
+
+        } else {
+
+            throw new CellParseException("Cell identifier '" + identifier + "' is not a valid cell reference.");
+
+        }
+
+    }
+
+    public static Range decodeCellRelative(String identifier, int row, int column) {
+
+        int offset = Integer.valueOf(identifier.substring(1).trim());
+        //        System.out.println("offset=" + offset);
+
+        if(identifier.startsWith("L") || identifier.startsWith("l")) {
+            return new Range(row, row, column-offset, column-offset);
+        } else if(identifier.startsWith("R") || identifier.startsWith("r")) {
+            return new Range(row, row, column+offset, column+offset);
+        } else if(identifier.startsWith("U") || identifier.startsWith("u")) {
+            return new Range(row-offset, row-offset, column, column);
+        } else if(identifier.startsWith("D") || identifier.startsWith("d")) {
+            return new Range(row+offset, row+offset, column, column);
+        } else {
+            throw new CellParseException("Relative cell syntax must begin with L|R|U|D.");
+        }
+
+    }
+
+    public static Range decodeCell(String identifier, int row, int column) {
+
+        if(identifier.startsWith("_")) {
+            return decodeCellRelative(identifier.substring(1), row, column);
+        } else {
+            return decodeCellAbsolute(identifier);
+        }
+
+    }
+
+    public static Range decodeReference(String identifier, int row, int column) {
+        if(!identifier.startsWith("&")) throw new CellParseException("A reference cell was expected.");
+        return decodeRange(identifier.substring(1), row, column);
+    }
+
+    public static List<Range> decodeRanges(String ranges){
+        String[] splitted = ranges.split(",");
+        List<Range> result = new ArrayList<>();
+        for(String split : splitted){
+            result.add(decodeRange(split));
+        }
+        return result;
+    }
+
+    public static Object extract(Object object, int row, int column) {
+        if(object instanceof List) {
+            @SuppressWarnings("rawtypes")
+            List list = (List)object;
+            if(list.size() <= row) return null;
+            Object item = list.get(row);
+            if(item instanceof Tuple) {
+                Tuple tuple = (Tuple)item;
+                if(tuple.length() <= column) return null;
+                return tuple.get(column);
+            }
+        }
+        return null;
+    }
+
+
+
+    public static int startRow(List<Range> ranges){
+        int s = -1;
+        for(Range r : ranges){
+            if(r.startRow<s || s==-1){
+                s = r.startRow;
+            }
+        }
+        return s;
+    }
+
+    public static int startColumn(List<Range> ranges){
+        int s = -1;
+        for(Range r : ranges){
+            if(r.startColumn<s || s==-1){
+                s = r.startColumn;
+            }
+        }
+        return s;
+    }
+
+    public static int amountOfRows(Range r){
+        int endRow = -2;
+        int startRow = -2;
+        if(r.isFullRows()){
+            return Range.MAXROWSPEC;
+        }
+        if(endRow == -2 && startRow == -2){
+            endRow = r.endRow;
+            startRow = r.startRow;
+        }
+        if(r.startRow<startRow){
+            startRow = r.startRow;
+        }
+        if(r.endRow>endRow){
+            endRow = r.endRow;
+        }
+        return endRow - startRow +1;
+    }
+
+    public static int amountOfColumns(Range r){
+        int endColumn = -2;
+        int startColumn = -2;
+        if(r.isFullColumns()){
+            return Range.MAXCOLUMNSPEC;
+        }
+        if(endColumn == -2 && startColumn == -2){
+            endColumn = r.endColumn; 
+            startColumn = r.startColumn;
+        }
+        if(r.startColumn<startColumn){
+            startColumn = r.startColumn;
+        }
+        if(r.endColumn>endColumn){
+            endColumn = r.endColumn;
+        }
+        return endColumn - startColumn +1;
+    }
+
+    public static Range decodeRange(String rangeOrCell) {
+        if(rangeOrCell.isEmpty()) return fullRange();
+        return decodeRange(rangeOrCell, 0, 0);
+    }
+
+    public static Range fullRange() {
+        return new Range(0, -1, 0, -1);
+    }
+
+    public static Range decodeRange(String rangeOrCell, int row, int column) {
+
+        String[] parts = rangeOrCell.split(":");
+        if(parts.length == 1) {
+
+            return decodeCell(rangeOrCell, row, column);
+
+        } else if (parts.length == 2) {
+
+            Range from = decodeCell(parts[0].trim(), row, column);
+            //            System.out.println("decodefrom=" + from);
+            Range to = decodeCell(parts[1].trim(), row, column);
+            //            System.out.println("decodeto=" + to);
+            return Range.combine(from, to);
+
+        } else {
+
+            throw new CellParseException("The reference cell syntax was invalid. At most 1 occurrence of ':' is expected.");
+
+        }
+
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetLineComponent.java
new file mode 100644 (file)
index 0000000..1173a48
--- /dev/null
@@ -0,0 +1,44 @@
+package org.simantics.spreadsheet.solver;
+
+import java.io.Serializable;
+
+import org.simantics.structural.synchronization.utils.ComponentBase;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
+public class SheetLineComponent extends ComponentBase<SheetLineComponent> implements Serializable {
+
+    private static final long serialVersionUID = 1777515716175831266L;
+
+    private THashMap<String, SheetLineComponent> childMap = new THashMap<>();
+
+    public SheetLineComponent(String uid) {
+        super(uid, 0);
+    }
+
+    @Override
+    public THashMap<String, SheetLineComponent> getChildMap() {
+        return childMap;
+    }
+
+    @Override
+    public void setChildMap(THashMap<String, SheetLineComponent> newChildMap) {
+        childMap = newChildMap;
+        if(childMap != null) {
+            childMap.forEachValue(new TObjectProcedure<SheetLineComponent>() {
+                @Override
+                public boolean execute(SheetLineComponent component) {
+                    component.parent = SheetLineComponent.this;
+                    return true;
+                }
+            });
+        }
+    }
+
+    @Override
+    public String toString() {
+        return solverComponentName + " (" + super.toString() + ")";
+    }
+
+}
similarity index 53%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SheetNode.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SheetNode.java
index d2ec679b7f8054cc7558abc8f48bae6afca08d31..13b198f94b7ff682b6de8596c7fbbf7404efc13d 100644 (file)
@@ -1,12 +1,12 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.io.Serializable;
 import java.util.Map;
 
 public interface SheetNode<Child extends SheetNode<?, ?>, Property extends SheetNode<?, ?>> extends Serializable {
 
-       String getName();
-       Map<String, Child> getChildren();
-       Map<String, Property> getProperties();
-       
+    String getName();
+    Map<String, Child> getChildren();
+    Map<String, Property> getProperties();
+
 }
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetBook.java
new file mode 100644 (file)
index 0000000..dfe9725
--- /dev/null
@@ -0,0 +1,536 @@
+package org.simantics.spreadsheet.solver;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+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.Optional;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.simantics.spreadsheet.ExternalRef;
+import org.simantics.spreadsheet.ExternalRef.ExternalRefListener;
+import org.simantics.spreadsheet.SpreadsheetCellStyle;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.synchronization.LineNodeUpdater;
+import org.simantics.spreadsheet.synchronization.LineUpdater;
+import org.simantics.spreadsheet.synchronization.NullUpdater;
+import org.simantics.spreadsheet.synchronization.StyleUpdater;
+import org.simantics.structural.synchronization.utils.ComponentFactory;
+import org.simantics.structural.synchronization.utils.MappingBase;
+import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
+import org.simantics.structural.synchronization.utils.ModuleUpdaterFactoryBase;
+import org.simantics.structural.synchronization.utils.Solver;
+import org.simantics.structural.synchronization.utils.SolverNameUtil;
+
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.longs.AbstractLongList;
+import it.unimi.dsi.fastutil.longs.AbstractLongSet;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.longs.LongArraySet;
+import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetBook implements StandardNodeManagerSupport<SheetNode>, SpreadsheetElement<SpreadsheetElement, SpreadsheetElement>, Serializable, SheetNode<SpreadsheetEngine, SheetNode>, Solver, SolverNameUtil, ComponentFactory<SheetLineComponent>, ModuleUpdaterFactoryBase<SheetLineComponent> {
+    
+    private static final long serialVersionUID = 7417208688311691396L;
+
+    public Serializable NotAvailableError = new Serializable() {
+        private static final long serialVersionUID = 2535371785498129460L;
+    };
+
+    public Long2ObjectOpenHashMap<AbstractLongSet> referenceMap = new Long2ObjectOpenHashMap<>();
+
+    private Int2ObjectArrayMap<SpreadsheetStyle> styles = new Int2ObjectArrayMap<>();
+    public ArrayList<SpreadsheetEngine> sheets = new ArrayList<SpreadsheetEngine>();
+
+    private SpreadsheetMapping mapping;
+    
+    private String context;
+
+    private int idCounter = 1;
+    
+    private transient boolean disposed = false;
+
+    public SpreadsheetBook(String context) {
+        getNewId(this);
+        System.err.println("SpreadsheetBook, context is " + context);
+        mapping = new SpreadsheetMapping(new SheetLineComponent(""));
+        this.context = context;
+    }
+
+    public Map<Integer, SpreadsheetElement> children = new HashMap<>();
+
+    private boolean iterationEnabled;
+
+    public int getNewId(SpreadsheetElement element) {
+        int result = idCounter++;
+        children.put(result, element);
+        return result; 
+    }
+
+    public long getEngineIndex(SpreadsheetEngine engine) {
+        for(int i=0;i<sheets.size();i++)
+            if(sheets.get(i) == engine) return i;
+        throw new IllegalStateException("Did not find sheet " + engine.getName());
+    }
+
+    public void registerReferences(long cell, AbstractLongList refs) {
+        for(int i=0;i<refs.size();i++) {
+            long key = refs.getLong(i);
+            AbstractLongSet set = referenceMap.get(key);
+            if(set == null) {
+                set = new LongArraySet();
+                referenceMap.put(key, set);
+            }
+            if(set.size() == 5) {
+                AbstractLongSet newSet = new LongLinkedOpenHashSet();
+                newSet.addAll(set);
+                set = newSet;
+                referenceMap.put(key, set);
+            }
+            set.add(cell);
+        }
+    }
+
+    @Override
+    public Binding getEngineBinding(SheetNode node) throws NodeManagerException {
+        Object value = getEngineValue(node);
+        if(value instanceof Variant) return Bindings.VARIANT;
+        if(value instanceof String) return Bindings.STRING;
+        if(value instanceof Boolean) return Bindings.BOOLEAN;
+        else return Bindings.getBindingUnchecked(value.getClass());
+    }
+
+    @Override
+    public Object getEngineValue(SheetNode node) {
+        if(node instanceof SpreadsheetCellContent) {
+            try {
+                SpreadsheetCellContent scc = (SpreadsheetCellContent)node;
+                Object content = scc.cell.evaluate(SpreadsheetEvaluationEnvironment.getInstance(this));
+                if(content == null) return Variant.ofInstance("");
+                if(content instanceof Variant) return content;
+                else return Variant.ofInstance(content);
+            } catch (Throwable t) {
+                t.printStackTrace();
+                return Variant.ofInstance(t.toString());
+            }
+        } else if (node instanceof SpreadsheetCellContentExpression) {
+            SpreadsheetCellContentExpression scce = (SpreadsheetCellContentExpression)node;
+            if (scce.cell.content instanceof SpreadsheetFormula) {
+                SpreadsheetFormula formula = (SpreadsheetFormula)scce.cell.content; 
+                return formula.expression;
+            } else if (scce.cell.content instanceof SpreadsheetSCLConstant) {
+                SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) scce.cell.content;
+                return "=" + sclConstant.expression;
+            } else {
+                System.out.println("Broken SpreadsheetCellContentExpression possibly due to overwriting an existing expression with a constant or something else (current content is " + scce.cell.content + ")");
+                if (scce.cell.content instanceof Variant) {
+                    return scce.cell.content;
+                } else {
+                    return Variant.ofInstance(scce.cell.content);
+                }
+            }
+        } else if (node instanceof SpreadsheetTypeNode) {
+            SpreadsheetTypeNode stn = (SpreadsheetTypeNode)node;
+            return stn.uri;
+        } else if (node instanceof SpreadsheetCellStyle) {
+            int styleId = ((SpreadsheetCellStyle) node).cell.style;
+            SpreadsheetStyle style = getStyle(styleId);
+            if (style == null) {
+                style = SpreadsheetStyle.empty();
+                if (styleId != style.getStyleId())
+                    new Exception("different style ids!" + styleId + "  " + style.getStyleId()).printStackTrace();
+                addStyle(style);
+            }
+            return style;
+        } else if (node instanceof SpreadsheetCellEditable) {
+            boolean editable = ((SpreadsheetCellEditable) node).editable();
+            return editable;
+        }
+        return null;
+    }
+
+    @Override
+    public void setEngineValue(SheetNode node, Object value) {
+    }
+
+    @Override
+    public String getName(SheetNode node) {
+        return node.getName();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Map<String, SheetNode> getChildren(SheetNode node) {
+        return node.getChildren();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Map<String, SheetNode> getProperties(SheetNode node) {
+        return node.getProperties();
+    }
+
+    @Override
+    public String getName() {
+        return "";
+    }
+
+    @Override
+    public Map<String, SpreadsheetEngine> getChildren() {
+        Map<String,SpreadsheetEngine> result = new HashMap<String,SpreadsheetEngine>();
+        for(SpreadsheetEngine engine : sheets)
+            result.put(engine.getName(), engine);
+        return result;
+    }
+
+    @Override
+    public Map<String, SheetNode> getProperties() {
+        return Collections.emptyMap();
+    }
+
+    public SpreadsheetCell get(String sheet, int row, int column) {
+        SpreadsheetEngine engine = getEngine(sheet);
+        if(engine == null) return null;
+        SpreadsheetLine line = engine.getLine(row);
+        if(line == null) return null;
+        if(line.cells.size() <= column) return null;
+        return line.cells.get(column);
+    }
+
+    public SpreadsheetCell get(SpreadsheetEngine engine, int row, int column) {
+        SpreadsheetLine line = engine.getLine(row);
+        if(line == null) return null;
+        if(line.cells.size() <= column) return null;
+        return line.cells.get(column);
+    }
+
+    public SpreadsheetEngine getEngine(String sheet) {
+        for(SpreadsheetEngine engine : sheets)
+            if(sheet.equals(engine.getName())) return engine;
+        return null;
+    }
+
+    @Override
+    public ModuleUpdaterBase<SheetLineComponent> createUpdater(String id) throws Exception {
+        if("http://www.simantics.org/Spreadsheet-1.2/Line".equals(id))
+            return new LineUpdater(id);
+        else if("http://www.simantics.org/Spreadsheet-1.2/LineNode".equals(id))
+            return new LineNodeUpdater(id);
+        else if ("http://www.simantics.org/Spreadsheet-1.2/Style".equals(id))
+            return new StyleUpdater(id);
+        else if("http://www.simantics.org/Spreadsheet-1.2/Lines".equals(id))
+            return new NullUpdater(id);
+        else if("http://www.simantics.org/Spreadsheet-1.2/Spreadsheet".equals(id))
+            return new NullUpdater(id);
+        else if("http://www.simantics.org/Spreadsheet-1.2/Book".equals(id))
+            return new NullUpdater(id);
+        else
+            throw new IllegalStateException("createUpdater " + id);
+    }
+
+    @Override
+    public SheetLineComponent create(String uid) {
+        return new SheetLineComponent(uid);
+    }
+
+    @Override
+    public String getFreshName(String parentName, String name) {
+        return parentName + "/" + name;
+    }
+
+    @Override
+    public String ensureNameIsVariationOf(String parentName, int id, String name) {
+        if (parentName.isEmpty())
+            return name;
+        return parentName + "/" + name;
+    }
+
+    final static int COMP_ROOT_POS = "COMP_ROOT/".length();
+
+    @Override
+    public int getId(String name) {
+
+        if("COMP_ROOT".equals(name)) return 1;
+
+        String path = name.substring(COMP_ROOT_POS);
+        String[] parts = path.split("/");
+        Object o = resolve(parts, 0);
+        if(o instanceof SpreadsheetLines) {
+            return ((SpreadsheetLines)o).getId();
+        } else if(o instanceof SpreadsheetLine) {
+            return ((SpreadsheetLine)o).getId();
+        } else if(o instanceof SpreadsheetEngine) {
+            return ((SpreadsheetEngine)o).getId();
+        } else if (o instanceof SpreadsheetStyle) {
+            return ((SpreadsheetStyle) o).getId();
+        }
+
+        throw new IllegalStateException("Resolved object for parts " + Arrays.toString(parts) + " is not the right type! It is " + o);
+
+    }
+
+    Object resolve(String[] parts, int index) {
+        String part = parts[index];
+        if (part.startsWith("Style")) {
+            for (SpreadsheetStyle style : styles.values()) {
+                if (style.name.equals(part)) {
+                    return style;
+                }
+            }
+        }
+        SpreadsheetEngine engine = getEngine(part);
+        if(engine == null) return 0;
+        if(index == parts.length-1) return engine;
+        else return engine.resolve(parts, index+1);
+    }
+
+    @Override
+    public String getName(int id) {
+        if(id == -2) return "http://www.simantics.org/Spreadsheet-1.2/Book";
+        else if(id == -3) return "http://www.simantics.org/Spreadsheet-1.2/Spreadsheet";
+        else if(id == -4) return "http://www.simantics.org/Spreadsheet-1.2/Lines";
+        else if(id == -5)
+            return "http://www.simantics.org/Spreadsheet-1.2/LineNode";
+        else if (id == -6)
+            return "http://www.simantics.org/Spreadsheet-1.2/Line";
+        else if(id == -7)
+            return "http://www.simantics.org/Spreadsheet-1.2/Style";
+        else return "" + id;
+    }
+
+    @Override
+    public int getModuleType(int id) {
+        Serializable s = children.get(id);
+        if(s instanceof SpreadsheetBook) return -2;
+        else if(s instanceof SpreadsheetEngine) return -3;
+        else if(s instanceof SpreadsheetLines) {
+            if("Lines".equals(((SpreadsheetLines) s).getName()))
+                return -4;
+            else
+                return -5;
+        }
+        else if(s instanceof SpreadsheetLine)
+            return -6;
+        else if (s instanceof SpreadsheetStyle)
+            return -7;
+        else throw new IllegalStateException();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void remove(int id) {
+
+        SpreadsheetElement child = children.get(id);
+        Optional<SpreadsheetElement> parent = child.getParent();
+
+        if (parent.isPresent()) {
+            parent.get().remove(child);
+            children.remove(id);
+        }
+    }
+
+    @Override
+    public void addSubprocess(String name, String subprocessType) {
+        ensureSubprocess(name);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T ensureSubprocess(String name) {
+        String[] parts = name.split("/");
+        if(parts.length == 2) {
+            SpreadsheetEngine engine = getEngine(parts[1]);
+            if(engine == null) {
+                engine = new SpreadsheetEngine(this, parts[1]);
+                sheets.add(engine);
+            }
+            return (T)engine;
+        } else if (parts.length > 2) {
+            SpreadsheetEngine engine = getEngine(parts[1]);
+            return (T)engine.ensureSubprocess(parts, 2);
+        }
+        throw new IllegalStateException();
+    }
+
+
+    @Override
+    public void includeSubprocess(String parentName, String subprocessName) {
+        // Nop
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getConcreteSolver() {
+        return (T)this;
+    }
+
+    @Override
+    public void accept(SpreadsheetVisitor v) {
+        v.visit(this);
+    }
+
+    private SpreadsheetCell cellByReferenceKey(long ref) {
+        long sheet = ref >> 40;
+        long row = (ref >> 20) & 0xFFFFF;
+        long col = (ref) & 0xFFFFF;
+        return  get(sheets.get((int)sheet), (int)row, (int)col);
+    }
+    
+    //Recursively find all SpreadsheetCells, invalidate them and return them all as a set
+    public Set<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
+        Set<SpreadsheetCell> result = new HashSet<>();
+        result.add(cell);
+        cell.invalidate();
+        long refKey = cell.makeReferenceKey();
+        AbstractLongSet refs = referenceMap.remove(refKey);
+        if(refs == null) return result;
+        for(long ref : refs) {
+            SpreadsheetCell referer = cellByReferenceKey(ref);
+            result.addAll(invalidate(referer));
+        }
+        return result;
+    }
+
+    @Deprecated
+    public List<SpreadsheetCell> invalidateShallow(SpreadsheetCell cell) {
+        ArrayList<SpreadsheetCell> result = new ArrayList<>();
+        result.add(cell);
+        cell.invalidate();
+        long refKey = cell.makeReferenceKey();
+        AbstractLongSet refs = referenceMap.remove(refKey);
+        if(refs == null) return result;
+        for(long ref : refs) {
+            SpreadsheetCell referer = cellByReferenceKey(ref);
+            invalidate(referer);
+            result.add(referer);
+        }
+        return result;
+    }
+
+    public void addStyle(SpreadsheetStyle style) {
+        if (style.name == null) {
+            new Exception("Trying to add style to book without name!!").printStackTrace();
+            return;
+        }
+        style.setSynchronizationId(getNewId(style));
+        styles.put(style.getStyleId(), style);
+    }
+
+    public SpreadsheetStyle getStyle(int styleId) {
+        return styles.get(styleId);
+    }
+
+    public MappingBase<SheetLineComponent> getMapping() {
+        return mapping;
+    }
+
+    @Override
+    public Optional<SpreadsheetElement> getParent() {
+        return Optional.empty();
+    }
+
+    @Override
+    public Collection<SpreadsheetElement> getSpreadsheetChildren() {
+        return children.values();
+    }
+
+    @Override
+    public void remove(SpreadsheetElement child) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setIterationEnabled(boolean value) {
+        this.iterationEnabled = value;
+    }
+
+    public boolean isIterationEnabled() {
+        return iterationEnabled;
+    }
+
+    static Variant DEFAULT = Variant.ofInstance("Pending external reference");
+
+    class ExternalRefData {
+        private Variant value = DEFAULT;
+        public ExternalRefData(long referenceKey, ExternalRef ref) {
+            System.err.println("listen to " + ref);
+            ref.listen(context, new ExternalRefListener() {
+                
+                boolean isDisposed = false;
+                
+                @Override
+                public void newValue(Variant newVariant) {
+                    SpreadsheetCell cell = cellByReferenceKey(referenceKey);
+                    if(cell.content instanceof SpreadsheetSCLConstant) {
+                        SpreadsheetSCLConstant ssc = (SpreadsheetSCLConstant)cell.content;
+                        if(ssc.content.equals(ref)) {
+                            value = newVariant;
+                            fireChanges(invalidate(cell));
+                            return;
+                        }
+                    }
+                    isDisposed = true;
+                }
+                @Override
+                public boolean isDisposed() {
+                    if(isDisposed)
+                        return true;
+                    return SpreadsheetBook.this.isDisposed();
+                }
+            });
+        }
+    }
+    
+    private Map<ExternalRef,ExternalRefData> externalRefMap = new HashMap<>();
+
+    void registerListening(long referenceKey, ExternalRef ref) {
+        ExternalRefData data = externalRefMap.get(ref);
+        if(data == null) {
+            data = new ExternalRefData(referenceKey, ref);
+            externalRefMap.put(ref, data);
+        } else {
+            // Already registered
+        }
+    }
+
+    Variant getExternalRefValue(long referenceKey, ExternalRef ref) {
+        System.err.println("getExternalRefValue " + ref);
+        ExternalRefData data = externalRefMap.get(ref);
+        if(data == null) {
+            registerListening(referenceKey, ref);
+            return DEFAULT;
+        }
+        return data.value;
+    }
+    
+    public boolean isDisposed() {
+        return disposed;
+    }
+
+    public static interface SpreadsheetBookListener {
+        void cellsChanged(Collection<SpreadsheetCell> cells);
+    }
+    
+    public void registerListener(SpreadsheetBookListener listener) {
+        listeners.add(listener);
+    }
+    
+    private transient ArrayList<SpreadsheetBookListener> listeners = new ArrayList<>();
+    
+    public void fireChanges(Collection<SpreadsheetCell> cells) {
+        for(SpreadsheetBookListener listener : listeners)
+            listener.cellsChanged(cells);
+    }
+    
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCell.java
new file mode 100644 (file)
index 0000000..6f6a372
--- /dev/null
@@ -0,0 +1,224 @@
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.ExternalRef;
+import org.simantics.spreadsheet.SpreadsheetCellStyle;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.CellValueVisitor;
+import org.simantics.spreadsheet.solver.formula.FormulaError2;
+import org.simantics.spreadsheet.solver.formula.SpreadsheetEvaluationEnvironment;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetCell implements SpreadsheetElement, SheetNode {
+
+    private static final long serialVersionUID = 6616793596542239339L;
+
+    public static SpreadsheetCell EMPTY;
+
+    static {
+        EMPTY = new SpreadsheetCell(null, -1);
+        EMPTY.setContent("");
+        EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId());
+    }
+
+    private boolean inProgress = false;
+    private int iterations = 0;
+
+    final private SpreadsheetLine line;
+    final private int column;
+    int style;
+    Object content;
+    final private Map<String, SheetNode> properties;
+
+    public SpreadsheetCell(SpreadsheetLine line, int column) {
+        this.properties = createProperties();
+        this.line = line;
+        this.column = column;
+    }
+
+    //All SpreadsheetCells have these properties - create them when object is created
+    private Map<String, SheetNode> createProperties() {
+        Map<String, SheetNode> p = new HashMap<>();        
+        p.put("typeURI", new SpreadsheetTypeNode(Spreadsheets.CELL_TYPE_URI));
+        p.put("content", new SpreadsheetCellContent(this));
+        p.put("style", new SpreadsheetCellStyle(this));
+        p.put("editable", new SpreadsheetCellEditable(this));
+        return p;
+    }
+
+    public boolean hasExpression() {
+        return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; 
+    }
+
+    public void setContent(Object newContent) {
+        this.content = newContent;
+    }
+
+    @Override
+    public String getName() {
+        return Spreadsheets.cellName(line.row, column);
+    }
+
+    @Override
+    public Map<?, ?> getChildren() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map<String, SheetNode> getProperties() {
+        return properties;
+    }
+
+    public SpreadsheetBook getBook() {
+        return line.getEngine().getBook();
+    }
+
+    public SpreadsheetEngine getEngine() {
+        return line.getEngine();
+    }
+
+    public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {
+        return evaluate(env, null);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) {
+        if(caller != null)
+            caller.addReference(makeReferenceKey());
+        if(content instanceof SpreadsheetFormula) {
+            SpreadsheetFormula f = (SpreadsheetFormula)content;
+            if(f.result == null) {
+                CellValueVisitor visitor = new CellValueVisitor(env, this);
+                AstValue value = ((SpreadsheetFormula)content).value;
+                if(this.inProgress == true) this.iterations++;
+
+                if(!env.getBook().isIterationEnabled()){
+                    if(this.inProgress == false){
+                        this.inProgress = true;
+                        f.result = value.accept(visitor);
+                    }
+                    else f.result = FormulaError2.CIRCULAR_REF.getString();
+                }
+                else if(this.iterations<env.iterationLimit){
+                    this.inProgress = true;
+                    f.result = value.accept(visitor);
+                }
+                else {
+                    if(f.result==null)
+                        f.result = 0.0;
+                }
+                env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
+            }
+            this.inProgress = false;
+            this.iterations = 0;
+            return (T)f.result;
+        } else if (content instanceof SpreadsheetSCLConstant) {
+            SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
+            if(sclConstant.content instanceof Variant) {
+                Variant v = (Variant)sclConstant.content;
+                return (T) sclConstant.content;
+            } else if (sclConstant.content instanceof ExternalRef) {
+                return (T)env.getBook().getExternalRefValue(makeReferenceKey(), (ExternalRef)sclConstant.content);
+            } else {
+                throw new IllegalStateException();
+            }
+        } else {
+            this.inProgress = false;
+            return (T)content;
+        }
+    }
+
+    public long makeReferenceKey() {
+        SpreadsheetBook book = getBook();
+        SpreadsheetEngine engine = getEngine();
+        long engineIndex = book.getEngineIndex(engine);
+        long row = line.row;
+        long col = column;
+        return (engineIndex << 40) + (row << 20) + col; 
+    }
+
+    public void invalidate() {
+        getEngine().rangeCache = null;
+        if(content instanceof SpreadsheetFormula) {
+            SpreadsheetFormula f = (SpreadsheetFormula)content;
+            f.result = null;
+        }
+    }
+
+    @Override
+    public void accept(SpreadsheetVisitor v) {
+        v.visit(this);
+    }
+
+    @Override
+    public Optional<SpreadsheetElement> getParent() {
+        return Optional.of(line);
+    }
+
+    @Override
+    public List<SpreadsheetElement> getSpreadsheetChildren() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void remove(SpreadsheetElement child) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + column;
+        result = prime * result + ((line == null) ? 0 : line.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SpreadsheetCell other = (SpreadsheetCell) obj;
+        if (column != other.column)
+            return false;
+        if (line == null) {
+            if (other.line != null)
+                return false;
+        } else if (!line.equals(other.line))
+            return false;
+        return true;
+    }
+
+    public void setStyle(int styleId) {
+        this.style = styleId;
+    }
+
+    public int getStyle() {
+        return style;
+    }
+
+    public Object getContent() {
+        return content;
+    }
+
+    public static SpreadsheetCell empty(SpreadsheetLine line, int column) {
+        SpreadsheetCell cell =  new SpreadsheetCell(line, column);
+        cell.setContent("");
+        cell.setStyle(SpreadsheetStyle.empty().getStyleId());
+        return cell;
+    }
+
+}
similarity index 53%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContent.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContent.java
index 3c1a4ff255862150bd0b6eceec91262bb3fde82b..5358d267338daeda2d1078099939fd7a522711f5 100644 (file)
@@ -1,34 +1,37 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.util.Collections;
 import java.util.Map;
 
+@SuppressWarnings("rawtypes")
 public class SpreadsheetCellContent implements SheetNode {
 
-       public final SpreadsheetCell cell;
-       
-       public SpreadsheetCellContent(SpreadsheetCell cell) {
-               this.cell = cell;
-       }
-       
-       @Override
-       public String getName() {
-               return "content";
-       }
-
-       @Override
-       public Map getChildren() {
-               return Collections.emptyMap();
-       }
-
-       @Override
-       public Map getProperties() {
-               if(cell.hasExpression()) {
-                       return Collections.singletonMap("expression", new SpreadsheetCellContentExpression(cell));
-               } else {
-                       return Collections.emptyMap();
-               }
-       }
+    private static final long serialVersionUID = 6463195673537211769L;
+    
+    public final SpreadsheetCell cell;
+
+    public SpreadsheetCellContent(SpreadsheetCell cell) {
+        this.cell = cell;
+    }
+
+    @Override
+    public String getName() {
+        return "content";
+    }
+
+    @Override
+    public Map getChildren() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map getProperties() {
+        if(cell.hasExpression()) {
+            return Collections.singletonMap("expression", new SpreadsheetCellContentExpression(cell));
+        } else {
+            return Collections.emptyMap();
+        }
+    }
 
     @Override
     public int hashCode() {
similarity index 61%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellContentExpression.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellContentExpression.java
index 7c0b0263c1cc01d9800e0f40b3e0e700ff8ee90f..b901367939a25bc2fec657e66179469bc210b506 100644 (file)
@@ -1,29 +1,32 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.util.Collections;
 import java.util.Map;
 
+@SuppressWarnings("rawtypes")
 public class SpreadsheetCellContentExpression implements SheetNode {
 
-       public final SpreadsheetCell cell;
-       
-       public SpreadsheetCellContentExpression(SpreadsheetCell cell) {
-               this.cell = cell;
-       }
-       
+    private static final long serialVersionUID = 917517945851971254L;
+    
+    public final SpreadsheetCell cell;
+
+    public SpreadsheetCellContentExpression(SpreadsheetCell cell) {
+        this.cell = cell;
+    }
+
+    @Override
+    public String getName() {
+        return "expression";
+    }
+
+    @Override
+    public Map getChildren() {
+        return Collections.emptyMap();
+    }
+
     @Override
-       public String getName() {
-               return "expression";
-       }
-
-       @Override
-       public Map getChildren() {
-               return Collections.emptyMap();
-       }
-
-       @Override
-       public Map getProperties() {
-               return Collections.emptyMap();
+    public Map getProperties() {
+        return Collections.emptyMap();
     }
 
     @Override
similarity index 73%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCellEditable.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetCellEditable.java
index 81033f44cf15367b6da72ccc726267c0866126e5..d3d57c4988709d04cbf43eed31ca2840c9f6a8a1 100644 (file)
@@ -1,14 +1,17 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.util.Collections;
 import java.util.Map;
 
 import org.simantics.databoard.binding.mutable.Variant;
 
+@SuppressWarnings("rawtypes")
 public class SpreadsheetCellEditable implements SheetNode {
 
-    public final SpreadsheetCell cell;
+    private static final long serialVersionUID = -5078387091775971986L;
     
+    public final SpreadsheetCell cell;
+
     public SpreadsheetCellEditable(SpreadsheetCell spreadsheetCell) {
         this.cell = spreadsheetCell;
     }
@@ -27,7 +30,7 @@ public class SpreadsheetCellEditable implements SheetNode {
     public Map getProperties() {
         return Collections.emptyMap();
     }
-    
+
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -57,19 +60,19 @@ public class SpreadsheetCellEditable implements SheetNode {
         if (cell.content == null || cell.content instanceof SpreadsheetFormula || cell.content instanceof SpreadsheetSCLConstant)
             return false;
         if (cell.content instanceof String) {
-               String content = (String) cell.content;
-               if (content.isEmpty())
-                       return false;
+            String content = (String) cell.content;
+            if (content.isEmpty())
+                return false;
         }
         if (cell.content instanceof Variant) {
-               Variant content = (Variant) cell.content;
-               if (content.getValue() == null)
-                       return false;
-               if (content.getValue() instanceof String) {
-                       String actualContent = (String) content.getValue();
-                       if (actualContent.isEmpty())
-                               return false;
-               }
+            Variant content = (Variant) cell.content;
+            if (content.getValue() == null)
+                return false;
+            if (content.getValue() instanceof String) {
+                String actualContent = (String) content.getValue();
+                if (actualContent.isEmpty())
+                    return false;
+            }
         }
 //        System.out.println("content is " + cell.content);
         return true;
similarity index 78%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetElement.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetElement.java
index 71bbd8f97a9ca5380c620f7b1eda91839697b9dd..05c4f1da3f2b04a5b6655462e6a312b7380007e2 100644 (file)
@@ -1,9 +1,11 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Optional;
 
+import org.simantics.spreadsheet.SpreadsheetVisitable;
+
 public interface SpreadsheetElement<Child extends SpreadsheetElement<?, ?>, Parent extends SpreadsheetElement<?, ?>> extends SpreadsheetVisitable, Serializable {
 
     Optional<Parent> getParent();
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetEngine.java
new file mode 100644 (file)
index 0000000..9ccbc6d
--- /dev/null
@@ -0,0 +1,163 @@
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetEngine implements SpreadsheetElement, SheetNode {
+
+    private static final long serialVersionUID = -5246063647558595642L;
+
+    private static final String LINES = "Lines";
+
+    private final SpreadsheetBook book;
+    private final String name;
+    private final int id;
+
+    public SpreadsheetLines lines;
+
+    transient public Map<String,Object> rangeCache;
+
+    public Map<String,Object> getRangeCache() {
+        if(rangeCache == null) rangeCache = new HashMap<String,Object>();
+        return rangeCache;
+    }
+
+    public Object getCachedRange(AstRange range) {
+        if(range.sheetName != null) return null;
+        return getRangeCache().get(range.first + ":" + range.second); 
+    }
+
+    public void cacheRange(AstRange range, Object value) {
+        if(range.sheetName != null) return;
+        getRangeCache().put(range.first + ":" + range.second, value);
+    }
+
+    public SpreadsheetEngine(SpreadsheetBook book, String name) {
+        this.book = book;
+        this.name = name;
+        this.id = book.getNewId(this);
+        this.lines = new SpreadsheetLines(this, LINES);
+    }
+
+    public SpreadsheetBook getBook() {
+        return book;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    Object resolve(String[] parts, int index) {
+
+        String part = parts[index];
+        if(!part.equals(LINES)) return null;
+
+        if(index == parts.length-1) return lines;
+
+        return lines.resolve(parts, index+1);
+
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Map<String, SheetNode> getChildren() {
+        return Collections.singletonMap(LINES, lines);
+    }
+
+    @Override
+    public Map<String, SheetNode> getProperties() {
+        return Collections.emptyMap();
+    } 
+
+    public Object ensureSubprocess(String[] path, int index) {
+
+        String name = path[index];
+        if(!LINES.equals(name)) throw new IllegalStateException();
+        if(index == path.length - 1) return lines;
+        return lines.ensureSubprocess(path, index+1);
+
+    }
+
+    public SpreadsheetLine getLine(int row) {
+        assert(lines.nodes.size() == 1);
+        SpreadsheetLines root = lines.nodes.values().iterator().next();
+        return root.getLine(row);
+    }
+
+    @Override
+    public void accept(SpreadsheetVisitor v) {
+        v.visit(this);
+    }
+
+    public Range actualRange(Range r) {
+        if(r.isFullRows()) {
+            SpreadsheetLines root = lines.nodes.values().iterator().next();
+            Range result = new Range(r);
+            result.startRow = 0;
+            result.endRow = root.getMaxRow(); 
+            return result;
+        } else {
+            return r;
+        }
+    }
+
+    @Override
+    public Optional<SpreadsheetElement> getParent() {
+        return Optional.of(book);
+    }
+
+    @Override
+    public List<SpreadsheetElement> getSpreadsheetChildren() {
+        return Collections.singletonList(lines);
+    }
+
+    @Override
+    public void remove(SpreadsheetElement child) {
+
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((book == null) ? 0 : book.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SpreadsheetEngine other = (SpreadsheetEngine) obj;
+        if (book == null) {
+            if (other.book != null)
+                return false;
+        } else if (!book.equals(other.book))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        return true;
+    }
+
+
+}
\ No newline at end of file
similarity index 62%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetFormula.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetFormula.java
index d171fd87e83bc72bfb6bea49f28813fa741dd7c2..6933356698bec1d5e1562d2eb20b925b17e5db9a 100644 (file)
@@ -1,21 +1,25 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.io.Serializable;
 
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
 
 public class SpreadsheetFormula implements Serializable {
-       
-       private static final long serialVersionUID = -3369406031425959191L;
-       
-       public AstValue value;
-       public String expression;
-       public Object result;
-       
-       public SpreadsheetFormula(AstValue value, String expression) {
-               this.value = value;
-               this.expression = expression;
-       }
+
+    public static Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetFormula.class);
+    
+    private static final long serialVersionUID = -3369406031425959191L;
+
+    public AstValue value;
+    public String expression;
+    public Object result;
+
+    public SpreadsheetFormula(AstValue value, String expression) {
+        this.value = value;
+        this.expression = expression;
+    }
 
     @Override
     public int hashCode() {
@@ -41,7 +45,7 @@ public class SpreadsheetFormula implements Serializable {
             return false;
         return true;
     }
-    
+
     @Override
     public String toString() {
         return getClass().getSimpleName() + " [" + expression +" => " + result != null ? result.toString() : "" + "]";
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLine.java
new file mode 100644 (file)
index 0000000..d11fdc6
--- /dev/null
@@ -0,0 +1,123 @@
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.Spreadsheets;
+
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetLine implements SpreadsheetElement<SpreadsheetCell, SpreadsheetLines>, SheetNode {
+
+    private static final long serialVersionUID = -304574098117404663L;
+
+    final private SpreadsheetLines parent;
+    final public int row;
+    int id;
+
+    public ObjectArrayList<SpreadsheetCell> cells = new ObjectArrayList<>();
+
+    public SpreadsheetLine(SpreadsheetLines parent, int row) {
+        this.parent = parent;
+        this.row = row;
+        this.id = getEngine().getBook().getNewId(this);
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public SpreadsheetEngine getEngine() {
+        return ((SpreadsheetLines)parent).getEngine();
+    }
+
+    @Override
+    public String getName() {
+        return "Row"+row;
+    }
+
+    @Override
+    public Map getChildren() {
+        String rowName = ""+row;
+        Map<String,SpreadsheetCell> result = new HashMap<>();
+        for(int i=0;i<cells.size();i++) {
+            SpreadsheetCell cell = cells.get(i);
+            if(SpreadsheetCell.EMPTY == cell) continue;
+            String name = "Row"+Spreadsheets.columnName(i) + rowName;
+            result.put(name, cell);
+        }
+        return result;
+    }
+
+    @Override
+    public Map getProperties() {
+        return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINE_TYPE_URI));
+    }
+
+    Object resolve(String[] parts, int index) {
+
+        if(index == parts.length) return this;
+
+        Range r = Spreadsheets.decodeCellAbsolute(parts[index]);
+        return cells.get(r.startColumn);
+
+    }
+
+    public void accept(SpreadsheetVisitor v) {
+        v.visit(this);
+    }
+
+    public String getPath() {
+        return ((SpreadsheetLines)parent).getPath() + "/" + getName();
+    }
+
+    @Override
+    public Optional<SpreadsheetLines> getParent() {
+        return Optional.of(parent);
+    }
+
+    @Override
+    public List<SpreadsheetCell> getSpreadsheetChildren() {
+        return cells;
+    }
+
+    @Override
+    public void remove(SpreadsheetCell child) {
+
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+        result = prime * result + row;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SpreadsheetLine other = (SpreadsheetLine) obj;
+        if (parent == null) {
+            if (other.parent != null)
+                return false;
+        } else if (!parent.equals(other.parent))
+            return false;
+        if (row != other.row)
+            return false;
+        return true;
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetLines.java
new file mode 100644 (file)
index 0000000..e53d7cb
--- /dev/null
@@ -0,0 +1,209 @@
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+
+import org.simantics.spreadsheet.SpreadsheetVisitor;
+import org.simantics.spreadsheet.Spreadsheets;
+
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetLines implements SpreadsheetElement<SpreadsheetLine, SpreadsheetEngine>, SheetNode {
+
+    private static final long serialVersionUID = -3615335969248723486L;
+
+    private final int id;
+    private SpreadsheetEngine parent;
+    private String name;
+    public Int2ObjectAVLTreeMap<SpreadsheetLines> nodes = new Int2ObjectAVLTreeMap<SpreadsheetLines>();
+    public Int2ObjectAVLTreeMap<SpreadsheetLine> lines = new Int2ObjectAVLTreeMap<SpreadsheetLine>();
+    public int[] keys;
+
+    public SpreadsheetLines(SpreadsheetEngine parent, String name) {
+        this.parent = parent;
+        this.name = name;
+        id = getEngine().getBook().getNewId(this);
+    }
+
+    public SpreadsheetEngine getEngine() {
+        return parent;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    @Override
+    public Map getChildren() {
+        Int2ObjectAVLTreeMap result = new Int2ObjectAVLTreeMap();
+        result.putAll(nodes);
+        result.putAll(lines);
+        return result;
+    }
+
+    @Override
+    public Map getProperties() {
+        return Collections.singletonMap("typeURI", new SpreadsheetTypeNode(Spreadsheets.LINES_TYPE_URI));
+    } 
+
+    Object resolve(String[] parts, int index) {
+
+        String part = parts[index];
+        if(part.charAt(0) == 'R') {
+            int indx = Integer.parseInt(part.substring(3));
+            SpreadsheetLine line = lines.get(-indx);
+            if(line != null) {
+                if(index == parts.length-1) return line;
+                else return line.resolve(parts, index+1);
+            }
+        } else {
+            int indx = Integer.parseInt(part);
+            SpreadsheetLines node = nodes.get(indx);
+            if(node != null) {
+                if(index == parts.length-1) return node;
+                else return node.resolve(parts, index+1);
+            }
+        }
+
+        return null;
+
+    }
+
+    public Object ensureSubprocess(String[] path, int index) {
+
+        String name = path[index];
+
+        int i = Integer.parseInt(name);
+        SpreadsheetLines line = nodes.get(i);
+        if(line == null) {
+            line = new SpreadsheetLines(parent, "" + i);
+            nodes.put(i, line);
+        }
+
+        if(index == path.length - 1) {
+            return line;
+        } else {
+            return line.ensureSubprocess(path, index+1);
+        }
+
+    }
+
+    public void setKeys(int[] keys) {
+        this.keys = keys;
+    }
+
+    @Override
+    public void accept(SpreadsheetVisitor v) {
+        v.visit(this);
+    }
+
+    public String getPath() {
+        return "/" + parent.getName() + "/" + parent.lines.getName() + "/" + getName();
+    }
+
+    private int getKey(int index) {
+        return keys[2*index+1];
+    }
+
+    private int getChild(int index) {
+        return keys[2*index];
+    }
+
+    /*
+     *  [(child,key),...,key)
+     * 
+     */
+    public SpreadsheetLine getLine(int k) {
+
+        int i=1;
+        int n = (keys.length - 1) / 2;
+
+        while(i <= n && k > getKey(i-1)) i++;
+
+        if(i <= n && k == getKey(i-1)) {
+            return lines.get(-k);
+        }
+
+        int nodeName = getChild(i-1);
+        SpreadsheetLines node = nodes.get(nodeName);
+        if(node == null) return null;
+        return node.getLine(k);
+
+    }
+
+    public int getMaxRow() {
+        // if keys == null then this is the root of BTree which has only one child 
+        if (keys == null) {
+            int maxRow = 0;
+            for (SpreadsheetLines node : nodes.values()) {
+                int row = node.getMaxRow();
+                if (row > maxRow)
+                    maxRow = row;
+            }
+            return maxRow;
+        }
+        int largestChild = keys[keys.length-1]; 
+        if(largestChild > 0) {
+            SpreadsheetLines child = nodes.get(largestChild);
+            return child.getMaxRow();
+        } else {
+            return keys[keys.length-2];
+        }
+    }
+
+    @Override
+    public Optional<SpreadsheetEngine> getParent() {
+        return Optional.of(parent);
+    }
+
+    @Override
+    public Collection<SpreadsheetLine> getSpreadsheetChildren() {
+        return lines.values();
+    }
+
+    @Override
+    public void remove(SpreadsheetLine child) {
+        lines.remove(-child.row);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SpreadsheetLines other = (SpreadsheetLines) obj;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (parent == null) {
+            if (other.parent != null)
+                return false;
+        } else if (!parent.equals(other.parent))
+            return false;
+        return true;
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetMapping.java
new file mode 100644 (file)
index 0000000..e08c6c0
--- /dev/null
@@ -0,0 +1,53 @@
+package org.simantics.spreadsheet.solver;
+
+import java.io.Serializable;
+
+import org.simantics.structural.synchronization.utils.ComponentFactory;
+import org.simantics.structural.synchronization.utils.MappingBase;
+import org.simantics.structural.synchronization.utils.Solver;
+import org.simantics.structural.synchronization.utils.StateUndoContextBase;
+
+public class SpreadsheetMapping extends MappingBase<SheetLineComponent> implements Serializable {
+
+    private static final long serialVersionUID = -7556699663877911393L;
+
+    final SheetLineComponent configuration;
+
+    public SpreadsheetMapping(SheetLineComponent configuration) {
+        super(configuration, true);
+        this.configuration = configuration;
+    }
+
+    @Override
+    public SheetLineComponent getConfiguration() {
+        return configuration;
+    }
+
+    @Override
+    public StateUndoContextBase createUndoContext() {
+        return new StateUndoContextBase() {
+
+            @Override
+            public void saveState(Solver solver, int componentId, String uid) {
+            }
+
+            @Override
+            public boolean loadState(Solver solver, int componentId, String uid) {
+                return false;
+            }
+        };
+    }
+
+    @Override
+    public ComponentFactory<SheetLineComponent> createComponentFactory() {
+        return new ComponentFactory<SheetLineComponent>() {
+
+            @Override
+            public SheetLineComponent create(String uid) {
+                return new SheetLineComponent(uid);
+            }
+
+        };
+    }
+
+}
similarity index 96%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetSCLConstant.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetSCLConstant.java
index e8d38b2c592d71bdcfa135e24fe78a18c69cecc1..2fe8f7cae69a4d1fe374ecd2396956d5a2b621c5 100644 (file)
@@ -1,4 +1,4 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.io.Serializable;
 
@@ -11,14 +11,14 @@ public class SpreadsheetSCLConstant implements Serializable {
 
     public String expression;
     public Object content;
-    
+
     public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetSCLConstant.class);
 
     public SpreadsheetSCLConstant(String expression, Object object) {
         this.content = object;
         this.expression = expression;
     }
-    
+
     @Override
     public String toString() {
         return super.toString();
similarity index 81%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetStyle.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetStyle.java
index ecd22175ede1f53603ffa5dd4fe9805fef9e646b..33dd5347be710a204d283ea1d703568838483642 100644 (file)
@@ -1,66 +1,70 @@
-package org.simantics.spreadsheet.graph;
+package org.simantics.spreadsheet.solver;
 
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Optional;
 
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
 import org.simantics.datatypes.literal.Font;
 import org.simantics.datatypes.literal.RGB;
+import org.simantics.spreadsheet.SpreadsheetVisitor;
 
+@SuppressWarnings("rawtypes")
 public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<SpreadsheetStyle, SpreadsheetStyle> {
 
-//    public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetStyle.class);
-    
+    public static final Binding BINDING = Bindings.getBindingUnchecked(SpreadsheetStyle.class);
+
     private static final SpreadsheetStyle EMPTY = SpreadsheetStyle.newInstace().name("Style_E").build();
-    
+
     private static final long serialVersionUID = -4969920277489585741L;
-    
+
     public final String name;
-       public final int border;
-       public final int align;
-       public final Font font;
-       public final RGB.Integer foreground;
-       public final RGB.Integer background;
-       public final boolean locked;
-       public final int rowSpan;
-       public final int columnSpan;
-
-       private transient int synchronizationId;
+    public final int border;
+    public final int align;
+    public final Font font;
+    public final RGB.Integer foreground;
+    public final RGB.Integer background;
+    public final boolean locked;
+    public final int rowSpan;
+    public final int columnSpan;
+
+    private transient int synchronizationId;
     private transient final int hashCode;
 
     public final String formatString;
     public final int formatIndex;
-       
-       public SpreadsheetStyle(String name, int border, int align2, Font font2, RGB.Integer foreground2, RGB.Integer background2, boolean locked2, int rowSpan2, int columnSpan2, String formatString, short formatIndex) {
-           this.name = name;
-           this.border = border;
-           this.align = align2;
-           this.font = font2;
-           this.foreground = foreground2;
-           this.background = background2;
-           this.locked = locked2;
-           this.rowSpan = rowSpan2;
-           this.columnSpan = columnSpan2;
-           
-           this.formatString = formatString;
-           this.formatIndex = formatIndex;
-           
-           
-           this.hashCode = hashCode();
+
+    public SpreadsheetStyle(String name, int border, int align2, Font font2, RGB.Integer foreground2, RGB.Integer background2, boolean locked2, int rowSpan2, int columnSpan2, String formatString, short formatIndex) {
+        this.name = name;
+        this.border = border;
+        this.align = align2;
+        this.font = font2;
+        this.foreground = foreground2;
+        this.background = background2;
+        this.locked = locked2;
+        this.rowSpan = rowSpan2;
+        this.columnSpan = columnSpan2;
+
+        this.formatString = formatString;
+        this.formatIndex = formatIndex;
+
+
+        this.hashCode = hashCode();
+    }
+
+    public int getId() {
+        return synchronizationId;
+    }
+
+    public int getStyleId() {
+        return hashCode();
     }
-       
-       public int getId() {
-           return synchronizationId;
-       }
-       
-       public int getStyleId() {
-           return hashCode();
-       }
 
     @Override
     public void accept(SpreadsheetVisitor v) {
-        
+
     }
 
     @Override
@@ -75,7 +79,7 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
 
     @Override
     public void remove(SpreadsheetStyle child) {
-        
+
     }
 
     @Override
@@ -97,7 +101,7 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
     public int hashCode() {
         if (hashCode != 0)
             return hashCode;
-        
+
         final int prime = 31;
         int result = 1;
         result = prime * result + align;
@@ -110,7 +114,7 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
         result = prime * result + ((foreground == null) ? 0 : foreground.hashCode());
         result = prime * result + (locked ? 1231 : 1237);
         result = prime * result + rowSpan;
-        
+
         return result;
     }
 
@@ -159,17 +163,17 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
             return false;
         return true;
     }
-    
+
     public static SpreadsheetStyleBuilder newInstace() {
         return new SpreadsheetStyleBuilder();
     }
-    
+
     public static SpreadsheetStyle empty() {
         return EMPTY;
     }
-    
+
     public static class SpreadsheetStyleBuilder {
-        
+
         private String name;
         private RGB.Integer foreground;
         private RGB.Integer background;
@@ -183,52 +187,52 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
         private short formatIndex;
 
         private SpreadsheetStyleBuilder() {}
-        
+
         public SpreadsheetStyleBuilder name(String name) {
             this.name = name;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder foreground(RGB.Integer foreground) {
             this.foreground = foreground;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder background(RGB.Integer background) {
             this.background = background;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder border(Integer border) {
             this.border = border == null ? 0 : border;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder align(Integer align) {
             this.align = align == null ? 0 : align;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder font(Font font) {
             this.font = font;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder locked(boolean locked) {
             this.locked = locked;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder rowSpan(int rowSpan) {
             this.rowSpan = rowSpan;
             return this;
         }
-        
+
         public SpreadsheetStyleBuilder font(int columnSpan) {
             this.columnSpan = columnSpan;
             return this;
         }
-        
+
         public SpreadsheetStyle build() {
             SpreadsheetStyle style = new SpreadsheetStyle(name, border, align, font, foreground, background, locked, rowSpan, columnSpan, formatString, formatIndex);
             return style;
@@ -253,5 +257,5 @@ public final class SpreadsheetStyle implements SheetNode, SpreadsheetElement<Spr
     public void setSynchronizationId(int newId) {
         this.synchronizationId = newId;
     }
-    
+
 }
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetTypeNode.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/SpreadsheetTypeNode.java
new file mode 100644 (file)
index 0000000..90ea58a
--- /dev/null
@@ -0,0 +1,32 @@
+package org.simantics.spreadsheet.solver;
+
+import java.util.Collections;
+import java.util.Map;
+
+@SuppressWarnings("rawtypes")
+public class SpreadsheetTypeNode implements SheetNode {
+
+    private static final long serialVersionUID = 8008959901150210428L;
+
+    public final String uri;
+
+    public SpreadsheetTypeNode(String uri) {
+        this.uri = uri;
+    }
+
+    @Override
+    public String getName() {
+        return "typeURI";
+    }
+
+    @Override
+    public Map getChildren() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Map getProperties() {
+        return Collections.emptyMap();
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AndFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AndFormulaFunction.java
new file mode 100644 (file)
index 0000000..bee0320
--- /dev/null
@@ -0,0 +1,23 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class AndFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() == 0)
+            throw new IllegalStateException();
+        Boolean finalResult = Boolean.TRUE;
+        for (int i = 0; i < args.values.size(); i++) {
+            Object res = (args.values.get(i).accept(visitor));
+            FormulaError2 err = FormulaError2.forObject(res);
+            if(err!=null) return err.getString();
+
+            if ((res instanceof Boolean && !((Boolean)res)) || !Spreadsheets.asBoolean(res))
+                finalResult = Boolean.FALSE;
+        }
+        return finalResult;
+    }
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/AverageFormulaFunction.java
new file mode 100644 (file)
index 0000000..05528e2
--- /dev/null
@@ -0,0 +1,51 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+
+public class AverageFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() == 0)
+            throw new IllegalStateException();
+        Double sum = 0.0;
+        double count = 0.0;
+        for(AstValue value : args.values){
+            Object res = value.accept(visitor);
+            if (res instanceof SpreadsheetMatrix) {
+                Object value2 = ((SpreadsheetMatrix) res).sumWithFormulaError();
+                if(value2 instanceof String) return value2;
+
+                sum += ((Number)value2).doubleValue();
+                count += ((SpreadsheetMatrix) res).countOfActualDoubleValues();
+            } else {
+                FormulaError2 err = FormulaError2.forObject(res);
+                if(err!=null) return err.getString();
+
+                if(res instanceof Variant){
+                    Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(res);
+                    if(dVal==null) res = ((Variant)res).toString();
+                    else res = dVal;
+                }
+
+                Double v = null;
+                if(res instanceof String && !res.equals("")){
+                    v = Spreadsheets.asDoubleWhereEmptyStringIsZero(res);
+                }
+                else if(res instanceof Number)
+                    v = Spreadsheets.asDoubleWhereEmptyStringIsZero(res);
+
+                if(v!=null){
+                    sum += v;
+                    count++;
+                }
+            }
+        }
+        if(count==0.0) return FormulaError2.DIV0.getString();
+        return sum/count;
+    }
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellFormulaFunction.java
new file mode 100644 (file)
index 0000000..d04bea1
--- /dev/null
@@ -0,0 +1,9 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public interface CellFormulaFunction<T> {
+
+    T evaluate(CellValueVisitor visitor, AstArgList args);
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CellValueVisitor.java
new file mode 100644 (file)
index 0000000..fd5ecd1
--- /dev/null
@@ -0,0 +1,481 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.Range;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetEngine;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstApply;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArithmeticExpression;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArray;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstBoolean;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstDouble;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstFactor;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstIdentifier;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstInteger;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstNull;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRelation;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstString;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstTerm;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValueVisitor;
+
+import it.unimi.dsi.fastutil.longs.AbstractLongList;
+import it.unimi.dsi.fastutil.longs.LongArrayList;
+
+public class CellValueVisitor implements AstValueVisitor<Object> {
+
+    final public SpreadsheetBook book;
+    final private SpreadsheetEvaluationEnvironment env;
+    final private SpreadsheetCell thisCell;
+    final private LongArrayList references = new LongArrayList();
+
+    public CellValueVisitor(SpreadsheetEvaluationEnvironment env, SpreadsheetCell thisCell) {
+        this.book = env.getBook();
+        this.env = env;
+        this.thisCell = thisCell;
+    }
+
+    public void addReference(long ref) {
+        references.add(ref);
+    }
+
+    public AbstractLongList getReferences() {
+        return references;
+    }
+
+    @Override
+    public Object visit(AstBoolean astBoolean) {
+        return astBoolean.value;
+    }
+
+    @Override
+    public Object visit(AstDouble astFloat) {
+        return astFloat.value;
+    }
+
+    @Override
+    public Object visit(AstInteger astInteger) {
+        return astInteger.value;
+    }
+
+    @Override
+    public Object visit(AstNull astNull) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public Object visit(AstString astString) {
+        return astString.value;
+    }
+
+    @Override
+    public Object visit(AstRange astRange) {
+
+        if(astRange.isRef()){
+            return FormulaError2.REF.getString();
+        }
+
+        if(astRange.isCell()) {
+            String ref = astRange.first;
+            Range r = Spreadsheets.decodeCell(ref, 0, 0);
+            String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
+            SpreadsheetCell cell = thisCell.getBook().get(sheetName, r.startRow, r.startColumn);
+            if(cell == null) {
+                SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
+                SpreadsheetLine line = eng.getLine(r.startRow);
+
+                if (line == null) {
+                    line = new SpreadsheetLine(eng.lines, r.startRow);
+                    eng.lines.lines.put(-r.startRow, line);
+                }
+                cell = SpreadsheetCell.empty(line, r.startColumn);
+            }
+            return cell.evaluate(env, this);
+
+        } else {
+
+            Object cached = thisCell.getEngine().getCachedRange(astRange);
+            if(cached != null) {
+
+                Range r_ = Spreadsheets.decodeRange(astRange.first + ":" + astRange.second);
+                String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
+                SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
+                Range r = eng.actualRange(r_);
+                for(int row=0; row < r.height();row++) {
+                    SpreadsheetLine line = eng.getLine(r.startRow + row);
+                    if(line != null) {
+                        for(int column=0; column < r.width();column++) {
+                            int col = r.startColumn + column;
+                            if(line.cells.size() > col) {
+                                SpreadsheetCell cell = line.cells.get(r.startColumn + column);
+                                //Add references, but do not evaluate if there exists a cached range.
+                                addReference(cell.makeReferenceKey());
+                            }
+                        }
+                    }
+                }      
+                return cached;
+            }
+
+            Range r_ = Spreadsheets.decodeRange(astRange.first + ":" + astRange.second);
+            String sheetName = astRange.sheetName != null ? astRange.sheetName : thisCell.getEngine().getName();
+            SpreadsheetEngine eng = thisCell.getBook().getEngine(sheetName);
+            // Full ranges are resolved here
+            Range r = eng.actualRange(r_);
+            SpreadsheetMatrix result = new SpreadsheetMatrix(r.width(), r.height());
+            for(int row=0; row < r.height();row++) {
+                SpreadsheetLine line = eng.getLine(r.startRow + row);
+                if(line != null) {
+                    for(int column=0; column < r.width();column++) {
+                        int col = r.startColumn + column;
+                        if(line.cells.size() > col) {
+                            SpreadsheetCell cell = line.cells.get(r.startColumn + column);
+                            result.values[r.width()*row + column] = cell.evaluate(env, this);
+                        }
+                    }
+                }
+            }
+            thisCell.getEngine().cacheRange(astRange, result);
+            return result;
+        }
+    }
+
+    @Override
+    public Object visit(AstArgList astArgList) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public Object visit(AstApply astApply) {
+        CellFormulaFunction<?> fn = env.getFunction(astApply.value);
+        if(fn != null) {
+            return fn.evaluate(this, astApply.args);
+        } else {
+            return FormulaError2.NAME.getString();
+        }
+    }
+
+    @Override
+    public Object visit(AstRelation astRelation) {
+
+        Object leftResult = astRelation.left.accept(this);
+        Object rightResult = astRelation.right.accept(this);
+
+        FormulaError2 err = FormulaError2.forObject(leftResult);
+        if(err!=null) return err.getString();
+        FormulaError2 err2 = FormulaError2.forObject(rightResult);
+        if(err2!=null) return err2.getString();
+
+        if(leftResult instanceof Variant){
+            Object leftTemp = ((Variant)leftResult).getValue();
+            Double leftVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftTemp);
+            if(leftVal==null) leftResult = leftTemp.toString();
+            else leftResult = leftVal;
+        }
+        if(rightResult instanceof Variant){
+            Object rightTemp = ((Variant)rightResult).getValue();
+            Double rightVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightTemp);
+            if(rightVal==null) rightResult = rightTemp.toString();
+            else rightResult = rightVal;
+        }
+        if ((leftResult instanceof String) && (rightResult instanceof String)) {
+            String leftString = (leftResult.toString()).toLowerCase();
+            String rightString = (rightResult.toString()).toLowerCase();
+            if("<".equals(astRelation.op.trim())) return leftString.compareTo(rightString) < 0;
+            else if(">".equals(astRelation.op.trim())) return leftString.compareTo(rightString) > 0;
+            else if("=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) == 0;
+            else if("<>".equals(astRelation.op.trim())) return leftString.compareTo(rightString) != 0 ;
+            else if("<=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) <= 0 ;
+            else if(">=".equals(astRelation.op.trim())) return leftString.compareTo(rightString) >= 0 ;
+            else throw new IllegalStateException();
+        } else {
+            Number leftNumber = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftResult);
+            Number rightNumber = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightResult);
+            if(leftNumber==null || rightNumber==null) return false;
+            if("<".equals(astRelation.op.trim())) return leftNumber.doubleValue() < rightNumber.doubleValue();
+            else if(">".equals(astRelation.op.trim())) return leftNumber.doubleValue() > rightNumber.doubleValue();
+            else if("=".equals(astRelation.op.trim())) return leftNumber.doubleValue() == rightNumber.doubleValue();
+            else if("<>".equals(astRelation.op.trim())) return leftNumber.doubleValue() != rightNumber.doubleValue();
+            else if("<=".equals(astRelation.op.trim())) return leftNumber.doubleValue() <= rightNumber.doubleValue();
+            else if(">=".equals(astRelation.op.trim())) return leftNumber.doubleValue() >= rightNumber.doubleValue();
+            else throw new IllegalStateException();
+        }
+    }
+
+    Object leftValueWithPrefix(Object result, AstValue value, String prefix, boolean forceNumber) {
+        if(result == null) {
+            Object obj = value.accept(this);
+            FormulaError2 err = FormulaError2.forObject(obj);
+            if(err!=null) return err.getString();
+
+            if("-".equals(prefix)) {
+                result = Spreadsheets.asNumber(obj);
+                return -((Number)result).doubleValue();
+            } else {
+                if(forceNumber) return Spreadsheets.asNumber(obj);
+                else return obj;
+            }
+        }
+        try{
+            return (Number)Double.parseDouble(result.toString());
+        } catch (NumberFormatException e){
+            return result;
+        }
+    }
+
+    @Override
+    public Object visit(AstArithmeticExpression exp) {
+        Object result = null;
+        Object other = null;
+        AstValue value = null;
+        Object acceptedValue = null;
+
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            value = exp.rightValue(i);
+            acceptedValue = value.accept(this);
+            if("+".equals(op)) {
+                result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+                if(!(result instanceof Number)) {
+                    FormulaError2 err = FormulaError2.forObject(result);
+                    if(err!=null) return err.getString();
+
+                    if(result instanceof String && !((String) result).isEmpty()){
+                        Number num = Spreadsheets.asValidNumber(result);
+                        if(num == null) {
+                            return FormulaError2.VALUE.getString();
+                        } else {
+                            result = num;
+                        }
+                    } 
+                    else if(result instanceof Variant){
+                        Object val = ((Variant)result).getValue();
+                        if(val instanceof String && (val.toString().isEmpty())){
+                            result = 0.0;
+                        } else {
+                            Number resNum = Spreadsheets.asDoubleWhereEmptyStringIsZero(val);
+                            if(resNum==null) return FormulaError2.VALUE.getString();
+                            else result = resNum;
+                        }
+                    } else {
+                        result = 0.0;
+                    }
+                }
+
+                FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+                if(err2!=null) return err2.getString();
+
+                other = Spreadsheets.asDoubleWhereEmptyStringIsZero(acceptedValue);
+                if(other==null)
+                    return FormulaError2.handleErrorCall(acceptedValue);
+
+                result = ((Number)result).doubleValue() + ((Number)other).doubleValue();
+
+            } else if("-".equals(op)) {
+                result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+                if(!(result instanceof Number)) {
+                    FormulaError2 err = FormulaError2.forObject(result);
+                    if(err!=null) return err.getString();
+
+                    if(result instanceof String && !((String) result).isEmpty()){
+                        Number num = Spreadsheets.asValidNumber(result);
+                        if(num == null) {
+                            return FormulaError2.VALUE.getString();
+                        } else {
+                            result = num;
+                        }
+                    } 
+                    else if(result instanceof Variant){
+                        Object val = ((Variant)result).getValue();
+                        if(val instanceof String && (val.toString().isEmpty())){
+                            result = 0.0;
+                        } else {
+                            Number resNum = Spreadsheets.asDoubleWhereEmptyStringIsZero(val);
+                            if(resNum==null)
+                                return FormulaError2.VALUE.getString();
+                            else result = resNum;
+                        }
+                    } else {
+                        result = 0.0;
+                    }
+                }
+                FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+                if(err2!=null) return err2.getString();
+
+                other = Spreadsheets.asDoubleWhereEmptyStringIsZero(acceptedValue);
+                if(other==null)
+                    return FormulaError2.handleErrorCall(acceptedValue);
+
+                result = ((Number)result).doubleValue() - ((Number)other).doubleValue();
+
+            } else if("&".equals(op)) {
+                result = leftValueWithPrefix(result, exp.left, exp.prefix, false);
+                FormulaError2 err = FormulaError2.forObject(result);
+                if(err!=null) return err.getString();
+                FormulaError2 err2 = FormulaError2.forObject(acceptedValue);
+                if(err2!=null) return err2.getString();
+
+                result = Spreadsheets.asString(result);
+                other = Spreadsheets.asString(acceptedValue);
+
+                result += (String)other;
+            }
+        }
+        return leftValueWithPrefix(result, exp.left, exp.prefix, false);
+
+    }
+
+    @Override
+    public Object visit(AstTerm exp) {
+        Number result = null;
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            AstValue value = exp.rightValue(i);
+            Object leftValue = exp.left.accept(this);
+            Object rightValue = value.accept(this);
+            if("*".equals(op)) {
+                if(result == null) {
+                    result = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftValue);
+                    if(result == null)
+                        return FormulaError2.handleErrorCall(leftValue);
+                }
+                Number other = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightValue);
+                if(other==null) return FormulaError2.handleErrorCall(rightValue);
+
+                result = new Double(result.doubleValue() * other.doubleValue());
+
+            } else if("/".equals(op)) {
+                if(result == null) {
+                    result = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftValue);
+                    if(result == null)
+                        return FormulaError2.handleErrorCall(leftValue);
+                }
+                Number other = Spreadsheets.asDoubleWhereEmptyStringIsZero(rightValue);
+                if(other==null) return FormulaError2.handleErrorCall(rightValue);
+                if(other.doubleValue()==0.0) return FormulaError2.DIV0.getString();
+
+                result = new Double(result.doubleValue() / other.doubleValue());       
+            }
+        }
+        if(result == null) result = Spreadsheets.asNumber(exp.left.accept(this));
+        return result;
+    }
+
+    @Override
+    public Object visit(AstFactor exp) {
+        Object result = null;
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            AstValue value = exp.rightValue(i);
+            if("^".equals(op)) {
+                if(result == null) {
+                    Object leftValue = exp.left.accept(this);
+
+                    FormulaError2 err = FormulaError2.forObject(leftValue);
+                    if(err!=null) return err.getString();
+
+                    if(leftValue instanceof Variant){
+                        Object leftTemp = ((Variant)leftValue).getValue();
+                        Double leftV = Spreadsheets.asDoubleWhereEmptyStringIsZero(leftTemp);
+                        if(leftV==null) leftValue = leftTemp.toString();
+                        else leftValue = leftV;
+                    }
+
+                    if(leftValue instanceof String){
+                        if((leftValue.toString()).isEmpty())
+                            result = 0;
+                        else 
+                            return FormulaError2.VALUE.getString();
+                    }
+                    else if(leftValue instanceof SpreadsheetMatrix) 
+                        result = leftValue;
+                    else 
+                        result = Spreadsheets.asNumber(leftValue);
+                }
+                Object otherValue = value.accept(this);
+
+                FormulaError2 err2 = FormulaError2.forObject(otherValue);
+                if(err2!=null) return err2.getString();
+
+                if(otherValue instanceof Variant){
+                    Object otherTemp = ((Variant)otherValue).getValue();
+                    Double otherV = Spreadsheets.asDoubleWhereEmptyStringIsZero(otherTemp);
+                    if(otherV==null) otherValue = otherTemp.toString();
+                    else otherValue = otherV;
+                }
+
+                if(otherValue instanceof String){
+                    if((otherValue.toString()).isEmpty())
+                        otherValue = 0;
+                    else 
+                        return FormulaError2.VALUE.getString();
+                }
+
+                if(result instanceof SpreadsheetMatrix) {
+                    result = ((SpreadsheetMatrix)result).pow(otherValue);
+                } else {
+                    if(otherValue instanceof SpreadsheetMatrix) {
+                        throw new IllegalStateException();
+                    } else {
+                        Double base = ((Number)result).doubleValue();
+                        Double exponent = Spreadsheets.asNumber(otherValue);
+                        if(exponent==0 && base==0)
+                            return FormulaError2.NUM.getString();
+                        if(exponent<0 && base==0)
+                            return FormulaError2.DIV0.getString();
+                        result = Math.pow(base, exponent);
+                        if(result instanceof Double && Double.isInfinite((Double)result)){
+                            return FormulaError2.NUM.getString();
+                        }
+                    }
+                }
+            }
+        }
+        if(result == null) result = Spreadsheets.asNumber(exp.left.accept(this));
+        return result;
+    }
+
+    @Override
+    public Object visit(AstIdentifier id) {
+        return FormulaError2.NAME.getString();
+        //throw new IllegalStateException();
+    }
+
+    @Override
+    public Object visit(AstArray array) {
+        SpreadsheetMatrix m = new SpreadsheetMatrix(array.values.size(), 1);
+        for(int i=0;i<array.values.size();i++) {
+            m.values[i] = array.values.get(i).accept(this);
+        }
+        return m; 
+    }
+
+    @Override
+    public Object visit(AstNothing array) {
+        return AstNothing.NOTHING;
+    }
+
+    @Override
+    public Object visit(AstArrayFormulaReference ref) {
+
+        Range thisRange = Spreadsheets.decodeRange(thisCell.getName());
+        Range arrayRange = Spreadsheets.decodeRange(ref.range);
+        int x = thisRange.startColumn - arrayRange.startColumn;
+        int y = thisRange.startRow - arrayRange.startRow;
+
+        SpreadsheetMatrix m = (SpreadsheetMatrix)ref.value.accept(this);
+        return m.get(y, x);
+
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CountifFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/CountifFormulaFunction.java
new file mode 100644 (file)
index 0000000..82a3ac1
--- /dev/null
@@ -0,0 +1,31 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange;
+
+public class CountifFormulaFunction implements CellFormulaFunction<Integer> {
+
+    @Override
+    public Integer evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() != 2) throw new IllegalStateException();
+
+        AstRange range = (AstRange) args.values.get(0);
+        SpreadsheetMatrix matrix = (SpreadsheetMatrix) range.accept(visitor);
+        Object crit = null;
+        try {
+            crit = args.values.get(1).accept(visitor);
+        } catch (IllegalStateException e){
+            return 0;
+        }
+
+        String criteria = Spreadsheets.asString(crit);
+        int result = 0;
+        for (Object value : matrix.values) {
+            if (Spreadsheets.matchCriteria(value, criteria))
+                result++;
+        }
+        return Integer.valueOf(result);
+    }
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/FormulaError2.java
new file mode 100644 (file)
index 0000000..d0f2b92
--- /dev/null
@@ -0,0 +1,55 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.util.Internal;
+import org.simantics.databoard.binding.mutable.Variant;
+
+public enum FormulaError2{
+    @Internal
+    _NO_ERROR(-1, "(no error)"),NULL(0x00, "#NULL"),DIV0(0x07,"#DIV/0!"),VALUE(0x0F,
+            "#VALUE!"),REF(0x17,"#REF!"),NAME(0x1D,"#NAME?"),NUM(0x24,"#NUM!"),NA(0x2A, "#N/A"),
+    CIRCULAR_REF(0xFFFFFFC4, "~CIRCULAR~REF~"),FUNCTION_NOT_IMPLEMENTED(0xFFFFFFE2,"~FUNCTION~NOT~IMPLEMENTED~");
+
+    private final String text;
+    //private final Integer longType;
+    //private final byte shortType;
+
+    private static Map<String, FormulaError2> smap = new HashMap<String, FormulaError2>();
+
+    private FormulaError2(int type, String text){
+        //this.longType = type;
+        //this.shortType = (byte)type;
+        this.text = text;
+    }
+
+    static {
+        for(FormulaError2 error : values()) {
+            smap.put(error.getString(), error);
+        }
+    }
+
+    public String getString(){
+        return this.text;
+    }
+
+    public static FormulaError2 forString(String errorName){
+        FormulaError2 err = smap.get(errorName);
+        return err;
+    }
+
+    public static FormulaError2 forObject(Object errorObj){
+        if(errorObj instanceof Variant)
+            return forString(((Variant)errorObj).getValue().toString());
+        else
+            return forString(errorObj.toString());
+    }
+
+    public static String handleErrorCall(Object value){
+        if(value==null) return VALUE.getString();
+        FormulaError2 error = FormulaError2.forObject(value);
+        if(error!=null) return error.getString();
+        return VALUE.getString();
+    }
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/GeomeanFormulaFunction.java
new file mode 100644 (file)
index 0000000..25f3f58
--- /dev/null
@@ -0,0 +1,45 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+
+public class GeomeanFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() == 0)
+            throw new IllegalStateException();
+        double result = 1.0;
+        double count = 0.0;
+        for (AstValue value : args.values){
+            Object r = value.accept(visitor);
+            if (r instanceof SpreadsheetMatrix) {
+                Object v = ((SpreadsheetMatrix) r).productWithFormulaError();
+                if(v instanceof String) return v;
+                double dval = ((Number)v).doubleValue();
+                if(dval!=0.0){
+                    result = result*dval;
+                    count += ((SpreadsheetMatrix) r).countOfActualDoubleValues();
+                }
+            } else {
+                FormulaError2 error = FormulaError2.forObject(r);
+                if(error!=null) return error.getString();
+
+                Number vNum = Spreadsheets.asValidNumber(r);
+                Double v = null;
+                if(vNum!=null) v = vNum.doubleValue();
+
+                if(v!=null){
+                    if(v<=0) return FormulaError2.NUM.getString();
+                    result = result*v;
+                    count++;
+                }
+            }
+        }
+        if(result==0.0 || count==0.0) return FormulaError2.NUM.getString();
+        return Double.valueOf(Math.pow(result, (1.0/count)));
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/HlookupFormulaFunction.java
new file mode 100644 (file)
index 0000000..c5e4a3e
--- /dev/null
@@ -0,0 +1,137 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class HlookupFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException();
+
+        Object lookupValue = args.values.get(0).accept(visitor);
+        boolean lookupIsString = lookupValue instanceof String;
+
+        FormulaError2 error = FormulaError2.forObject(lookupValue);
+        if(error!=null) return error.getString();
+
+        if(lookupValue instanceof Variant){
+            Object varVal = ((Variant)lookupValue).getValue();
+            Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(varVal);
+            if(dVal==null) {
+                lookupValue = varVal.toString();
+                lookupIsString = true;
+            }
+            else lookupValue = dVal;
+        }
+
+        SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
+
+        boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true;
+
+        if(array.values.length != 0){
+            if(lookupIsString){
+                Object obj = array.values[0];
+                if(obj instanceof Variant)
+                    obj = ((Variant)obj).getValue();
+                if(Spreadsheets.asValidNumber(obj)!=null)
+                    return FormulaError2.NA.getString();
+                obj = obj.toString();
+                String valStr = ((String)obj).toLowerCase();
+                if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 )
+                    return FormulaError2.NA.getString();
+            }
+            else if(lookupValue instanceof Number){
+                Double d = ((Number)lookupValue).doubleValue();
+                Number d2 = Spreadsheets.asValidNumber(array.values[0]);
+                if(d2==null || d<(d2.doubleValue()))
+                    return FormulaError2.NA.getString();
+            }
+        }
+
+        Number rowIndexN = (Number) Spreadsheets.asValidNumber(args.values.get(2).accept(visitor));
+        if(rowIndexN==null) return FormulaError2.REF.getString();
+        int rowIndexNum = rowIndexN.intValue();
+        if(rowIndexNum>array.getHeight()) return FormulaError2.REF.getString();
+
+        if (approximateMatch) {
+            Integer colPosOfLargestValSmallerThanLookUp = null;
+            if(lookupIsString){
+                String largestValSmallerThanLookUp = null;
+                String ref = lookupValue.toString();
+                String previousValue = null;
+                for(int i = 0; i < array.getWidth(); i++){
+                    Object val = array.get(0, i);
+                    if(val instanceof Variant)
+                        val = ((Variant)val).getValue();
+                    String currValue = val.toString();
+                    int currCompedToRef = currValue.compareTo(ref);
+                    if(currCompedToRef>=0){
+                        if(i==0)
+                            return array.get(rowIndexNum-1, i);
+                        else if(previousValue.compareTo(ref) > currCompedToRef )
+                            return array.get(rowIndexNum-1, i);
+                        else 
+                            return array.get(rowIndexNum - 1, i - 1);
+                    }
+                    if(colPosOfLargestValSmallerThanLookUp==null){
+                        colPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = currValue;
+                    } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){
+                        colPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = currValue;
+                    }
+                    previousValue = currValue;
+                }
+
+            } else {
+                double ref = Spreadsheets.asNumber(lookupValue);
+                double lastDiff = Double.MIN_VALUE;
+                Double largestValSmallerThanLookUp = null;
+                for (int i = 0; i < array.getWidth(); i++) {
+                    Object value = array.get(0, i);
+                    double n = Spreadsheets.asNumber(value);
+                    double diff = n - ref;
+                    if (diff >= 0) {
+                        if (i == 0)
+                            return array.get(rowIndexNum - 1, i);
+                        else if (diff < -lastDiff)
+                            return array.get(rowIndexNum - 1, i);
+                        else
+                            return array.get(rowIndexNum - 1, i - 1);
+                    }
+                    if(colPosOfLargestValSmallerThanLookUp==null){
+                        colPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = n;
+                    } else if(largestValSmallerThanLookUp < n){
+                        colPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = n;
+                    }
+                    lastDiff = diff;
+                }
+            }
+            if(colPosOfLargestValSmallerThanLookUp!=null) return array.get(rowIndexNum - 1, colPosOfLargestValSmallerThanLookUp);
+
+        } else {
+
+            for (int i = 0; i < array.getWidth(); i++) {
+                Object value = array.get(0, i);
+                if(value instanceof Variant){
+                    if(lookupIsString)
+                        value = ((Variant)value).getValue().toString();
+                    else 
+                        value = Spreadsheets.asNumber(value);
+                }
+                if (Spreadsheets.excelEquals(lookupValue, value)) {
+                    return array.get(rowIndexNum - 1, i);
+                }
+            }
+
+        }
+
+        return FormulaError2.NA.getString();
+    }
+
+}
similarity index 63%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfErrorFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfErrorFormulaFunction.java
index 891992c7d23c93f588a6ed7f61247cb373a643bd..9c79234826369753dc169ab69f65322318dc4d5b 100644 (file)
@@ -1,16 +1,14 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class IfErrorFormulaFunction implements CellFormulaFunction<Object> {
-       
-       @Override
+
+    @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-               
+
         if (args.values.size() != 2) throw new IllegalStateException();
-        
+
         Object condition = args.values.get(0).accept(visitor);
         FormulaError2 error = FormulaError2.forObject(condition);
         if(error!=null) return error.getString();
similarity index 51%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IfFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IfFormulaFunction.java
index 2d2ef8c5b74e9ce41a5398b7629e98320dae6cc3..351d6258f0d0638d6a688cb7c3d10ad94e5c5fbf 100644 (file)
@@ -1,41 +1,39 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstNothing;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
 
 public class IfFormulaFunction implements CellFormulaFunction<Object> {
 
     @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
         if (args.values.size() != 3) throw new IllegalStateException();
-        
+
         Object condition = args.values.get(0).accept(visitor);
         AstValue ifTrueResult = args.values.get(1);
         AstValue ifFalseResult = args.values.get(2);
-        
+
         FormulaError2 error = FormulaError2.forObject(condition);
-               if(error!=null) return error.getString();
+        if(error!=null) return error.getString();
 
-        if (SpreadsheetGraphUtils.asBoolean(condition)) {
+        if (Spreadsheets.asBoolean(condition)) {
             if(ifTrueResult==null || ifTrueResult instanceof AstNothing)
-               return 0;
+                return 0;
             try {
-               return ifTrueResult.accept(visitor);
+                return ifTrueResult.accept(visitor);
             } catch (IllegalStateException e){
-               return FormulaError2.NAME.getString();
+                return FormulaError2.NAME.getString();
             }
         }
         else {
             if(ifFalseResult==null || ifFalseResult instanceof AstNothing)
-               return 0;
+                return 0;
             try {
-               return ifFalseResult.accept(visitor);
+                return ifFalseResult.accept(visitor);
             } catch (IllegalStateException e){
-               return FormulaError2.NAME.getString();
+                return FormulaError2.NAME.getString();
             }
         }
     }
similarity index 50%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/IsErrorFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/IsErrorFormulaFunction.java
index 922b8af13d61db9b7258b78d6a44f3b322e134f9..c2680cbf4e439754f1a9f4ad4cc5d2f0e90c6e84 100644 (file)
@@ -1,20 +1,18 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class IsErrorFormulaFunction implements CellFormulaFunction<Object>{
 
-       @Override
+    @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
-               
+
         if (args.values.size() != 1) throw new IllegalStateException();
-        
+
         Object condition = args.values.get(0).accept(visitor);
         if(condition instanceof String){
-               FormulaError2 error = FormulaError2.forString((String)condition);
-               return (error!=null);
+            FormulaError2 error = FormulaError2.forString((String)condition);
+            return (error!=null);
         }
         return false;
     }
similarity index 82%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/LinestFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/LinestFormulaFunction.java
index dd037e9eaae010927dee651aadca7a5474d19014..8d952c1ac8f4e9f61cc8a60c9e4f0303ea22093d 100644 (file)
@@ -1,11 +1,9 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
 import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class LinestFormulaFunction implements CellFormulaFunction<SpreadsheetMatrix> {
 
@@ -30,9 +28,9 @@ public class LinestFormulaFunction implements CellFormulaFunction<SpreadsheetMat
                 double x[][] = new double[ysm.values.length][xsm.getWidth()];
 
                 for (int i = 0; i < ysm.values.length; i++) {
-                    y[i] = SpreadsheetGraphUtils.asNumber(ysm.values[i]);
+                    y[i] = Spreadsheets.asNumber(ysm.values[i]);
                     for (int j = 0; j < xsm.getWidth(); j++) {
-                        x[i][j] = SpreadsheetGraphUtils.asNumber(xsm.get(i, j));
+                        x[i][j] = Spreadsheets.asNumber(xsm.get(i, j));
                     }
                 }
 
@@ -64,7 +62,7 @@ public class LinestFormulaFunction implements CellFormulaFunction<SpreadsheetMat
                 result.set(2,2, FormulaError2.NA.getString());
                 result.set(3,2, FormulaError2.NA.getString());
                 result.set(4,2, FormulaError2.NA.getString());
-                
+
                 return result;
 
             }
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/MatchFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/MatchFormulaFunction.java
new file mode 100644 (file)
index 0000000..db7bf8c
--- /dev/null
@@ -0,0 +1,200 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class MatchFormulaFunction implements CellFormulaFunction<Object>{
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() < 2 || args.values.size() > 3) throw new IllegalStateException();
+
+        SpreadsheetMatrix lookup_array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
+        if(lookup_array.getWidth()!=1 && lookup_array.getHeight()!=1) return FormulaError2.NA.getString();
+
+        Object lookup_value = args.values.get(0).accept(visitor);
+
+        int match_type = 1;
+        try{
+            if(args.values.size()==3){
+                int matchArg = ((Number)args.values.get(2).accept(visitor)).intValue();
+                if(matchArg<0)
+                    match_type = -1;
+                else if(matchArg>0)
+                    match_type = 1;
+                else
+                    match_type = 0;
+            }
+        } catch(Exception e) {
+            return FormulaError2.NA.getString();
+        }
+
+        boolean useHeight = false;
+        if(lookup_array.getWidth()==1) useHeight = true;
+
+        int max = 0;
+        if(useHeight) max = lookup_array.getHeight();
+        else max = lookup_array.getWidth();
+
+        Integer pos = null;
+        if(lookup_value instanceof Variant){
+            Object obj = ((Variant)lookup_value).getValue();
+            Number nVal = Spreadsheets.asValidNumber(obj);
+            if(nVal!=null) obj = nVal;
+            else obj = obj.toString();
+        }
+
+        if(lookup_value instanceof Number){
+            Double previousValue = null;
+            Double closestMatch = null;
+            Double lookup = ((Number)lookup_value).doubleValue();
+            int indexWhereCorrectOrderStartsAt = 0;
+
+            if(match_type!=0) {
+                for(int i = 0; i < max;i++){
+                    Double currValue = null;
+                    Number currNum;
+                    if(useHeight){
+                        currNum = Spreadsheets.asValidNumber(lookup_array.get(i,0));
+                    } else {
+                        currNum = Spreadsheets.asValidNumber(lookup_array.get(0,i));
+                    }
+                    if(currNum!=null){
+                        currValue = currNum.doubleValue();
+                        if(currValue != null){
+                            if(previousValue!=null){
+                                if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue))
+                                    indexWhereCorrectOrderStartsAt = i;
+                                else
+                                    break;
+                            }
+                            previousValue = currValue;
+                        }
+                    }
+                }
+            }
+            int begin = indexWhereCorrectOrderStartsAt;
+
+            for(int i = begin; i < max;i++){
+                Double currValue = null;
+                Number currNum;
+                if(useHeight){
+                    currNum = Spreadsheets.asValidNumber(lookup_array.get(i,0));
+                } else {
+                    currNum = Spreadsheets.asValidNumber(lookup_array.get(0,i));
+                }
+                if(currNum!=null){
+                    currValue = currNum.doubleValue();
+                    if(currValue != null){
+                        if(previousValue==null) previousValue = currValue;
+                        if((match_type==-1 && currValue>previousValue) || (match_type==1 && currValue<previousValue)){
+                            if(pos!=null)
+                                return pos+1;
+                            previousValue = currValue;
+                        }
+                        int comp = lookup.compareTo(currValue);
+                        if(comp == 0){
+                            closestMatch = currValue;
+                            pos = i;
+                        }
+                        else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){
+                            if(closestMatch==null && pos==null){
+                                closestMatch = currValue;
+                                pos = i;
+                            }
+                            else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){
+                                closestMatch = currValue;
+                                pos = i;
+                            }
+                        }
+                        previousValue = currValue;
+                    }
+                }
+            }
+        }
+
+        else if(lookup_value instanceof String){
+            String previousValue = null;
+            String closestMatch = null;
+            String lookup = (String)lookup_value;
+            int indexWhereCorrectOrderStartsAt = 0;
+
+            if(match_type!=0) {
+                for(int i = 0; i < max;i++){
+                    String currValue = null;
+                    Object obj;
+                    if(useHeight){
+                        obj = lookup_array.get(i,0);
+                    } else {
+                        obj = lookup_array.get(0,i);
+                    }
+                    if(obj instanceof Variant){
+                        obj = ((Variant)obj).getValue();
+                    }
+                    if(obj!=null && !(obj instanceof Number)){
+                        currValue = obj.toString();
+                        currValue = currValue.toLowerCase();
+                    }
+                    if(currValue != null && !currValue.equals("")){
+                        if(previousValue!=null){
+                            if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0))
+                                indexWhereCorrectOrderStartsAt = i;
+                            else
+                                break;
+                        }
+                        previousValue = currValue;
+                    }
+                }
+            }
+
+            int begin = indexWhereCorrectOrderStartsAt;
+
+            for(int i = begin; i < max;i++){
+                String currValue = null;
+                Object obj;
+                if(useHeight){
+                    obj = lookup_array.get(i,0);
+                } else {
+                    obj = lookup_array.get(0,i);
+                }
+                if(obj instanceof Variant){
+                    obj = ((Variant)obj).getValue();
+                }
+                if(obj!=null && !(obj instanceof Number)){
+                    currValue = obj.toString();
+                    currValue = currValue.toLowerCase();
+                }
+
+                if(currValue != null && !currValue.equals("")){
+                    if(previousValue==null) previousValue = currValue;
+                    if((match_type==-1 && currValue.compareTo(previousValue)>0) || (match_type==1 && currValue.compareTo(previousValue)<0)){
+                        if(pos!=null)
+                            return pos+1;
+                        previousValue = currValue;
+                    }
+                    int comp = lookup.compareTo(currValue);
+                    if(comp == 0){
+                        closestMatch = currValue;
+                        pos = i;
+                    }
+                    else if((comp > 0 && match_type==1) || (comp<0 && match_type==-1)){
+                        if(closestMatch==null && pos==null){
+                            closestMatch = currValue;
+                            pos = i;
+                        }
+                        else if((currValue.compareTo(closestMatch)>=0 && match_type==1) || (currValue.compareTo(closestMatch)<=0 && match_type==-1)){
+                            closestMatch = currValue;
+                            pos = i;
+                        }
+                    }
+                    previousValue = currValue;
+                }
+            }
+        }
+
+        if(pos==null)return FormulaError2.NA.getString();
+        return pos+1;
+    }
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/OrFormulaFunction.java
new file mode 100644 (file)
index 0000000..a852ecc
--- /dev/null
@@ -0,0 +1,28 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class OrFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() == 0) throw new IllegalStateException();
+
+        for (int i = 0; i < args.values.size(); i++) {
+            Object obj = null;
+            try {
+                obj = args.values.get(i).accept(visitor);
+            } catch (IllegalStateException e){
+                return FormulaError2.NAME.getString();
+            }
+            FormulaError2 error = FormulaError2.forObject(obj);
+            if(error!=null) return error.getString();
+
+            if (Spreadsheets.asBoolean(obj))
+                return Boolean.TRUE;
+        }
+        return Boolean.FALSE;
+    }
+
+}
similarity index 53%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/PiFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PiFormulaFunction.java
index 8f62ac4cc8a264f38185b2fef558d5d29e84ec88..a6f2859814a3fbb359c3434912134d704812781c 100644 (file)
@@ -1,8 +1,6 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class PiFormulaFunction implements CellFormulaFunction<Double> {
 
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/PrintVisitor.java
new file mode 100644 (file)
index 0000000..1738feb
--- /dev/null
@@ -0,0 +1,168 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstApply;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArithmeticExpression;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArray;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstBoolean;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstDouble;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstFactor;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstIdentifier;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstInteger;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstNothing;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstNull;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRange;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstRelation;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstString;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstTerm;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValueVisitor;
+
+public class PrintVisitor implements AstValueVisitor<String> {
+
+    @Override
+    public String visit(AstBoolean astBoolean) {
+        return "" + astBoolean.value;
+    }
+
+    @Override
+    public String visit(AstDouble astFloat) {
+        return "" + astFloat.value;
+    }
+
+    @Override
+    public String visit(AstInteger astInteger) {
+        return "" + astInteger.value;
+    }
+
+    @Override
+    public String visit(AstNull astNull) {
+        return "AstNull";
+    }
+
+    @Override
+    public String visit(AstString astString) {
+        return "\"" + astString.value + "\"";  
+    }
+
+    @Override
+    public String visit(AstRange astRange) {
+        if(astRange.isCell()) {
+            return astRange.first;
+        } else {
+            return astRange.first + ":" + astRange.second;
+        }
+    }
+
+    @Override
+    public String visit(AstArgList astArgList) {
+        StringBuilder b = new StringBuilder();
+        for(int i=0;i<astArgList.values.size();i++) {
+            if(i > 0) b.append(";");
+            b.append(astArgList.values.get(i).accept(this));
+        }
+        return b.toString();
+    }
+
+    @Override
+    public String visit(AstApply astApply) {
+        if(astApply.args == null) {
+            return astApply.value + "()";
+        } else {
+            return astApply.value + "(" + astApply.args.accept(this) + ")";
+        }
+    }
+
+    @Override
+    public String visit(AstRelation astRelation) {
+
+        StringBuilder b = new StringBuilder();
+        b.append(astRelation.left.accept(this));
+        b.append(astRelation.op.trim());
+        b.append(astRelation.right.accept(this));
+        return b.toString();
+
+    }
+
+    @Override
+    public String visit(AstArithmeticExpression exp) {
+
+        StringBuilder b = new StringBuilder();
+        if(exp.prefix != null) b.append(exp.prefix);
+
+        b.append(exp.left.accept(this));
+
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            b.append(op);
+            AstValue value = exp.rightValue(i);
+            b.append(value.accept(this));
+        }
+
+        return b.toString();
+
+    }
+
+    @Override
+    public String visit(AstTerm exp) {
+
+        StringBuilder b = new StringBuilder();
+
+        b.append(exp.left.accept(this));
+
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            b.append(op);
+            AstValue value = exp.rightValue(i);
+            b.append(value.accept(this));
+        }
+
+        return b.toString();
+
+    }
+
+    @Override
+    public String visit(AstFactor exp) {
+
+        StringBuilder b = new StringBuilder();
+
+        b.append(exp.left.accept(this));
+
+        for(int i=0;i<exp.rightCount();i++) {
+            String op = exp.rightOp(i);
+            b.append(op);
+            AstValue value = exp.rightValue(i);
+            b.append(value.accept(this));
+        }
+
+        return b.toString();
+
+    }
+
+    @Override
+    public String visit(AstIdentifier id) {
+        return "AstIdentifier";
+    }
+
+    @Override
+    public String visit(AstArray array) {
+        StringBuilder b = new StringBuilder();
+        for(int i=0;i<array.values.size();i++) {
+            if(i > 0) b.append(";");
+            b.append(array.values.get(i).accept(this));
+        }
+        return b.toString();
+    }
+
+    @Override
+    public String visit(AstNothing array) {
+        return "AstNothing";
+    }
+
+    @Override
+    public String visit(AstArrayFormulaReference ref) {
+        return "{" + ref.value.accept(this) + "}";
+    }
+
+}
similarity index 62%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundFormulaFunction.java
index b350bbc035a2d4924a0595044ea32703b7639103..0a87291f4517cc83dc20dc3a277d55945eae9d41 100644 (file)
@@ -1,26 +1,24 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class RoundFormulaFunction implements CellFormulaFunction<Object> {
 
     @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
         if (args.values.size() != 2) throw new IllegalStateException();
-        
+
         Object number = args.values.get(0).accept(visitor);
         Object digits = args.values.get(1).accept(visitor);
-        
+
         FormulaError2 err1 = FormulaError2.forObject(number);
         if(err1!=null) return err1.getString();
         FormulaError2 err2 = FormulaError2.forObject(digits);
         if(err2!=null) return err2.getString();
-        
-        double n = SpreadsheetGraphUtils.asNumber(number);
-        double n2 = SpreadsheetGraphUtils.asNumber(digits);
+
+        double n = Spreadsheets.asNumber(number);
+        double n2 = Spreadsheets.asNumber(digits);
         Double scale = Math.pow(10, n2);
 
         long l = Math.round(scale * n);
similarity index 62%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/RoundupFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/RoundupFormulaFunction.java
index 20c057a8952bebf086ea7f07ee1a8924ee782aae..7ba59d7e49b59b0ed528b8b67a20663f0fd0ec79 100644 (file)
@@ -1,27 +1,25 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class RoundupFormulaFunction implements CellFormulaFunction<Object> {
 
     @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
         if (args.values.size() != 2) throw new IllegalStateException();
-        
+
         Object number = args.values.get(0).accept(visitor);
         Object digits = args.values.get(1).accept(visitor);
-        
+
         FormulaError2 err1 = FormulaError2.forObject(number);
         if(err1!=null) return err1.getString();
         FormulaError2 err2 = FormulaError2.forObject(digits);
         if(err2!=null) return err2.getString();
-        
-        double n = SpreadsheetGraphUtils.asNumber(number);
-        double n2 = SpreadsheetGraphUtils.asNumber(digits);
-        
+
+        double n = Spreadsheets.asNumber(number);
+        double n2 = Spreadsheets.asNumber(digits);
+
         Double scale = Math.pow(10, n2);
 
         double l = Math.ceil(scale * n);
@@ -1,10 +1,9 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
 import java.util.HashMap;
 import java.util.Map;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
 
 public class SpreadsheetEvaluationEnvironment {
 
similarity index 54%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SqrtFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SqrtFormulaFunction.java
index ae841568f5ddc926db73ef089e99a54395e7a686..a5bccaa43407498ff38a789bc6f99865363de81d 100644 (file)
@@ -1,18 +1,16 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class SqrtFormulaFunction implements CellFormulaFunction<Object> {
 
     @Override
     public Object evaluate(CellValueVisitor visitor, AstArgList args) {
         if (args.values.size() != 1) throw new IllegalStateException();
-        
+
         Object number = args.values.get(0).accept(visitor);
-        Double dVal = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(number);
+        Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(number);
         if(dVal==null) return FormulaError2.handleErrorCall(number);
         if(dVal<0) return FormulaError2.NUM.getString();
 
similarity index 52%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumFormulaFunction.java
index 299973db59329d0d56ea9dfff0e5f1251b4fbcc1..97f864709c14a8be3126106a57e20b6bf4ef7cec 100644 (file)
@@ -1,11 +1,9 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
-import org.simantics.spreadsheet.graph.parser.ast.AstValue;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
 
 class SumFormulaFunction implements CellFormulaFunction<Object> {
 
@@ -14,21 +12,21 @@ class SumFormulaFunction implements CellFormulaFunction<Object> {
         Double sum = 0.0;
         for (AstValue value : args.values) {
             Object result = value.accept(visitor);
-            
+
             if (result instanceof SpreadsheetMatrix) {
                 Object value2 = ((SpreadsheetMatrix) result).sumWithFormulaError();
                 if(value2 instanceof String) return value2; //means sumWithFormulaError returned an Error message.
                 sum += ((Number)value2).doubleValue();
             } else if(result instanceof String && !result.equals("")){
-               FormulaError2 error = FormulaError2.forString(result.toString());
-               if(error!=null) return error.getString();
-               Double v = SpreadsheetGraphUtils.asDoubleWhereEmptyStringIsZero(result);
-               if(v!=null)
-                       sum += v;
+                FormulaError2 error = FormulaError2.forString(result.toString());
+                if(error!=null) return error.getString();
+                Double v = Spreadsheets.asDoubleWhereEmptyStringIsZero(result);
+                if(v!=null)
+                    sum += v;
             } else if(result instanceof Number){
                 sum += ((Number)result).doubleValue();
             } else {
-                sum += SpreadsheetGraphUtils.asNumber(result);
+                sum += Spreadsheets.asNumber(result);
             }
         }
         return sum;
similarity index 65%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/SumifFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/SumifFormulaFunction.java
index 8826a384220b554976ed012e515749841a0fdd55..6ed9f00aca404279c1b4fd953dc7a81b586b75fd 100644 (file)
@@ -1,10 +1,8 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.SpreadsheetGraphUtils;
-import org.simantics.spreadsheet.graph.SpreadsheetMatrix;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 class SumifFormulaFunction implements CellFormulaFunction<Object> {
 
@@ -14,26 +12,26 @@ class SumifFormulaFunction implements CellFormulaFunction<Object> {
             Object test = args.values.get(0).accept(visitor);
             Object criteria = null;
             try {
-               criteria = args.values.get(1).accept(visitor);
+                criteria = args.values.get(1).accept(visitor);
             } catch (IllegalStateException e){
-               return 0;
+                return 0;
             }
             FormulaError2 error = FormulaError2.forObject(criteria);
             if(error!=null) return error.getString();
-            
+
             if (test instanceof SpreadsheetMatrix) {
                 double sum = 0.0;
                 SpreadsheetMatrix tm = (SpreadsheetMatrix) test;
                 for (int i = 0; i < tm.values.length; i++) {
-                    if (SpreadsheetGraphUtils.matchCriteria(tm.values[i], criteria)) {
-                        double d = SpreadsheetGraphUtils.asNumber(tm.values[i]);
+                    if (Spreadsheets.matchCriteria(tm.values[i], criteria)) {
+                        double d = Spreadsheets.asNumber(tm.values[i]);
                         if (Double.isFinite(d))
                             sum += d;
                     }
                 }
                 return sum;
             } else {
-                Double d = SpreadsheetGraphUtils.asNumber(test);
+                Double d = Spreadsheets.asNumber(test);
                 return d;
             }
         }
@@ -42,13 +40,13 @@ class SumifFormulaFunction implements CellFormulaFunction<Object> {
             Object test = args.values.get(0).accept(visitor);
             Object criteria = null;
             try {
-               criteria = args.values.get(1).accept(visitor);
+                criteria = args.values.get(1).accept(visitor);
             } catch (IllegalStateException e){
-               return 0;
+                return 0;
             }
             FormulaError2 error = FormulaError2.forObject(criteria);
             if(error!=null) return error.getString();
-            
+
             Object range = args.values.get(2).accept(visitor);
 
             if (test instanceof SpreadsheetMatrix) {
@@ -56,15 +54,15 @@ class SumifFormulaFunction implements CellFormulaFunction<Object> {
                 SpreadsheetMatrix tm = (SpreadsheetMatrix) test;
                 SpreadsheetMatrix rm = (SpreadsheetMatrix) range;
                 for (int i = 0; i < tm.values.length; i++) {
-                    if (SpreadsheetGraphUtils.matchCriteria(tm.values[i], criteria)) {
-                        double d = SpreadsheetGraphUtils.asNumber(rm.values[i]);
+                    if (Spreadsheets.matchCriteria(tm.values[i], criteria)) {
+                        double d = Spreadsheets.asNumber(rm.values[i]);
                         if (Double.isFinite(d))
                             sum += d;
                     }
                 }
                 return sum;
             } else {
-                Double d = SpreadsheetGraphUtils.asNumber(test);
+                Double d = Spreadsheets.asNumber(test);
                 return d;
             }
 
similarity index 66%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/formula/TodayFormulaFunction.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/TodayFormulaFunction.java
index c4488f3499c1b98aae2ed0310928b591a311bfb5..61d4da3754b49a11f70eec1d7dded560bea0efb5 100644 (file)
@@ -1,13 +1,11 @@
-package org.simantics.spreadsheet.graph.formula;
+package org.simantics.spreadsheet.solver.formula;
 
 import java.time.LocalDate;
 import java.time.Month;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.Temporal;
 
-import org.simantics.spreadsheet.graph.CellFormulaFunction;
-import org.simantics.spreadsheet.graph.CellValueVisitor;
-import org.simantics.spreadsheet.graph.parser.ast.AstArgList;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
 
 public class TodayFormulaFunction implements CellFormulaFunction<Long> {
 
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/VlookupFormulaFunction.java
new file mode 100644 (file)
index 0000000..0c8bc8f
--- /dev/null
@@ -0,0 +1,161 @@
+package org.simantics.spreadsheet.solver.formula;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.SpreadsheetMatrix;
+import org.simantics.spreadsheet.Spreadsheets;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArgList;
+
+public class VlookupFormulaFunction implements CellFormulaFunction<Object> {
+
+    @Override
+    public Object evaluate(CellValueVisitor visitor, AstArgList args) {
+        if (args.values.size() < 3 || args.values.size() > 4) throw new IllegalStateException();
+
+        Object lookupValue = args.values.get(0).accept(visitor);
+        boolean lookupIsString = lookupValue instanceof String;
+
+        FormulaError2 error = FormulaError2.forObject(lookupValue);
+        if(error!=null) return error.getString();
+
+        if(lookupValue instanceof Variant){
+            Object varVal = ((Variant)lookupValue).getValue();
+            Double dVal = Spreadsheets.asDoubleWhereEmptyStringIsZero(varVal);
+            if(dVal==null) {
+                lookupValue = varVal.toString();
+                lookupIsString = true;
+            }
+            else lookupValue = dVal;
+        }
+
+
+        SpreadsheetMatrix array = (SpreadsheetMatrix) args.values.get(1).accept(visitor);
+
+        boolean approximateMatch = args.values.size() == 4 ? (Boolean) args.values.get(3).accept(visitor) : true;
+
+        boolean valueExists = false;
+        if(array.values.length != 0){
+            for(int i = 0; i < array.getHeight(); i++){
+                if(lookupIsString){
+                    Object obj = array.get(i,0);
+                    if(obj instanceof Variant)
+                        obj = ((Variant)obj).getValue();
+                    if(obj!=null && Spreadsheets.asValidNumber(obj)==null){
+                        obj = obj.toString();
+                        String valStr = ((String)obj).toLowerCase();
+                        if((lookupValue.toString().toLowerCase()).compareTo(valStr)>=0 ){
+                            valueExists = true;
+                            break;
+                        }
+                    }
+                }
+                else if(lookupValue instanceof Number){
+                    Double d = ((Number)lookupValue).doubleValue();
+                    Number d2 = Spreadsheets.asValidNumber(array.get(i,0));
+                    if(d2!=null && d>=(d2.doubleValue())){
+                        valueExists = true;
+                        break;
+                    }
+                }
+            }
+//                     if(lookupIsString){
+//                             Object obj = array.values[0];
+//                             if(obj instanceof Variant)
+//                                     obj = ((Variant)obj).getValue();
+//                             if(Spreadsheets.asValidNumber(obj)!=null)
+//                                     return FormulaError2.NA.getString();
+//                             obj = obj.toString();
+//                             String valStr = ((String)obj).toLowerCase();
+//                             if((lookupValue.toString().toLowerCase()).compareTo(valStr)<0 )
+//                                     return FormulaError2.NA.getString();
+//                     }
+//                     else if(lookupValue instanceof Number){
+//                             Double d = ((Number)lookupValue).doubleValue();
+//                             Number d2 = Spreadsheets.asValidNumber(array.values[0]);
+//                             if(d2==null || d<(d2.doubleValue()))
+//                                     return FormulaError2.NA.getString();
+//                     }
+        }
+        if(!valueExists) return FormulaError2.NA.getString();
+
+        Number colIndexN = Spreadsheets.asValidNumber(args.values.get(2).accept(visitor));
+        if(colIndexN==null) return FormulaError2.REF.getString();
+        int colIndexNum = colIndexN.intValue();
+        if(colIndexNum>array.getWidth()) return FormulaError2.REF.getString();
+
+        if (approximateMatch) {
+            Integer rowPosOfLargestValSmallerThanLookUp = null;
+            if(lookupIsString){
+                String ref = lookupValue.toString().toLowerCase();
+                String previousValue = null;
+                String largestValSmallerThanLookUp = null;
+                for(int i = 0; i < array.getHeight(); i++){
+                    Object val = array.get(i, 0);
+                    if(val instanceof Variant)
+                        val = ((Variant)val).getValue();
+                    String currValue = val.toString().toLowerCase();
+                    if(currValue.compareTo(ref)>0){
+                        if(i==0)
+                            return array.get(i, colIndexNum-1);
+                        else if(previousValue.compareTo(ref) > currValue.compareTo(ref))
+                            return array.get(i, colIndexNum-1);
+                        else 
+                            return array.get(i - 1, colIndexNum - 1);
+                    }
+                    if(rowPosOfLargestValSmallerThanLookUp==null){
+                        rowPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = currValue;
+                    } else if(largestValSmallerThanLookUp.compareTo(currValue)<0){
+                        rowPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = currValue;
+                    }
+                    previousValue = currValue;
+                }
+
+            } else {
+                double ref = Spreadsheets.asNumber(lookupValue);
+                double lastDiff = Double.MIN_VALUE;
+                Double largestValSmallerThanLookUp = null;
+                for (int i = 0; i < array.getHeight(); i++) {
+                    Object value = array.get(i, 0);
+                    double n = Spreadsheets.asNumber(value);
+                    double diff = n - ref;
+                    if (diff > 0) {
+                        if (i == 0)
+                            return array.get(i, colIndexNum - 1);
+                        else if (diff < -lastDiff)
+                            return array.get(i, colIndexNum - 1);
+                        else
+                            return array.get(i - 1, colIndexNum - 1);
+                    }
+                    if(rowPosOfLargestValSmallerThanLookUp==null){
+                        rowPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = n;
+                    } else if(largestValSmallerThanLookUp < n){
+                        rowPosOfLargestValSmallerThanLookUp = i;
+                        largestValSmallerThanLookUp = n;
+                    }
+                    lastDiff = diff;
+                }
+            }
+
+            if(rowPosOfLargestValSmallerThanLookUp!=null) return array.get(rowPosOfLargestValSmallerThanLookUp, colIndexNum - 1);
+
+        } else {
+            for (int i = 0; i < array.getHeight(); i++) {
+                Object value = array.get(i, 0);
+                if(value instanceof Variant){
+                    if(lookupIsString)
+                        value = ((Variant)value).getValue().toString();
+                    else 
+                        value = Spreadsheets.asNumber(value);
+                }
+                if (Spreadsheets.excelEquals(lookupValue, value)) {
+                    return array.get(i, colIndexNum - 1);
+                }
+            }
+        }
+
+        return FormulaError2.NA.getString();
+    }
+
+}
similarity index 99%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ParseException.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ParseException.java
index 6bb308ab4c5554d4464f8cb52d36ced0f001f625..76b38cdbaa81fe655b5f2ceccf4c48b77633a56a 100644 (file)
@@ -1,6 +1,6 @@
 /* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
 /* JavaCCOptions:KEEP_LINE_COL=null */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
 /**
  * This exception is thrown when parse errors are encountered.
similarity index 99%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetFormulaParser.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetFormulaParser.java
index 4913c99d350dae17edfabc621de83247e0b0a4c3..79326f034e2cf654b333a76835206b1e334f023e 100644 (file)
@@ -1,7 +1,7 @@
 /* Generated By:JavaCC: Do not edit this line. SheetFormulaParser.java */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
-import org.simantics.spreadsheet.graph.parser.ast.*;
+import org.simantics.spreadsheet.solver.formula.parser.ast.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Collections;
@@ -1,6 +1,6 @@
 /* Generated By:JavaCC: Do not edit this line. SheetFormulaParserTokenManager.java */
-package org.simantics.spreadsheet.graph.parser;
-import org.simantics.spreadsheet.graph.parser.ast.*;
+package org.simantics.spreadsheet.solver.formula.parser;
+import org.simantics.spreadsheet.solver.formula.parser.ast.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Collections;
similarity index 96%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SheetParserUtils.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SheetParserUtils.java
index 034682803f1ec04bdcc221551e9f4df49a910830..970fb1d86850429922aa4e2c64e9190020713256 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
 public class SheetParserUtils {
 
similarity index 99%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/SimpleCharStream.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/SimpleCharStream.java
index d504d68eb5f0102708e76cae323a75bdd8c49075..534aa209e35386a51834115e5f4b02b1e9890809 100644 (file)
@@ -1,6 +1,6 @@
 /* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
 /* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
 /**
  * An implementation of interface CharStream, where the stream is assumed to
similarity index 98%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/Token.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/Token.java
index 0fe4b1b217281f2432e14e9aad69d5de374a36fc..ede6504bc921dccd5f5377ae1effe0476a0f7127 100644 (file)
@@ -1,6 +1,6 @@
 /* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
 /* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
 /**
  * Describes the input token stream.
similarity index 98%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/TokenMgrError.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/TokenMgrError.java
index e333f22e7c8246d22163cceaf5ead17daabfd536..7ef95c8961b9d75c393e03d2fbac8d849c37ec07 100644 (file)
@@ -1,6 +1,6 @@
 /* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
 /* JavaCCOptions: */
-package org.simantics.spreadsheet.graph.parser;
+package org.simantics.spreadsheet.solver.formula.parser;
 
 /** Token Manager Error. */
 public class TokenMgrError extends Error
similarity index 89%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstApply.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstApply.java
index fec2ffc36051c9593679307d139d9fc5700b98f4..eb1791cffa4b90830e8e97672b3e3a55eb8f8bad 100644 (file)
@@ -9,9 +9,9 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
-import org.simantics.spreadsheet.graph.PrintVisitor;
+import org.simantics.spreadsheet.solver.formula.PrintVisitor;
 
 public class AstApply implements AstValue {
        
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArgList.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArgList.java
index 075ef48fd897a814cd052bb6e25441bdad63b568..ab415f75b1ba551488097568a5a5b61a5ba74a18 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 import java.util.ArrayList;
 
@@ -9,9 +9,9 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
-import org.simantics.spreadsheet.graph.PrintVisitor;
+import org.simantics.spreadsheet.solver.formula.PrintVisitor;
 
 public class AstArithmeticExpression extends AstList {
        
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstArray.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstArray.java
index d492c206cf8c152d53a10d511875260dccc9086b..917936aa2c48584f29fff016ebad307d475e3406 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 import java.util.ArrayList;
 
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstArrayFormulaReference implements AstValue {
        
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstBoolean.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstBoolean.java
index aa8caa9a498f41e051faf9f923a4c20f4909752b..d9fc5f3c56b36161359f304b42a8afcd614973c9 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public enum AstBoolean implements AstValue {
        FALSE(false),
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstDouble.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstDouble.java
index da8859d9745bceedf543ccb6f5806105b8893415..11364b0691304ae993cf85f79c437b539e5a851a 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstDouble implements AstValue {
        
similarity index 88%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstFactor.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstFactor.java
index 03f4d2abca452c17b36ab4895cf52f1099d7c1f3..6f1add8befe74f67b693bbbd5dcacf3e7d0d8ae4 100644 (file)
@@ -9,9 +9,9 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
-import org.simantics.spreadsheet.graph.PrintVisitor;
+import org.simantics.spreadsheet.solver.formula.PrintVisitor;
 
 public class AstFactor extends AstList {
 
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstIdentifier.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstIdentifier.java
index 92b4fea29aa1d23036db20b43920ecc1fcf572ec..dffc58ba6e9dbe8f47e424e42d6d5eea13a167f0 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstIdentifier implements AstValue {
        
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstInteger.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstInteger.java
index 9e498bd2bb0eb9afc9890884f03500aa2e0388a0..4a493783c995ee6031a3bcfb0a612d3c7e773822 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstInteger implements AstValue {
        public final Integer value;
similarity index 94%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNothing.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNothing.java
index 74d2f4ec8782814d45001a86de976ac5de5a9a26..4101c31f9c534493fa1bd4dd64c5076f615afaf9 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 import java.io.Serializable;
 
similarity index 92%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstNull.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstNull.java
index 852e4bb023b9b855f8290435bb4a4dd2c6f052f5..a7fddfb50fb161e1513af1f34c254b47524033c4 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public enum AstNull implements AstValue {
        NULL;
similarity index 92%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRange.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRange.java
index 471c47dd3b0252ef7f4347adea3847fd9a73e65a..7b9c0c03857f9931d1063d0f15b2c732841610f7 100644 (file)
@@ -9,9 +9,9 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
-import org.simantics.spreadsheet.graph.PrintVisitor;
+import org.simantics.spreadsheet.solver.formula.PrintVisitor;
 
 public class AstRange implements AstValue {
        
similarity index 94%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstRelation.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstRelation.java
index a86ea7f7b5c5acb846d0d4d88e4bb5160f906e23..2c525fb437e6107944b2504aa2bfc4ee24a26971 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstRelation implements AstValue {
 
similarity index 93%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstString.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstString.java
index d8e39e07a6506a13ab6b89f39a9ae2c1dfad2e0e..b7a933adf908aeb441ec31ebdd3bea046645fef2 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public class AstString implements AstValue {
        
similarity index 88%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstTerm.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstTerm.java
index 7d8b5b3a0066e68be29196dc82178eea0c95d25b..5efa32bd32270367f7a41c7cb218d74b93ee87dc 100644 (file)
@@ -9,9 +9,9 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
-import org.simantics.spreadsheet.graph.PrintVisitor;
+import org.simantics.spreadsheet.solver.formula.PrintVisitor;
 
 public class AstTerm extends AstList {
 
similarity index 92%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValue.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValue.java
index 3cdeaa0eed7f62be50205e4024a29b8857d63605..c2815cb34767db5355d36403468101b906a87268 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 import java.io.Serializable;
 
similarity index 94%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/parser/ast/AstValueVisitor.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/solver/formula/parser/ast/AstValueVisitor.java
index 14ae6f76ac93029296a8516f1d067de201f9bb25..79ddb1aea09920a400b8e3fa8dd302407ad33358 100644 (file)
@@ -9,7 +9,7 @@
  *  Contributors:
  *      VTT Technical Research Centre of Finland - initial API and implementation
  *******************************************************************************/
-package org.simantics.spreadsheet.graph.parser.ast;
+package org.simantics.spreadsheet.solver.formula.parser.ast;
 
 public interface AstValueVisitor<T> {
 
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelArrayFormula.java
new file mode 100644 (file)
index 0000000..8727963
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.spreadsheet.synchronization;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+
+public class ExcelArrayFormula {
+
+    public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelArrayFormula.class);
+
+    public String range;
+    public String expression;
+
+    public ExcelArrayFormula(String range, String expression) {
+        this.range = range;
+        this.expression = expression;
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/ExcelFormula.java
new file mode 100644 (file)
index 0000000..10d9e03
--- /dev/null
@@ -0,0 +1,16 @@
+package org.simantics.spreadsheet.synchronization;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+
+public class ExcelFormula {
+
+    public static final Binding BINDING = Bindings.getBindingUnchecked(ExcelFormula.class);
+
+    public String expression;
+
+    public ExcelFormula(String expression) {
+        this.expression = expression;
+    }
+
+}
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineCommandBuilder.java
new file mode 100644 (file)
index 0000000..227038e
--- /dev/null
@@ -0,0 +1,126 @@
+package org.simantics.spreadsheet.synchronization;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.ExternalRef;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetCell;
+import org.simantics.spreadsheet.solver.SpreadsheetFormula;
+import org.simantics.spreadsheet.solver.SpreadsheetLine;
+import org.simantics.spreadsheet.solver.SpreadsheetLines;
+import org.simantics.spreadsheet.solver.SpreadsheetSCLConstant;
+import org.simantics.spreadsheet.solver.formula.parser.SheetFormulaParser;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstArrayFormulaReference;
+import org.simantics.spreadsheet.solver.formula.parser.ast.AstValue;
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.Solver;
+
+public class LineCommandBuilder implements CommandBuilder {
+
+    private String name;
+    LineContentBean bean;
+
+    public LineCommandBuilder(String name, boolean update) {
+        this.name = name;
+    }
+
+    @Override
+    public void apply(Solver solver) {
+
+        SpreadsheetBook book = solver.getConcreteSolver();
+
+        String path = name.substring(0, name.lastIndexOf("/"));
+        String lineName = name.substring(name.lastIndexOf("/")+1);
+        int row = Integer.parseInt(lineName.substring(3));
+
+        SpreadsheetLines node = book.ensureSubprocess(path);
+        SpreadsheetLine line = node.lines.get(-row);
+        if(line == null) {
+            line = new SpreadsheetLine(node, row);
+            node.lines.put(-row, line);
+        }
+        
+        ArrayList<SpreadsheetCell> changes = new ArrayList<>();
+
+        for(int i=0;i<bean.cells.length;i++) {
+
+            SpreadsheetCell currentCell;
+            if (line.cells.size() > i) {
+                currentCell = line.cells.get(i);
+            } else {
+                currentCell = new SpreadsheetCell(line, i);
+                line.cells.add(currentCell);
+            }
+
+            LineContentBeanCell cell = bean.cells[i];
+
+            try {
+                Object content = cell.getContent();
+                if (content instanceof Variant) {
+                    Variant cellVariant = (Variant) content;
+                    if (cellVariant == LineContentBeanCell.EMPTY) {
+                        currentCell.setStyle(cell.getStyleId());
+                        // Empty content
+                        currentCell.setContent("");
+                    } else if(ExcelFormula.BINDING.type().equals(cellVariant.getBinding().type())) {
+                        ExcelFormula formula = (ExcelFormula)cellVariant.getValue(ExcelFormula.BINDING);
+                        SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
+                        AstValue v = p.relation();
+                        currentCell.setStyle(cell.getStyleId());
+                        SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression);
+                        currentCell.setContent(sformula);
+                    } else if (ExcelArrayFormula.BINDING.type().equals(cellVariant.getBinding().type())) {
+                        ExcelArrayFormula formula = (ExcelArrayFormula)cellVariant.getValue(ExcelArrayFormula.BINDING);
+                        SheetFormulaParser p = new SheetFormulaParser(new StringReader(formula.expression));
+                        AstArrayFormulaReference v = new AstArrayFormulaReference(formula.range, p.relation());
+                        currentCell.setStyle(cell.getStyleId());
+                        SpreadsheetFormula sformula = new SpreadsheetFormula(v, formula.expression);
+                        currentCell.setContent(sformula);
+                    } else if (cellVariant.getValue() instanceof ExternalRef){
+                        throw new IllegalStateException();
+                    } else {
+                        currentCell.setStyle(cell.getStyleId());
+                        // DO not update constant values during update
+                        currentCell.setContent(cellVariant.getValue());
+                    }
+                } else if (content instanceof ExternalRef){
+                    throw new IllegalStateException();
+                } else if (content instanceof SpreadsheetSCLConstant){
+                    currentCell.setStyle(cell.getStyleId());
+                    currentCell.setContent(content);
+                }
+            } catch (Throwable e) {
+                Object content = cell.getContent();
+                if (content instanceof Variant) {
+                    Variant cellVariant = (Variant) content;
+                    currentCell.setStyle(cell.getStyleId());
+                    currentCell.setContent(content);
+                    try {
+                        new Exception("failed: " + ((ExcelFormula)(cellVariant.getValue(ExcelFormula.BINDING))).expression, e).printStackTrace();
+                    } catch (AdaptException e1) {
+                        e1.printStackTrace();
+                    }
+                } else {
+                    currentCell.setStyle(cell.getStyleId());
+                    currentCell.setContent("LCB error happened");
+                }
+            }
+            
+            changes.add(currentCell);
+            
+        }
+        
+        book.fireChanges(changes);
+        
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getConcrete() {
+        return (T)this;
+    }
+
+}
\ No newline at end of file
similarity index 66%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBean.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBean.java
index 90a4f3dd5958642eef3c5b70ba950a24c6aaac5e..54d93d9467f815907583b1bfd0758c374b1edd64 100644 (file)
@@ -1,16 +1,20 @@
-package org.simantics.spreadsheet.graph.function;
+package org.simantics.spreadsheet.synchronization;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.binding.Binding;
 
 public class LineContentBean {
-       
+
     public static final Binding BINDING = Bindings.getBindingUnchecked(LineContentBean.class);
-    
+
     static {
+        register();
+    }
+    
+    public static void register() {
         Bindings.defaultBindingRepository.put(BINDING.type(), BINDING);
     }
 
-       public LineContentBeanCell cells[];
-       
+    public LineContentBeanCell cells[];
+
 }
similarity index 78%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/function/LineContentBeanCell.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineContentBeanCell.java
index 7c060da310a0d68c752e9da39575f16271ca35de..3f0d0c9229f4ef7aa0b5d312ea75ddc6f749738e 100644 (file)
@@ -1,12 +1,12 @@
-package org.simantics.spreadsheet.graph.function;
+package org.simantics.spreadsheet.synchronization;
 
 import org.simantics.databoard.binding.mutable.Variant;
-import org.simantics.spreadsheet.graph.SpreadsheetStyle;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
 
 public class LineContentBeanCell {
 
     public static final Variant EMPTY = new Variant();
-    
+
     public Variant content;
     public final int styleID;
 
@@ -19,7 +19,6 @@ public class LineContentBeanCell {
     }
 
     public LineContentBeanCell(Variant content, int styleId) {
-//        System.err.println("LineContentBeanCell.construct: " + content + " " + styleId);
         this.content = content;
         this.styleID = styleId;
     }
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineNodeUpdater.java
new file mode 100644 (file)
index 0000000..0e0e56f
--- /dev/null
@@ -0,0 +1,53 @@
+package org.simantics.spreadsheet.synchronization;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.ModuleUpdateContext;
+import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
+import org.simantics.structural.synchronization.utils.PropertyUpdateRule;
+
+public class LineNodeUpdater extends ModuleUpdaterBase<SheetLineComponent> {
+
+    public LineNodeUpdater(String id) {
+
+        super(id);
+
+        isComposite = true;
+
+        addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
+
+            @Override
+            public String getPropertyName() {
+                return "keys";
+            }
+
+            @Override
+            public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
+                    Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
+
+                LinesCommandBuilder builder = context.<LinesCommandBuilder>getConcreteCommand();
+                Variant v = propertyMap.get("keys");
+                if (v != null & v.getValue() != null)
+                    builder.keys = (int[])v.getValue();
+
+            }
+
+        });
+
+    }
+
+    @Override
+    public CommandBuilder createAddCommandBuilder(String name) {
+        return new LinesCommandBuilder(name, false);
+    }
+
+    @Override
+    public CommandBuilder createUpdateCommandBuilder(String name) {
+        return new LinesCommandBuilder(name, true);
+    }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LineUpdater.java
new file mode 100644 (file)
index 0000000..c50f99f
--- /dev/null
@@ -0,0 +1,50 @@
+package org.simantics.spreadsheet.synchronization;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.ModuleUpdateContext;
+import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
+import org.simantics.structural.synchronization.utils.PropertyUpdateRule;
+
+public class LineUpdater extends ModuleUpdaterBase<SheetLineComponent> {
+
+    public LineUpdater(String id) {
+        super(id);
+        addPropertyUpdateRule(new PropertyUpdateRule<SheetLineComponent>() {
+            @Override
+            public String getPropertyName() {
+                return "content";
+            }
+            @Override
+            public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating,
+                    Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
+                System.err.println("LineUpdater.apply " + value);
+                LineCommandBuilder builder = context.<LineCommandBuilder>getConcreteCommand();
+                try {
+                    LineContentBean valuee = (LineContentBean) value.getValue(LineContentBean.BINDING);
+                    builder.bean = valuee;
+                } catch (AdaptException e) {
+                    e.printStackTrace();
+                } catch (ClassCastException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+    @Override
+    public CommandBuilder createAddCommandBuilder(String name) {
+        return new LineCommandBuilder(name, false);
+    }
+
+    @Override
+    public CommandBuilder createUpdateCommandBuilder(String name) {
+        return new LineCommandBuilder(name, true);
+    }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/LinesCommandBuilder.java
new file mode 100644 (file)
index 0000000..740bda3
--- /dev/null
@@ -0,0 +1,32 @@
+package org.simantics.spreadsheet.synchronization;
+
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetLines;
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.Solver;
+
+public class LinesCommandBuilder implements CommandBuilder {
+
+    private String name;
+    int[] keys;
+
+    public LinesCommandBuilder(String name, boolean update) {
+        this.name = name;
+    }
+
+    @Override
+    public void apply(Solver solver) {
+
+        SpreadsheetBook book = solver.getConcreteSolver();
+        SpreadsheetLines node = book.ensureSubprocess(name);
+        node.setKeys(keys);
+
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getConcrete() {
+        return (T)this;
+    }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullCommandBuilder.java
new file mode 100644 (file)
index 0000000..e407750
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.spreadsheet.synchronization;
+
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.Solver;
+
+public class NullCommandBuilder implements CommandBuilder {
+
+    @Override
+    public void apply(Solver solver) {
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getConcrete() {
+        return (T)this;
+    }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java b/bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/NullUpdater.java
new file mode 100644 (file)
index 0000000..daef439
--- /dev/null
@@ -0,0 +1,24 @@
+package org.simantics.spreadsheet.synchronization;
+
+import org.simantics.spreadsheet.solver.SheetLineComponent;
+import org.simantics.structural.synchronization.utils.CommandBuilder;
+import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
+
+public class NullUpdater extends ModuleUpdaterBase<SheetLineComponent> {
+
+    public NullUpdater(String typeId) {
+        super(typeId);
+        isComposite = true;
+    }
+
+    @Override
+    public CommandBuilder createAddCommandBuilder(String name) {
+        return new NullCommandBuilder();
+    }
+
+    @Override
+    public CommandBuilder createUpdateCommandBuilder(String name) {
+        return new NullCommandBuilder();
+    }
+
+}
\ No newline at end of file
similarity index 96%
rename from bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/synchronization/StyleUpdater.java
rename to bundles/org.simantics.spreadsheet/src/org/simantics/spreadsheet/synchronization/StyleUpdater.java
index be020a6257c803541d777a7ed29ca02736f2390d..bac9fbc5075ef743304e38f164b05c0b5d2bcee3 100644 (file)
@@ -1,4 +1,4 @@
-package org.simantics.spreadsheet.graph.synchronization;
+package org.simantics.spreadsheet.synchronization;
 
 import java.util.Collection;
 import java.util.Map;
@@ -6,8 +6,9 @@ import java.util.Map;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.datatypes.literal.Font;
 import org.simantics.datatypes.literal.RGB;
-import org.simantics.spreadsheet.graph.SpreadsheetBook;
-import org.simantics.spreadsheet.graph.SpreadsheetStyle;
+import org.simantics.spreadsheet.solver.SheetLineComponent;
+import org.simantics.spreadsheet.solver.SpreadsheetBook;
+import org.simantics.spreadsheet.solver.SpreadsheetStyle;
 import org.simantics.structural.synchronization.utils.CommandBuilder;
 import org.simantics.structural.synchronization.utils.ModuleUpdateContext;
 import org.simantics.structural.synchronization.utils.ModuleUpdaterBase;
@@ -21,7 +22,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
         public String getPropertyName() {
             return "foreground";
         }
-        
+
         @Override
         public void apply(ModuleUpdateContext<SheetLineComponent> context, boolean isCreating, Map<String, Variant> propertyMap, Map<String, Collection<String>> connectionMap, Variant value) {
             StyleCommandBuilder builder = context.getConcreteCommand();
@@ -29,7 +30,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.foreground = color;
         }
     }
-    
+
     private static class BackgroundUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -43,7 +44,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.background = color;
         }
     }
-    
+
     private static class FontUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -71,7 +72,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.align = align;
         }
     }
-    
+
     private static class FormatStringUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -113,7 +114,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.border = border;
         }
     }
-    
+
     private static class LockedUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -127,7 +128,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.locked = locked;
         }
     }
-    
+
     private static class ColumnSpanUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -141,7 +142,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
             builder.columnSpan = columnSpan;
         }
     }
-    
+
     private static class RowSpanUpdateRule implements PropertyUpdateRule<SheetLineComponent> {
         @Override
         public String getPropertyName() {
@@ -156,10 +157,10 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
         }
     }
 
-    
+
     public StyleUpdater(String moduleType) {
         super(moduleType);
-        
+
         addPropertyUpdateRule(new ForegroundUpdateRule());
         addPropertyUpdateRule(new BackgroundUpdateRule());
         addPropertyUpdateRule(new FontUpdateRule());
@@ -181,7 +182,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
     public CommandBuilder createUpdateCommandBuilder(String name) {
         return new StyleCommandBuilder(name, true);
     }
-    
+
     private static class StyleCommandBuilder implements CommandBuilder {
 
         protected int rowSpan;
@@ -194,15 +195,13 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
         protected org.simantics.datatypes.literal.RGB.Integer foreground;
         protected Font font;
         protected int align;
-        
-        private boolean update;
+
         private String name;
-        
+
         public StyleCommandBuilder(String name, boolean update) {
             this.name = name.split("/")[1];
-            this.update = update;
         }
-        
+
         @Override
         public void apply(Solver solver) {
             SpreadsheetBook book = solver.getConcreteSolver();
@@ -211,7 +210,7 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
                     .columnSpan(columnSpan).formatIndex((short) formatIndex).formatString(formatString).build();
             if (book.getStyle(style.getStyleId()) == null)
                 book.addStyle(style);
-            
+
         }
 
         @SuppressWarnings("unchecked")
@@ -219,14 +218,14 @@ public class StyleUpdater extends ModuleUpdaterBase<SheetLineComponent> {
         public <T> T getConcrete() {
             return (T) this;
         }
-        
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("StyleCommandBuilder for ").append(name).append(" [background=").append(background).append(", foregroung=").append(foreground).append(", font=").append(font).append(", align=").append(align).append("]");
             return sb.toString();
         }
-        
+
     }
-    
+
 }