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
100 Resource variable = v.getRepresents(graph);
\r
102 // Return the enumerations assigned to that variable
\r
103 Resource arrayIndexes = graph.getPossibleObject(variable, sr.Variable_arrayIndexes);
\r
104 if(arrayIndexes != null) {
\r
105 LinkedHashMap<String, Resource> result = new LinkedHashMap<String, Resource>();
\r
106 for(Resource enumeration : OrderedSetUtils.toList(graph, arrayIndexes)) {
\r
107 String enumerationName = NameUtils.getSafeName(graph, enumeration);
\r
108 result.put(enumerationName, enumeration);
\r
112 } catch (DatabaseException e) {
\r
113 // No variable was found, return null
\r
118 }, new Listener<LinkedHashMap<String, Resource>>() {
\r
121 public void execute(LinkedHashMap<String, Resource> result) {
\r
125 // Always modify the composite, even with null result
\r
126 composite.getDisplay().asyncExec(new RunnableWithObject(result) {
\r
128 public void run() {
\r
129 if(composite == null || composite.isDisposed())
\r
132 // Remove all content (even with null result)
\r
133 for(Control child : composite.getChildren())
\r
136 if(getObject() == null)
\r
139 // New widgetSupport for the combos
\r
140 WidgetSupportImpl support = new WidgetSupportImpl();
\r
143 TrackedCombo combo;
\r
144 LinkedHashMap<?, ?> result = (LinkedHashMap<?, ?>)getObject();
\r
145 Iterator<?> iterator = result.keySet().iterator();
\r
147 // For each array index (enumeration), create a label and a combo
\r
149 while(iterator.hasNext()) {
\r
150 Object key = iterator.next();
\r
151 Composite c = new Composite(composite, SWT.NONE);
\r
152 GridDataFactory.fillDefaults().applyTo(c);
\r
153 GridLayoutFactory.fillDefaults().applyTo(c);
\r
155 label = new Label(c, SWT.NONE);
\r
156 label.setText((String)key);
\r
157 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.END).applyTo(label);
\r
159 combo = new TrackedCombo(c, support, SWT.READ_ONLY);
\r
160 combo.setItemFactory(new RangeItemFactory(index, (Resource)result.get(key)));
\r
161 combo.setSelectionFactory(new RangeSelectionFactory(index));
\r
162 combo.addModifyListener(new RangeModifyListener(index, result.size()));
\r
163 GridDataFactory.fillDefaults().applyTo(combo.getWidget());
\r
167 // Set the width of the combo
\r
168 GridLayout gl = (GridLayout)composite.getLayout();
\r
169 gl.numColumns = index;
\r
171 // Set input for the combos
\r
172 support.fireInput(context, input);
\r
175 * Find out if this composite is located in a scrolled composite.
\r
176 * If it is, resize the scrolled composite
\r
178 Composite previousParent = composite.getParent();
\r
179 for(int i = 0; i < 5; i++) {
\r
180 if(previousParent.getParent() instanceof ScrolledComposite) {
\r
181 previousParent.layout();
\r
182 ScrolledComposite sc = (ScrolledComposite) previousParent.getParent();
\r
183 Point size = previousParent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
\r
184 sc.setMinSize(size);
\r
187 previousParent = previousParent.getParent();
\r
194 public void exception(Throwable t) {
\r
195 t.printStackTrace();
\r
199 public boolean isDisposed() {
\r
200 return composite == null || composite.isDisposed();
\r
207 * @author Teemu Lempinen
\r
210 private class RangeSelectionFactory extends ReadFactoryImpl<Resource, String> {
\r
216 * @param index Index of the enumeration in the variable
\r
218 public RangeSelectionFactory(int index) {
\r
219 this.index = index;
\r
222 public Object getIdentity(Object inputContents) {
\r
223 return new Triple<Object, Integer, Class<?>>(inputContents, index, getClass());
\r
227 public String perform(ReadGraph graph, Resource series) throws DatabaseException {
\r
228 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
229 String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);
\r
232 * If no filter was found or the index is not applicable, return "All"
\r
236 else if(filter.length < index)
\r
239 return filter[index];
\r
245 * RangeItemFactory finds all inexes of a given enumeration
\r
246 * and adds "Sum" and "All" to the returned indexes
\r
247 * @author Teemu Lempinen
\r
250 private class RangeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {
\r
253 private Resource enumeration;
\r
257 * @param index Index of the enumeration in the variable
\r
258 * @param enumeration The enumeration
\r
260 public RangeItemFactory(int index, Resource enumeration) {
\r
261 this.index = index;
\r
262 this.enumeration = enumeration;
\r
265 public Object getIdentity(Object inputContents) {
\r
266 return new Quad<Object, Integer, Resource, Class<?>>(inputContents, index, enumeration, getClass());
\r
269 public Map<String, Object> perform(ReadGraph graph, Resource series) throws DatabaseException {
\r
270 SysdynResource sr = SysdynResource.getInstance(graph);
\r
271 LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>();
\r
272 Resource enumerationIndexes = graph.getPossibleObject(enumeration, sr.Enumeration_enumerationIndexes);
\r
273 List<Resource> indexes = OrderedSetUtils.toList(graph, enumerationIndexes);
\r
274 // First add "All" and "Sum", then all of the enumeration indexes in order
\r
275 result.put("All", "All");
\r
276 result.put("Sum", "Sum");
\r
277 for(Resource index : indexes) {
\r
278 String name = NameUtils.getSafeName(graph, index);
\r
279 result.put(name, name);
\r
286 * RangeModifyListener for modifying a range filter in chart series
\r
287 * @author Teemu Lempinen
\r
290 private class RangeModifyListener extends ComboModifyListenerImpl<Resource> {
\r
292 private int index, size;
\r
296 * @param index Index of the modified range filter
\r
297 * @param size Size of the whole filter (for situations where there is no filter)
\r
299 public RangeModifyListener(int index, int size) {
\r
300 this.index = index;
\r
305 public void applyText(WriteGraph graph, Resource series, String text) throws DatabaseException {
\r
306 JFreeChartResource jfree = JFreeChartResource.getInstance(graph);
\r
307 String[] filter = graph.getPossibleRelatedValue(series, jfree.variableFilter, Bindings.STRING_ARRAY);
\r
309 // If there is no filter, create a default filter with all indexes "All"
\r
310 if(filter == null) {
\r
311 filter = new String[size];
\r
312 for(int i = 0; i < filter.length; i++) {
\r
317 // Modify the filter index
\r
318 filter[index] = text;
\r
319 graph.claimLiteral(series, jfree.variableFilter, filter, Bindings.STRING_ARRAY);
\r