From 2ad0e81cadedffc06f2b7bbc18c2c35d62f15056 Mon Sep 17 00:00:00 2001 From: lempinen Date: Thu, 20 Jan 2011 14:37:23 +0000 Subject: [PATCH] Select which indexes of multidimensional variables are shown in the trend view git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@19440 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ui/plugin.xml | 10 + .../sysdyn/ui/properties/EnumerationTab.java | 256 ++++++++++-------- .../widgets/arrays/EnumerationIndexNode.java | 23 +- .../ui/properties/widgets/arrays/Keys.java | 7 + .../widgets/arrays/ShowInChartsCheckBox.java | 21 ++ .../SysdynDatasetSelectionListener.java | 55 +++- .../simantics/sysdyn/manager/SysdynModel.java | 15 +- 7 files changed, 268 insertions(+), 119 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/ShowInChartsCheckBox.java diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index af4921f5..68d404b5 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -828,4 +828,14 @@ label="System Dynamics ontology dependencies"> + + + + + + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EnumerationTab.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EnumerationTab.java index d006e9c2..8573747f 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EnumerationTab.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/EnumerationTab.java @@ -1,5 +1,7 @@ package org.simantics.sysdyn.ui.properties; +import java.util.List; + import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelection; @@ -10,8 +12,12 @@ import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IWorkbenchSite; +import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.swt.PropertyTabContributorImpl; import org.simantics.browsing.ui.swt.SingleSelectionInputSource; import org.simantics.browsing.ui.swt.widgets.Button; @@ -21,6 +27,7 @@ import org.simantics.browsing.ui.swt.widgets.Table; import org.simantics.browsing.ui.swt.widgets.TrackedText; import org.simantics.browsing.ui.swt.widgets.impl.Widget; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.databoard.Bindings; import org.simantics.db.Builtins; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; @@ -30,9 +37,13 @@ import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.management.ISessionContext; +import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.layer0.utils.direct.GraphUtils; import org.simantics.sysdyn.SysdynResource; +import org.simantics.sysdyn.manager.SysdynModel; +import org.simantics.sysdyn.manager.SysdynModelManager; +import org.simantics.sysdyn.ui.properties.widgets.arrays.EnumerationIndexNode; import org.simantics.sysdyn.ui.properties.widgets.factories.VariableNamePropertyModifier; import org.simantics.sysdyn.ui.properties.widgets.factories.VariableNameValidator; import org.simantics.ui.SimanticsUI; @@ -43,6 +54,8 @@ import org.simantics.utils.ui.ISelectionUtils; public class EnumerationTab extends PropertyTabContributorImpl { GraphExplorerComposite indexExplorer; + + Button showAll; Table table; @@ -52,147 +65,72 @@ public class EnumerationTab extends PropertyTabContributorImpl { Composite container = new Composite(body, SWT.None); GridDataFactory.fillDefaults().grab(true, true).applyTo(container); - GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(2).applyTo(container); + GridLayoutFactory.fillDefaults().margins(3, 3).numColumns(3).applyTo(container); TrackedText nameText = new TrackedText(container, support, SWT.BORDER); nameText.setTextFactory(new StringPropertyFactory(Builtins.URIs.HasName)); nameText.addModifyListener(new VariableNamePropertyModifier(context, Builtins.URIs.HasName)); nameText.setInputValidator(new VariableNameValidator(support)); - GridDataFactory.fillDefaults().grab(true, false).span(2,1).applyTo(nameText.getWidget()); + GridDataFactory.fillDefaults().grab(true, false).span(3,1).applyTo(nameText.getWidget()); indexExplorer = new GraphExplorerComposite(ArrayMap.keys( - "displaySelectors", "displayFilter").values(false, false), site, container, support, SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI); + "displaySelectors", "displayFilter").values(false, false), site, container, support, SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI | SWT.CHECK); indexExplorer .setBrowseContexts("http://www.simantics.org/Sysdyn-1.0/EnumerationIndexes"); indexExplorer.setInputSource(new SingleSelectionInputSource( Resource.class)); + ((Tree)indexExplorer.getExplorerControl()).addListener(SWT.Selection, new Listener () { + + @Override + public void handleEvent (Event event) { + if(event.detail == SWT.CHECK) { + final TreeItem item = (TreeItem)event.item; + final boolean checked = item.getChecked(); + NodeContext context = (NodeContext)item.getData(); + final EnumerationIndexNode node = (EnumerationIndexNode) context.getAdapter(EnumerationIndexNode.class); + node.setShowInChartsSelected(checked); + + SimanticsUI.getSession().asyncRequest(new ReadRequest() { + @Override + public void run(ReadGraph graph) throws DatabaseException { + Layer0 l0 = Layer0.getInstance(graph); + Resource enumeration = (Resource)indexExplorer.getExplorer().getRoot().getAdapter(Resource.class); + Resource configuration = graph.getSingleObject(enumeration, l0.PartOf); + SysdynModel model = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); + // update results in graphs + model.resultChanged(); + } + }); + } + } + }); + indexExplorer.finish(); - GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo( + GridDataFactory.fillDefaults().grab(true, true).span(3, 1).applyTo( indexExplorer); Control c = indexExplorer.getExplorerControl(); if (c instanceof Tree) ((Tree) c).setLinesVisible(true); - - - /* - - - table = new Table(container, support, SWT.BORDER); - table.setItemFactory(new ReadFactoryImpl>>() { - @Override - public List> perform(ReadGraph graph, - Object input) throws DatabaseException { - Resource enumeration = (Resource)input; - SysdynResource sr = SysdynResource.getInstance(graph); - Resource list = graph.getSingleObject(enumeration, sr.HasEnumerationIndexes); - List resourceList = OrderedSetUtils.toList(graph, list); - - List> result = new ArrayList>(); - for(Resource r : resourceList) { - result.add(new Pair( - (String)graph.getRelatedValue(r, Layer0.getInstance(graph).HasName, Bindings.STRING) - , r)); - } - return result; - } - }); - table.setSelectionFactory(new ReadFactoryImpl() { - - @Override - public String perform(ReadGraph graph, final Resource input) throws DatabaseException { - return graph.getRelatedValue(input, Layer0.getInstance(graph).HasName); - } - }); - GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(table.getWidget()); - - - final TableEditor editor = new TableEditor(table.getWidget()); - // The editor must have the same size as the cell and must - // not be any smaller than 50 pixels. - editor.horizontalAlignment = SWT.LEFT; - editor.grabHorizontal = true; - editor.minimumWidth = 50; - // editing the second column - final int EDITABLECOLUMN = 0; - - table.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - // Clean up any previous editor control - Control oldEditor = editor.getEditor(); - if (oldEditor != null) - oldEditor.dispose(); - - // Identify the selected row - final TableItem item = (TableItem) e.item; - if (item == null) - return; - - // The control that will be the editor must be a child of the - // Table - Text newEditor = new Text(item.getParent(), SWT.NONE); - final String originalText = item.getText(EDITABLECOLUMN); - final Resource resource = (Resource) item.getData(); - newEditor.setText(originalText); - newEditor.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent me) { - Text text = (Text) editor.getEditor(); - if(!text.isDisposed()) { - TableItem item = editor.getItem(); - if(!item.isDisposed()) - item.setText(EDITABLECOLUMN, text.getText()); - } - } - }); - newEditor.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - final Text text = (Text) editor.getEditor(); - if(!text.getText().equals(originalText)) { - final String newText = text.getText(); - try { - context.getSession().syncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - graph.claimLiteral( - resource, - Layer0.getInstance(graph).HasName, - newText); - } - }); - } catch (DatabaseException e1) { - e1.printStackTrace(); - } - } - } - }); - newEditor.selectAll(); - newEditor.setFocus(); - editor.setEditor(newEditor, item, EDITABLECOLUMN); - } - }); - - - - - */ - Button add = new Button(container, support, SWT.None); - add.setText("Add index"); + add.setText("Add"); add.addSelectionListener(new addEnumerationIndexListener(support)); Button remove = new Button(container, support, SWT.None); remove.setText("Remove"); remove.addSelectionListener(new removeEnumerationIndexListener(support)); + + showAll = new Button(container, support, SWT.CHECK); + showAll.setText("Show all in charts"); + showAll.addSelectionListener(new ShowAllIndexesListener(support)); } private class addEnumerationIndexListener implements SelectionListener, Widget { @@ -304,4 +242,102 @@ public class EnumerationTab extends PropertyTabContributorImpl { } } + + private class ShowAllIndexesListener implements SelectionListener, Widget { + + Resource enumerationIndexes; + + public ShowAllIndexesListener(WidgetSupport support) { + support.register(this); + } + + @Override + public void setInput(ISessionContext context, Object input) { + final Resource enumeration = ISelectionUtils.filterSingleSelection((ISelection)input, Resource.class); + + context.getSession().asyncRequest(new Read() { + + @Override + public Boolean perform(ReadGraph graph) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + enumerationIndexes = graph.getSingleObject(enumeration, sr.HasEnumerationIndexes); + List indexes = OrderedSetUtils.toList(graph, enumerationIndexes); + for(Resource index : indexes) { + Boolean show = graph.getPossibleRelatedValue(index, sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); + if(!Boolean.TRUE.equals(show)) + return false; + } + return true; + } + + }, new org.simantics.db.procedure.Listener() { + + @Override + public void execute(final Boolean result) { + showAll.getWidget().getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + showAll.getWidget().setSelection(result.booleanValue()); + } + }); + } + + + @Override + public void exception(Throwable t) { + t.printStackTrace(); + } + + @Override + public boolean isDisposed() { + if(showAll == null) + return true; + return showAll.getWidget().isDisposed(); + } + }); + + } + + @Override + public void widgetSelected(SelectionEvent e) { + final boolean selected = showAll.getWidget().getSelection(); + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + List indexes = OrderedSetUtils.toList(graph, enumerationIndexes); + for(Resource index : indexes) { + Boolean show = graph.getPossibleRelatedValue(index, sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); + if(selected && !Boolean.TRUE.equals(show)) { + graph.claimLiteral(index, sr.ShowEnumerationIndexInCharts, true, Bindings.BOOLEAN); + } else if(!selected && !Boolean.FALSE.equals(show)) { + graph.claimLiteral(index, sr.ShowEnumerationIndexInCharts, false, Bindings.BOOLEAN); + } + } + + Resource enumeration = graph.getSingleObject(enumerationIndexes, sr.HasEnumerationIndexes_Inverse); + Resource configuration = graph.getSingleObject(enumeration, Layer0.getInstance(graph).PartOf); + SysdynModel model = SysdynModelManager.getInstance(graph.getSession()).getModel(graph, configuration); + // update results in graphs + model.resultChanged(); + + } + }); + } catch (DatabaseException e1) { + e1.printStackTrace(); + } + + + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + + } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/EnumerationIndexNode.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/EnumerationIndexNode.java index 94909cda..da74629d 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/EnumerationIndexNode.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/EnumerationIndexNode.java @@ -1,6 +1,7 @@ package org.simantics.sysdyn.ui.properties.widgets.arrays; import org.simantics.browsing.ui.common.node.AbstractNode; +import org.simantics.browsing.ui.common.node.IDoubleClickableNode; import org.simantics.browsing.ui.common.node.IModifiableNode; import org.simantics.browsing.ui.content.Labeler.Modifier; import org.simantics.db.ReadGraph; @@ -10,10 +11,11 @@ import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; +import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.utils.VariableNameUtils; import org.simantics.ui.SimanticsUI; -public class EnumerationIndexNode extends AbstractNode implements IModifiableNode { +public class EnumerationIndexNode extends AbstractNode implements IModifiableNode, IDoubleClickableNode { public EnumerationIndexNode(Resource resource) { super(resource); @@ -69,4 +71,23 @@ public class EnumerationIndexNode extends AbstractNode implements IMo } + @Override + public boolean handleDoubleClick() { + return true; + } + + public void setShowInChartsSelected(final boolean selected) { + try { + SimanticsUI.getSession().syncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + graph.claimLiteral(data, sr.ShowEnumerationIndexInCharts, selected); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + } + } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/Keys.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/Keys.java index 57dd8e2b..993723d0 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/Keys.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/Keys.java @@ -7,6 +7,7 @@ public class Keys { public static final String ENUMERATION = "Enumeration"; public static final String INDEXES = "Indexes"; + public static final String SHOW_IN_CHARTS = "ShowInCharts"; public static String[] ENUMERATION_COLUMNS_KEYS = { ENUMERATION, INDEXES }; public static Column[] ENUMERATION_TABLE_COLUMNS = new Column[] { @@ -15,4 +16,10 @@ public class Keys { }; + public static String[] ENUMERATION_INDEX_COLUMNS_KEYS = { ENUMERATION, SHOW_IN_CHARTS }; + public static Column[] ENUMERATION_INDEX_TABLE_COLUMNS = new Column[] { + new Column(ENUMERATION, Align.LEFT, 100, "Enumeration", true), + new Column(SHOW_IN_CHARTS, Align.LEFT, 20, "Show in charts", false), + }; + } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/ShowInChartsCheckBox.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/ShowInChartsCheckBox.java new file mode 100644 index 00000000..232db37b --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/arrays/ShowInChartsCheckBox.java @@ -0,0 +1,21 @@ +package org.simantics.sysdyn.ui.properties.widgets.arrays; + +import org.simantics.browsing.ui.CheckedState; +import org.simantics.browsing.ui.graph.contributor.labeler.CheckedStateContributor; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.sysdyn.SysdynResource; + +public class ShowInChartsCheckBox extends CheckedStateContributor { + + @Override + public CheckedState getState(ReadGraph graph, EnumerationIndexNode input) + throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Boolean selected = graph.getPossibleRelatedValue(input.data, sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); + return selected ? CheckedState.CHECKED : CheckedState.NOT_CHECKED; + } + +} + diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java index 7a37cc2b..79738f17 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/viewUtils/SysdynDatasetSelectionListener.java @@ -22,15 +22,19 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.common.utils.OrderedSetUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.SelectionHints; +import org.simantics.db.layer0.variable.RepresentsProperty; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.layer0.Layer0; import org.simantics.modeling.ModelingUtils; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.sysdyn.SysdynResource; @@ -140,7 +144,8 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen protected Collection loadAllActive(ReadGraph g, Variable variable) throws DatabaseException { ArrayList dataSets = new ArrayList(); - + HashMap rvis = new HashMap(); + String rvi = Variables.getRVI(g, variable); if (rvi == null) return dataSets; @@ -148,6 +153,17 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen rvi = rvi.length() > 0 ? rvi.substring(1) : rvi; rvi = rvi.replace("/", "."); + RepresentsProperty rp = (RepresentsProperty)variable.getProperty(g, Variables.REPRESENTS); + Resource r = rp.getValue(g); + + SysdynResource sr = SysdynResource.getInstance(g); + Resource arrayIndexes = g.getPossibleObject(r, sr.HasArrayIndexes); + if(arrayIndexes == null) { + rvis.put(rvi, rvi); + } else { + traverseIndexes(g, rvi, rvis, OrderedSetUtils.toList(g, arrayIndexes)); + } + Resource modelResource = Variables.getModel(g, variable); SysdynModel model = getSysdynModel(g, modelResource); @@ -156,14 +172,45 @@ public abstract class SysdynDatasetSelectionListener implements ISelectionListen Collection activeResults = model.getActiveResults(g); for(SysdynResult sysdynResult : activeResults) { - SysdynDataSet sds = sysdynResult.getDataSet(rvi); - if(sds != null) - dataSets.add(sds); + for(String currvi : rvis.keySet()) { + SysdynDataSet sds = sysdynResult.getDataSet(currvi); + if(sds != null) { + sds.name = rvis.get(currvi); + dataSets.add(sds); + } + } } return dataSets; } + private void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes) throws DatabaseException { + traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(0), "", ""); + } + + private void traverseIndexes(ReadGraph g, String rvi, HashMap rvis, List arrayIndexes, Resource currentEnumeration, String indexesSoFar, String indexNamesSoFar) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + Resource enumerationIndexes = g.getPossibleObject(currentEnumeration, sr.HasEnumerationIndexes); + if(enumerationIndexes == null) + return; + List indexes = OrderedSetUtils.toList(g, enumerationIndexes); + for(int i = 0; i < indexes.size(); i++) { + Boolean b = g.getPossibleRelatedValue(indexes.get(i), sr.ShowEnumerationIndexInCharts, Bindings.BOOLEAN); + if(Boolean.TRUE.equals(b)) { + int arrayIndex = arrayIndexes.indexOf(currentEnumeration); + String name = g.getRelatedValue(indexes.get(i), Layer0.getInstance(g).HasName); + if(arrayIndex < arrayIndexes.size() - 1) + traverseIndexes(g, rvi, rvis, arrayIndexes, arrayIndexes.get(arrayIndex + 1), + indexesSoFar + (i + 1) +",", indexNamesSoFar + (name) +","); + else { + rvis.put( + rvi + "[" + indexesSoFar + (i + 1) + "]", + rvi + "[" + indexNamesSoFar + (name) + "]"); + } + } + } + } + private Variable getVariable(ReadGraph g, Resource element, Resource runtime) throws DatabaseException { SysdynResource sr = SysdynResource.getInstance(g); DiagramResource dr = DiagramResource.getInstance(g); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java index cb6fe078..c1abc57e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -251,10 +251,9 @@ public class SysdynModel implements IMappingListener, IModel { result.filter(); sysdynResult.setResult(result); progressMonitor.worked(1); - synchronized(resultListeners) { - for(Runnable listener : resultListeners) - listener.run(); - } + + resultChanged(); + setExperimentStopped(experiment); } } catch (FileNotFoundException e) { @@ -348,6 +347,14 @@ public class SysdynModel implements IMappingListener, IModel { resultListeners.remove(listener); } } + + public void resultChanged() { + synchronized(resultListeners) { + for(Runnable listener : resultListeners) { + listener.run(); + } + } + } public void addModificationListener(Runnable listener) { synchronized(modificationListeners) { -- 2.47.1