From 951fb51cea7634b6132acc7993ad0ebe9f9bd916 Mon Sep 17 00:00:00 2001 From: lempinen Date: Fri, 1 Jun 2012 11:33:44 +0000 Subject: [PATCH] Small improvements: Alphabetic order for variables in model browser, module structure view displays where the selected variable is located in the module structure, game experiment progress displays the correct percentage when using output interval, withlookup expressions accept spreadsheet tables, modelicawriter uses model name instead of misguiding "Model_n", created a new "minmax" built-in function. (refs #3414) git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@25091 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ontology/graph.tg | Bin 63977 -> 64358 bytes .../graph/SysdynFunctions.pgraph | 9 +++++ .../org/simantics/sysdyn/SysdynResource.java | 3 ++ .../browser/contributions/Configuration.java | 35 +++++++++++------- .../contributions/FunctionLibraries.java | 22 ++++++++--- .../contributions/LibraryFunctions.java | 21 +++++++++-- .../ui/browser/contributions/ModuleType.java | 32 ++++++++++++++-- .../ModuleStructureGraphRequest.java | 27 +++++++++++--- .../sysdyn/manager/SysdynExperiment.java | 2 +- .../sysdyn/manager/SysdynGameExperiment.java | 2 + .../simantics/sysdyn/manager/SysdynModel.java | 10 ++--- .../sysdyn/modelica/ModelicaWriter.java | 2 +- .../sysdyn/representation/Configuration.java | 2 +- .../expressions/WithLookupExpression.java | 3 +- .../sysdyn/simulation/SimulationJob.java | 6 +-- 15 files changed, 133 insertions(+), 43 deletions(-) diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index 185aa2016d61749af563452940037e17ea6eb9a0..8185e6cc23e6ced9e888f380ad97437aa17e3792 100644 GIT binary patch literal 64358 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 diff --git a/org.simantics.sysdyn.ontology/graph/SysdynFunctions.pgraph b/org.simantics.sysdyn.ontology/graph/SysdynFunctions.pgraph index 09ced343..4595b360 100644 --- a/org.simantics.sysdyn.ontology/graph/SysdynFunctions.pgraph +++ b/org.simantics.sysdyn.ontology/graph/SysdynFunctions.pgraph @@ -3,6 +3,15 @@ SYSDYN = FL = : SYSDYN.SysdynModelicaFunctionLibrary +FL.minmax : SYSDYN.SysdynModelicaFunction + L0.HasDescription "Limits the result of an equation to between the given minimum and maximum values." + SYSDYN.SysdynModelicaFunction.modelicaFunctionCode """ input Real expression; + input Real minimum; + input Real maximum; + output Real result; +algorithm + result := min(maximum, max(minimum, expression));""" + FL.xidz : SYSDYN.SysdynModelicaFunction L0.HasDescription "X if divided by zero" diff --git a/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java b/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java index c4f222e9..79f98c2a 100644 --- a/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java +++ b/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java @@ -51,6 +51,7 @@ public class SysdynResource { public final Resource Built$in_Functions_Vensim_Functions_ZIDZ; public final Resource Built$in_Functions_interpolate; public final Resource Built$in_Functions_interpolateFull; + public final Resource Built$in_Functions_minmax; public final Resource Built$in_Functions_xidz; public final Resource Built$in_Functions_zidz; public final Resource Center; @@ -403,6 +404,7 @@ public class SysdynResource { public static final String Built$in_Functions_Vensim_Functions_ZIDZ = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Vensim%20Functions/ZIDZ"; public static final String Built$in_Functions_interpolate = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/interpolate"; public static final String Built$in_Functions_interpolateFull = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/interpolateFull"; + public static final String Built$in_Functions_minmax = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/minmax"; public static final String Built$in_Functions_xidz = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/xidz"; public static final String Built$in_Functions_zidz = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/zidz"; public static final String Center = "http://www.simantics.org/Sysdyn-1.1/Center"; @@ -765,6 +767,7 @@ public class SysdynResource { Built$in_Functions_Vensim_Functions_ZIDZ = getResourceOrNull(graph, URIs.Built$in_Functions_Vensim_Functions_ZIDZ); Built$in_Functions_interpolate = getResourceOrNull(graph, URIs.Built$in_Functions_interpolate); Built$in_Functions_interpolateFull = getResourceOrNull(graph, URIs.Built$in_Functions_interpolateFull); + Built$in_Functions_minmax = getResourceOrNull(graph, URIs.Built$in_Functions_minmax); Built$in_Functions_xidz = getResourceOrNull(graph, URIs.Built$in_Functions_xidz); Built$in_Functions_zidz = getResourceOrNull(graph, URIs.Built$in_Functions_zidz); Center = getResourceOrNull(graph, URIs.Center); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java index c874e042..d50bfbc2 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/Configuration.java @@ -13,6 +13,7 @@ package org.simantics.sysdyn.ui.browser.contributions; import java.util.ArrayList; import java.util.Collection; +import java.util.TreeMap; import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; import org.simantics.db.ReadGraph; @@ -22,7 +23,6 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.layer0.Layer0; -import org.simantics.modeling.ui.modelBrowser2.model.SheetsNode; import org.simantics.spreadsheet.resource.SpreadsheetResource; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.browser.nodes.BookNode; @@ -31,6 +31,7 @@ import org.simantics.sysdyn.ui.browser.nodes.EnumerationNode; import org.simantics.sysdyn.ui.browser.nodes.InputNode; import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; import org.simantics.sysdyn.ui.browser.nodes.VariableNode; +import org.simantics.utils.strings.AlphanumComparator; public class Configuration extends ViewpointContributor> { @@ -44,37 +45,45 @@ public class Configuration extends ViewpointContributor variables = new ArrayList(); - ArrayList inputs = new ArrayList(); - ArrayList modules = new ArrayList(); - ArrayList enumerations = new ArrayList(); + TreeMap variables = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + TreeMap inputs = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + TreeMap modules = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + TreeMap enumerations = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + for(Variable child : variable.browseChildren(graph)) { Resource represents = (Resource)child.getPropertyValue(graph, Variables.REPRESENTS); if(graph.isInstanceOf(represents, sr.IndependentVariable)) { - variables.add(child); + variables.put(child.getName(graph), child); } else if (graph.isInstanceOf(represents, sr.Input)) { - inputs.add(child); + inputs.put(child.getName(graph), child); } else if (graph.isInstanceOf(represents, sr.Module)) { - modules.add(child); + modules.put(child.getName(graph), child); } else if (graph.isInstanceOf(represents, sr.Enumeration)) { - enumerations.add(child); + enumerations.put(child.getName(graph), child); } } - for (Variable v : variables) { + for (String s : variables.keySet()) { + Variable v = variables.get(s); Resource represents = (Resource)v.getPropertyValue(graph, Variables.REPRESENTS); result.add(new VariableNode(v, represents)); } - for (Variable v : inputs) { + + for (String s : inputs.keySet()) { + Variable v = inputs.get(s); Resource represents = (Resource)v.getPropertyValue(graph, Variables.REPRESENTS); result.add(new InputNode(v, represents)); } - for (Variable v : modules) { + + for (String s : modules.keySet()) { + Variable v = modules.get(s); Resource represents = (Resource)v.getPropertyValue(graph, Variables.REPRESENTS); result.add(new ModuleNode(v, represents)); } - for (Variable v : enumerations) { + + for (String s : enumerations.keySet()) { + Variable v = enumerations.get(s); Resource represents = (Resource)v.getPropertyValue(graph, Variables.REPRESENTS); result.add(new EnumerationNode(v, represents)); } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/FunctionLibraries.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/FunctionLibraries.java index 87151394..5cd6bbee 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/FunctionLibraries.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/FunctionLibraries.java @@ -13,12 +13,14 @@ package org.simantics.sysdyn.ui.browser.contributions; import java.util.ArrayList; import java.util.Collection; +import java.util.TreeMap; import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.Layer0; import org.simantics.sysdyn.SysdynResource; @@ -26,6 +28,7 @@ import org.simantics.sysdyn.ui.browser.nodes.FunctionLibraryNode; import org.simantics.sysdyn.ui.browser.nodes.FunctionNode; import org.simantics.sysdyn.ui.browser.nodes.FunctionsFolder; import org.simantics.sysdyn.ui.browser.nodes.SharedFunctionsFolder; +import org.simantics.utils.strings.AlphanumComparator; public class FunctionLibraries extends ViewpointContributor { @@ -38,16 +41,23 @@ public class FunctionLibraries extends ViewpointContributor { ArrayList> result = new ArrayList>(); - // Find model functions + TreeMap sortResult = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + // Find and sort model functions for(Resource function : graph.syncRequest(new ObjectsWithType(functionsFolder.data, l0.ConsistsOf, sr.SysdynModelicaFunction))) { - result.add(new FunctionNode(function)); + sortResult.put(NameUtils.getSafeName(graph, function), function); } + for(Resource function : sortResult.values()) + result.add(new FunctionNode(function)); - // Find model function libraries + // Find and sort model function libraries + sortResult.clear(); for(Resource functionLibrary : graph.syncRequest(new ObjectsWithType(functionsFolder.data, l0.ConsistsOf, sr.SysdynModelicaFunctionLibrary))) { - result.add(new FunctionLibraryNode(functionLibrary)); - } - + sortResult.put(NameUtils.getSafeName(graph, functionLibrary), functionLibrary); + } + for(Resource functionLibrary : sortResult.values()) + result.add(new FunctionLibraryNode(functionLibrary)); + + // Find built-in functions Resource sysdyn = graph.getPossibleResource("http://www.simantics.org/Sysdyn-1.1"); if(sysdyn != null) { for(Resource library : graph.syncRequest(new ObjectsWithType(sysdyn, l0.ConsistsOf, sr.SysdynModelicaFunctionLibrary))) { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryFunctions.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryFunctions.java index c37ea465..6e3a1a1f 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryFunctions.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/LibraryFunctions.java @@ -13,17 +13,20 @@ package org.simantics.sysdyn.ui.browser.contributions; import java.util.ArrayList; import java.util.Collection; +import java.util.TreeMap; import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.layer0.Layer0; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.browser.nodes.FunctionLibraryNode; import org.simantics.sysdyn.ui.browser.nodes.FunctionNode; +import org.simantics.utils.strings.AlphanumComparator; public class LibraryFunctions extends ViewpointContributor> { @@ -32,16 +35,28 @@ public class LibraryFunctions extends ViewpointContributor library) throws DatabaseException { Layer0 l0 = Layer0.getInstance(graph); ArrayList> result = new ArrayList>(); + + TreeMap sortResult = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); + + // Find and sort functions in library for(Resource function : graph.syncRequest(new ObjectsWithType(library.data, l0.ConsistsOf, SysdynResource.getInstance(graph).SysdynModelicaFunction))) { - result.add(new FunctionNode(function)); + sortResult.put(NameUtils.getSafeName(graph, function), function); } + for(Resource function : sortResult.values()) + result.add(new FunctionNode(function)); + + // Find and sort libraries in library + sortResult.clear(); for(Resource functionLibrary : graph.syncRequest(new ObjectsWithType(library.data, l0.ConsistsOf, SysdynResource.getInstance(graph).SysdynModelicaFunctionLibrary))) { - result.add(new FunctionLibraryNode(functionLibrary)); + sortResult.put(NameUtils.getSafeName(graph, functionLibrary), functionLibrary); } + for(Resource functionLibrary : sortResult.values()) + result.add(new FunctionLibraryNode(functionLibrary)); + return result; } - + @Override public String getViewpointId() { return "Standard"; diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java index ed5a9ead..4ebe335e 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/browser/contributions/ModuleType.java @@ -13,9 +13,11 @@ package org.simantics.sysdyn.ui.browser.contributions; import java.util.ArrayList; import java.util.Collection; +import java.util.TreeMap; import org.simantics.browsing.ui.common.node.AbstractNode; import org.simantics.browsing.ui.graph.contributor.viewpoint.ViewpointContributor; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ObjectsWithType; @@ -29,6 +31,7 @@ import org.simantics.sysdyn.ui.browser.nodes.InputNode; import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; import org.simantics.sysdyn.ui.browser.nodes.ModuleTypeNode; import org.simantics.sysdyn.ui.browser.nodes.VariableNode; +import org.simantics.utils.strings.AlphanumComparator; public class ModuleType extends ViewpointContributor { @@ -44,18 +47,39 @@ public class ModuleType extends ViewpointContributor { if(instance == null) return result; Resource conf = graph.getSingleObject(instance, str.IsDefinedBy); + + // Independent variables + TreeMap variables = new TreeMap(AlphanumComparator.CASE_INSENSITIVE_COMPARATOR); for(Resource r : graph.syncRequest(new ObjectsWithType(conf, l0.ConsistsOf, sr.IndependentVariable))) { - result.add(new VariableNode(r)); + variables.put((String)graph.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING), r); } + for(String key : variables.keySet()) + result.add(new VariableNode(variables.get(key))); + + // Inputs + variables.clear(); for(Resource r : graph.syncRequest(new ObjectsWithType(conf, l0.ConsistsOf, sr.Input))) { - result.add(new InputNode(r)); + variables.put((String)graph.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING), r); } + for(String key : variables.keySet()) + result.add(new InputNode(variables.get(key))); + + // Modules + variables.clear(); for(Resource r : graph.syncRequest(new ObjectsWithType(conf, l0.ConsistsOf, sr.Module))) { - result.add(new ModuleNode(r)); + variables.put((String)graph.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING), r); } + for(String key : variables.keySet()) + result.add(new ModuleNode(variables.get(key))); + + // Enumerations + variables.clear(); for(Resource r : graph.syncRequest(new ObjectsWithType(conf, l0.ConsistsOf, sr.Enumeration))) { - result.add(new EnumerationNode(r)); + variables.put((String)graph.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING), r); } + for(String key : variables.keySet()) + result.add(new EnumerationNode(variables.get(key))); + return result; } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java index 4724a0d5..c32a3004 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java @@ -24,6 +24,8 @@ import org.simantics.graphviz.Edge; import org.simantics.graphviz.Graph; import org.simantics.graphviz.Node; import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.simulation.ontology.SimulationResource; import org.simantics.sysdyn.SysdynResource; /** @@ -61,13 +63,21 @@ public class ModuleStructureGraphRequest implements Read { // Model root was not found, return empty graph if(model == null) return g; + + // Find the parent module/model of the selected resource + Resource parentResource = graph.getPossibleObject(resource, l0.PartOf); + if(graph.isInstanceOf(parentResource, sr.ConfigurationDiagram)) { + parentResource = graph.getPossibleObject(parentResource, ModelingResources.getInstance(graph).DiagramToComposite); + } else if(graph.isInstanceOf(parentResource, sr.SysdynModel)) { + parentResource = graph.getPossibleObject(model, SimulationResource.getInstance(graph).HasConfiguration); + } // Set root node Node rootNode = new Node(g, NameUtils.getSafeLabel(graph, model)); rootNode.setShape("rectangle"); HashSet visited = new HashSet(); visited.add(model); - findChildModules(g, rootNode, graph, model, visited); + findChildModules(g, rootNode, graph, model, parentResource, visited); return g; @@ -79,17 +89,23 @@ public class ModuleStructureGraphRequest implements Read { * @param parent Parent module or model * @param graph ReadGraph * @param resource Module type or model + * @param parent2 * @param visited All visited modules. Needed to check for loops in the structure. Loops are not allowed. * @throws DatabaseException */ - private void findChildModules(Graph g, Node parent, ReadGraph graph, Resource resource, HashSet visited) throws DatabaseException { + private void findChildModules(Graph g, Node parent, ReadGraph graph, Resource resource, Resource parentResource, HashSet visited) throws DatabaseException { SysdynResource sr = SysdynResource.getInstance(graph); Layer0 l0 = Layer0.getInstance(graph); + Resource configuration = graph.syncRequest(new PossibleObjectWithType(resource, l0.ConsistsOf, sr.Configuration)); + + // Set the parent color different, if it is the parent of the selected resource + if(configuration.equals(parentResource)) + parent.setColor("#ff8c00"); + HashMap modules = new HashMap(); // Find all module children - Resource configuration = graph.syncRequest(new PossibleObjectWithType(resource, l0.ConsistsOf, sr.Configuration)); for(Resource m : graph.getObjects(configuration, l0.ConsistsOf)) { Resource type = graph.getPossibleObject(m, l0.InstanceOf); if(graph.isInheritedFrom(type, sr.Module)) { @@ -120,8 +136,9 @@ public class ModuleStructureGraphRequest implements Read { node.setFontColor("#FF0000"); continue; } else { - visited.add(type); - findChildModules(g, node, graph, type, visited); + HashSet copy = new HashSet(visited); + copy.add(type); + findChildModules(g, node, graph, type, parentResource, copy); } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java index d0e8f385..1c1852b1 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynExperiment.java @@ -352,7 +352,7 @@ public class SysdynExperiment extends Experiment implements IDynamicExperiment { protected static SimulationLocation createSimulationFiles(SysdynModel sysdynModel, String modelText, HashMap inits, String additionalScript, boolean fmu) throws IOException { return ModelicaManager.createSimulationFiles( sysdynModel.getSimulationDir(), - sysdynModel.getConfiguration().getName(), + sysdynModel.getConfiguration().getLabel(), modelText, inits, additionalScript, diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java index 8bb2e09c..f5918430 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynGameExperiment.java @@ -274,6 +274,8 @@ public class SysdynGameExperiment extends SysdynExperiment { for(int k = 0; k < subscription.length; k++) { SysdynGameExperiment.this.results.get(subscription[k]).add(results[k]); } + } else { + monitor.worked(1); } stepNumber++; monitor.worked(1); 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 740ae5a2..3912a70e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/manager/SysdynModel.java @@ -213,10 +213,6 @@ public class SysdynModel implements IMappingListener, IModel { e.printStackTrace(); } - // Add the current result if there is one - if(getSysdynResult() != null) - activeResults.add(0, getSysdynResult() ); - return activeResults; } @@ -224,6 +220,10 @@ public class SysdynModel implements IMappingListener, IModel { @Override public void execute(ArrayList result) { + // Add the current result if there is one + if(result != null && getSysdynResult() != null) + result.add(0, getSysdynResult() ); + activeResults = result; resultChanged(); } @@ -497,7 +497,7 @@ public class SysdynModel implements IMappingListener, IModel { public File getSimulationDir() { if(simulationDir == null) { File modelsDir = Activator.getBundleContext().getDataFile("models"); - String configName = configuration.getName(); + String configName = configuration.getLabel(); List files = Arrays.asList(modelsDir.list()); if (files.contains(configName)) { int i = 2; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java index 090af57a..ea24ec70 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/modelica/ModelicaWriter.java @@ -141,7 +141,7 @@ public class ModelicaWriter { // If the configuration is model configuration, use model name. Otherwise, use configuration name. ModuleType mt = configuration.getModuleType(); - String className = mt != null ? (mt.getName().replace(" ", "")) : (configuration.getName().replace(" ", "")); + String className = mt != null ? (mt.getName().replace(" ", "")) : (configuration.getLabel().replace(" ", "")); b.append("class ").append(className); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java index f13b4044..00d0efb3 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/Configuration.java @@ -75,7 +75,7 @@ public class Configuration { } public String getLabel() { - return label; + return label != null ? label : name; } public ModuleType getModuleType() { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java index 15e34766..f40cc43e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/expressions/WithLookupExpression.java @@ -17,6 +17,7 @@ import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.utils.FormatUtils; import org.simantics.sysdyn.representation.utils.IndexUtils; +import org.simantics.sysdyn.representation.utils.SheetFormatUtils; /** * Representation of a withlookup expression @@ -38,7 +39,7 @@ public class WithLookupExpression extends Expression { String range = IndexUtils.rangeToIndexes(variable, this.getArrayRange()); return - " " + variable.getName() + (range.equals("[:]") ? "" : range) + " = interpolate(" + equation + ", " + lookupTable + ");\n"; + " " + variable.getName() + (range.equals("[:]") ? "" : range) + " = interpolate(" + equation + ", " + SheetFormatUtils.reformatSheetReferences(variable, lookupTable) + ");\n"; } @Override diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java index df6b06ae..ccb4d92e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/simulation/SimulationJob.java @@ -42,7 +42,7 @@ public class SimulationJob extends Job { IModelicaMonitor monitor; public SimulationJob(SysdynModel model, Experiment experiment) { - super("Simulate " + model.getConfiguration().getName()); + super("Simulate " + model.getConfiguration().getLabel()); this.model = model; this.experiment = experiment; if(PlatformUI.isWorkbenchRunning()) { @@ -55,8 +55,8 @@ public class SimulationJob extends Job { @Override protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask("Simulate " + model.getConfiguration().getName(), 5); - this.monitor.message("Simulate " + model.getConfiguration().getName()); + monitor.beginTask("Simulate " + model.getConfiguration().getLabel(), 5); + this.monitor.message("Simulate " + model.getConfiguration().getLabel()); try { model.update(); if(experiment instanceof SysdynExperiment) -- 2.47.1