From be58863d9c781cbbf35fa7cea04deab990879899 Mon Sep 17 00:00:00 2001 From: lempinen Date: Wed, 16 Jun 2010 13:09:27 +0000 Subject: [PATCH] Equation view changed to tabbed property view git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@16180 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../ui/project/SysdynPerspectiveFactory.java | 2 +- .../sysdyn/ui/properties/EquationTab.java | 137 +++++- .../ui/properties/SysdynPropertyPage.java | 1 - .../widgets/ExpressionTypeWidget.java | 60 +-- .../properties/widgets/ExpressionTypes.java | 56 +++ .../properties/widgets/ExpressionWidget.java | 143 ++++++ .../ui/properties/widgets/NameWidget.java | 90 +++- .../properties/widgets/ShortcutTabWidget.java | 16 + .../ui/properties/widgets/UnitWidget.java | 74 ++- .../expressions/AuxiliaryExpression.java | 26 ++ .../widgets/expressions/BasicExpression.java | 145 ++++++ .../widgets/expressions/ColorManager.java | 43 ++ .../expressions/ConstantExpression.java | 25 + .../widgets/expressions/DelayExpression.java | 74 +++ .../widgets/expressions/EmptyExpression.java | 74 +++ .../widgets/expressions/ExpressionField.java | 187 ++++++++ .../ExpressionFieldConfiguration.java | 180 ++++++++ .../expressions/ExpressionValidation.java | 132 ++++++ .../widgets/expressions/IExpression.java | 33 ++ .../widgets/expressions/LookupChartInfo.java | 63 +++ .../widgets/expressions/LookupChartPanel.java | 152 ++++++ .../widgets/expressions/LookupExpression.java | 74 +++ .../expressions/LookupInputOutputTable.java | 202 ++++++++ .../widgets/expressions/LookupPopup.java | 435 ++++++++++++++++++ .../expressions/ParameterExpression.java | 29 ++ .../widgets/expressions/StockExpression.java | 216 +++++++++ .../expressions/WithLookupExpression.java | 227 +++++++++ 27 files changed, 2816 insertions(+), 80 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java index 4ced7a11..ae0d0534 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java @@ -35,7 +35,7 @@ public class SysdynPerspectiveFactory implements IPerspectiveFactory { IFolderLayout bottom1 = layout.createFolder("bottom1", IPageLayout.BOTTOM, 0.75f, editorArea); IFolderLayout bottom2 = layout.createFolder("bottom2", IPageLayout.LEFT, 0.4f, "bottom1"); - bottom1.addView("org.simantics.sysdyn.ui.equation.view"); + bottom1.addView("org.simantics.browsing.ui.graph.propertyView"); bottom1.addView(IConsoleConstants.ID_CONSOLE_VIEW); bottom1.addView("org.simantics.sysdyn.ui.configurationView"); bottom2.addView("org.simantics.sysdyn.ui.trend.view"); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java index 2c628aa7..9a0972ee 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EquationTab.java @@ -3,8 +3,20 @@ package org.simantics.sysdyn.ui.properties; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.IWorkbenchSite; import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory; @@ -13,6 +25,7 @@ import org.simantics.db.Builtins; import org.simantics.db.management.ISessionContext; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypeWidget; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionWidget; import org.simantics.sysdyn.ui.properties.widgets.NameWidget; import org.simantics.sysdyn.ui.properties.widgets.ShortcutTabWidget; import org.simantics.sysdyn.ui.properties.widgets.UnitWidget; @@ -20,23 +33,125 @@ import org.simantics.sysdyn.ui.properties.widgets.UnitWidget; public class EquationTab extends PropertyTabContributorImpl { static public final Font FONT = new Font(null, "Courier New", 12, SWT.NORMAL); - + + NameWidget nameWidget; + ExpressionTypeWidget expressionTypeWidget; + UnitWidget unitWidget; + ShortcutTabWidget shortcutTabWidget; + ExpressionWidget expressionWidget; + @Override public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, WidgetSupport support) { Composite composite = new Composite(body, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(composite); - GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(4).applyTo(composite); - NameWidget nameWidget = new NameWidget(composite, support, SWT.BORDER); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(6).applyTo(composite); + nameWidget = new NameWidget(composite, support, SWT.BORDER); nameWidget.setTextFactory(new StringPropertyFactory(context, Builtins.URIs.HasName)); - - @SuppressWarnings("unused") - ExpressionTypeWidget expressionTypeWidget = new ExpressionTypeWidget(composite, support, SWT.NONE); - - UnitWidget unitWidget = new UnitWidget(composite, support, SWT.NONE); + + + Label label = new Label(composite, SWT.SINGLE ); + label.setFont(EquationTab.FONT); + label.setText("Type:"); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + expressionTypeWidget = new ExpressionTypeWidget(composite, support, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); + + + label = new Label(composite, SWT.SINGLE ); + label.setFont(EquationTab.FONT); + label.setText("Unit:"); + GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); + + unitWidget = new UnitWidget(composite, support, SWT.DROP_DOWN | SWT.BORDER); unitWidget.setTextFactory(new StringPropertyFactory(context, SysdynResource.URIs.HasUnit)); + + shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE); + + + Composite expressionComposite = new Composite(composite, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).span(5, 1).applyTo(expressionComposite); + expressionWidget = new ExpressionWidget(expressionComposite, support, SWT.NONE); + + addListeners(); + } + + private void addListeners() { + + expressionTypeWidget.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + expressionWidget.displayExpression(expressionTypeWidget.getSelecetedType(), false); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + } + }); + + shortcutTabWidget.addMouseListener(new MouseListener(){ + + @Override + public void mouseDoubleClick(MouseEvent e) { + Table table = (Table)e.widget; + TableItem item = table.getItem(new Point(e.x, e.y)); + if(item != null) { + final String var = (String)item.getData(); + table.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(expressionWidget!= null) { + expressionWidget.getExpression().replaceSelection(var); + } + } + }); + } + } + + @Override + public void mouseDown(MouseEvent e) { + expressionWidget.getExpression().focus(); + } + + @Override + public void mouseUp(MouseEvent e) { + expressionWidget.getExpression().focus(); + } + + }); + shortcutTabWidget.addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + } + + @Override + public void focusLost(FocusEvent e) { + ((Table)e.widget).deselectAll(); + } + + }); + + expressionWidget.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + expressionWidget.validateFields(shortcutTabWidget.getVariableTable().getItems()); + } + }); - @SuppressWarnings("unused") - ShortcutTabWidget shortcutTabWidget = new ShortcutTabWidget(composite, support, SWT.NONE); - + expressionWidget.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent e) { + expressionWidget.save(); + } + + @Override + public void focusGained(FocusEvent e) { + expressionWidget.validateFields(shortcutTabWidget.getVariableTable().getItems()); + } + }); } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java index a3b0f8f6..7e042f2e 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/SysdynPropertyPage.java @@ -10,7 +10,6 @@ public class SysdynPropertyPage extends StandardPropertyPage { public SysdynPropertyPage(IWorkbenchPartSite site, Set set) { super(site, set); - System.out.println("sysdynpropertypage"); } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypeWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypeWidget.java index fb299a7d..ef1da39d 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypeWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypeWidget.java @@ -2,14 +2,12 @@ package org.simantics.sysdyn.ui.properties.widgets; import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; import org.simantics.browsing.ui.swt.widgets.impl.Widget; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; import org.simantics.db.ReadGraph; @@ -28,17 +26,8 @@ public class ExpressionTypeWidget implements Widget { public ExpressionTypeWidget(Composite parent, WidgetSupport support, int style) { support.register(this); - - Composite composite = new Composite(parent, style); - GridDataFactory.fillDefaults().applyTo(composite); - GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite); - Label label = new Label(composite, SWT.SINGLE ); - label.setFont(EquationTab.FONT); - label.setText("Type:"); - GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); - - typeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); + typeCombo = new Combo(parent, style); typeCombo.setFont(EquationTab.FONT); int columns = 6; @@ -55,6 +44,7 @@ public class ExpressionTypeWidget implements Widget { if(input instanceof IStructuredSelection) { final Resource variable = ISelectionUtils.filterSingleSelection((IStructuredSelection)input, Resource.class); if(variable != null) { + final ExpressionType et = ExpressionTypes.getExpressionTypeForVariable(variable); SimanticsUI.getSession().asyncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { @@ -69,40 +59,7 @@ public class ExpressionTypeWidget implements Widget { expressionTypes = ExpressionTypes.valveExpressions; else expressionTypes = new ExpressionType[] {}; - - - final ExpressionType et; - Resource expression = graph.getPossibleObject(variable, sr.HasExpression); - if(expression == null) { - if(graph.isInstanceOf(variable, sr.Auxiliary)) { - et = ExpressionType.Auxiliary; - } - else if(graph.isInstanceOf(variable, sr.Valve)) { - et = ExpressionType.Auxiliary; - } - else if(graph.isInstanceOf(variable, sr.Stock)) { - et = ExpressionType.Stock; - } else - et = ExpressionType.Empty; - } else { - if(graph.isInstanceOf(expression, sr.NormalExpression)) { - et = ExpressionType.Auxiliary; - } else if (graph.isInstanceOf(expression, sr.StockExpression)) { - et = ExpressionType.Stock; - } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) { - et = ExpressionType.Parameter; - } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) { - et = ExpressionType.Constant; - } else if (graph.isInstanceOf(expression, sr.DelayExpression)) { - et = ExpressionType.Delay; - } else if (graph.isInstanceOf(expression, sr.LookupExpression)) { - et = ExpressionType.Lookup; - } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) { - et = ExpressionType.WithLookup; - } else { - et = ExpressionType.Empty; - } - } + typeCombo.getDisplay().asyncExec(new Runnable() { @@ -135,4 +92,13 @@ public class ExpressionTypeWidget implements Widget { typeCombo.select(index); } } + + + public void addSelectionListener(SelectionListener listener) { + this.typeCombo.addSelectionListener(listener); + } + + public String getSelecetedType() { + return this.typeCombo.getItem(this.typeCombo.getSelectionIndex()); + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java index 4cebd8a7..fdc1f986 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionTypes.java @@ -1,5 +1,12 @@ package org.simantics.sysdyn.ui.properties.widgets; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + public class ExpressionTypes { public static enum ExpressionType {Auxiliary, Parameter, Constant, Lookup, WithLookup, Stock, Delay, Empty}; @@ -19,5 +26,54 @@ public class ExpressionTypes { public static ExpressionType[] stockExpressions = new ExpressionType[] { ExpressionType.Stock}; + + public static ExpressionType getExpressionTypeForVariable(final Resource variable) { + try { + return SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public ExpressionType perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + final ExpressionType et; + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if(expression == null) { + if(graph.isInstanceOf(variable, sr.Auxiliary)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Valve)) { + et = ExpressionType.Auxiliary; + } + else if(graph.isInstanceOf(variable, sr.Stock)) { + et = ExpressionType.Stock; + } else + et = ExpressionType.Empty; + } else { + if(graph.isInstanceOf(expression, sr.NormalExpression)) { + et = ExpressionType.Auxiliary; + } else if (graph.isInstanceOf(expression, sr.StockExpression)) { + et = ExpressionType.Stock; + } else if (graph.isInstanceOf(expression, sr.ParameterExpression)) { + et = ExpressionType.Parameter; + } else if (graph.isInstanceOf(expression, sr.ConstantExpression)) { + et = ExpressionType.Constant; + } else if (graph.isInstanceOf(expression, sr.DelayExpression)) { + et = ExpressionType.Delay; + } else if (graph.isInstanceOf(expression, sr.LookupExpression)) { + et = ExpressionType.Lookup; + } else if (graph.isInstanceOf(expression, sr.WithLookupExpression)) { + et = ExpressionType.WithLookup; + } else { + et = ExpressionType.Empty; + } + } + return et; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + return null; + } + + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java new file mode 100644 index 00000000..3aa6b563 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ExpressionWidget.java @@ -0,0 +1,143 @@ +package org.simantics.sysdyn.ui.properties.widgets; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.ui.properties.widgets.ExpressionTypes.ExpressionType; +import org.simantics.sysdyn.ui.properties.widgets.expressions.AuxiliaryExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ConstantExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.DelayExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.EmptyExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ExpressionValidation; +import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.ParameterExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.StockExpression; +import org.simantics.sysdyn.ui.properties.widgets.expressions.WithLookupExpression; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; + +public class ExpressionWidget implements Widget { + + private Resource variable; + private Composite parent; + private Map data; + private IExpression expression; + private ModifyListener modifyListener; + private FocusListener focusListener; + + + public ExpressionWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3).applyTo(parent); + this.parent = parent; + this.data = new HashMap(); + } + + @Override + public void setInput(Object input) { + if(input instanceof ISelection) { + ISelection selection = (ISelection)input; + if(selection instanceof IStructuredSelection) { + Resource resource = ISelectionUtils.filterSingleSelection(selection, Resource.class); + if(resource != null) { + variable = resource; + } + } + } + + ExpressionType et = ExpressionTypes.getExpressionTypeForVariable(variable); + + displayExpression(et.toString(), true); + } + + + public void displayExpression(String expressionType, boolean original) { + if(expressionType == null) + return; + + if(this.expression != null) expression.updateData(data); + ExpressionType et = ExpressionType.valueOf(expressionType); + IExpression exp = null; + switch (et) { + case Auxiliary: + exp = new AuxiliaryExpression(); break; + case Parameter: + exp = new ParameterExpression(); break; + case Constant: + exp = new ConstantExpression(); break; + case Lookup: + exp = new LookupExpression(); break; + case WithLookup: + exp = new WithLookupExpression(variable); break; + case Stock: + exp = new StockExpression(); break; + case Delay: + exp = new DelayExpression(); break; + default: + exp = new EmptyExpression(); + } + + if (exp != null) { + for(Control c : parent.getChildren()) { + c.dispose(); + } + + if(original) + exp.readData(variable, data); + + exp.createExpressionFields(parent, data); + exp.addModifyListener(modifyListener); + exp.addFocusListener(focusListener); + this.expression = exp; + this.parent.layout(); + } + } + + public IExpression getExpression() { + return expression; + } + + public void validateFields(TableItem[] connectedVariables) { + try { + final Resource configuration = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + Resource configuration = graph.getSingleObject(variable, graph.getBuiltins().PartOf); + return configuration; + } + }); + ExpressionValidation.validateExpressionFields(expression, connectedVariables, configuration); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + } + + public void addModifyListener(ModifyListener listener) { + this.modifyListener = listener; + } + + public void addFocusListener(FocusListener listener) { + this.focusListener = listener; + } + + public void save() { + this.expression.save(variable, data); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/NameWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/NameWidget.java index ca645a7c..4f645252 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/NameWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/NameWidget.java @@ -1,7 +1,12 @@ package org.simantics.sysdyn.ui.properties.widgets; +import java.util.ArrayList; + import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.viewers.ISelection; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyEvent; @@ -13,14 +18,30 @@ import org.eclipse.swt.widgets.Text; import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory; import org.simantics.browsing.ui.swt.widgets.impl.Widget; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.Variable; import org.simantics.sysdyn.ui.properties.EquationTab; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.ui.ISelectionUtils; public class NameWidget implements Widget { - final private org.eclipse.swt.widgets.Text nameText; - String originalName = ""; + private org.eclipse.swt.widgets.Text nameText; + private String originalName = ""; private ReadFactory textFactory; + private Resource variable; + private Resource configuration; public NameWidget(Composite parent, WidgetSupport support, int style) { support.register(this); @@ -45,8 +66,11 @@ public class NameWidget implements Widget { @Override public void modifyText(ModifyEvent e) { - if(((Text)e.widget).getText().contains(" ")) { - ((Text)e.widget).setText(originalName); + Text t = (Text) e.widget; + String txt = t.getText(); + // Don't allow this to produce an eternal loop + if (!txt.equals(originalName) && txt.contains(" ")) { + t.setText(originalName); } } }); @@ -66,11 +90,28 @@ public class NameWidget implements Widget { } } }); + + nameText.addFocusListener(new FocusAdapter() { + public void focusLost(FocusEvent e) { + save(); + } + }); } @Override public void setInput(Object input) { - + if(input instanceof ISelection) { + variable = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); + SimanticsUI.getSession().asyncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + configuration = graph.getSingleObject(variable, graph.getBuiltins().PartOf); + } + }); + + + } if(textFactory != null) { textFactory.listen(input, new Listener() { @@ -91,6 +132,7 @@ public class NameWidget implements Widget { if(isDisposed()) return; nameText.setText(text); + originalName = text; } @@ -112,4 +154,42 @@ public class NameWidget implements Widget { } + public void save() { + final String nameNew = this.nameText.getText(); + if(nameNew != null && !nameNew.equals(this.originalName) && variable != null) { + SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); + SysdynModel model = sdm.getModel(configuration); + Configuration conf = model.getConfiguration(); + IElement thisElement = model.getElement(variable); + ArrayList elements = conf.elements; + for(IElement e : elements) { + if(e instanceof Variable) { + Variable v = (Variable)e; + if(v != thisElement && v.getName().equals(this.nameText.getText())) { + this.nameText.setText(this.originalName); + this.nameText.setSelection(this.originalName.length()); + return; + } + } + } + + + + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + Builtins b = g.getBuiltins(); + g.claimValue(variable, b.HasName, nameNew); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java index 1de6fb4f..a8cd943d 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java @@ -7,6 +7,8 @@ import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; @@ -121,6 +123,20 @@ public class ShortcutTabWidget implements Widget { return variables; } + + public void addFocusListener(FocusListener listener) { + this.functionTable.addFocusListener(listener); + this.variableTable.addFocusListener(listener); + } + + public void addMouseListener(MouseListener listener) { + this.functionTable.addMouseListener(listener); + this.variableTable.addMouseListener(listener); + } + + public Table getVariableTable() { + return variableTable; + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/UnitWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/UnitWidget.java index c93676fd..c5ef7732 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/UnitWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/UnitWidget.java @@ -4,21 +4,25 @@ import java.util.ArrayList; import java.util.Collection; import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory; import org.simantics.browsing.ui.swt.widgets.impl.Widget; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; import org.simantics.db.Builtins; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.db.request.Read; @@ -32,22 +36,13 @@ public class UnitWidget implements Widget { Combo unitCombo; private ReadFactory textFactory; + Resource variable; + String unit; public UnitWidget(Composite parent, WidgetSupport support, int style) { support.register(this); - Composite composite = new Composite(parent, style); - GridDataFactory.fillDefaults().applyTo(composite); - GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite); - - Label label = new Label(composite, SWT.SINGLE ); - label.setFont(EquationTab.FONT); - label.setText("Unit:"); - //label.setAlignment(SWT.RIGHT); - GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label); - - - unitCombo = new Combo(composite, SWT.DROP_DOWN | SWT.BORDER); + unitCombo = new Combo(parent, style); unitCombo.setFont(EquationTab.FONT); int columns = 6; @@ -57,6 +52,27 @@ public class UnitWidget implements Widget { int height = fm.getHeight (); gc.dispose (); GridDataFactory.fillDefaults().hint(unitCombo.computeSize(width, height)).applyTo(unitCombo); + + unitCombo.addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.ESC && unit != null) { + ((Combo)e.widget).setText(unit); + } + } + }); + + unitCombo.addFocusListener(new FocusAdapter() { + public void focusLost(FocusEvent e) { + save(); + } + }); } public void setTextFactory(ReadFactory textFactory) { @@ -65,6 +81,8 @@ public class UnitWidget implements Widget { @Override public void setInput(final Object input) { + if(input instanceof ISelection) + variable = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); if(textFactory != null) { textFactory.listen(input, new Listener() { @@ -95,8 +113,10 @@ public class UnitWidget implements Widget { if(unitCombo.indexOf(text) >= 0) unitCombo.select(unitCombo.indexOf(text)); - else + else unitCombo.setText(text); + unit = text; + } }); @@ -151,4 +171,28 @@ public class UnitWidget implements Widget { } return units; } + + public void save() { + final String unitNew = unitCombo.getText(); + + if(unitNew != null && !unitNew.equals(unit) && variable != null) { + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + if (!unitNew.equals("")) { + g.claimValue(variable, sr.HasUnit, unitNew); + } + else if (g.getPossibleRelatedValue(variable, sr.HasUnit) != null) + g.deny(variable, sr.HasUnit); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java new file mode 100644 index 00000000..2f4c1906 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/AuxiliaryExpression.java @@ -0,0 +1,26 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class AuxiliaryExpression extends BasicExpression { + + public AuxiliaryExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).NormalExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java new file mode 100644 index 00000000..ac5b56bc --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/BasicExpression.java @@ -0,0 +1,145 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.EquationTab; +import org.simantics.ui.SimanticsUI; + +public class BasicExpression implements IExpression { + + ExpressionField expression; + Resource expressionType; + + @Override + public void createExpressionFields(Composite parent, Map data) { + String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + + Label l = new Label(parent, SWT.NONE); + l.setFont(EquationTab.FONT); + l.setText("="); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + + @Override + public void readData(final Resource variable, Map data) { + String equation = null; + if (variable != null && data.get("equation") == null && expressionType != null) { + try { + equation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, expressionType)) { + return graph.getRelatedValue(expression, sr.HasEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", equation); + } + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null && expressionType != null) { + data.put("equation", currentText); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, expressionType); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentText); + } + + }); + } + expression.setExpression(currentText); + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java new file mode 100644 index 00000000..9a733b98 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ColorManager.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.HashMap; + +import org.eclipse.jface.text.source.ISharedTextColors; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +public class ColorManager implements ISharedTextColors { + + protected HashMap colorTable = new HashMap(); + + @Override + public void dispose() { + for(Color c : colorTable.values()) + c.dispose(); + colorTable.clear(); + } + + @Override + public Color getColor(RGB rgb) { + Color color = colorTable.get(rgb); + if (color == null) { + color = new Color(Display.getCurrent(), rgb); + colorTable.put(rgb, color); + } + return color; + + + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java new file mode 100644 index 00000000..a0b52542 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ConstantExpression.java @@ -0,0 +1,25 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ConstantExpression extends BasicExpression { + + public ConstantExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).ConstantExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java new file mode 100644 index 00000000..8c9eb5de --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/DelayExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class DelayExpression implements IExpression { + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java new file mode 100644 index 00000000..f2a99fd3 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/EmptyExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class EmptyExpression implements IExpression { + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java new file mode 100644 index 00000000..d564d062 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionField.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.PaintManager; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.AnnotationPainter; +import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; +import org.eclipse.jface.text.source.IAnnotationAccess; +import org.eclipse.jface.text.source.MatchingCharacterPainter; +import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; +import org.eclipse.swt.graphics.Point; +import org.simantics.sysdyn.expressionParser.Token; + +public class ExpressionField extends Composite { + + protected SourceViewer _sourceViewer; + protected IDocument _document; + protected AnnotationModel _annotationModel; + + String oldExpression; + + ColorManager cManager = new ColorManager(); + + IAnnotationAccess annotationAccess = new DefaultMarkerAnnotationAccess(); + + public ExpressionField(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + + int styles = SWT.V_SCROLL + | SWT.MULTI + | SWT.FULL_SELECTION + | SWT.WRAP; + + _document = new Document(); + _document.set(""); + + _annotationModel = new AnnotationModel(); + _annotationModel.connect(_document); + + _sourceViewer = new SourceViewer(this, + + null, + null, + true, + styles); + _sourceViewer.configure(new ExpressionFieldConfiguration(cManager)); + + AnnotationPainter painter = new AnnotationPainter(_sourceViewer, annotationAccess); + _sourceViewer.addPainter(painter); + + painter.addAnnotationType("MissingLink"); + painter.setAnnotationTypeColor("MissingLink", new Color(this.getDisplay(), 255,0,0)); + painter.addAnnotationType("NoSuchVariable"); + painter.setAnnotationTypeColor("NoSuchVariable", new Color(this.getDisplay(), 255,0,0)); + + _sourceViewer.setDocument(_document, _annotationModel); + + GridDataFactory.fillDefaults().grab(true, true).applyTo(_sourceViewer.getControl()); +// _sourceViewer.getControl().setLayoutData(new GridData(SWT.FILL, +// SWT.FILL, +// true, +// true)); + + PaintManager paintManager = new PaintManager(_sourceViewer); + MatchingCharacterPainter matchingCharacterPainter = new MatchingCharacterPainter(_sourceViewer, + new DefaultCharacterPairMatcher( new char[] {'(', ')', '{', '}', '[', ']'} )); + matchingCharacterPainter.setColor(new Color(Display.getCurrent(), new RGB(160, 160, 160))); + paintManager.addPainter(matchingCharacterPainter); + + + _sourceViewer.getTextWidget().addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.ESC && getExpression() != null) { + ((StyledText)e.widget).setText(oldExpression); + ((StyledText)e.widget).setSelection(getExpression().length()); + } + } + }); + + } + + public SourceViewer getSourceViewer() { + return this._sourceViewer; + } + + public void setMissingLinkAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("No link to this variable"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setNoSuchVariableAnnotations(List positions){ + for(Position p : positions) { + Annotation annotation = new Annotation(false); + annotation.setType("NoSuchVariable"); + annotation.setText("No such variable in model"); + _annotationModel.addAnnotation(annotation, p); + } + } + + public void setSyntaxError(Token token){ + int start = 0; + int offset = this._document.getLength(); + if(token.image != null && this._document.getLength() > 0) { + try { + start = this._document.getLineOffset(token.beginLine - 1) + token.beginColumn - 1; + offset = this._document.getLineOffset(token.endLine - 1) + token.endColumn - start; + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + Annotation annotation = new Annotation(false); + annotation.setType("MissingLink"); + annotation.setText("Syntax error"); + Position p = new Position(start, offset); + _annotationModel.addAnnotation(annotation, p); + } + + public void resetAnnotations() { + _annotationModel.removeAllAnnotations(); + } + public void setExpression(String expression) { + _document.set(expression); + this.oldExpression = expression; + } + + public String getExpression() { + return this._document.get(); + } + + public Point getSelection() { + return _sourceViewer.getSelectedRange(); + } + + public void setSelection(int selection) { + this._sourceViewer.setSelectedRange(selection, 0); + } + + public IDocument getDocument() { + return _document; + } + + public void focus() { + this._sourceViewer.getTextWidget().forceFocus(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java new file mode 100644 index 00000000..68d46d86 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionFieldConfiguration.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.text.DefaultTextHover; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.ITokenScanner; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.RuleBasedScanner; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; +import org.eclipse.jface.text.source.DefaultAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; + +public class ExpressionFieldConfiguration extends SourceViewerConfiguration { + + + ColorManager colorManager; + + public ExpressionFieldConfiguration(ColorManager colorManager) { + super(); + this.colorManager = colorManager; + } + + public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) { + return new String[] { + IDocument.DEFAULT_CONTENT_TYPE + }; + } + + /* + @Override + public IAutoEditStrategy[] getAutoEditStrategies( + ISourceViewer sourceViewer, String contentType) { + return new IAutoEditStrategy[] { + new ReplaceTabsBySpaces(), + new IndentLineEditStrategy(), + new MatchingBracketsEditStrategy() + }; + } + */ + + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getSclTokenScanner()); + + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + + return reconciler; + } + + /* + * + */ + ITokenScanner getSclTokenScanner() { + RuleBasedScanner scanner = new RuleBasedScanner(); + + final Token reserved = new Token( + new TextAttribute( + colorManager.getColor(new RGB(127, 0, 85)), + null, + SWT.BOLD + )); + + + WordRule reservedWord = new WordRule(new IWordDetector() { + @Override + public boolean isWordStart(char c) { + return Character.isLetter(c); + } + + @Override + public boolean isWordPart(char c) { + return Character.isLetter(c); + } + }); + + for(String s : keywords) { + reservedWord.addWord(s, reserved); + } + + IRule[] rules = new IRule[] { + reservedWord + }; + scanner.setRules(rules); + + return scanner; + } + + @Override + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + return new DefaultTextHover(sourceViewer); + } + + @Override + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new DefaultAnnotationHover(); + } + + static final Set keywords = new HashSet(); + + static { + keywords.add("within"); + keywords.add("final"); + keywords.add("public"); + keywords.add("protected"); + keywords.add("connect"); + keywords.add("when"); + keywords.add("then"); + keywords.add("elsewhen"); + keywords.add("if"); + keywords.add("end"); + keywords.add("elseif"); + keywords.add("else"); + keywords.add("for"); + keywords.add("while"); + keywords.add("loop"); + keywords.add("der"); + keywords.add("enumeration"); + keywords.add("extends"); + keywords.add("class"); + keywords.add("partial"); + keywords.add("encapsulated"); + keywords.add("model"); + keywords.add("record"); + keywords.add("block"); + keywords.add("expandable"); + keywords.add("connector"); + keywords.add("type"); + keywords.add("package"); + keywords.add("function"); + keywords.add("import"); + keywords.add("external"); + keywords.add("constrainedby"); + keywords.add("redeclare"); + keywords.add("replaceable"); + keywords.add("flow"); + keywords.add("discrete"); + keywords.add("parameter"); + keywords.add("constant"); + keywords.add("input"); + keywords.add("output"); + keywords.add("annotation"); + keywords.add("false"); + keywords.add("true"); + keywords.add("each"); + keywords.add("initial"); + keywords.add("algorithm"); + keywords.add("equation"); + keywords.add("or"); + keywords.add("and"); + keywords.add("not"); + keywords.add("break"); + keywords.add("return"); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java new file mode 100644 index 00000000..a4448215 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ExpressionValidation.java @@ -0,0 +1,132 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.text.Position; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.TableItem; +import org.simantics.db.Resource; +import org.simantics.sysdyn.expressionParser.ExpressionParser; +import org.simantics.sysdyn.expressionParser.ParseException; +import org.simantics.sysdyn.expressionParser.Token; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.representation.Configuration; +import org.simantics.sysdyn.representation.IElement; +import org.simantics.sysdyn.representation.Variable; +import org.simantics.sysdyn.ui.properties.widgets.expressions.IExpression; +import org.simantics.ui.SimanticsUI; + +public class ExpressionValidation { + + static public void validateExpressionFields(IExpression expression, TableItem[] connectedVariables, Resource configuration) { + ExpressionParser parser = new ExpressionParser(new StringReader("")); + Set variables = new HashSet(); + HashMap>> references = new HashMap>>(); + + + // Build references and variable array + for(ExpressionField ef : expression.getExpressionFields()) { + ef.resetAnnotations(); + String textString = ef.getExpression(); + parser.ReInit(new StringReader(textString)); + try { + parser.expr(); + HashMap> cr = parser.getReferences(); + references.put(ef, cr); + for(String t : cr.keySet()) + variables.add(t); + } catch (ParseException e1) { + ef.setSyntaxError(e1.currentToken); + } + } + + // Remove variables from variable array that don't exist in the model. Create annotations + if(!variables.isEmpty()) { + ArrayList modelVariables = new ArrayList(); + Set noSuchVariables = new HashSet(); + SysdynModelManager sdm = SysdynModelManager.getInstance(SimanticsUI.getSession()); + SysdynModel model = sdm.getModel(configuration); + Configuration conf = model.getConfiguration(); + ArrayList elements = conf.elements; + for(IElement e : elements) { + if(e instanceof Variable) { + Variable v = (Variable) e; + modelVariables.add(v.getName()); + } + } + + + for(String v : variables) { + if(!modelVariables.contains(v)) { + noSuchVariables.add(v); + } + } + + if(!noSuchVariables.isEmpty()) { + // remove no such variables from variable list + for(String s : noSuchVariables) + variables.remove(s); + // create annotations + HashMap> positions = getPositionsForVariables(references, noSuchVariables); + for(ExpressionField ef : positions.keySet()) { + ef.setNoSuchVariableAnnotations(positions.get(ef)); + } + } + } + + // Check that the variables that exist have connections and the connected variables have references in the expressions + if(!(expression instanceof StockExpression)) { + for(TableItem ti : connectedVariables) { + if(!variables.contains(ti.getText())) { + ti.setForeground(new Color(ti.getDisplay(), 255, 0, 0)); + } else { + ti.setForeground(new Color(ti.getDisplay(), 0, 0, 0)); + variables.remove(ti.getText()); + } + } + + if(!variables.isEmpty()) { + HashMap> positions = getPositionsForVariables(references, variables); + for(ExpressionField ef : positions.keySet()) { + ef.setMissingLinkAnnotations(positions.get(ef)); + } + + } + } + + } + + @SuppressWarnings("unchecked") + static private HashMap> getPositionsForVariables(HashMap>> references, Set variables) { + HashMap> result = new HashMap>(); + for(String s : variables) { + List tlist = new ArrayList(); + for(ExpressionField ef : references.keySet()) { + ArrayList positions = new ArrayList(); + tlist = references.get(ef).get(s); + if(tlist != null) + for(Token t : tlist) { + StyledText st = ef.getSourceViewer().getTextWidget(); + int start = st.getOffsetAtLine(t.beginLine - 1) + t.beginColumn - 1; + int offset = st.getOffsetAtLine(t.endLine - 1) + t.endColumn - start; + positions.add(new Position( + start, + offset)); + } + if(result.keySet().contains(ef)) { + result.get(ef).addAll((ArrayList)positions.clone()); + } else { + result.put(ef, (ArrayList)positions.clone()); + } + } + } + return result; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java new file mode 100644 index 00000000..6c8c152c --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/IExpression.java @@ -0,0 +1,33 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public interface IExpression { + + public void createExpressionFields(Composite parent, Map data); + + public void readData(final Resource variable, Map data); + + public void save(final Resource variable, Map data); + + public void focus(); + + public void replaceSelection(String var); + + public void updateData(Map data); + + public List getExpressionFields(); + + public void addModifyListener(ModifyListener listener); + + public void addKeyListener(KeyListener listener); + + public void addFocusListener(FocusListener listener); +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java new file mode 100644 index 00000000..e556d048 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartInfo.java @@ -0,0 +1,63 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Map; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class LookupChartInfo { + + String lookupTable, expression; + Double minX, maxX, minY, maxY; + + private static Double MINX = 0.0; + private static Double MAXX = 10.0; + private static Double MINY = 0.0; + private static Double MAXY = 10.0; + + public LookupChartInfo(String expression, String lookupTable, final Resource variable, Map data) { + this.lookupTable = lookupTable != null ? lookupTable : ""; + this.expression = expression != null ? expression : ""; + this.minX = (Double)data.get("minX"); + this.maxX = (Double)data.get("maxX"); + this.minY = (Double)data.get("minY"); + this.maxY = (Double)data.get("maxY"); + if(variable != null && (minX == null || maxX == null || minY == null || maxY == null)) { + try { + SimanticsUI.getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if(expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + minX = graph.getPossibleRelatedValue(expression, sr.HasMinX); + if(minX == null) minX = MINX; + maxX = graph.getPossibleRelatedValue(expression, sr.HasMaxX); + if(maxX == null) maxX = MAXX; + minY = graph.getPossibleRelatedValue(expression, sr.HasMinY); + if(minY == null) minY = MINY; + maxY = graph.getPossibleRelatedValue(expression, sr.HasMaxY); + if(maxY == null) maxY = MAXY; + } else { + defaultValues(); + } + + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } + + private void defaultValues() { + minX = MINX; + maxX = MAXX; + minY = MINY; + maxY = MAXY; + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java new file mode 100644 index 00000000..21224331 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupChartPanel.java @@ -0,0 +1,152 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartRenderingInfo; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.entity.ChartEntity; +import org.jfree.chart.entity.PlotEntity; +import org.jfree.chart.entity.XYItemEntity; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +@SuppressWarnings("serial") +public class LookupChartPanel extends ChartPanel { + + private XYItemEntity dragPrevEntity; + private boolean drawing; + private XYSeries series; + private JFreeChart chart; + private LookupInputOutputTable table; + + public LookupChartPanel(JFreeChart chart) { + super(chart); + this.chart = chart; + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + series = collection.getSeries(0); + } + + public void setTable(LookupInputOutputTable table) { + this.table = table; + } + + public void mouseDragged(MouseEvent e) + { + if(dragPrevEntity != null) { + + int item = dragPrevEntity.getItem(); + XYPlot plot = (XYPlot)chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + Point2D location = getLocationOnChart(getMouseLocation(e)); + Number prevX = item == 0 ? null : series.getX(item - 1); + Number nextX = item == series.getItemCount() - 1 ? null : series.getX(item + 1); + + + if(series.indexOf(location.getX()) >= 0 && series.indexOf(location.getX()) != item) + return; + else if (prevX != null && location.getX() < prevX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (nextX != null && location.getX() > nextX.doubleValue()) + location.setLocation(series.getX(item).doubleValue(), location.getY()); + else if (location.getX() > domainAxis.getUpperBound()) + location.setLocation(domainAxis.getUpperBound(), location.getY()); + else if (location.getX() < domainAxis.getLowerBound()) + location.setLocation(domainAxis.getLowerBound(), location.getY()); + + if (location.getY() > rangeAxis.getUpperBound()) + location.setLocation(location.getX(), rangeAxis.getUpperBound()); + else if (location.getY() < rangeAxis.getLowerBound()) + location.setLocation(location.getX(), rangeAxis.getLowerBound()); + + removeItemFromSeries(dragPrevEntity.getItem()); + addLocationToSeries(location); + } else { + ChartEntity currEntity = this.getEntityForPoint(e.getX(),e.getY()); + if(!drawing && currEntity instanceof XYItemEntity) { + dragPrevEntity = ((XYItemEntity)currEntity); + } else if (currEntity instanceof PlotEntity){ + drawing = true; + Point2D locationOnChart = getLocationOnChart(getMouseLocation(e)); + int item = series.indexOf(locationOnChart.getX()); + if (item >= 0) { + Point2D location = new Point2D.Double(series.getX(item).doubleValue(), series.getY(item).doubleValue()); + Point2D javaLocation = getLocationOnJava2D(location); + removeItemFromSeries(item); + addLocationToSeries(getLocationOnChart(new Point2D.Double(javaLocation.getX(), e.getY()))); + } + } + } + + } + + public void mouseReleased(MouseEvent e) { + + dragPrevEntity = null; + drawing = false; + } + + public void mouseClicked(MouseEvent e) + { + if(e.getButton() == MouseEvent.BUTTON1) { + addLocationToSeries(getLocationOnChart(getMouseLocation(e))); + } else if (e.getButton() == MouseEvent.BUTTON3) { + ChartEntity entity = this.getEntityForPoint(e.getX(),e.getY()); + if(entity instanceof XYItemEntity) { + XYItemEntity xyentity = ((XYItemEntity)entity); + removeItemFromSeries(xyentity.getItem()); + } + } + } + + private Point2D getLocationOnChart(Point2D coordinates) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double chartX = plot.getDomainAxis().java2DToValue(coordinates.getX(), dataArea, + plot.getDomainAxisEdge()); + double chartY = plot.getRangeAxis().java2DToValue(coordinates.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(chartX, chartY); + } + + private Point2D getLocationOnJava2D(Point2D location) { + XYPlot plot = (XYPlot)chart.getPlot(); + ChartRenderingInfo info = getChartRenderingInfo(); + Rectangle2D dataArea = info.getPlotInfo().getDataArea(); + double javaX = plot.getDomainAxis().valueToJava2D(location.getX(), dataArea, + plot.getDomainAxisEdge()); + double javaY = plot.getRangeAxis().valueToJava2D(location.getY(), dataArea, + plot.getRangeAxisEdge()); + return new Point2D.Double(javaX, javaY); + } + + public void addLocationToSeries(Point2D location) { + if(series.indexOf(location.getX()) < 0) { + series.add(location.getX(), location.getY()); + table.addLocation(location); + } + } + + public void removeItemFromSeries(int item){ + Point2D location = new Point2D.Double(series.getX(item).doubleValue(),series.getY(item).doubleValue()); + series.remove(item); + table.removeLocation(location); + } + + private Point2D getMouseLocation(MouseEvent e) { + int mouseX = e.getX(); + int mouseY = e.getY(); + Point2D p = translateScreenToJava2D( + new Point(mouseX, mouseY)); + return p; + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java new file mode 100644 index 00000000..4bb7fb32 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupExpression.java @@ -0,0 +1,74 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.List; +import java.util.Map; + +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.widgets.Composite; +import org.simantics.db.Resource; + +public class LookupExpression implements IExpression { + + @Override + public void focus() { + // TODO Auto-generated method stub + + } + + @Override + public List getExpressionFields() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void readData(final Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void replaceSelection(String var) { + // TODO Auto-generated method stub + + } + + @Override + public void save(final Resource variable, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void updateData(Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void createExpressionFields(Composite parent, Map data) { + // TODO Auto-generated method stub + + } + + @Override + public void addKeyListener(KeyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addModifyListener(ModifyListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFocusListener(FocusListener listener) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java new file mode 100644 index 00000000..9ed5030f --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupInputOutputTable.java @@ -0,0 +1,202 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +public class LookupInputOutputTable extends Composite { + + public static final String INPUT = "Input"; + public static final String OUTPUT = "Output"; + public static final String[] PROPS = { INPUT, OUTPUT }; + + Table table; + TableViewer tableViewer; + List tableRows; + + public LookupInputOutputTable(Composite parent, int style) { + super(parent, style); + + GridLayoutFactory.fillDefaults().applyTo(this); + GridDataFactory.fillDefaults().grab(true, true).applyTo(this); + table = new Table(this, SWT.BORDER|SWT.SINGLE|SWT.FULL_SELECTION); + GridDataFactory.fillDefaults().grab(true, true).applyTo(table); + table.setHeaderVisible (true); + table.setLinesVisible(true); + table.getVerticalBar().setVisible(true); + TableColumn column1 = new TableColumn (table, SWT.LEFT); + column1.setText (INPUT); + column1.setWidth (85); + + TableColumn column2 = new TableColumn (table, SWT.LEFT); + column2.setText (OUTPUT); + column2.setWidth (85); + + // Create the viewer and connect it to the view + tableViewer = new TableViewer (table); + + tableViewer.setContentProvider (new ArrayContentProvider()); + tableViewer.setLabelProvider (new InputOutputLabelProvider()); + + tableRows = new ArrayList(); + tableViewer.setInput(tableRows); + + CellEditor[] editors = new CellEditor[2]; + editors[0] = new TextCellEditor(table); + editors[1] = new TextCellEditor(table); + tableViewer.setCellEditors(editors); + tableViewer.setColumnProperties(PROPS); + + } + + private class InputOutputLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage (Object element, int columnIndex) { + return null; + } + public String getColumnText (Object element, int columnIndex) { + if(element instanceof InputOutput) { + InputOutput io = (InputOutput)element; + switch (columnIndex) { + case 0: return (String)io.getInput(String.class); + case 1: return (String)io.getOutput(String.class); + } + } + return ""; + } + } + + public void addLocation(Point2D location) { + tableRows.add(new InputOutput(location.getX(), location.getY())); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + + } + + public void removeLocation(Point2D location) { + for(InputOutput io : tableRows) { + if((Double)io.getInput(Double.class) == location.getX()) { + tableRows.remove(io); + tableViewer.getTable().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + refresh(); + } + }); + break; + } + } + + } + + + class InputOutput { + private double input, output; + + public InputOutput(double input, double output) { + this.input = input; + this.output = output; + } + + /** + * + * @param clazz String.class or Double.class + * @return input as string or double or null if asked for something else + */ + @SuppressWarnings("unchecked") + public Object getInput(Class clazz) { + if(clazz == String.class) { + return "" + input; + } else if (clazz == Double.class) { + return input; + } + return null; + } + + public Double setInput(String input) { + try { + this.input = Double.parseDouble(input); + return this.input; + } catch (NumberFormatException e) { + return null; + } + } + + public void setInput(double input) { + this.input = input; + } + + /** + * + * @param clazz String.class or Double.class + * @return output as string or double or null if asked for something else + */ + @SuppressWarnings("unchecked") + public Object getOutput(Class clazz) { + if(clazz == String.class) { + return "" + output; + } else if (clazz == Double.class) { + return output; + } + return null; + } + + public void setOutput(String output) { + try { + this.output = Double.parseDouble(output); + } catch (NumberFormatException e) { + + } + } + + public void setOutput(double output) { + this.output = output; + } + + } + + class InputOutputComparator extends ViewerComparator { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if ((e1 instanceof InputOutput) && + (e2 instanceof InputOutput)) { + InputOutput io1 = (InputOutput)e1; + InputOutput io2 = (InputOutput)e2; + Double d1 = (Double)io1.getInput((Double.class)); + Double d2 = (Double)io2.getInput((Double.class)); + return d1.compareTo(d2); + } + return 0; + } + } + + public TableViewer getTableViewer() { + return this.tableViewer; + } + + public void refresh() { + tableViewer.setComparator(new InputOutputComparator()); + tableViewer.refresh(); + } +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java new file mode 100644 index 00000000..c7d3cfdd --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/LookupPopup.java @@ -0,0 +1,435 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.event.MouseEvent; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Iterator; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYDataset; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.simantics.g2d.chassis.SWTAWTComponent; +import org.simantics.sysdyn.tableParser.ParseException; +import org.simantics.sysdyn.tableParser.Token; +import org.simantics.sysdyn.tableParser.TableParser; +import org.simantics.sysdyn.ui.properties.widgets.expressions.LookupInputOutputTable.InputOutput; + +public class LookupPopup extends Dialog { + + JFreeChart chart; + LookupInputOutputTable table; + ArrayList dataPoints; + Text input, output; + Text minX, maxX, minY, maxY; + Label unit; + LookupChartInfo chartInfo; + + protected LookupPopup(Shell parentShell, LookupChartInfo chartInfo) { + super(parentShell); + this.chartInfo = chartInfo; + this.dataPoints = new ArrayList(); + TableParser parser = new TableParser(new StringReader("")); + parser.ReInit(new StringReader(chartInfo.lookupTable)); + try { + parser.table(); + ArrayList xTokens = parser.getXTokens(); + for(Token token : xTokens) { + dataPoints.add(new Point2D.Double( + Double.parseDouble(token.image), + Double.parseDouble(token.next.next.image))); + } + } catch (ParseException e1) { + } + + } + + @Override + protected Control createDialogArea(Composite parent) { + KeyListener enterListener = new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) {} + + @Override + public void keyPressed(KeyEvent e) { + if(e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) + getButton(IDialogConstants.OK_ID).forceFocus(); + } + }; + + final LookupChartPanel chartPanel = new LookupChartPanel(createChart()); + chartPanel.setPreferredSize(new java.awt.Dimension(500, 270)); + chartPanel.setMouseZoomable(true, false); + chartPanel.setDomainZoomable(false); + chartPanel.setRangeZoomable(false); + + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + + Composite container = new Composite(parent, SWT.None); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(container); + + Composite yAxis = new Composite(container, SWT.NONE); + GridLayoutFactory.fillDefaults().applyTo(yAxis); + GridDataFactory.fillDefaults().grab(false, true).applyTo(yAxis); + maxY = new Text(yAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxY); + maxY.addKeyListener(enterListener); + maxY.addModifyListener(getAxisBoundModifyListener()); + maxY.setText("" + rangeAxis.getUpperBound()); + Composite fillY = new Composite(yAxis, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(false, true).applyTo(fillY); + GridLayoutFactory.fillDefaults().applyTo(fillY); + unit = new Label(fillY, SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(unit); + unit.setText(""); //TODO: how to get and update units? + unit.addKeyListener(enterListener); + minY = new Text(yAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minY); + minY.addKeyListener(enterListener); + minY.addModifyListener(getAxisBoundModifyListener()); + minY.setText("" + rangeAxis.getLowerBound()); + + SWTAWTComponent c = new SWTAWTComponent(container, SWT.BORDER) { + @Override + protected JComponent createSwingComponent() { + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(1, 1)); + panel.setPreferredSize(new java.awt.Dimension(500, 270)); + panel.add(chartPanel); + panel.doLayout(); + return panel; + } + }; + GridDataFactory.fillDefaults().hint(500, 300).applyTo(c); + c.populate(); + + + Composite valueTableComposite = new Composite(container, SWT.NONE); + GridDataFactory.fillDefaults().span(1, 2).grab(true, true).applyTo(valueTableComposite); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(valueTableComposite); + + + table = new LookupInputOutputTable(valueTableComposite, SWT.NONE); + GridDataFactory.fillDefaults().span(3, 1).grab(true, true).applyTo(table); + chartPanel.setTable(table); + table.getTableViewer().setCellModifier(new InputOutputCellModifier()); + table.getTableViewer().getTable().addMouseListener(new MouseListener() { + + @Override + public void mouseUp(org.eclipse.swt.events.MouseEvent e) { + if(e.button == MouseEvent.BUTTON3) { + Table table = (Table)e.widget; + TableItem item = (TableItem)table.getItem(new org.eclipse.swt.graphics.Point(e.x, e.y)); + chartPanel.removeItemFromSeries(table.indexOf(item)); + } + } + @Override + public void mouseDown(org.eclipse.swt.events.MouseEvent e) { } + @Override + public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) { } + }); + for(Point2D location : this.dataPoints) { + chartPanel.addLocationToSeries(location); + } + + input = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(input); + input.setText(""); + output = new Text(valueTableComposite, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(60, SWT.DEFAULT).applyTo(output); + output.setText(""); + + Button add = new Button(valueTableComposite, SWT.None); + add.setText("Add"); + add.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + chartPanel.addLocationToSeries(new Point2D.Double(in, out)); + } catch (NumberFormatException e1) { + input.setText(""); + output.setText(""); + } + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) {} + }); + + FocusListener flistener = new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + Text text = (Text)e.widget; + text.setSelection(0, text.getCharCount()); + } + @Override + public void focusLost(FocusEvent e) { } + }; + + + KeyListener listener = new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + try { + Double in = Double.parseDouble(input.getText()); + Double out = Double.parseDouble(output.getText()); + chartPanel.addLocationToSeries(new Point2D.Double(in, out)); + } catch (NumberFormatException e1) { + if(input.getText().isEmpty() && output.getText().isEmpty()) { + getButton(IDialogConstants.OK_ID).forceFocus(); + return; + } + } + input.setText(""); + output.setText(""); + input.setFocus(); + } + } + + @Override + public void keyReleased(KeyEvent e) { } + + }; + + input.addFocusListener(flistener); + input.addKeyListener(listener); + output.addFocusListener(flistener); + output.addKeyListener(listener); + + Label l = new Label(container, SWT.NONE); + l.setText(""); + + Composite xAxis = new Composite(container, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, false).applyTo(xAxis); + GridLayoutFactory.fillDefaults().numColumns(3).applyTo(xAxis); + minX = new Text(xAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(minX); + minX.addKeyListener(enterListener); + minX.addModifyListener(getAxisBoundModifyListener()); + minX.setText("" + domainAxis.getLowerBound()); + Composite fillX = new Composite(xAxis, SWT.CENTER); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(true, false).applyTo(fillX); + GridLayoutFactory.fillDefaults().applyTo(fillX); + l = new Label(fillX, SWT.NONE); + l.setText(chartInfo.expression); + maxX = new Text(xAxis, SWT.BORDER | SWT.RIGHT); + GridDataFactory.fillDefaults().hint(40, SWT.DEFAULT).applyTo(maxX); + maxX.addKeyListener(enterListener); + maxX.addModifyListener(getAxisBoundModifyListener()); + maxX.setText("" + domainAxis.getUpperBound()); + + return null; + } + + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Cancel buttons by default + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, + false); + createButton(parent, IDialogConstants.CANCEL_ID, + IDialogConstants.CANCEL_LABEL, false); + } + + public LookupChartInfo open(Boolean bool) { + Shell shell = this.getShell(); + if (shell == null || shell.isDisposed()) { + shell = null; + create(); + shell = this.getShell(); + } + constrainShellSize(); + shell.open(); + getButton(IDialogConstants.OK_ID).setFocus(); + Display display = getParentShell().getDisplay(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + return chartInfo; + } + + @Override + public void okPressed() { + chartInfo.lookupTable = graphToModelicaTable(); + chartInfo.minX = Double.parseDouble(minX.getText()); + chartInfo.maxX = Double.parseDouble(maxX.getText()); + chartInfo.minY = Double.parseDouble(minY.getText()); + chartInfo.maxY = Double.parseDouble(maxY.getText()); + super.okPressed(); + } + + @SuppressWarnings("unchecked") + private String graphToModelicaTable() { + StringBuilder b = new StringBuilder(); + b.append("{"); + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + XYSeries series = collection.getSeries(0); + if(series.isEmpty()) + return ""; + Iterator iterator = series.getItems().iterator(); + while(iterator.hasNext()){ + XYDataItem item = (XYDataItem)iterator.next(); + b.append("{" + item.getX() + "," + item.getY() + "}"); + if(iterator.hasNext()) + b.append(","); + } + b.append("}"); + return b.toString(); + } + + private JFreeChart createChart() { + XYDataset dataset = createDataset(); + chart = ChartFactory.createXYLineChart(null, null, null, + dataset, PlotOrientation.VERTICAL, false, true, false); + XYPlot plot = (XYPlot) chart.getPlot(); + XYLineAndShapeRenderer renderer + = (XYLineAndShapeRenderer) plot.getRenderer(); + renderer.setBaseShapesVisible(true); + renderer.setDrawOutlines(true); + renderer.setUseFillPaint(true); + renderer.setBaseFillPaint(Color.white); + renderer.setSeriesStroke(0, new BasicStroke(3.0f)); + renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0f)); + renderer.setSeriesShape(0, new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0)); + + ValueAxis rangeAxis = plot.getRangeAxis(); + rangeAxis.setAutoRange(false); + rangeAxis.setRange(chartInfo.minY, chartInfo.maxY); + ValueAxis domainAxis = plot.getDomainAxis(); + domainAxis.setAutoRange(false); + domainAxis.setRange(chartInfo.minX, chartInfo.maxX); + return chart; + } + + public XYDataset createDataset() { + XYSeries series = new XYSeries("Series"); + XYSeriesCollection dataset = new XYSeriesCollection(); + dataset.addSeries(series); + return dataset; + } + + private ModifyListener getAxisBoundModifyListener() { + return new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + Widget widget = e.widget; + if(widget instanceof Text) { + Text text = (Text)widget; + Double value; + try { + value = Double.parseDouble(text.getText()); + } catch (NumberFormatException e1 ) { + return; + } + XYPlot plot = (XYPlot) chart.getPlot(); + ValueAxis rangeAxis = plot.getRangeAxis(); + ValueAxis domainAxis = plot.getDomainAxis(); + if(text == minX) { + domainAxis.setLowerBound(value); + } else if (text == maxX) { + domainAxis.setUpperBound(value); + } else if (text == minY) { + rangeAxis.setLowerBound(value); + } else if (text == maxY) { + rangeAxis.setUpperBound(value); + } + } + } + }; + } + + private class InputOutputCellModifier implements ICellModifier { + + XYSeries series; + + public InputOutputCellModifier() { + XYSeriesCollection collection = (XYSeriesCollection) ((XYPlot)chart.getPlot()).getDataset(); + series = collection.getSeries(0); + } + + public boolean canModify(Object element, String property) { + return true; + } + + public Object getValue(Object element, String property) { + InputOutput io = (InputOutput)element; + if (LookupInputOutputTable.INPUT.equals(property)) + return (String)io.getInput(String.class); + else if (LookupInputOutputTable.OUTPUT.equals(property)) + return (String)io.getOutput(String.class); + else + return null; + } + + public void modify(Object element, String property, Object value) { + if (element instanceof Item) element = ((Item) element).getData(); + + InputOutput io = (InputOutput)element; + Double x = (Double)io.getInput(Double.class); + int item = series.indexOf(x); + series.remove(item); + + if (LookupInputOutputTable.INPUT.equals(property)) { + Double newX = io.setInput((String)value); + // if has the same x-value, revert back + if(newX != null && series.indexOf(newX) >= 0) { + io.setInput(x); + } + } else if (LookupInputOutputTable.OUTPUT.equals(property)) { + io.setOutput((String)value); + } + + series.add((Double)io.getInput(Double.class), (Double)io.getOutput(Double.class)); + + table.refresh(); + } + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java new file mode 100644 index 00000000..7cc116de --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/ParameterExpression.java @@ -0,0 +1,29 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.ui.SimanticsUI; + +public class ParameterExpression extends BasicExpression { + + + public ParameterExpression() { + try { + this.expressionType = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public Resource perform(ReadGraph graph) throws DatabaseException { + return SysdynResource.getInstance(graph).ParameterExpression; + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java new file mode 100644 index 00000000..398858ee --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/StockExpression.java @@ -0,0 +1,216 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.EquationTab; +import org.simantics.ui.SimanticsUI; + +public class StockExpression implements IExpression { + + private Text integral; + private ExpressionField expression; + + @Override + public void createExpressionFields(Composite parent, Map data) { + String initialEquation = data.get("initialEquation") != null ? (String)data.get("initialEquation") : ""; + String integralEquation = data.get("integral") != null ? (String)data.get("integral") : ""; + + + Label label = new Label(parent, SWT.NONE); + label.setFont(EquationTab.FONT); + label.setText("Integral"); + + integral = new Text(parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); + integral.setEditable(false); + integral.setFont(EquationTab.FONT); + integral.setText(integralEquation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(integral); + + + label = new Label(parent, SWT.NONE); + label.setFont(EquationTab.FONT); + label.setText("Initial\nValue"); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(initialEquation); + + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + } + + @Override + public void focus() { + if(this.expression != null) this.expression.focus(); + + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression); + } + + @Override + public void readData(final Resource variable, Map data) { + String initialEquation = null; + + if (variable != null && data.get("initialEquation") == null) { + try { + initialEquation = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.StockExpression)) { + return graph.getRelatedValue(expression, sr.HasInitialEquation); + } else { + return ""; + } + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("initialEquation", initialEquation); + } + + data.put("integral", getIntegral(variable)); + + } + + @Override + public void replaceSelection(String var) { + if(expression != null) { + IDocument doc = expression.getDocument(); + try { + Point selection = expression.getSelection(); + doc.replace(selection.x, selection.y, var); + expression.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentText = expression.getExpression(); + if(currentText != null) { + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.StockExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasInitialEquation, currentText); + } + + }); + } + expression.setExpression(currentText); + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("initialEquation", this.expression.getExpression()); + if(this.integral != null && this.integral.getText() != null) + data.put("integral", this.integral.getText()); + } + + + private String getIntegral(final Resource variable) { + String integral = ""; + try { + integral = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Builtins b = graph.getBuiltins(); + Collection heads = graph.getObjects(variable, sr.IsHeadOf); + Collection tails = graph.getObjects(variable, sr.IsTailOf); + + StringBuilder builder = new StringBuilder(); + builder.append(""); + for (Resource r : heads) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource tail = graph.getPossibleObject(r, sr.HasTail); + if(tail != null) { + Object name = graph.getPossibleRelatedValue(tail, b.HasName); + if (name != null) + builder.append(" + " + name); + } + } + } + for (Resource r : tails) { + if(graph.isInstanceOf(r, sr.Flow)) { + Resource head = graph.getPossibleObject(r, sr.HasHead); + if(head != null) { + Object name = graph.getPossibleRelatedValue(head, b.HasName); + if (name != null) + builder.append(" - " + name); + } + } + } + if (builder.indexOf(" + ") == 0) + builder.delete(0, 3); + return builder.toString().trim(); + } + + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + return integral; + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java new file mode 100644 index 00000000..ea0bbc74 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/WithLookupExpression.java @@ -0,0 +1,227 @@ +package org.simantics.sysdyn.ui.properties.widgets.expressions; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.simantics.db.Builtins; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.request.Read; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.ui.properties.EquationTab; +import org.simantics.ui.SimanticsUI; + +public class WithLookupExpression implements IExpression { + + private ExpressionField expression; + private ExpressionField lookup; + private Button asGraph; + private ExpressionField lastSelectedText = expression; + private Resource variable; + private LookupChartInfo chartInfo; + + public WithLookupExpression(Resource variable) { + this.variable = variable; + } + + @Override + public void createExpressionFields(Composite parent, final Map data) { + + String equation = data.get("equation") != null ? (String)data.get("equation") : ""; + String lookupTable = data.get("lookup") != null ? (String)data.get("lookup") : ""; + + Label l = new Label(parent, SWT.NONE); + l.setFont(EquationTab.FONT); + l.setText("With\nLookup"); + + expression = new ExpressionField(parent, SWT.BORDER); + expression.setExpression(equation); + GridDataFactory.fillDefaults().grab(true, true).applyTo(expression); + + expression.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = expression; + } + }); + + + l = new Label(parent, SWT.NONE); + l.setFont(EquationTab.FONT); + l.setText("Lookup\ntable"); + + lookup = new ExpressionField(parent, SWT.BORDER); + lookup.setExpression(lookupTable); + GridDataFactory.fillDefaults().grab(true, true).applyTo(lookup); + + lookup.getSourceViewer().getTextWidget().addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + lastSelectedText = lookup; + } + }); + + asGraph = new Button(parent, SWT.None); + asGraph.setText("As graph"); + asGraph.setFont(EquationTab.FONT); + asGraph.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if(chartInfo == null) chartInfo = new LookupChartInfo(expression.getExpression(), lookup.getExpression(), variable, data); + LookupPopup pud = new LookupPopup(asGraph.getParent().getShell(), chartInfo); + LookupChartInfo newInfo = pud.open(false); + if(pud.getReturnCode() == org.eclipse.jface.window.Window.OK) { + chartInfo = newInfo; + lookup.setExpression(chartInfo.lookupTable); + lookup.focus(); + } + } + }); + + } + + @Override + public void focus() { + if(this.lastSelectedText != null) this.lastSelectedText.focus(); + } + + @Override + public List getExpressionFields() { + return Arrays.asList(this.expression, this.lookup); + } + + @Override + public void readData(final Resource variable, Map data) { + String[] results = null; + if (variable != null && data.get("equation") == null) { + try { + results = SimanticsUI.getSession().syncRequest(new Read() { + + @Override + public String[] perform(ReadGraph graph) throws DatabaseException { + String[] results = new String[2]; + SysdynResource sr = SysdynResource.getInstance(graph); + Resource expression = graph.getPossibleObject(variable, sr.HasExpression); + if (expression != null && graph.isInstanceOf(expression, sr.WithLookupExpression)) { + results[0] = graph.getRelatedValue(expression, sr.HasEquation); + results[1] = graph.getRelatedValue(expression, sr.HasLookup); + } else { + results[0] = ""; + results[1] = ""; + } + return results; + } + + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + data.put("equation", results[0]); + data.put("lookup", results[1]); + } + + } + + @Override + public void replaceSelection(String var) { + if(lastSelectedText != null) { + IDocument doc = lastSelectedText.getDocument(); + try { + Point selection = lastSelectedText.getSelection(); + doc.replace(selection.x, selection.y, var); + lastSelectedText.setSelection(selection.x + var.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + @Override + public void save(final Resource variable, Map data) { + final String currentExpression = expression.getExpression(); + final String currentLookupTable = lookup.getExpression(); + + if(currentExpression != null && currentLookupTable != null) { + data.putAll(data); + data.put("equation", currentExpression); + data.put("lookup", currentLookupTable); + SimanticsUI.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph g) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource expression = g.getPossibleObject(variable, sr.HasExpression); + Builtins b = g.getBuiltins(); + if(expression != null) { + g.deny(variable, sr.HasExpression); + } + expression = g.newResource(); + g.claim(expression, b.InstanceOf, null, sr.WithLookupExpression); + g.claim(variable, sr.HasExpression, expression); + g.claimValue(expression, sr.HasEquation, currentExpression); + g.claimValue(expression, sr.HasLookup, currentLookupTable); + if(chartInfo != null) { + g.claimValue(expression, sr.HasMinX, chartInfo.minX); + g.claimValue(expression, sr.HasMaxX, chartInfo.maxX); + g.claimValue(expression, sr.HasMinY, chartInfo.minY); + g.claimValue(expression, sr.HasMaxY, chartInfo.maxY); + } + } + }); + } + + } + + @Override + public void updateData(Map data) { + if(this.expression != null && this.expression.getExpression() != null) + data.put("equation", this.expression.getExpression()); + if(this.lookup != null && this.lookup.getExpression() != null) + data.put("lookup", this.lookup.getExpression()); + if(this.chartInfo != null) { + data.put("minX", chartInfo.minX); + data.put("maxX", chartInfo.maxX); + data.put("minY", chartInfo.minY); + data.put("maxY", chartInfo.maxY); + } + } + + @Override + public void addKeyListener(KeyListener listener) { + this.expression.getSourceViewer().getTextWidget().addKeyListener(listener); + this.lookup.getSourceViewer().getTextWidget().addKeyListener(listener); + } + + @Override + public void addModifyListener(ModifyListener listener) { + this.expression.getSourceViewer().getTextWidget().addModifyListener(listener); + this.lookup.getSourceViewer().getTextWidget().addModifyListener(listener); + } + + @Override + public void addFocusListener(FocusListener listener) { + this.expression.getSourceViewer().getTextWidget().addFocusListener(listener); + this.lookup.getSourceViewer().getTextWidget().addFocusListener(listener); + } + +} -- 2.47.1