1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.sysdyn.ui.properties.widgets;
14 import java.awt.event.ActionEvent;
15 import java.awt.event.ActionListener;
16 import java.util.HashMap;
19 import javax.swing.Timer;
21 import org.eclipse.jface.resource.JFaceResources;
22 import org.eclipse.jface.resource.LocalResourceManager;
23 import org.eclipse.swt.custom.VerifyKeyListener;
24 import org.eclipse.swt.events.FocusListener;
25 import org.eclipse.swt.events.ModifyListener;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Table;
29 import org.simantics.Simantics;
30 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
31 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
32 import org.simantics.db.ReadGraph;
33 import org.simantics.db.Resource;
34 import org.simantics.db.exception.DatabaseException;
35 import org.simantics.db.layer0.variable.Variable;
36 import org.simantics.db.management.ISessionContext;
37 import org.simantics.db.request.Read;
38 import org.simantics.layer0.Layer0;
39 import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType;
40 import org.simantics.sysdyn.ui.properties.widgets.expressions.AuxiliaryExpression;
41 import org.simantics.sysdyn.ui.properties.widgets.expressions.ConstantExpression;
42 import org.simantics.sysdyn.ui.properties.widgets.expressions.DelayExpression;
43 import org.simantics.sysdyn.ui.properties.widgets.expressions.EmptyExpression;
44 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionComposite;
45 import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionWidgetInput;
46 import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression;
47 import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupExpression;
48 import org.simantics.sysdyn.ui.properties.widgets.expressions.ParameterExpression;
49 import org.simantics.sysdyn.ui.properties.widgets.expressions.StockExpression;
50 import org.simantics.sysdyn.ui.properties.widgets.expressions.WithLookupExpression;
51 import org.simantics.sysdyn.ui.utils.ExpressionUtils;
52 import org.simantics.utils.ui.AdaptionUtils;
55 * Widget for displaying an expression. Widget creates the IExpression for displaying
56 * properties for each expression type and adds validation, saving and other services
57 * to the active IExpression.
59 * @author Teemu Lempinen
60 * @author Tuomas Miettinen
63 public class ExpressionWidget implements Widget {
65 private ExpressionWidgetInput input;
66 private Resource expr;
67 private Variable variable;
68 private Composite parent;
69 private Map<String, Object> data;
70 private IExpression expression;
71 private ModifyListener modifyListener;
72 private FocusListener focusListener;
73 private Table variableTable;
74 private VerifyKeyListener verifyKeyListener;
75 private Timer validationTimer;
76 private static int VALIDATION_DELAY_TIME = 500;
77 private final LocalResourceManager resourceManager;
80 * Create a new expression widget
85 public ExpressionWidget(Composite parent, WidgetSupport support, int style) {
86 support.register(this);
88 if (parent instanceof ExpressionComposite) {
89 ExpressionComposite expressionComposite = (ExpressionComposite)parent;
90 expressionComposite.setExpressionWidget(this);
92 this.data = new HashMap<String, Object>();
94 // Create a ResourceManager to dispose images when the widget is disposed.
95 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), this.parent);
98 * Create a validation timer for expression fields. Validation timer
99 * validates the field as the modeler is typing an expression
101 validationTimer = new Timer(VALIDATION_DELAY_TIME, new ActionListener() {
104 public void actionPerformed(ActionEvent e) {
105 if(variableTable == null || variableTable.isDisposed())
107 variableTable.getDisplay().asyncExec(new Runnable() {
116 validationTimer.setRepeats(false);
120 public void setInput(ISessionContext context, Object input) {
121 // Update IExpression based on the newly selected expression
122 ExpressionWidgetInput i = AdaptionUtils.adaptToSingle(input, ExpressionWidgetInput.class);
125 variable = i.variable;
126 ExpressionType et = ExpressionTypes.getExpressionType(expr);
127 displayExpression(et.toString(), true);
131 * Displays IExpression corresponding to expressionType.
132 * @param expressionType Expression type
133 * @param original Is the displayed expression for a newly selected expression (true) or did the
134 * expression change its type (false)
136 public void displayExpression(String expressionType, boolean original) {
137 if(expressionType == null || parent.isDisposed()) {
141 // Get up-to-date data to data-map
142 if(this.expression != null) expression.updateData(data);
144 // Create the new expression
145 ExpressionType et = ExpressionType.valueOf(expressionType);
146 IExpression exp = null;
149 exp = new AuxiliaryExpression(input); break;
151 exp = new ParameterExpression(input); break;
153 exp = new ConstantExpression(input); break;
155 exp = new LookupExpression(); break;
157 exp = new WithLookupExpression(input); break;
159 exp = new StockExpression(input); break;
161 exp = new DelayExpression(input); break;
163 exp = new EmptyExpression();
167 // If expression was created, remove the old one
168 for(Control c : parent.getChildren()) {
172 // If a completely new expression was selected, read data
174 exp.readData(expr, data);
176 // Create the visual representation of the expression type
177 exp.createExpressionFields(parent, data, variableTable);
180 if(modifyListener != null)
181 exp.addModifyListener(modifyListener);
182 if(focusListener != null)
183 exp.addFocusListener(focusListener);
184 if(verifyKeyListener != null)
185 exp.addVerifyKeyListener(verifyKeyListener);
186 this.expression = exp;
187 this.parent.layout();
188 validateFieldsTimed();
195 * Get current IExpression
196 * @return current IExpression
198 public IExpression getExpression() {
203 * Set the variable table that contains information about variables that are connected
207 public void setVariableTable(Table table) {
208 this.variableTable = table;
212 * Set timed field validation with default delay time
214 public void validateFieldsTimed() {
215 validateFieldsTimed(VALIDATION_DELAY_TIME);
219 * Set timed field validation
220 * @param delay Delay time for validation
222 public void validateFieldsTimed(int delay) {
223 validationTimer.setDelay(delay);
224 if(!validationTimer.isRunning())
225 validationTimer.start();
227 validationTimer.restart();
231 * Validates expression fields in current IExpression
233 public void validateFields() {
234 if(this.variableTable == null) return;
237 // Find the variable for this experession
238 Resource variable = Simantics.getSession().syncRequest(new Read<Resource>() {
241 public Resource perform(ReadGraph graph) throws DatabaseException {
242 Layer0 l0 = Layer0.getInstance(graph);
243 return graph.getPossibleObject(expr, l0.PartOf);
246 // Validate the variable
248 ExpressionUtils.validateExpressionFields(variable, expression, variableTable, resourceManager);
249 } catch (DatabaseException e) {
255 public void addModifyListener(ModifyListener listener) {
256 this.modifyListener = listener;
259 public void addVerifyKeyListener(VerifyKeyListener listener) {
260 this.verifyKeyListener = listener;
263 public void addFocusListener(FocusListener listener) {
264 this.focusListener = listener;
268 if(this.expression != null)
269 this.expression.save(expr, data);