1 /*******************************************************************************
\r
2 * Copyright (c) 2010, 2012 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.properties;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collection;
\r
16 import java.util.Collections;
\r
17 import java.util.List;
\r
19 import org.eclipse.jface.viewers.ISelection;
\r
20 import org.simantics.browsing.ui.NodeContext;
\r
21 import org.simantics.browsing.ui.model.nodetypes.NodeType;
\r
22 import org.simantics.browsing.ui.model.nodetypes.SpecialNodeType;
\r
23 import org.simantics.db.ReadGraph;
\r
24 import org.simantics.db.Resource;
\r
25 import org.simantics.db.common.request.ObjectsWithType;
\r
26 import org.simantics.db.common.utils.ListUtils;
\r
27 import org.simantics.db.common.utils.NameUtils;
\r
28 import org.simantics.db.exception.DatabaseException;
\r
29 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
\r
30 import org.simantics.db.exception.ServiceException;
\r
31 import org.simantics.db.layer0.request.PossibleActiveVariableFromVariable;
\r
32 import org.simantics.db.layer0.variable.Variable;
\r
33 import org.simantics.diagram.stubs.DiagramResource;
\r
34 import org.simantics.jfreechart.ChartSelectionTabContributor;
\r
35 import org.simantics.jfreechart.chart.properties.xyline.XYLineGeneralPropertiesTab;
\r
36 import org.simantics.layer0.Layer0;
\r
37 import org.simantics.modeling.ModelingResources;
\r
38 import org.simantics.modeling.ui.property.svg.SVGElementComposite;
\r
39 import org.simantics.selectionview.ComparableTabContributor;
\r
40 import org.simantics.selectionview.SelectionProcessor;
\r
41 import org.simantics.simulation.ontology.SimulationResource;
\r
42 import org.simantics.sysdyn.JFreeChartResource;
\r
43 import org.simantics.sysdyn.SysdynResource;
\r
44 import org.simantics.sysdyn.ui.browser.nodes.SharedFunctionsFolder;
\r
45 import org.simantics.sysdyn.ui.trend.SensitivityChartAxisAndVariablesTab;
\r
46 import org.simantics.ui.selection.AnyVariable;
\r
47 import org.simantics.ui.selection.WorkbenchSelectionElement;
\r
48 import org.simantics.utils.ui.AdaptionUtils;
\r
49 import org.simantics.utils.ui.ISelectionUtils;
\r
52 * SelectionProcessor for processing selections for property view in system dynamics
\r
54 * @author Teemu Lempinen
\r
55 * @author Tuomas Miettinen
\r
58 public class ResourceSelectionProcessor implements SelectionProcessor<Object, ReadGraph> {
\r
60 private SpecialNodeType sharedFunctionsTestNode;
\r
63 public Collection<?> process(Object selection, ReadGraph backend) {
\r
64 List<ComparableTabContributor> tabs = new ArrayList<ComparableTabContributor>();
\r
65 SysdynResource sr = SysdynResource.getInstance(backend);
\r
66 DiagramResource dr = DiagramResource.getInstance(backend);
\r
67 ModelingResources mr = ModelingResources.getInstance(backend);
\r
68 SimulationResource simu = SimulationResource.getInstance(backend);
\r
69 // JFreeChartResource jfree = JFreeChartResource.getInstance(backend);
\r
72 if(sharedFunctionsTestNode == null)
\r
73 sharedFunctionsTestNode = new SpecialNodeType(sr.ModelingBrowseContext_SharedFunctionsFolder, Resource.class);
\r
77 if (selection instanceof ArrayList<?> && ((ArrayList<?>) selection).size() > 1) {
\r
78 List<Resource> variables = new ArrayList<Resource>();
\r
79 List<Resource> dependencies = new ArrayList<Resource>();
\r
80 List<Resource> flows = new ArrayList<Resource>();
\r
81 Resource model = null;
\r
82 for(Object o : (ArrayList<?>)selection) {
\r
83 Resource r = AdaptionUtils.adaptToSingle(o, Resource.class);
\r
86 Resource component = backend.getPossibleObject(r, mr.ElementToComponent);
\r
87 if (component != null) {
\r
91 Resource connection = backend.getPossibleObject(r, mr.DiagramConnectionToConnection);
\r
92 if(connection != null)
\r
98 model = backend.getPossibleObject(r, Layer0.getInstance(backend).PartOf);
\r
99 if(model != null && model.equals( backend.getSingleObject(r, Layer0.getInstance(backend).PartOf))) {
\r
100 if (backend.isInstanceOf(r, sr.Variable)) {
\r
102 } else if (backend.isInstanceOf(r, sr.Dependency)) {
\r
103 Resource diaConnection = backend.getPossibleObject(r, ModelingResources.getInstance(backend).ConnectionToDiagramConnection);
\r
104 dependencies.add(diaConnection);
\r
105 } else if (backend.isInstanceOf(r, sr.Flow)) {
\r
106 Resource diaConnection = backend.getPossibleObject(r, ModelingResources.getInstance(backend).ConnectionToDiagramConnection);
\r
107 flows.add(diaConnection);
\r
113 if (!variables.isEmpty())
\r
114 // Do we have at least one variable
\r
115 tabs.add(new ComparableTabContributor(
\r
116 new ArrayIndexesTab(),
\r
120 else if (!dependencies.isEmpty()) {
\r
121 // Dependencies only
\r
122 tabs.add(new ComparableTabContributor(
\r
123 new ArrayDependencyTab(),
\r
126 "Dependency Properties"));
\r
128 else if (!flows.isEmpty()) {
\r
130 tabs.add(new ComparableTabContributor(
\r
131 new ArrayFlowTab(),
\r
134 "Flow Properties"));
\r
140 Variable var = null;
\r
141 WorkbenchSelectionElement wse = ISelectionUtils.filterSingleSelection(selection, WorkbenchSelectionElement.class);
\r
143 var = wse.getContent(new AnyVariable(backend));
\r
145 var = AdaptionUtils.adaptToSingle(selection, Variable.class);
\r
147 Variable possibleActiveVariable = backend.syncRequest(new PossibleActiveVariableFromVariable(var));
\r
148 if(possibleActiveVariable != null)
\r
149 var = possibleActiveVariable;
\r
154 Resource r = AdaptionUtils.adaptToSingle(selection, Resource.class);
\r
156 // Selection is not directly a resource, try if it is a variable
\r
157 var = AdaptionUtils.adaptToSingle(selection, Variable.class);
\r
159 r = var.getRepresents(backend);
\r
163 // SharedFunctionsFolder has properties but no adapted resource
\r
164 SharedFunctionsFolder sff = AdaptionUtils.adaptToSingle(selection, SharedFunctionsFolder.class);
\r
166 return Collections.singleton(new ComparableTabContributor(
\r
167 new SharedFunctionLibrariesTab(),
\r
170 "Shared Functions"));
\r
173 return Collections.emptyList();
\r
176 NodeContext nc = AdaptionUtils.adaptToSingle(selection, NodeContext.class);
\r
178 NodeType type = nc.getConstant(NodeType.TYPE);
\r
179 if(type != null && type.equals(sharedFunctionsTestNode)) {
\r
180 return Collections.singleton(new ComparableTabContributor(
\r
181 new SharedFunctionLibrariesTab(),
\r
184 "Shared Functions"));
\r
188 // SVG elements in symbol editor
\r
189 if (backend.isInstanceOf(r, dr.SVGElement))
\r
190 return Collections.singleton(SVGElementComposite.make(r, 1, "SVG"));
\r
192 // if r == diagram element, change it to component
\r
193 if (backend.isInstanceOf(r, dr.Element)) {
\r
194 Resource component = backend.getPossibleObject(r, mr.ElementToComponent);
\r
195 if (component != null) {
\r
198 Resource connection = backend.getPossibleObject(r, mr.DiagramConnectionToConnection);
\r
199 if(connection != null)
\r
205 // Check that var has found the correct variable
\r
206 if(r != null && var != null) {
\r
207 if(!r.equals(var.getRepresents(backend)))
\r
208 // Var found the wrong variable. This may happen with ModuleType editors
\r
213 // If shadow variable, display properties of the original variable
\r
214 if(backend.isInstanceOf(r, sr.Shadow)) {
\r
215 Resource original = backend.getPossibleObject(r, sr.Shadow_original);
\r
216 if(original != null && var != null) {
\r
218 Variable parent = var.getParent(backend);
\r
219 var = parent.getPossibleChild(backend, NameUtils.getSafeName(backend, r));
\r
224 if(backend.isInstanceOf(r, sr.Loop)) {
\r
225 return Collections.singleton(
\r
226 (new ComparableTabContributor(
\r
233 // Independent variable
\r
234 if (backend.isInstanceOf(r, sr.IndependentVariable)) {
\r
235 Resource activeExpression = backend.getPossibleObject(r, sr.IndependentVariable_activeExpression);
\r
236 Resource expression = null;
\r
237 if(activeExpression != null)
\r
238 // if variable has active expression, display it
\r
239 expression = activeExpression;
\r
240 else if (backend.hasStatement(r, sr.Variable_expressionList)){
\r
241 // else display the first expression of the variable
\r
242 Resource expressions = backend.getPossibleObject(r, sr.Variable_expressionList);
\r
243 List<Resource> expressionList = ListUtils.toList(backend, expressions);
\r
244 if(expressionList.isEmpty()) {
\r
245 System.err.println("expressionList is empty for " + r);
\r
246 return Collections.emptyList();
\r
248 expression = expressionList.get(0);
\r
250 tabs.add(new ComparableTabContributor(
\r
253 var != null ? var : r,
\r
255 if(expression != null && backend.isInstanceOf(expression, sr.WithLookupExpression)) {
\r
256 // WithLookupExpression has its own extra tab for visual configuration
\r
257 tabs.add(new ComparableTabContributor(
\r
258 new LookupTableTab(),
\r
264 tabs.add(new ComparableTabContributor(
\r
265 new ArrayIndexesTab(),
\r
270 tabs.add(new ComparableTabContributor(
\r
271 new VariableInformationTab(),
\r
274 "Additional Information"));
\r
279 if (backend.isInstanceOf(r, sr.Input)) {
\r
280 tabs.add(new ComparableTabContributor(
\r
281 new InputVariableTab(),
\r
286 tabs.add(new ComparableTabContributor(
\r
287 new ArrayIndexesTab(),
\r
292 tabs.add(new ComparableTabContributor(
\r
293 new VariableInformationTab(),
\r
296 "Additional Information"));
\r
301 if (backend.isInstanceOf(r, sr.Enumeration)) {
\r
302 Object s = AdaptionUtils.adaptToSingle(selection, ISelection.class);
\r
305 // give either variable or the actual resource
\r
306 return Collections.singleton(new ComparableTabContributor(
\r
307 new EnumerationTab(),
\r
313 // Configuration and model. They both show the properties of the configuration
\r
314 if ( backend.isInstanceOf(r, sr.Configuration) || backend.isInstanceOf(r, sr.SysdynModel)) {
\r
315 if(!backend.isInstanceOf(r, sr.SysdynModel))
\r
316 r = backend.getPossibleObject(r, SimulationResource.getInstance(backend).IsConfigurationOf);
\r
318 return Collections.singleton(
\r
319 new ComparableTabContributor(
\r
320 new ConfigurationTab(),
\r
323 "Model Properties"));
\r
327 if (backend.isInstanceOf(r, sr.Module)){
\r
328 tabs.add(new ComparableTabContributor(
\r
332 "Module Properties"));
\r
333 tabs.add(new ComparableTabContributor(
\r
334 new ModuleParameterTab(),
\r
338 tabs.add(new ComparableTabContributor(
\r
339 new ModuleInputTab(),
\r
343 tabs.add(new ComparableTabContributor(
\r
344 new ModuleOutputTab(),
\r
351 // Playback experiment
\r
352 if (backend.isInstanceOf(r, sr.PlaybackExperiment))
\r
353 return Collections.singleton(
\r
354 new ComparableTabContributor(
\r
355 new PlaybackExperimentTab(),
\r
358 "Experiment Properties"));
\r
361 if (backend.isInstanceOf(r, sr.GameExperiment))
\r
362 return Collections.singleton(
\r
363 new ComparableTabContributor(
\r
364 new GameExperimentTab(),
\r
367 "Experiment Properties"));
\r
369 // Sensitivity analysis experiment
\r
370 if (backend.isInstanceOf(r, sr.SensitivityAnalysisExperiment))
\r
371 return Collections.singleton(
\r
372 new ComparableTabContributor(
\r
373 new SensitivityAnalysisExperimentTab(),
\r
376 "Experiment Properties"));
\r
378 // Default experiment
\r
379 if (backend.isInstanceOf(r, simu.Experiment))
\r
380 return Collections.singleton(
\r
381 new ComparableTabContributor(
\r
382 new ExperimentTab(),
\r
385 "Experiment Properties"));
\r
388 if (backend.isInstanceOf(r, sr.HistoryDataset))
\r
389 return Collections.singleton(
\r
390 new ComparableTabContributor(
\r
391 new HistoryDataTab(),
\r
394 "History Data Properties"));
\r
396 // Saved simulation result
\r
397 if (backend.isInstanceOf(r, sr.Result))
\r
398 return Collections.singleton(
\r
399 new ComparableTabContributor(
\r
403 "Result Properties"));
\r
406 if (backend.isInstanceOf(r, sr.Dependency))
\r
407 if (backend.hasStatement(r, sr.Dependency_refersTo)) {
\r
408 Resource diaConnection = backend.getPossibleObject(r, ModelingResources.getInstance(backend).ConnectionToDiagramConnection);
\r
409 return Collections.singleton(
\r
410 new ComparableTabContributor(
\r
411 new DependencyTab(),
\r
414 "Reference Properties"));
\r
416 Resource diaConnection = backend.getPossibleObject(r, ModelingResources.getInstance(backend).ConnectionToDiagramConnection);
\r
417 return Collections.singleton(
\r
418 new ComparableTabContributor(
\r
419 new DependencyTab(),
\r
422 "Dependency Properties"));
\r
426 if (backend.isInstanceOf(r, sr.Flow)) {
\r
427 Resource diaConnection = backend.getPossibleObject(r, ModelingResources.getInstance(backend).ConnectionToDiagramConnection);
\r
428 return Collections.singleton(
\r
429 new ComparableTabContributor(
\r
433 "Flow Properties"));
\r
436 // Module symbol. Modules in modules-folder are actually symbol resources
\r
437 if (backend.isInheritedFrom(r, sr.ModuleSymbol)) {
\r
438 // Find the component resource
\r
439 r = backend.getPossibleObject(r, mr.SymbolToComponentType);
\r
441 return Collections.singleton(
\r
442 new ComparableTabContributor(
\r
443 new ModuleTypeTab(),
\r
446 "Module Type Properties"));
\r
450 if (backend.isInstanceOf(r, sr.SysdynModelicaFunction)) {
\r
451 tabs.add(new ComparableTabContributor(
\r
456 tabs.add(new ComparableTabContributor(
\r
457 new ExternalFilesTab(),
\r
460 "External files"));
\r
464 // Function library
\r
465 if (backend.isInstanceOf(r, sr.SysdynModelicaFunctionLibrary)) {
\r
466 Object s = AdaptionUtils.adaptToSingle(selection, ISelection.class);
\r
469 // give either variable or the actual resource
\r
470 return Collections.singleton(new ComparableTabContributor(
\r
471 new FunctionLibraryTab(),
\r
474 "Function library"));
\r
477 // Try sensitivity chart before other charts
\r
478 if (contributeSensitivityChart(backend, r, tabs)) {
\r
482 // Try normal charts
\r
483 if (ChartSelectionTabContributor.contibuteTabs(backend, r, tabs)) {
\r
487 // Default experiment
\r
488 if (backend.isInstanceOf(r, sr.AdditionalSymbols_MultilineText))
\r
489 return Collections.singleton(
\r
490 new ComparableTabContributor(
\r
496 } catch (ServiceException e) {
\r
497 e.printStackTrace();
\r
498 } catch (ManyObjectsForFunctionalRelationException e) {
\r
499 e.printStackTrace();
\r
500 } catch (DatabaseException e) {
\r
501 e.printStackTrace();
\r
503 return Collections.emptyList();
\r
506 public static boolean contributeSensitivityChart(ReadGraph backend, Resource r, List<ComparableTabContributor> tabs) throws DatabaseException {
\r
507 JFreeChartResource jfree = JFreeChartResource.getInstance(backend);
\r
508 if(backend.isInstanceOf(r, jfree.ChartElement)) {
\r
509 if(backend.hasStatement(r, jfree.ChartElement_component))
\r
510 r = backend.getSingleObject(r, jfree.ChartElement_component);
\r
513 if (backend.isInstanceOf(r, jfree.Chart)) {
\r
515 Collection<Resource> plots = backend.syncRequest(new ObjectsWithType(r, Layer0.getInstance(backend).ConsistsOf, jfree.Plot));
\r
516 if(!plots.isEmpty()) {
\r
517 Resource plot = plots.iterator().next();
\r
519 if(backend.isInstanceOf(plot, SysdynResource.getInstance(backend).Charts_SensitivityPlot)) {
\r
520 tabs.add(new ComparableTabContributor(
\r
521 new XYLineGeneralPropertiesTab(),
\r
525 tabs.add(new ComparableTabContributor(
\r
526 new SensitivityChartAxisAndVariablesTab(),
\r
529 "Axis and Variables"));
\r