import org.simantics.simulation.experiment.IExperiment;\r
import org.simantics.simulation.project.IExperimentManager;\r
import org.simantics.sysdyn.adapter.SysdynVariableProperties;\r
+import org.simantics.sysdyn.adapter.VariableRVIUtils;\r
+import org.simantics.sysdyn.manager.SysdynDataSet;\r
import org.simantics.sysdyn.manager.SysdynPlaybackExperiment;\r
import org.simantics.ui.SimanticsUI;\r
import org.simantics.utils.datastructures.Triple;\r
*\r
*/\r
public class SimulationPlaybackStyle extends StyleBase<Triple<AffineTransform, Double, ColorGradient>> {\r
- \r
+\r
Resource gradientResource;\r
ColorGradient cg;\r
byte[] gradient;\r
- \r
+\r
/**\r
* Determine if style needs to be redrawn and return objects that are needed to redraw the style.\r
* \r
*/\r
@Override\r
public Triple<AffineTransform, Double, ColorGradient> calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException {\r
- \r
+\r
// Find SimulationPlaybackExperiment\r
IProject project = SimanticsUI.getProject();\r
IExperimentManager em = project.getHint(IExperimentManager.KEY_EXPERIMENT_MANAGER);\r
IExperiment experiment = em.getActiveExperiment();\r
if(!(experiment instanceof SysdynPlaybackExperiment))\r
return null;\r
- \r
+\r
ModelingResources mr = ModelingResources.getInstance(graph);\r
DiagramResource dr = DiagramResource.getInstance(graph);\r
\r
ColorGradient cg = null;\r
- \r
+\r
Resource component = graph.getPossibleObject(element, mr.ElementToComponent);\r
if (component == null)\r
return null;\r
Variable var = diagramVariable.browsePossible(graph, component);\r
if(var == null)\r
return null;\r
- \r
- // Get simulation rsult values for this component\r
- double[] va = var.getPossiblePropertyValue(graph, SysdynVariableProperties.VALUES , Bindings.DOUBLE_ARRAY);\r
- if(va == null || va.length < 2)\r
+\r
+ // Get simulation result values for this component\r
+ // Get values\r
+ Object object = var.getPossiblePropertyValue(graph, SysdynVariableProperties.ACTIVE_DATASETS , Bindings.VARIANT);\r
+ if(object == null || !(object instanceof ArrayList<?>))\r
+ return null;\r
+\r
+ ArrayList<SysdynDataSet> datasets = new ArrayList<SysdynDataSet>();\r
+\r
+ for(Object o : (ArrayList<?>)object) {\r
+ if(o instanceof SysdynDataSet)\r
+ datasets.add((SysdynDataSet)o);\r
+ }\r
+\r
+ if(datasets.size() == 0)\r
return null;\r
+\r
+ if(datasets.size() > 1) {\r
+ String range = datasets.get(0).name.substring(\r
+ datasets.get(0).name.indexOf('[') + 1,\r
+ datasets.get(0).name.indexOf(']'));\r
+ int size = range.split(",").length;\r
+ String[] filter = new String[size];\r
+ for(int i = 0; i < size; i++)\r
+ filter[i] = "Sum";\r
+\r
+ ArrayList<SysdynDataSet> result2 = VariableRVIUtils.getDataset(datasets, filter);\r
+ if(result2 != null) {\r
+ datasets = result2;\r
+ }\r
+\r
+ }\r
+\r
+ // The datasets list should always be size == 1\r
+ SysdynDataSet dataset = datasets.get(0);\r
\r
+ // Get values (or sum of values)\r
+ double[] va = dataset.values;\r
+ if(va.length < 2)\r
+ return null;\r
+\r
// Get simulation timesteps for this component\r
- double[] ta = var.getPossiblePropertyValue(graph, SysdynVariableProperties.TIMES , Bindings.DOUBLE_ARRAY);\r
+ double[] ta = dataset.times;\r
if(ta == null || ta.length < 2)\r
return null;\r
- \r
+\r
if(va.length == 0 || va.length == 2)\r
return null;\r
- \r
+\r
// Get playback time from the experiment\r
Double time = var.getPossiblePropertyValue(graph, SysdynVariableProperties.TIME , Bindings.DOUBLE);\r
if(time == null)\r
return null;\r
- \r
+\r
// Find minimum and maximum values for this variable\r
double min = va[0], max = va[0];\r
for(double d : va) {\r
if(d > max)\r
max = d;\r
}\r
- \r
+\r
// Find the index in time and value arrays for this time \r
// (time steps may vary, we need to loop to find the correct time) \r
int index = 0;\r
while(ta[index] < time && index < ta.length - 1)\r
index++;\r
}\r
- \r
+\r
double value = va[index];\r
- \r
+\r
// Calculate where the value is located between min and max values [0..1]. \r
double multiplier = (value - min) / (max - min);\r
\r
- \r
+\r
// Get the transform of this element\r
AffineTransform at = (AffineTransform) DiagramGraphUtil.getAffineTransform(graph, element, G2DResource.getInstance(graph).HasTransform, true).clone();\r
- \r
+\r
// Find the gradient used to draw this style\r
G2DResource g2d = G2DResource.getInstance(graph);\r
Resource gradient = graph.getPossibleObject(experiment.getResource(), g2d.HasColorGradient);\r
} else {\r
cg = this.cg;\r
}\r
- \r
+\r
return new Triple<AffineTransform, Double, ColorGradient>(at, multiplier, cg);\r
- \r
+\r
} catch(Exception ignore) {\r
ignore.printStackTrace();\r
}\r
public void applyStyleForNode(EvaluationContext observer, INode _node, Triple<AffineTransform, Double, ColorGradient> result) {\r
Double multiplier;\r
if (result != null && (multiplier = result.second) != null && !multiplier.isNaN()) {\r
- \r
+\r
// Create a node that will show the style effect\r
A node = ProfileVariables.claimChild(_node, "", "playbackColour", A.class, observer);\r
if (node == null)\r
this.cg = result.third;\r
this.gradient = cg.getGradientArray(101);\r
}\r
- \r
+\r
// Get integer values for red, green and blue\r
int i = (int)(multiplier * 100);\r
int r = (int)(gradient[i * 3 + 0] & 0xff);\r
node.setStroke(null);\r
node.setValue("shape", expandedElementBounds);\r
node.setTransform(at);\r
- \r
+\r
// Find z-index for the TextNode associated with the element and place the style node just below that text node \r
int zIndex = -1;\r
if(n != null) {\r
protected void cleanupStyleForNode(INode node) {\r
ProfileVariables.denyChild(node, "", "playbackColour");\r
}\r
- \r
- \r
+\r
+\r
/**\r
* Dummy class for displaying the style\r
* \r
public Rectangle2D getBounds() {\r
return null;\r
}\r
- \r
+\r
}\r
}\r
Resource seriesList = graph.getPossibleObject(resource, jfree.Dataset_seriesList);\r
if(seriesList != null)\r
this.seriesList = ListUtils.toList(graph, seriesList);\r
- \r
+\r
Resource rendererResource = graph.getPossibleObject(resource, jfree.Dataset_renderer);\r
renderer = graph.adapt(rendererResource, IRenderer.class);\r
- \r
+\r
} catch (DatabaseException e) {\r
e.printStackTrace();\r
}\r
}\r
\r
private DatasetListener listener;\r
- \r
+\r
@Override\r
public Dataset getDataset() {\r
- \r
+\r
if(seriesList == null || seriesList.isEmpty())\r
return null;\r
\r
if(dataset == null) {\r
dataset = new DefaultCategoryDataset();\r
}\r
- \r
+\r
if(listener == null || listener.isDisposed()) {\r
listener = new DatasetListener();\r
SimanticsUI.getSession().asyncRequest(new Read<ArrayList<TempSeries>>() {\r
try {\r
// Get a variable for the series\r
Variable v = Variables.getVariable(graph, realizationURI + rvi);\r
- \r
+\r
// Get values\r
Object object = v.getPossiblePropertyValue(graph, SysdynVariableProperties.ACTIVE_DATASETS , Bindings.VARIANT);\r
if(object == null || !(object instanceof ArrayList<?>))\r
return series;\r
- \r
+\r
ArrayList<SysdynDataSet> datasets = new ArrayList<SysdynDataSet>();\r
- \r
+\r
for(Object o : (ArrayList<?>)object) {\r
if(o instanceof SysdynDataSet)\r
datasets.add((SysdynDataSet)o);\r
}\r
- \r
+\r
String[] filter = graph.getPossibleRelatedValue(r, jfree.variableFilter);\r
if(filter != null) {\r
ArrayList<SysdynDataSet> result2 = VariableRVIUtils.getDataset(datasets, filter);\r
datasets = result2;\r
}\r
}\r
- \r
+\r
for(SysdynDataSet dataset : datasets) {\r
double[] va = dataset.values;\r
- \r
- \r
+\r
+\r
if(va == null || va.length == 0)\r
continue;\r
\r
public AbstractRenderer getRenderer() {\r
return renderer.getRenderer();\r
}\r
- \r
+\r
private class DatasetListener implements Listener<ArrayList<TempSeries>> {\r
private boolean disposed = false;\r
- \r
+\r
public void dispose() {\r
disposed = true;\r
}\r
\r
// Remove all unused series\r
dataset.clear();\r
- ((BarRenderer)getRenderer()).getPlot().setDrawingSupplier(new DefaultDrawingSupplier());\r
- \r
+ BarRenderer renderer = ((BarRenderer)getRenderer());\r
+ renderer.getPlot().setDrawingSupplier(new DefaultDrawingSupplier());\r
+\r
// Add found series\r
for(int i = 0; i < series.size(); i++) {\r
TempSeries s = series.get(i);\r
- dataset.addValue(s.value, s.series, s.name);\r
+ if(renderer instanceof org.jfree.chart.renderer.category.StackedBarRenderer) {\r
+ String category = s.name.substring(0, s.name.indexOf('['));\r
+ String series = s.name.substring(s.name.indexOf('['));\r
+ dataset.addValue(s.value, series, category);\r
+ } else {\r
+ dataset.addValue(s.value, s.series, s.name);\r
+ }\r
}\r
}\r
});\r
return disposed;\r
}\r
};\r
- \r
+\r
@Override\r
public void dispose() {\r
super.dispose();\r
frame = SWT_AWT.new_Frame(composite);\r
\r
// Add a listener displaying the contents of the chart. Chart is re-drawn if the definition changes\r
- Simantics.getSession().asyncRequest(new Read<JFreeChart>() {\r
+ Simantics.getSession().asyncRequest(new Read<IJFreeChart>() {\r
\r
@Override\r
- public JFreeChart perform(ReadGraph graph) throws DatabaseException {\r
+ public IJFreeChart perform(ReadGraph graph) throws DatabaseException {\r
// Adapt chartResource to a chart (XY, pie, bar, ...)\r
if(graph.isInstanceOf(chartResource, JFreeChartResource.getInstance(graph).Chart)) {\r
if(chart != null)\r
chart.dispose();\r
chart = graph.adapt(chartResource, IJFreeChart.class);\r
- return chart.getChart();\r
+ return chart;\r
} else {\r
return null;\r
}\r
}\r
\r
- } , new AsyncListener<JFreeChart>() {\r
+ } , new AsyncListener<IJFreeChart>() {\r
\r
@Override\r
public boolean isDisposed() {\r
}\r
\r
@Override\r
- public void execute(AsyncReadGraph graph, JFreeChart chart) {\r
+ public void execute(AsyncReadGraph graph, IJFreeChart chart) {\r
if(chart == null)\r
return;\r
+ \r
+ JFreeChart jfreeChart = chart.getChart();\r
// Display the result chart\r
- composite.getDisplay().asyncExec(new RunnableWithObject(chart) {\r
+ composite.getDisplay().asyncExec(new RunnableWithObject(jfreeChart) {\r
\r
@Override\r
public void run() {\r
*******************************************************************************/\r
package org.simantics.sysdyn.ui.trend.chart.properties.bar;\r
\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
import org.eclipse.jface.layout.GridDataFactory;\r
import org.eclipse.jface.layout.GridLayoutFactory;\r
import org.eclipse.swt.SWT;\r
import org.eclipse.swt.custom.ScrolledComposite;\r
import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.widgets.Combo;\r
import org.eclipse.swt.widgets.Composite;\r
import org.eclipse.swt.widgets.Group;\r
import org.eclipse.swt.widgets.Label;\r
import org.simantics.browsing.ui.swt.widgets.Button;\r
import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedCombo;\r
import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl;\r
import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;\r
import org.simantics.browsing.ui.swt.widgets.impl.TextModifyListener;\r
import org.simantics.browsing.ui.swt.widgets.impl.TrackedModifyEvent;\r
import org.simantics.db.exception.DatabaseException;\r
import org.simantics.db.management.ISessionContext;\r
import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.direct.GraphUtils;\r
import org.simantics.sysdyn.JFreeChartResource;\r
import org.simantics.sysdyn.ui.properties.LabelPropertyTabContributor;\r
import org.simantics.sysdyn.ui.trend.chart.properties.BooleanPropertyFactory;\r
private Composite composite;\r
private Button hgrid, htitle, hlegend;\r
private TrackedText name, title;\r
- private Combo type;\r
+ private TrackedCombo type;\r
private TrackedSpinner angle;\r
\r
@Override\r
GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(label);\r
label.setText("Type:");\r
\r
- type = new Combo(c, SWT.BORDER | SWT.READ_ONLY);\r
- type.setItems(new String[] {"Normal", "Stacked"});\r
- type.select(0);\r
+ type = new TrackedCombo(c, support, SWT.BORDER | SWT.READ_ONLY);\r
+ type.addModifyListener(new TypeModifyListener());\r
+ type.setItemFactory(new TypeItemFactory());\r
+ type.setSelectionFactory(new TypeSelectionFactory());\r
+ GridDataFactory.fillDefaults().applyTo(type.getWidget());\r
\r
// Title (Which is different than name)\r
label = new Label(general, SWT.NONE);\r
sc.setMinSize(size);\r
}\r
\r
+ /**\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeSelectionFactory extends ReadFactoryImpl<Resource, String> {\r
+ @Override\r
+ public String perform(ReadGraph graph, Resource chart) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ \r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.CategoryPlot));\r
+ if(plot != null) {\r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.CategoryDataset));\r
+ \r
+ if(dataset != null) {\r
+ Resource renderer = graph.syncRequest(new PossibleObjectWithType(dataset, l0.ConsistsOf, jfree.Dataset_renderer));\r
+\r
+ if(renderer != null && graph.isInstanceOf(renderer, jfree.StackedBarRenderer))\r
+ return "Stacked";\r
+ }\r
+ }\r
+ return "Normal";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * RangeItemFactory finds all inexes of a given enumeration \r
+ * and adds "Sum" and "All" to the returned indexes\r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {\r
+ @Override\r
+ public Map<String, Object> perform(ReadGraph graph, Resource series) throws DatabaseException {\r
+ LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();\r
+ result.put("Normal", "Normal");\r
+ result.put("Stacked", "Stacked");\r
+ return result;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * TypeModifyListener for modifying the type of a bar chart \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+ private class TypeModifyListener extends ComboModifyListenerImpl<Resource> {\r
+ @Override\r
+ public void applyText(WriteGraph graph, Resource chart, String text) throws DatabaseException {\r
+ JFreeChartResource jfree = JFreeChartResource.getInstance(graph);\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+ Resource plot = graph.syncRequest(new PossibleObjectWithType(chart, l0.ConsistsOf, jfree.CategoryPlot));\r
+ if(plot == null)\r
+ return;\r
+\r
+ Resource dataset = graph.syncRequest(new PossibleObjectWithType(plot, l0.ConsistsOf, jfree.CategoryDataset));\r
+ if(dataset == null)\r
+ return;\r
+\r
+ graph.deny(dataset, jfree.Dataset_renderer);\r
+\r
+ Resource renderer;\r
+ if(text.equals("Stacked"))\r
+ renderer = GraphUtils.create2(graph, jfree.StackedBarRenderer);\r
+ else\r
+ renderer = GraphUtils.create2(graph, jfree.BarRenderer);\r
+\r
+ graph.claim(dataset, jfree.Dataset_renderer, renderer);\r
+ }\r
+ }\r
+\r
+\r
+\r
/**\r
* ModifyListener for the angle {@link TrackedSpinner}\r
* \r