1 package org.simantics.selectionview.function;
\r
3 import java.io.IOException;
\r
4 import java.util.ArrayList;
\r
5 import java.util.Map;
\r
6 import java.util.function.Consumer;
\r
8 import org.eclipse.swt.graphics.FontData;
\r
9 import org.eclipse.swt.graphics.RGB;
\r
10 import org.eclipse.swt.widgets.ColorDialog;
\r
11 import org.eclipse.swt.widgets.Control;
\r
12 import org.eclipse.swt.widgets.FontDialog;
\r
13 import org.simantics.Simantics;
\r
14 import org.simantics.browsing.ui.NodeContext;
\r
15 import org.simantics.browsing.ui.content.Labeler.DialogModifier;
\r
16 import org.simantics.common.format.Formatter;
\r
17 import org.simantics.databoard.Bindings;
\r
18 import org.simantics.databoard.Datatypes;
\r
19 import org.simantics.databoard.adapter.AdaptException;
\r
20 import org.simantics.databoard.binding.Binding;
\r
21 import org.simantics.databoard.binding.NumberBinding;
\r
22 import org.simantics.databoard.binding.StringBinding;
\r
23 import org.simantics.databoard.binding.error.BindingConstructionException;
\r
24 import org.simantics.databoard.binding.error.BindingException;
\r
25 import org.simantics.databoard.binding.mutable.MutableStringBinding;
\r
26 import org.simantics.databoard.binding.mutable.Variant;
\r
27 import org.simantics.databoard.parser.DataValuePrinter;
\r
28 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
\r
29 import org.simantics.databoard.parser.repository.DataValueRepository;
\r
30 import org.simantics.databoard.primitives.MutableString;
\r
31 import org.simantics.databoard.type.Datatype;
\r
32 import org.simantics.databoard.util.ObjectUtils;
\r
33 import org.simantics.datatypes.literal.Font;
\r
34 import org.simantics.db.ReadGraph;
\r
35 import org.simantics.db.Resource;
\r
36 import org.simantics.db.Statement;
\r
37 import org.simantics.db.WriteGraph;
\r
38 import org.simantics.db.common.CommentMetadata;
\r
39 import org.simantics.db.common.request.EnumerationMap;
\r
40 import org.simantics.db.common.request.InstanceEnumerationMap;
\r
41 import org.simantics.db.common.request.IsEnumeratedValue;
\r
42 import org.simantics.db.common.request.UniqueRead;
\r
43 import org.simantics.db.common.request.WriteRequest;
\r
44 import org.simantics.db.common.utils.NameUtils;
\r
45 import org.simantics.db.exception.DatabaseException;
\r
46 import org.simantics.db.layer0.util.Layer0Utils;
\r
47 import org.simantics.db.layer0.variable.ValueAccessor;
\r
48 import org.simantics.db.layer0.variable.Variable;
\r
49 import org.simantics.db.layer0.variable.Variables;
\r
50 import org.simantics.layer0.Layer0;
\r
51 import org.simantics.modeling.ModelingResources;
\r
52 import org.simantics.scl.compiler.types.TVar;
\r
53 import org.simantics.scl.compiler.types.Type;
\r
54 import org.simantics.scl.compiler.types.Types;
\r
55 import org.simantics.scl.reflection.annotations.SCLValue;
\r
56 import org.simantics.selectionview.SelectionInput;
\r
57 import org.simantics.selectionview.StandardSelectionInput;
\r
58 import org.simantics.ui.colors.Colors;
\r
59 import org.simantics.ui.fonts.Fonts;
\r
60 import org.simantics.ui.selection.WorkbenchSelectionElement;
\r
61 import org.simantics.ui.selection.WorkbenchSelectionUtils;
\r
62 import org.simantics.utils.datastructures.collections.CollectionUtils;
\r
63 import org.simantics.utils.ui.AdaptionUtils;
\r
64 import org.simantics.utils.ui.ErrorLogger;
\r
65 import org.simantics.utils.ui.ISelectionUtils;
\r
69 final private static Binding datatype_binging = Bindings.getBindingUnchecked(Datatype.class);
\r
71 @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
\r
72 public static Object colorModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
\r
73 return new DialogModifier() {
\r
76 public String getValue() {
\r
81 public String isValid(String label) {
\r
86 public void modify(final String label) {
\r
87 Simantics.getSession().async(new WriteRequest() {
\r
90 public void perform(WriteGraph graph) throws DatabaseException {
\r
91 Variable displayValue = context.getParent(graph);
\r
92 displayValue.setValue(graph, label, org.simantics.datatypes.literal.RGB.Integer.BINDING);
\r
98 public String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer<String> applyCallback) {
\r
99 Control ctrl = (Control) parentControl;
\r
101 RGB initialValue = null;
\r
102 final Variable v = AdaptionUtils.adaptToSingle(context, Variable.class);
\r
105 org.simantics.datatypes.literal.RGB.Integer rgb = Simantics.getSession().syncRequest(new UniqueRead<org.simantics.datatypes.literal.RGB.Integer>() {
\r
107 public org.simantics.datatypes.literal.RGB.Integer perform(ReadGraph graph) throws DatabaseException {
\r
108 return v.getPossibleValue(graph, org.simantics.datatypes.literal.RGB.Integer.BINDING);
\r
112 initialValue = Colors.rgb(rgb);
\r
114 } catch (DatabaseException e) {
\r
115 ErrorLogger.defaultLogError(e);
\r
119 ColorDialog dialog = new ColorDialog(ctrl.getShell());
\r
120 if (initialValue != null)
\r
121 dialog.setRGB(initialValue);
\r
122 RGB rgb = dialog.open();
\r
124 applyCallback.accept("(" + rgb.red + "," + rgb.green + "," + rgb.blue + ")");
\r
131 @SCLValue(type = "ReadGraph -> Resource -> Variable -> b")
\r
132 public static Object fontModifier(ReadGraph graph, Resource resource, final Variable context) throws DatabaseException {
\r
133 return new DialogModifier() {
\r
136 public String getValue() {
\r
141 public String isValid(String label) {
\r
146 public void modify(final String label) {
\r
147 Simantics.getSession().async(new WriteRequest() {
\r
150 public void perform(WriteGraph graph) throws DatabaseException {
\r
151 Variable displayValue = context.getParent(graph);
\r
152 displayValue.setValue(graph, label, Font.BINDING);
\r
158 public String query(Object parentControl, Object controlItem, int columnIndex, NodeContext context, Consumer<String> applyCallback) {
\r
159 Control ctrl = (Control) parentControl;
\r
161 FontData[] initialValue = null;
\r
162 final Variable v = AdaptionUtils.adaptToSingle(context, Variable.class);
\r
165 Font font = Simantics.getSession().syncRequest(new UniqueRead<Font>() {
\r
167 public Font perform(ReadGraph graph) throws DatabaseException {
\r
168 return v.getPossibleValue(graph, Font.BINDING);
\r
171 if (font != null) {
\r
172 initialValue = new FontData[] { Fonts.swtFontData(font) };
\r
174 } catch (DatabaseException e) {
\r
175 ErrorLogger.defaultLogError(e);
\r
179 FontDialog dialog = new FontDialog(ctrl.getShell());
\r
180 if (initialValue != null)
\r
181 dialog.setFontList(initialValue);
\r
182 FontData font = dialog.open();
\r
184 applyCallback.accept("(\"" + font.getName() + "\"," + font.getHeight() + ",\"" + Fonts.fromSwtStyle(font.getStyle()) + "\")");
\r
191 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
192 public static Object getEnumerationValues(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
193 if(context instanceof Variable) {
\r
194 Layer0 L0 = Layer0.getInstance(graph);
\r
195 Variable parameter = ((Variable)context).browse(graph, "..");
\r
196 Resource parameterResource = parameter.getRepresents(graph);
\r
197 if(graph.sync(new IsEnumeratedValue(parameterResource))) {
\r
198 Map<String, Resource> map = graph.sync(new InstanceEnumerationMap(parameterResource));
\r
199 return new ArrayList<String>(map.keySet());
\r
200 } else if(graph.isInstanceOf(parameterResource, L0.Boolean)) {
\r
201 return CollectionUtils.toList("true", "false");
\r
207 @SCLValue(type = "ReadGraph -> Resource -> a -> b")
\r
208 public static Object getPropertyChildName(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
\r
209 if(context instanceof Variable) {
\r
210 Variable variable = (Variable)context;
\r
211 return variable.getParent(graph).getName(graph);
\r
213 throw new DatabaseException("Unknown context " + context);
\r
216 @SCLValue(type = "WriteGraph -> Variable -> a -> b -> String")
\r
217 public static String inputModifier(WriteGraph graph, Variable variable, Object value, Object _binding) throws DatabaseException {
\r
219 // System.err.println("inputModifier " + variable.getURI(graph));
\r
220 Layer0 L0 = Layer0.getInstance(graph);
\r
222 Variable parent = variable.getParent(graph);
\r
223 Resource property = variable.getPredicateResource(graph);
\r
225 Resource container = parent.getRepresents(graph);
\r
226 if(container == null) return null;
\r
227 if(property == null) return null;
\r
229 Statement object = graph.getPossibleStatement(container, property);
\r
230 if(object == null) return null;
\r
232 Resource objectResource = object.getObject();
\r
233 if(graph.sync(new IsEnumeratedValue(objectResource))) {
\r
235 Resource type = graph.getSingleObject(objectResource, L0.PartOf);
\r
237 Map<String, Resource> enumMap = graph.syncRequest(new EnumerationMap(type));
\r
238 Resource newLiteral = enumMap.get(value);
\r
239 graph.deny(container, property, objectResource);
\r
240 graph.claim(container, property, newLiteral);
\r
246 Resource newType = Layer0Utils.getPossibleLiteralType(graph, variable);
\r
247 if(newType == null) {
\r
248 Type type = Layer0Utils.getSCLType(graph, variable);
\r
249 // This means that type is a wildcard e.g. "a"
\r
250 if(Types.canonical(type) instanceof TVar) {
\r
251 newType = Layer0Utils.inferLiteralTypeFromString(graph, value.toString());
\r
253 throw new DatabaseException("Failed to find type for property " + NameUtils.getSafeName(graph, property));
\r
257 boolean correctType = graph.getPossibleType(objectResource, newType) != null;
\r
258 boolean asserted = object.isAsserted(container);
\r
259 if(asserted || !correctType) {
\r
263 Statement dt = graph.getPossibleStatement(objectResource, L0.HasDataType);
\r
264 Datatype custom = dt.isAsserted(objectResource) ? null : (Datatype)graph.getValue(dt.getObject(), datatype_binging);
\r
266 objectResource = graph.newResource();
\r
267 graph.claim(objectResource, L0.InstanceOf, null, newType);
\r
268 graph.claim(container, property, objectResource);
\r
269 if(custom != null) {
\r
270 // Only set HasValueType if the calculated new SCL type differs from the asserted value type
\r
271 String newValueType = Layer0Utils.getSCLType(custom);
\r
272 String currentValueType = graph.getPossibleRelatedValue(objectResource, L0.HasValueType, Bindings.STRING);
\r
273 if (!newValueType.equals(currentValueType)) {
\r
274 graph.addLiteral(objectResource, L0.HasValueType, L0.HasValueType_Inverse, L0.String, newValueType, Bindings.STRING);
\r
276 graph.addLiteral(objectResource, L0.HasDataType, L0.HasDataType_Inverse, L0.DataType, custom, datatype_binging);
\r
281 if(newType != null) {
\r
283 if(!correctType && !asserted) // if not correct type and not asserted, remove the old value
\r
284 graph.deny(container, property, objectResource);
\r
286 objectResource = graph.newResource();
\r
287 graph.claim(objectResource, L0.InstanceOf, newType);
\r
288 graph.claim(container, property, objectResource);
\r
296 Datatype datatype = variable.getDatatype(graph);
\r
297 Binding binding = (Binding)_binding;
\r
298 Layer0Utils.claimAdaptedValue(graph, objectResource, value, binding, datatype);
\r
304 @SCLValue(type = "ReadGraph -> a -> Resource")
\r
305 public static Resource singleResourceTransformation(ReadGraph graph, Object input) throws DatabaseException {
\r
306 return WorkbenchSelectionUtils.getPossibleResource(graph, input);
\r
310 @SCLValue(type = "ReadGraph -> a -> Variable")
\r
311 public static Variable singleVariableTransformation(ReadGraph graph, Object input) throws DatabaseException {
\r
312 Variable single = WorkbenchSelectionUtils.getPossibleVariable(graph, input);
\r
313 if(single != null) return single;
\r
314 return ISelectionUtils.filterSingleSelection(input, Variable.class);
\r
317 @SCLValue(type = "ReadGraph -> a -> Variable")
\r
318 public static Variable singleResourceToVariableTransformation(ReadGraph graph, Object input) throws DatabaseException {
\r
319 Resource r = WorkbenchSelectionUtils.getPossibleResource(graph, input);
\r
322 return Variables.getPossibleVariable(graph, r);
\r
325 @SCLValue(type = "ReadGraph -> a -> SelectionInput")
\r
326 public static SelectionInput standardSelectionInputTransformation(ReadGraph graph, Object input) throws DatabaseException {
\r
327 WorkbenchSelectionElement wse = WorkbenchSelectionUtils.getPossibleSelectionElement(input);
\r
330 return new StandardSelectionInput(wse);
\r
333 @SCLValue(type = "ValueAccessor")
\r
334 public static ValueAccessor displayUnitValueAccessor = new ValueAccessor() {
\r
337 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
338 return Variables.getPossibleUnit(graph, context.getParent(graph));
\r
342 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
344 Object value = Variables.getPossibleUnit(graph, context.getParent(graph));
\r
345 if(value == null) return null;
\r
346 Binding srcBinding = Bindings.OBJECT.getContentBinding(value);
\r
347 return Bindings.adapt(value, srcBinding, binding);
\r
348 } catch (AdaptException e) {
\r
349 throw new DatabaseException(e);
\r
350 } catch (BindingException e) {
\r
351 throw new DatabaseException(e);
\r
356 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
\r
357 throw new UnsupportedOperationException();
\r
361 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
\r
362 throw new UnsupportedOperationException();
\r
366 public Datatype getDatatype(ReadGraph graph, Variable context) throws DatabaseException {
\r
367 return org.simantics.db.layer0.function.All.getDatatypeFromValue(graph, context);
\r
372 @SCLValue(type = "ValueAccessor")
\r
373 public static ValueAccessor displayPropertyValueAccessor = new ValueAccessor() {
\r
376 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
377 return getValue(graph, context, Bindings.STRING);
\r
381 public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
\r
382 Layer0 L0 = Layer0.getInstance(graph);
\r
383 Variable property = context.getParent(graph);
\r
384 Resource predicate = property.getPossiblePredicateResource(graph);
\r
385 if(predicate == null) return property.getName(graph);
\r
386 String value = graph.getPossibleRelatedValue2(predicate, L0.HasLabel, Bindings.STRING);
\r
388 value = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING);
\r
390 return Bindings.adapt(value, binding, Bindings.STRING);
\r
391 } catch (AdaptException e) {
\r
392 throw new DatabaseException(e);
\r
397 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
\r
398 throw new UnsupportedOperationException();
\r
402 public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
\r
403 throw new UnsupportedOperationException();
\r
407 public Datatype getDatatype(ReadGraph graph, Variable context)
\r
408 throws DatabaseException {
\r
409 return Datatypes.STRING;
\r
414 @SCLValue(type = "ValueAccessor")
\r
415 public static ValueAccessor displayValueValueAccessor = new ValueAccessor() {
\r
418 public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
\r
419 return getValue(graph, context, Bindings.STRING);
\r
422 public boolean isPrimitive(Datatype dt) {
\r
423 if(Datatypes.STRING.equals(dt)) return true;
\r
427 private String possibleExpression(ReadGraph graph, Variable variable) throws DatabaseException {
\r
429 Layer0 L0 = Layer0.getInstance(graph);
\r
430 Resource object = variable.getPossibleRepresents(graph);
\r
431 if(object != null && graph.isInstanceOf(object, L0.SCLValue)) {
\r
432 String expression = graph.getPossibleRelatedValue(object, L0.SCLValue_expression);
\r
433 if (expression != null)
\r
434 return "=" + expression;
\r
441 public Object getValue(ReadGraph graph, Variable context, Binding _binding) throws DatabaseException {
\r
443 Variable property = context.getParent(graph);
\r
445 String expression = possibleExpression(graph, property);
\r
446 if(expression != null) return expression;
\r
448 Object value = null;
\r
449 Resource formatter = property.getPossiblePropertyValue(graph, Variables.FORMATTER);
\r
450 if(formatter != null) {
\r
452 Formatter fmt = graph.adaptContextual(formatter, property, Variable.class, Formatter.class);
\r
453 value = fmt.format(property.getValue(graph));
\r
457 Variant variant = property.getVariantValue(graph);
\r
458 value = variant.getValue();
\r
460 Binding binding = variant.getBinding();
\r
461 if(binding != null) {
\r
462 Datatype dt = binding.type();
\r
464 if(!isPrimitive(dt)) {
\r
466 value = DataValuePrinter.writeValueSingleLine(binding, value);
\r
467 } catch (IOException e) {
\r
468 e.printStackTrace();
\r
469 } catch (BindingException e) {
\r
470 e.printStackTrace();
\r
479 return Bindings.adapt(value != null ? value.toString() : "null", _binding, Bindings.STRING);
\r
480 } catch (AdaptException e) {
\r
481 throw new DatabaseException(e);
\r
486 public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
\r
488 Binding binding = Bindings.getBinding(value.getClass());
\r
489 setValue(graph, context, value, binding);
\r
490 } catch (BindingConstructionException e) {
\r
491 throw new DatabaseException(e);
\r
496 public void setValue(WriteGraph graph, Variable context, Object _value, Binding _binding) throws DatabaseException {
\r
499 if(!(_value instanceof String)) throw new DatabaseException("setValue for HasDisplayValue only accepts String (got " + _value.getClass().getSimpleName() + ")");
\r
501 String text = (String)_value;
\r
502 if(text.startsWith("=")) {
\r
503 Variable property = context.getParent(graph);
\r
504 Layer0Utils.setExpression(graph, property, text, ModelingResources.getInstance(graph).SCLValue);
\r
508 String parsedLabel = (String)_value;
\r
509 Object value = parsedLabel;
\r
511 Datatype type = context.getParent(graph).getPossibleDatatype(graph);
\r
512 if (type != null) {
\r
514 Binding binding = Bindings.getBinding(type);
\r
516 if (binding instanceof StringBinding) {
\r
518 if (binding instanceof MutableStringBinding)
\r
519 value = new MutableString(parsedLabel);
\r
521 value = parsedLabel;
\r
525 if (binding instanceof NumberBinding) {
\r
526 parsedLabel = parsedLabel.replace(",", ".");
\r
529 value = binding.parseValue(parsedLabel, new DataValueRepository());
\r
532 //System.out.println("VariableWrite " + ObjectUtils.toString(value));
\r
533 context.getParent(graph).setValue(graph, value, binding);
\r
537 context.getParent(graph).setValue(graph, value);
\r
542 // Add a comment to metadata.
\r
543 CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
\r
544 graph.addMetadata(cm.add("Set value " + ObjectUtils.toString(value)));
\r
546 } catch (DataTypeSyntaxError e) {
\r
547 throw new DatabaseException(e);
\r
548 } catch (BindingException e) {
\r
549 throw new DatabaseException(e);
\r
554 public Datatype getDatatype(ReadGraph graph, Variable context)
\r
555 throws DatabaseException {
\r
556 return Datatypes.STRING;
\r