Cells referencing other cells weren't updated after change
"
8c8283a01e63980527d605936286747006bea601" (see in History view), in
StandardNodeManager.java. I added a new setValue function that takes a
list of Nodes that need to be updated (removes them from valueCache),
which allows only specific cells to be updated when another cell is
updated.
I also removed invalidation code from Spreadsheet's "All.java" class and
added them to the value updated in SpreadsheetNodeManager, which
invalidates recursively the cells the use another cell.
I also made sure that SpreadsheetCells jave the same properties through
their life-cycle, rather than creating a properties map whenever the
properties are called.
gitlab #48
gitlab #54
gitlab #55
Change-Id: I125f644e014310937ed7697e9f44ec33825f9b0f
@Override
public void setValue(Node node, Object value, Binding binding)
throws NodeManagerException {
+ updateValueInner(node, value, binding);
+ refreshVariable(node);
+ }
+
+ //Update the value of the node and remove from valueCache only the references nodes
+ public void setValueAndFireSelectedListeners(Node node, Object value, Binding binding, Set<Node> references) throws NodeManagerException {
+ if(references.size() > 0) {
+ for(Node n : references) {
+ valueCache.remove(n);
+ }
+ }
+ updateValueInner(node, value, binding);
+ fireNodeListenersSync();
+ }
+
+ //Update the value of the node helper method
+ private void updateValueInner(Node node, Object value, Binding binding) throws NodeManagerException {
checkThreadAccess();
Binding targetBinding = realm.getEngine().getEngineBinding(node);
if(binding.equals(targetBinding)) {
throw new NodeManagerException(e);
}
}
- refreshVariable(node);
}
@Override
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;
v.visit(this);
}
- public List<SpreadsheetCell> invalidate(SpreadsheetCell cell) {
+ //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();
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;
}
@Override
public Map<String, SheetNode> getProperties() {
- Map<String, SheetNode> properties = new HashMap<>();
-
if (GraphUI.DEBUG)
System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style);
-
- properties.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell));
- properties.put("content", new SpreadsheetCellContent(this));
- properties.put("style", new SpreadsheetCellStyle(this));
- properties.put("editable", new SpreadsheetCellEditable(this));
- return properties;
+ return properties; //Return this SpreadsheetCells's properties, rather than a new HashMap
}
public SpreadsheetBook getBook() {
package org.simantics.spreadsheet.graph;
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.layer0.Layer0;
import org.simantics.simulator.toolkit.StandardNodeManager;
import org.simantics.simulator.variable.exceptions.NodeManagerException;
return null;
}
}
-
+
+ //Custom setValue logic for SpreadsheetNodeManager - calls the setValueAndFireSelectedListeners
+ @Override
+ public void setValue(SheetNode node, Object value, Binding binding) throws NodeManagerException {
+ Set<SheetNode> dirtyNodeContents = findDirtyNodeContents(node);
+ super.setValueAndFireSelectedListeners(node, value, binding, dirtyNodeContents);
+ }
+
+ //Find the cells that are used by this cell and their SpreadsheetContents, so that they can be marked as dirty later
+ public Set<SheetNode> findDirtyNodeContents(SheetNode node){
+ Set<SheetNode> dirty = new HashSet<>();
+
+ SpreadsheetCell sscell = null;
+ if(node instanceof SpreadsheetCell) {
+ sscell = (SpreadsheetCell)node;
+ } else if (node instanceof SpreadsheetCellContent) {
+ sscell = ((SpreadsheetCellContent)node).cell;
+ }
+
+ if(sscell != null) {
+ Set<SpreadsheetCell> result = ((SpreadsheetRealm)super.getRealm()).getEngine().invalidate(sscell);
+ dirty.addAll(result);
+ }
+
+ Set<SheetNode> dirtyNodeContents = new HashSet<>();
+ for(SheetNode cell : dirty) {
+ Map<String, SheetNode> properties = cell.getProperties();
+ dirtyNodeContents.add((SpreadsheetCellContent)properties.get("content"));
+ }
+
+ return dirtyNodeContents;
+ }
}
SpreadsheetCell sc = book.get(sheet.getName(graph), r.startRow, r.startColumn);
sc.setContent(value);
// book.accept(new InvalidateAll());
- List<SpreadsheetCell> changed = book.invalidate(sc);
+// List<SpreadsheetCell> changed = book.invalidate(sc); //Invalidation handled by SpreadsheetNodeManager
realm.asyncExec(new Runnable() {
@Override
final Object cell = table.getValueAt(selectedRows[0], selectedColumns[0]);
if(cell != null) {
- String expression = clientModel.getPossiblePropertyAt(SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
+
+ String expression = "";
+
+ Object expressionO = clientModel.getPossiblePropertyAt(SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT_EXPRESSION);
+ if(expressionO instanceof String) {
+ expression = (String)expressionO;
+ } else if(expressionO instanceof Variant) {
+ expression = ((Variant)expressionO).toString();
+ }
+
if(expression == null) {
Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, SpreadsheetUtils.cellName(selectedRows[0], selectedColumns[0]), ClientModel.CONTENT);
if(content != null)
import java.awt.BorderLayout;
import java.awt.Color;
+import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
etl = new ExpressionTextListener(expression, serverInterface.getAdapter(CellEditor.class));
expression.addFocusListener(etl);
expression.addKeyListener(etl);
+
+ //Large default size so that the expression field is clearly visible
+ expression.setPreferredSize(new Dimension(600, 32));
sheets.addItemListener(sheetsListener);
String str = (String)getCellEditorValue();
String cellName = SpreadsheetUtils.cellName(row, column);
- String expression = clientModel.getPossiblePropertyAt(cellName, ClientModel.CONTENT_EXPRESSION);
+ Object expressionO = clientModel.getPossiblePropertyAt(cellName, ClientModel.CONTENT_EXPRESSION);
+ String expression = null;
+ if(expressionO instanceof String) {
+ expression = (String)expressionO;
+ } else if(expressionO instanceof Variant) {
+ expression = ((Variant)expressionO).getValue().toString();
+ }
+
if(expression == null) {
Variant content = SpreadsheetUtils.getSafeClientVariant(clientModel, cellName, ClientModel.CONTENT);
if(content != null)