]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.selectionview/src/org/simantics/selectionview/function/All.java
Check for property tab contribution change.
[simantics/platform.git] / bundles / org.simantics.selectionview / src / org / simantics / selectionview / function / All.java
1 package org.simantics.selectionview.function;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.Map;
7 import java.util.function.Consumer;
8
9 import org.eclipse.swt.graphics.FontData;
10 import org.eclipse.swt.graphics.RGB;
11 import org.eclipse.swt.widgets.ColorDialog;
12 import org.eclipse.swt.widgets.Control;
13 import org.eclipse.swt.widgets.FontDialog;
14 import org.simantics.Simantics;
15 import org.simantics.browsing.ui.NodeContext;
16 import org.simantics.browsing.ui.content.Labeler.DialogModifier;
17 import org.simantics.browsing.ui.graph.impl.GetEnumerationValue;
18 import org.simantics.common.format.Formatter;
19 import org.simantics.databoard.Bindings;
20 import org.simantics.databoard.Datatypes;
21 import org.simantics.databoard.adapter.AdaptException;
22 import org.simantics.databoard.binding.Binding;
23 import org.simantics.databoard.binding.NumberBinding;
24 import org.simantics.databoard.binding.StringBinding;
25 import org.simantics.databoard.binding.error.BindingConstructionException;
26 import org.simantics.databoard.binding.error.BindingException;
27 import org.simantics.databoard.binding.mutable.MutableStringBinding;
28 import org.simantics.databoard.binding.mutable.Variant;
29 import org.simantics.databoard.parser.DataValuePrinter;
30 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
31 import org.simantics.databoard.parser.repository.DataValueRepository;
32 import org.simantics.databoard.primitives.MutableString;
33 import org.simantics.databoard.type.Datatype;
34 import org.simantics.databoard.util.ObjectUtils;
35 import org.simantics.datatypes.literal.Font;
36 import org.simantics.db.ReadGraph;
37 import org.simantics.db.Resource;
38 import org.simantics.db.Statement;
39 import org.simantics.db.WriteGraph;
40 import org.simantics.db.common.CommentMetadata;
41 import org.simantics.db.common.request.EnumerationMap;
42 import org.simantics.db.common.request.InstanceEnumerationMap;
43 import org.simantics.db.common.request.IsEnumeratedValue;
44 import org.simantics.db.common.request.UniqueRead;
45 import org.simantics.db.common.request.WriteRequest;
46 import org.simantics.db.common.utils.CommonDBUtils;
47 import org.simantics.db.common.utils.NameUtils;
48 import org.simantics.db.exception.DatabaseException;
49 import org.simantics.db.layer0.util.Layer0Utils;
50 import org.simantics.db.layer0.variable.ValueAccessor;
51 import org.simantics.db.layer0.variable.Variable;
52 import org.simantics.db.layer0.variable.Variables;
53 import org.simantics.layer0.Layer0;
54 import org.simantics.modeling.ModelingResources;
55 import org.simantics.scl.compiler.types.TVar;
56 import org.simantics.scl.compiler.types.Type;
57 import org.simantics.scl.compiler.types.Types;
58 import org.simantics.scl.reflection.annotations.SCLValue;
59 import org.simantics.scl.runtime.function.Function1;
60 import org.simantics.selectionview.SelectionInput;
61 import org.simantics.selectionview.SelectionViewResources;
62 import org.simantics.selectionview.StandardSelectionInput;
63 import org.simantics.ui.colors.Colors;
64 import org.simantics.ui.fonts.Fonts;
65 import org.simantics.ui.selection.WorkbenchSelectionElement;
66 import org.simantics.ui.selection.WorkbenchSelectionUtils;
67 import org.simantics.utils.datastructures.collections.CollectionUtils;
68 import org.simantics.utils.strings.AlphanumComparator;
69 import org.simantics.utils.ui.AdaptionUtils;
70 import org.simantics.utils.ui.ErrorLogger;
71 import org.simantics.utils.ui.ISelectionUtils;
72
73 public class All {
74
75         final private static Binding datatype_binging = Bindings.getBindingUnchecked(Datatype.class);
76
77         @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
78         public static Object colorModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
79                 return new DialogModifier() {
80
81                         @Override
82                         public String getValue() {
83                                 return null;
84                         }
85
86                         @Override
87                         public String isValid(String label) {
88                                 return null;
89                         }
90
91                         @Override
92                         public void modify(final String label) {
93                                 Simantics.getSession().async(new WriteRequest() {
94
95                                         @Override
96                                         public void perform(WriteGraph graph) throws DatabaseException {
97                                                 Variable displayValue = context.getParent(graph);
98                                                 displayValue.setValue(graph, label, org.simantics.datatypes.literal.RGB.Integer.BINDING);
99                                         }
100
101                                 });
102                         }
103
104                         public String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer<String> applyCallback) {
105                                 Control ctrl = (Control) parentControl;
106
107                                 RGB initialValue = null;
108                                 final Variable v = AdaptionUtils.adaptToSingle(context, Variable.class);
109                                 if (v != null) {
110                                         try {
111                                                 org.simantics.datatypes.literal.RGB.Integer rgb = Simantics.getSession().syncRequest(new UniqueRead<org.simantics.datatypes.literal.RGB.Integer>() {
112                                                         @Override
113                                                         public org.simantics.datatypes.literal.RGB.Integer perform(ReadGraph graph) throws DatabaseException {
114                                                                 return v.getPossibleValue(graph, org.simantics.datatypes.literal.RGB.Integer.BINDING);
115                                                         }
116                                                 });
117                                                 if (rgb != null) {
118                                                         initialValue = Colors.rgb(rgb);
119                                                 }
120                                         } catch (DatabaseException e) {
121                                                 ErrorLogger.defaultLogError(e);
122                                         }
123                                 }
124
125                                 ColorDialog dialog = new ColorDialog(ctrl.getShell());
126                                 if (initialValue != null)
127                                         dialog.setRGB(initialValue);
128                                 RGB rgb = dialog.open();
129                                 if (rgb != null)
130                                         applyCallback.accept("(" + rgb.red + "," + rgb.green + "," + rgb.blue + ")");
131                                 return null;
132                         }
133
134                 };
135         }
136
137         @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
138         public static Object fontModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
139                 return new DialogModifier() {
140
141                         @Override
142                         public String getValue() {
143                                 return null;
144                         }
145
146                         @Override
147                         public String isValid(String label) {
148                                 return null;
149                         }
150
151                         @Override
152                         public void modify(final String label) {
153                                 Simantics.getSession().async(new WriteRequest() {
154
155                                         @Override
156                                         public void perform(WriteGraph graph) throws DatabaseException {
157                                                 Variable displayValue = context.getParent(graph);
158                                                 displayValue.setValue(graph, label, Font.BINDING);
159                                         }
160
161                                 });
162                         }
163
164                         public String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer<String> applyCallback) {
165                                 Control ctrl = (Control) parentControl;
166
167                                 FontData[] initialValue = null;
168                                 final Variable v = AdaptionUtils.adaptToSingle(context, Variable.class);
169                                 if (v != null) {
170                                         try {
171                                                 Font font = Simantics.getSession().syncRequest(new UniqueRead<Font>() {
172                                                         @Override
173                                                         public Font perform(ReadGraph graph) throws DatabaseException {
174                                                                 return v.getPossibleValue(graph, Font.BINDING);
175                                                         }
176                                                 });
177                                                 if (font != null) {
178                                                         initialValue = new FontData[] { Fonts.swtFontData(font) };
179                                                 }
180                                         } catch (DatabaseException e) {
181                                                 ErrorLogger.defaultLogError(e);
182                                         }
183                                 }
184
185                                 FontDialog dialog = new FontDialog(ctrl.getShell());
186                                 if (initialValue != null)
187                                         dialog.setFontList(initialValue);
188                                 FontData font = dialog.open();
189                                 if (font != null)
190                                         applyCallback.accept("(\"" + font.getName() + "\"," + font.getHeight() + ",\"" + Fonts.fromSwtStyle(font.getStyle()) + "\")");
191                                 return null;
192                         }
193
194                 };
195         }
196
197         @SCLValue(type = "ReadGraph -> Resource -> a -> b")
198         public static Object getEnumerationValues(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
199                 if(context instanceof Variable) {
200                         Layer0 L0 = Layer0.getInstance(graph);
201                         Variable parameter = ((Variable)context).browse(graph, "..");
202                         Resource parameterResource = parameter.getRepresents(graph);
203                         if(graph.sync(new IsEnumeratedValue(parameterResource))) {
204                                 Map<String, Resource> map = graph.sync(new InstanceEnumerationMap(parameterResource));
205                                 ArrayList<String> values = new ArrayList<>(map.keySet());
206                                 Collections.sort(values, AlphanumComparator.COMPARATOR);
207                                 return values;
208                         } else if(graph.isInstanceOf(parameterResource, L0.Boolean)) {
209                                 return CollectionUtils.toList("true", "false");
210                         }
211                 }
212                 return null;
213         }
214
215         @SCLValue(type = "ReadGraph -> Resource -> a -> b")
216         public static Object getPropertyChildName(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
217                 if(context instanceof Variable) {
218                         Variable variable = (Variable)context;
219                         String label = variable.getParent(graph).getPossiblePropertyValue(graph, "HasLabel", Bindings.STRING);
220                         if(label != null)
221                                 return label;
222                         return variable.getParent(graph).getName(graph);
223                 }
224                 throw new DatabaseException("Unknown context " + context);
225         }
226         
227         @SCLValue(type = "WriteGraph -> Variable -> a -> b -> String")
228         public static String inputModifier(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException {
229
230                 //      System.err.println("inputModifier " + variable.getURI(graph));
231                 Layer0 L0 = Layer0.getInstance(graph);
232
233                 Variable parent = variable.getParent(graph);
234                 Resource property = variable.getPredicateResource(graph);
235
236                 Resource container = parent.getRepresents(graph);
237                 if(container == null) return null;
238                 if(property == null) return null;
239
240                 Statement object = graph.getPossibleStatement(container, property);
241                 if(object == null) return null;
242
243                 Resource objectResource = object.getObject();
244                 if(graph.sync(new IsEnumeratedValue(objectResource))) {
245
246                         Resource type = graph.getSingleObject(objectResource, L0.PartOf);
247
248                         Map<String, Resource> enumMap = graph.syncRequest(new EnumerationMap(type));
249                         Resource newLiteral = enumMap.get(value);
250                         graph.deny(container, property, objectResource);
251                         graph.claim(container, property, newLiteral);
252
253                         return null;
254
255                 }
256
257                 Resource newType = Layer0Utils.getPossibleLiteralType(graph, variable);
258                 if(newType == null) {
259                         Type type = Layer0Utils.getSCLType(graph, variable);
260                         // This means that type is a wildcard e.g. "a"
261                         if(Types.canonical(type) instanceof TVar) {
262                                 newType = Layer0Utils.inferLiteralTypeFromString(graph, value.toString());
263                         } else {
264                                 throw new DatabaseException("Failed to find type for property " + NameUtils.getSafeName(graph, property));
265                         }
266                 }
267
268                 boolean correctType = graph.getPossibleType(objectResource, newType) != null;
269                 boolean asserted = object.isAsserted(container);
270                 if(asserted || !correctType) {
271
272                         if(correctType) {
273
274                                 Statement dt = graph.getPossibleStatement(objectResource, L0.HasDataType);
275                                 Datatype custom = dt.isAsserted(objectResource) ? null : (Datatype)graph.getValue(dt.getObject(), datatype_binging);
276
277                                 objectResource = graph.newResource();
278                                 graph.claim(objectResource, L0.InstanceOf, null, newType);
279                                 graph.claim(container, property, objectResource);
280                                 if(custom != null) {
281                                         // Only set HasValueType if the calculated new SCL type differs from the asserted value type
282                                         String newValueType = Layer0Utils.getSCLType(custom);
283                                         String currentValueType = graph.getPossibleRelatedValue(objectResource, L0.HasValueType, Bindings.STRING);
284                                         if (!newValueType.equals(currentValueType)) {
285                                                 graph.addLiteral(objectResource, L0.HasValueType, L0.HasValueType_Inverse, L0.String, newValueType, Bindings.STRING);
286                                         }
287                                         graph.addLiteral(objectResource, L0.HasDataType, L0.HasDataType_Inverse, L0.DataType, custom, datatype_binging);
288                                 }
289
290                         } else {
291
292                                 if(newType != null) {
293
294                                         if(!correctType && !asserted) // if not correct type and not asserted, remove the old value
295                                                 graph.deny(container, property, objectResource);
296
297                                         objectResource = graph.newResource();
298                                         graph.claim(objectResource, L0.InstanceOf, newType);
299                                         graph.claim(container, property, objectResource);
300
301                                 }
302
303                         }
304
305                 }
306
307                 Datatype datatype = variable.getDatatype(graph);
308                 Binding binding = (Binding)_binding;
309                 Layer0Utils.claimAdaptedValue(graph, objectResource, value, binding, datatype);
310
311                 return null;
312
313         }
314
315         @SCLValue(type = "ReadGraph -> a -> Resource")
316         public static Resource singleResourceTransformation(ReadGraph graph, Object input) throws DatabaseException {
317                 return WorkbenchSelectionUtils.getPossibleResource(graph, input);
318         }
319
320
321         @SCLValue(type = "ReadGraph -> a -> Variable")
322         public static Variable singleVariableTransformation(ReadGraph graph, Object input) throws DatabaseException {
323                 Variable single = WorkbenchSelectionUtils.getPossibleVariable(graph, input);
324                 if(single != null) return single;
325                 return ISelectionUtils.filterSingleSelection(input, Variable.class);
326         }
327
328         @SCLValue(type = "ReadGraph -> a -> Variable")
329         public static Variable singleResourceToVariableTransformation(ReadGraph graph, Object input) throws DatabaseException {
330                 Resource r = WorkbenchSelectionUtils.getPossibleResource(graph, input);
331                 if (r == null)
332                         return null;
333                 return Variables.getPossibleVariable(graph, r);
334         }
335
336         @SCLValue(type = "ReadGraph -> a -> SelectionInput")
337         public static SelectionInput standardSelectionInputTransformation(ReadGraph graph, Object input) throws DatabaseException {
338                 WorkbenchSelectionElement wse = WorkbenchSelectionUtils.getPossibleSelectionElement(input);
339                 if (wse == null)
340                         return null;
341                 return new StandardSelectionInput(wse);
342         }
343
344         @SCLValue(type = "ValueAccessor")
345         public static ValueAccessor displayUnitValueAccessor = new ValueAccessor() {
346
347                 @Override
348                 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
349                         return Variables.getPossibleUnit(graph, context.getParent(graph));
350                 }
351
352                 @Override
353                 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
354                         try {
355                                 Object value = Variables.getPossibleUnit(graph, context.getParent(graph));
356                                 if(value == null) return null;
357                                 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
358                                 return Bindings.adapt(value, srcBinding, binding);
359                         } catch (AdaptException e) {
360                                 throw new DatabaseException(e);
361                         } catch (BindingException e) {
362                                 throw new DatabaseException(e);
363                         }
364                 }
365
366                 @Override
367                 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
368                         throw new UnsupportedOperationException();
369                 }
370
371                 @Override
372                 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
373                         throw new UnsupportedOperationException();
374                 }
375
376                 @Override
377                 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
378                         return org.simantics.db.layer0.function.All.getDatatypeFromValue(graph, context);
379                 }
380
381         };
382
383         @SCLValue(type = "ValueAccessor")
384         public static ValueAccessor displayPropertyValueAccessor = new ValueAccessor() {
385
386                 @Override
387                 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
388                         return getValue(graph, context, Bindings.STRING);
389                 }
390
391                 @Override
392                 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
393                         Layer0 L0 = Layer0.getInstance(graph);
394                         Variable property = context.getParent(graph);
395                         Resource predicate = property.getPossiblePredicateResource(graph);
396                         if(predicate == null) return property.getName(graph);
397                         String value = graph.getPossibleRelatedValue2(predicate, L0.HasLabel, Bindings.STRING);
398                         if(value == null)
399                             value = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
400                         try {
401                                 return Bindings.adapt(value, binding, Bindings.STRING);
402                         } catch (AdaptException e) {
403                                 throw new DatabaseException(e);
404                         }
405                 }
406
407                 @Override
408                 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
409                         throw new UnsupportedOperationException();
410                 }
411
412                 @Override
413                 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
414                         throw new UnsupportedOperationException();
415                 }
416
417                 @Override
418                 public Datatype getDatatype(ReadGraph graph, Variable context)
419                                 throws DatabaseException {
420                         return Datatypes.STRING;
421                 }
422
423         };      
424
425         @SCLValue(type = "ValueAccessor")
426         public static ValueAccessor displayValueValueAccessor = new ValueAccessor() {
427
428                 @Override
429                 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
430                         return getValue(graph, context, Bindings.STRING);
431                 }
432
433                 public boolean isPrimitive(Datatype dt) {
434                         if(Datatypes.STRING.equals(dt)) return true;
435                         else return false;
436                 }
437
438                 private String possibleExpression(ReadGraph graph, Variable variable) throws DatabaseException {
439
440                         Layer0 L0 = Layer0.getInstance(graph);
441                         Resource object = variable.getPossibleRepresents(graph);
442                         if(object != null && graph.isInstanceOf(object, L0.SCLValue)) {
443                                 String expression = graph.getPossibleRelatedValue(object, L0.SCLValue_expression);
444                                 if (expression != null)
445                                         return "=" + expression;
446                         }
447                         return null;
448
449                 }
450
451                 @Override
452                 public Object getValue(ReadGraph graph, Variable context, Binding _binding) throws DatabaseException {
453
454                         Variable property = context.getParent(graph);
455
456                         String expression = possibleExpression(graph, property);
457                         if(expression != null) return expression;
458
459                         Object value = null;
460                         Resource formatter = property.getPossiblePropertyValue(graph, Variables.FORMATTER);
461                         if(formatter != null) {
462                                 Formatter fmt = graph.adaptContextual(formatter, property, Variable.class, Formatter.class);
463                                 value = fmt.format(property.getValue(graph));
464                         }
465                         if(value == null) {
466                                 SelectionViewResources SEL = SelectionViewResources.getInstance(graph);
467                                 Function1<Object,String> formatterFunction = property.getPossiblePropertyValue(graph, SEL.formatter);
468                                 if(formatterFunction != null) {
469                                         value = formatterFunction.apply(property.getValue(graph));
470                                 }
471                         }
472
473                         Resource possibleValue = context.getParent(graph).getPossibleRepresents(graph);
474                         if(possibleValue != null) {
475                                 if(graph.syncRequest(new IsEnumeratedValue(possibleValue))) {
476                                         return CommonDBUtils.getEnumerationValueName(graph, possibleValue);
477                                 }
478                         }
479
480                         if(value == null) {
481
482                                 Variant variant = property.getVariantValue(graph);
483                                 value = variant.getValue();
484                                 Binding binding = variant.getBinding();
485                                 if(binding != null) {
486                                         Datatype dt = binding.type();   
487                                         if(dt != null) {
488                                                 if(!isPrimitive(dt)) {
489                                                         try {
490                                                                 value = DataValuePrinter.writeValueSingleLine(binding, value);
491                                                         } catch (IOException e) {
492                                                                 e.printStackTrace();
493                                                         } catch (BindingException e) {
494                                                                 e.printStackTrace();
495                                                         }
496                                                 }
497                                         }
498                                 }
499
500                         }
501
502                         try {
503                                 return Bindings.adapt(value != null ? value.toString() : "null", _binding, Bindings.STRING);
504                         } catch (AdaptException e) {
505                                 throw new DatabaseException(e);
506                         }
507                 }
508
509                 @Override
510                 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
511                         try {
512                                 Binding binding = Bindings.getBinding(value.getClass());
513                                 setValue(graph, context, value, binding);
514                         } catch (BindingConstructionException e) {
515                                 throw new DatabaseException(e);
516                         }
517                 }
518
519                 @Override
520                 public void setValue(WriteGraph graph, Variable context, Object _value, Binding _binding) throws DatabaseException {
521                         try {
522
523                                 if(!(_value instanceof String)) throw new DatabaseException("setValue for HasDisplayValue only accepts String (got " + _value.getClass().getSimpleName() + ")");
524
525                                 String text = (String)_value;
526                                 if(text.startsWith("=")) {
527                                         Variable property = context.getParent(graph);
528                                         Layer0Utils.setExpression(graph, property, text, ModelingResources.getInstance(graph).SCLValue);
529                                         return;
530                                 }
531
532                                 String parsedLabel = (String)_value;
533                                 Object value = parsedLabel;
534
535                                 boolean isEnumeration = false;
536                                 Resource possibleValue = context.getParent(graph).getPossibleRepresents(graph);
537                                 if(possibleValue != null) {
538                                         isEnumeration = graph.syncRequest(new IsEnumeratedValue(possibleValue));
539                                 }
540
541                                 Datatype type = context.getParent(graph).getPossibleDatatype(graph);
542                                 if (type != null && !isEnumeration) {
543
544                                         Binding binding = Bindings.getBinding(type);
545
546                                         if (binding instanceof StringBinding) {
547
548                                                 if (binding instanceof MutableStringBinding)
549                                                         value = new MutableString(parsedLabel);
550                                                 else
551                                                         value = parsedLabel;
552
553                                         } else {
554
555                                                 if (binding instanceof NumberBinding) {
556                                                         parsedLabel = parsedLabel.replace(",", ".");
557                                                 }
558
559                                                 value = binding.parseValue(parsedLabel, new DataValueRepository());
560                                         }
561
562                                         //System.out.println("VariableWrite " + ObjectUtils.toString(value));
563                                         context.getParent(graph).setValue(graph, value, binding);
564
565                                 } else {
566
567                                         context.getParent(graph).setValue(graph, value);
568
569                                 }
570
571
572                                 // Add a comment to metadata.
573                                 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
574                                 graph.addMetadata(cm.add("Set value " + ObjectUtils.toString(value)));
575
576                         } catch (DataTypeSyntaxError e) {
577                                 throw new DatabaseException(e);
578                         } catch (BindingException e) {
579                                 throw new DatabaseException(e);
580                         }
581                 }
582
583                 @Override
584                 public Datatype getDatatype(ReadGraph graph, Variable context)
585                                 throws DatabaseException {
586                         return Datatypes.STRING;
587                 }
588
589         };              
590 }