1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2011 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.trend.chart.properties;
\r
14 import java.util.Iterator;
\r
15 import java.util.LinkedHashMap;
\r
16 import java.util.List;
\r
17 import java.util.Map;
\r
19 import org.eclipse.jface.layout.GridDataFactory;
\r
20 import org.eclipse.jface.layout.GridLayoutFactory;
\r
21 import org.eclipse.swt.SWT;
\r
22 import org.eclipse.swt.custom.ScrolledComposite;
\r
23 import org.eclipse.swt.graphics.Point;
\r
24 import org.eclipse.swt.layout.GridLayout;
\r
25 import org.eclipse.swt.widgets.Composite;
\r
26 import org.eclipse.swt.widgets.Control;
\r
27 import org.eclipse.swt.widgets.Label;
\r
28 import org.simantics.browsing.ui.swt.widgets.TrackedCombo;
\r
29 import org.simantics.browsing.ui.swt.widgets.impl.ComboModifyListenerImpl;
\r
30 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactoryImpl;
\r
31 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
\r
32 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
\r
33 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;
\r
34 import org.simantics.databoard.Bindings;
\r
35 import org.simantics.db.ReadGraph;
\r
36 import org.simantics.db.Resource;
\r
37 import org.simantics.db.WriteGraph;
\r
38 import org.simantics.db.common.utils.NameUtils;
\r
39 import org.simantics.db.common.utils.OrderedSetUtils;
\r
40 import org.simantics.db.exception.DatabaseException;
\r
41 import org.simantics.db.layer0.variable.Variable;
\r
42 import org.simantics.db.layer0.variable.Variables;
\r
43 import org.simantics.db.management.ISessionContext;
\r
44 import org.simantics.db.procedure.Listener;
\r
45 import org.simantics.db.request.Read;
\r
46 import org.simantics.sysdyn.JFreeChartResource;
\r
47 import org.simantics.sysdyn.SysdynResource;
\r
48 import org.simantics.sysdyn.ui.trend.chart.ChartUtils;
\r
49 import org.simantics.ui.utils.AdaptionUtils;
\r
50 import org.simantics.utils.RunnableWithObject;
\r
51 import org.simantics.utils.datastructures.Quad;
\r
52 import org.simantics.utils.datastructures.Triple;
\r
55 * Composite for range controls in chart series properties
\r
56 * @author Teemu Lempinen
\r
59 public class RangeComposite extends Composite implements Widget {
\r
61 private Composite composite;
\r
63 public RangeComposite(Composite parent, ISessionContext context, WidgetSupport support, int style) {
\r
64 super(parent, style);
\r
65 support.register(this);
\r
66 GridLayoutFactory.fillDefaults().spacing(3, 0).margins(3, 3).applyTo(this);
\r
67 GridDataFactory.fillDefaults().grab(true, false).applyTo(this);
\r
72 public void setInput(final ISessionContext context, final Object input) {
\r
73 if(composite == null || composite.isDisposed())
\r
76 final Resource series = AdaptionUtils.adaptToSingle(input, Resource.class);
\r
79 * Listen to the enumerations assigned to the variable in this series.
\r
80 * Listener is needed because the user can change the variableRVI for the series
\r
81 * and that changes the options for range
\r
83 context.getSession().asyncRequest(new Read<LinkedHashMap<String, Resource>>() {
\r
86 public LinkedHashMap<String, Resource> perform(ReadGraph graph) throws DatabaseException {
\r
87 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
88 SysdynResource sr = SysdynResource.getInstance(graph);
\r
90 String realizationURI = ChartUtils.getCurrentRealizationURI(graph, series);
\r
91 String rvi = graph.getPossibleRelatedValue(series, jfree.variableRVI);
\r
96 // Find the variable for the current variableRVI
\r
97 Variable v = Variables.getVariable(graph, realizationURI + rvi.trim());
\r
98 Resource variable = v.getRepresents(graph);
\r
100 // Return the enumerations assigned to that variable
\r
101 Resource arrayIndexes = graph.getPossibleObject(variable, sr.HasArrayIndexes);
\r
102 if(arrayIndexes != null) {
\r
103 LinkedHashMap<String, Resource> result = new LinkedHashMap<String, Resource>();
\r
104 for(Resource enumeration : OrderedSetUtils.toList(graph, arrayIndexes)) {
\r
105 String enumerationName = NameUtils.getSafeName(graph, enumeration);
\r
106 result.put(enumerationName, enumeration);
\r
110 } catch (DatabaseException e) {
\r
111 // No variable was found, return null
\r
116 }, new Listener<LinkedHashMap<String, Resource>>() {
\r
119 public void execute(LinkedHashMap<String, Resource> result) {
\r
123 // Always modify the composite, even with null result
\r
124 composite.getDisplay().asyncExec(new RunnableWithObject(result) {
\r
126 public void run() {
\r
127 if(composite == null || composite.isDisposed())
\r
130 // Remove all content (even with null result)
\r
131 for(Control child : composite.getChildren())
\r
134 if(getObject() == null)
\r
137 // New widgetSupport for the combos
\r
138 WidgetSupportImpl support = new WidgetSupportImpl();
\r
141 TrackedCombo combo;
\r
142 LinkedHashMap<?, ?> result = (LinkedHashMap<?, ?>)getObject();
\r
143 Iterator<?> iterator = result.keySet().iterator();
\r
145 // For each array index (enumeration), create a label and a combo
\r
147 while(iterator.hasNext()) {
\r
148 Object key = iterator.next();
\r
149 Composite c = new Composite(composite, SWT.NONE);
\r
150 GridDataFactory.fillDefaults().applyTo(c);
\r
151 GridLayoutFactory.fillDefaults().applyTo(c);
\r
153 label = new Label(c, SWT.NONE);
\r
154 label.setText((String)key);
\r
155 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.END).applyTo(label);
\r
157 combo = new TrackedCombo(c, support, SWT.READ_ONLY);
\r
158 combo.setItemFactory(new RangeItemFactory(index, (Resource)result.get(key)));
\r
159 combo.setSelectionFactory(new RangeSelectionFactory(index));
\r
160 combo.addModifyListener(new RangeModifyListener(index, result.size()));
\r
161 GridDataFactory.fillDefaults().applyTo(combo.getWidget());
\r
165 // Set the width of the combo
\r
166 GridLayout gl = (GridLayout)composite.getLayout();
\r
167 gl.numColumns = index;
\r
169 // Set input for the combos
\r
170 support.fireInput(context, input);
\r
173 * Find out if this composite is located in a scrolled composite.
\r
174 * If it is, resize the scrolled composite
\r
176 Composite previousParent = composite.getParent();
\r
177 for(int i = 0; i < 5; i++) {
\r
178 if(previousParent.getParent() instanceof ScrolledComposite) {
\r
179 previousParent.layout();
\r
180 ScrolledComposite sc = (ScrolledComposite) previousParent.getParent();
\r
181 Point size = previousParent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
\r
182 sc.setMinSize(size);
\r
185 previousParent = previousParent.getParent();
\r
192 public void exception(Throwable t) {
\r
193 t.printStackTrace();
\r
197 public boolean isDisposed() {
\r
198 return composite == null || composite.isDisposed();
\r
205 * @author Teemu Lempinen
\r
208 private class RangeSelectionFactory extends ReadFactoryImpl<Resource, String> {
\r
214 * @param index Index of the enumeration in the variable
\r
216 public RangeSelectionFactory(int index) {
\r
217 this.index = index;
\r
220 public Object getIdentity(Object inputContents) {
\r
221 return new Triple<Object, Integer, Class<?>>(inputContents, index, getClass());
\r
225 public String perform(ReadGraph graph, Resource series) throws DatabaseException {
\r
226 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
227 String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);
\r
230 * If no filter was found or the index is not applicable, return "All"
\r
234 else if(filter.length < index)
\r
237 return filter[index];
\r
243 * RangeItemFactory finds all inexes of a given enumeration
\r
244 * and adds "Sum" and "All" to the returned indexes
\r
245 * @author Teemu Lempinen
\r
248 private class RangeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {
\r
251 private Resource enumeration;
\r
255 * @param index Index of the enumeration in the variable
\r
256 * @param enumeration The enumeration
\r
258 public RangeItemFactory(int index, Resource enumeration) {
\r
259 this.index = index;
\r
260 this.enumeration = enumeration;
\r
263 public Object getIdentity(Object inputContents) {
\r
264 return new Quad<Object, Integer, Resource, Class<?>>(inputContents, index, enumeration, getClass());
\r
267 public Map<String, Object> perform(ReadGraph graph, Resource series) throws DatabaseException {
\r
268 SysdynResource sr = SysdynResource.getInstance(graph);
\r
269 LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();
\r
270 Resource enumerationIndexes = graph.getPossibleObject(enumeration, sr.HasEnumerationIndexes);
\r
271 List<Resource> indexes = OrderedSetUtils.toList(graph, enumerationIndexes);
\r
272 // First add "All" and "Sum", then all of the enumeration indexes in order
\r
273 result.put("All", "All");
\r
274 result.put("Sum", "Sum");
\r
275 for(Resource index : indexes) {
\r
276 String name = NameUtils.getSafeName(graph, index);
\r
277 result.put(name, name);
\r
284 * RangeModifyListener for modifying a range filter in chart series
\r
285 * @author Teemu Lempinen
\r
288 private class RangeModifyListener extends ComboModifyListenerImpl<Resource> {
\r
290 private int index, size;
\r
294 * @param index Index of the modified range filter
\r
295 * @param size Size of the whole filter (for situations where there is no filter)
\r
297 public RangeModifyListener(int index, int size) {
\r
298 this.index = index;
\r
303 public void applyText(WriteGraph graph, Resource series, String text) throws DatabaseException {
\r
304 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
305 String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);
\r
307 // If there is no filter, create a default filter with all indexes "All"
\r
308 if(filter == null) {
\r
309 filter = new String[size];
\r
310 for(int i = 0; i < filter.length; i++) {
\r
315 // Modify the filter index
\r
316 filter[index] = text;
\r
317 graph.claimLiteral(series, jfree.variableFilter, filter, Bindings.STRING_ARRAY);
\r