]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.graph/src/org/simantics/spreadsheet/graph/SpreadsheetCell.java
Spreadsheet updates cell values properly
[simantics/platform.git] / bundles / org.simantics.spreadsheet.graph / src / org / simantics / spreadsheet / graph / SpreadsheetCell.java
1 package org.simantics.spreadsheet.graph;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Optional;
8
9 import org.simantics.spreadsheet.graph.formula.FormulaError2;
10 import org.simantics.spreadsheet.graph.formula.SpreadsheetEvaluationEnvironment;
11 import org.simantics.spreadsheet.graph.parser.ast.AstValue;
12 import org.simantics.spreadsheet.resource.SpreadsheetResource;
13 import org.simantics.spreadsheet.util.SpreadsheetUtils;
14
15 public class SpreadsheetCell implements SpreadsheetElement, SheetNode {
16
17         private static final long serialVersionUID = 6616793596542239339L;
18
19         public static SpreadsheetCell EMPTY;
20         
21         static {
22             EMPTY = new SpreadsheetCell(null, -1);
23             EMPTY.setContent("");
24             EMPTY.setStyle(SpreadsheetStyle.empty().getStyleId());
25         }
26         
27         private boolean inProgress = false;
28         private int iterations = 0;
29         
30         final private SpreadsheetLine line;
31         final private int column;
32         int style;
33         Object content;
34         final private Map<String, SheetNode> properties;
35         
36         public SpreadsheetCell(SpreadsheetLine line, int column) {
37                 this.properties = createProperties();
38                 this.line = line;
39                 this.column = column;
40         }
41
42         //All SpreadsheetCells have these properties - create them when object is created
43         private Map<String, SheetNode> createProperties() {
44             Map<String, SheetNode> p = new HashMap<>();     
45             p.put("typeURI", new SpreadsheetTypeNode(SpreadsheetResource.URIs.Cell));
46             p.put("content", new SpreadsheetCellContent(this));
47         p.put("style", new SpreadsheetCellStyle(this));
48         p.put("editable", new SpreadsheetCellEditable(this));
49         return p;
50         }
51         
52     public boolean hasExpression() {
53                 return content instanceof SpreadsheetFormula || content instanceof SpreadsheetSCLConstant; 
54         }
55         
56         public void setContent(Object newContent) {
57 //       if(newContent != null) {
58 //            if (!(newContent instanceof Serializable)) {
59 //                throw new AssertionError("content not instanceof Serializable but it is " + newContent.getClass().getSimpleName());
60 //            }
61 //        }
62             if (GraphUI.DEBUG)
63                 System.out.println("SpreadsheetCell.setContent "+ this + " " + newContent);
64                 this.content = newContent;
65         }
66
67         @Override
68         public String getName() {
69                 return SpreadsheetUtils.cellName(line.row, column);
70         }
71
72         @Override
73         public Map<?, ?> getChildren() {
74                 return Collections.emptyMap();
75         }
76         
77         private static String[] keys = { "typeURI", "content" };
78         
79         @Override
80         public Map<String, SheetNode> getProperties() {
81             if (GraphUI.DEBUG)
82                 System.out.println("SpreadsheetCell.getProperties: " + this + " " + content + " " + style);
83             return properties; //Return this SpreadsheetCells's properties, rather than a new HashMap
84         }
85         
86         public SpreadsheetBook getBook() {
87                 return line.getEngine().getBook();
88         }
89
90         public SpreadsheetEngine getEngine() {
91                 return line.getEngine();
92         }
93
94         public <T> T evaluate(SpreadsheetEvaluationEnvironment env) {
95                 return evaluate(env, null);
96         }
97
98         public <T> T evaluate(SpreadsheetEvaluationEnvironment env, CellValueVisitor caller) {
99 //          System.err.println(getEngine().getName() + ":" + getName() + ": evaluate");
100                 if(caller != null)
101                         caller.addReference(makeReferenceKey());
102                 if(content instanceof SpreadsheetFormula) {
103                         SpreadsheetFormula f = (SpreadsheetFormula)content;
104                         if(f.result == null) {
105                                 CellValueVisitor visitor = new CellValueVisitor(env, this);
106                                 AstValue value = ((SpreadsheetFormula)content).value;
107                                 if(this.inProgress == true) this.iterations++;
108                                 
109                                 if(!env.getBook().isIterationEnabled()){
110                                         if(this.inProgress == false){
111                                                 this.inProgress = true;
112                                                 f.result = value.accept(visitor);
113                                         }
114                                         else f.result = FormulaError2.CIRCULAR_REF.getString();
115                                 }
116                                 else if(this.iterations<env.iterationLimit){
117                                         this.inProgress = true;
118                                         f.result = value.accept(visitor);
119                                 }
120                                 else {
121                                         if(f.result==null)
122                                                 f.result = 0.0;
123                                 }
124                                 
125                                 env.getBook().registerReferences(makeReferenceKey(), visitor.getReferences());
126                         }
127                         this.inProgress = false;
128                         this.iterations = 0;
129                         return (T)f.result;
130                 } else if (content instanceof SpreadsheetSCLConstant) {
131                     SpreadsheetSCLConstant sclConstant = (SpreadsheetSCLConstant) content;
132                     return (T) sclConstant.content;
133                 } else {
134                         this.inProgress = false;
135                         return (T)content;
136                 }
137         }
138         
139         public long makeReferenceKey() {
140                 SpreadsheetBook book = getBook();
141                 SpreadsheetEngine engine = getEngine();
142                 long engineIndex = book.getEngineIndex(engine);
143                 long row = line.row;
144                 long col = column;
145                 return (engineIndex << 40) + (row << 20) + col; 
146         }
147         
148         public void invalidate() {
149                 getEngine().rangeCache = null;
150                 if(content instanceof SpreadsheetFormula) {
151                         SpreadsheetFormula f = (SpreadsheetFormula)content;
152                         f.result = null;
153                 }
154         }
155
156         @Override
157         public void accept(SpreadsheetVisitor v) {
158                 v.visit(this);
159         }
160
161     @Override
162     public Optional<SpreadsheetElement> getParent() {
163         return Optional.of(line);
164     }
165
166     @Override
167     public List<SpreadsheetElement> getSpreadsheetChildren() {
168         return Collections.emptyList();
169     }
170
171     @Override
172     public void remove(SpreadsheetElement child) {
173         // TODO Auto-generated method stub
174         
175     }
176
177     @Override
178     public int hashCode() {
179         final int prime = 31;
180         int result = 1;
181         result = prime * result + column;
182         result = prime * result + ((line == null) ? 0 : line.hashCode());
183         return result;
184     }
185
186     @Override
187     public boolean equals(Object obj) {
188         if (this == obj)
189             return true;
190         if (obj == null)
191             return false;
192         if (getClass() != obj.getClass())
193             return false;
194         SpreadsheetCell other = (SpreadsheetCell) obj;
195         if (column != other.column)
196             return false;
197         if (line == null) {
198             if (other.line != null)
199                 return false;
200         } else if (!line.equals(other.line))
201             return false;
202         return true;
203     }
204
205     public void setStyle(int styleId) {
206         this.style = styleId;
207     }
208
209     public int getStyle() {
210         return style;
211     }
212
213     public Object getContent() {
214         return content;
215     }
216     
217     public static SpreadsheetCell empty(SpreadsheetLine line, int column) {
218         SpreadsheetCell cell =  new SpreadsheetCell(line, column);
219         cell.setContent("");
220         cell.setStyle(SpreadsheetStyle.empty().getStyleId());
221         return cell;
222     }
223
224 }