]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
40cbadefc777ba073b94b5d5a677a3bdfb2a038d
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\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
8  *\r
9  * Contributors:\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
13 \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
18 \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
53 \r
54 /**\r
55  * Composite for range controls in chart series properties\r
56  * @author Teemu Lempinen\r
57  *\r
58  */\r
59 public class RangeComposite extends Composite implements Widget {\r
60 \r
61     private Composite composite;\r
62     \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
68         composite = this;\r
69     }\r
70 \r
71     @Override\r
72     public void setInput(final ISessionContext context, final Object input) {\r
73         if(composite == null || composite.isDisposed())\r
74             return;\r
75 \r
76         final Resource series = AdaptionUtils.adaptToSingle(input, Resource.class);\r
77 \r
78         /*\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
82          */\r
83         context.getSession().asyncRequest(new Read<LinkedHashMap<String, Resource>>() {\r
84 \r
85             @Override\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
89 \r
90                 String realizationURI = ChartUtils.getCurrentRealizationURI(graph, series);\r
91                 String rvi = graph.getPossibleRelatedValue(series, jfree.variableRVI);\r
92                 if(rvi == null)\r
93                     return null;\r
94                 \r
95                 try {\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
99                     \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
107                         }\r
108                         return result;\r
109                     }\r
110                 } catch (DatabaseException e) {\r
111                     // No variable was found, return null\r
112                 }\r
113                 return null;\r
114             }\r
115 \r
116         }, new Listener<LinkedHashMap<String, Resource>>() {\r
117 \r
118             @Override\r
119             public void execute(LinkedHashMap<String, Resource> result) {\r
120                 if(isDisposed())\r
121                     return;\r
122 \r
123                 // Always modify the composite, even with null result\r
124                 composite.getDisplay().asyncExec(new RunnableWithObject(result) {\r
125                     @Override\r
126                     public void run() {\r
127                         if(composite == null || composite.isDisposed())\r
128                             return;\r
129 \r
130                         // Remove all content (even with null result)\r
131                         for(Control child : composite.getChildren())\r
132                             child.dispose();\r
133 \r
134                         if(getObject() == null)\r
135                             return;\r
136 \r
137                         // New widgetSupport for the combos\r
138                         WidgetSupportImpl support = new WidgetSupportImpl();\r
139 \r
140                         Label label;\r
141                         TrackedCombo combo;\r
142                         LinkedHashMap<?, ?> result = (LinkedHashMap<?, ?>)getObject();\r
143                         Iterator<?> iterator = result.keySet().iterator();\r
144                         \r
145                         // For each array index (enumeration), create a label and a combo \r
146                         int index = 0;\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
152                             \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
156 \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
162                             index++;\r
163                         }\r
164                         \r
165                         // Set the width of the combo \r
166                         GridLayout gl = (GridLayout)composite.getLayout();\r
167                         gl.numColumns = index;\r
168                         \r
169                         // Set input for the combos\r
170                         support.fireInput(context, input);\r
171                         \r
172                         /*\r
173                          *  Find out if this composite is located in a scrolled composite. \r
174                          *  If it is, resize the scrolled composite\r
175                          */\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
183                                 break;\r
184                             }\r
185                             previousParent = previousParent.getParent();\r
186                         }\r
187                     }\r
188                 });                    \r
189             }\r
190 \r
191             @Override\r
192             public void exception(Throwable t) {\r
193                 t.printStackTrace();\r
194             }\r
195 \r
196             @Override\r
197             public boolean isDisposed() {\r
198                 return composite == null || composite.isDisposed();\r
199             }\r
200         });\r
201     }\r
202 \r
203     /**\r
204      * \r
205      * @author Teemu Lempinen\r
206      *\r
207      */\r
208     private class RangeSelectionFactory extends ReadFactoryImpl<Resource, String> {\r
209 \r
210         int index;\r
211 \r
212         /**\r
213          * \r
214          * @param index Index of the enumeration in the variable\r
215          */\r
216         public RangeSelectionFactory(int index) {\r
217             this.index = index;\r
218         }\r
219 \r
220         public Object getIdentity(Object inputContents) {\r
221             return new Triple<Object, Integer, Class<?>>(inputContents, index, getClass());\r
222         }\r
223 \r
224         @Override\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
228             \r
229             /*\r
230              * If no filter was found or the index is not applicable, return "All"\r
231              */\r
232             if(filter == null)\r
233                 return "All";\r
234             else if(filter.length < index)\r
235                 return "All";\r
236             else\r
237                 return filter[index];\r
238         }\r
239 \r
240     }\r
241 \r
242     /**\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
246      *\r
247      */\r
248     private class RangeItemFactory extends ReadFactoryImpl<Resource, Map<String, Object>> {\r
249 \r
250         private int index;\r
251         private Resource enumeration;\r
252 \r
253         /**\r
254          * \r
255          * @param index Index of the enumeration in the variable\r
256          * @param enumeration The enumeration\r
257          */\r
258         public RangeItemFactory(int index, Resource enumeration) {\r
259             this.index = index;\r
260             this.enumeration = enumeration;\r
261         }\r
262 \r
263         public Object getIdentity(Object inputContents) {\r
264             return new Quad<Object, Integer, Resource, Class<?>>(inputContents, index, enumeration, getClass());\r
265         }\r
266         @Override\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
278             }\r
279             return result;\r
280         }\r
281     }\r
282 \r
283     /**\r
284      * RangeModifyListener for modifying a range filter in chart series \r
285      * @author Teemu Lempinen\r
286      *\r
287      */\r
288     private class RangeModifyListener  extends ComboModifyListenerImpl<Resource> {\r
289         \r
290         private int index, size;\r
291 \r
292         /**\r
293          * \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
296          */\r
297         public RangeModifyListener(int index, int size) {\r
298             this.index = index;\r
299             this.size = size;\r
300         }\r
301 \r
302         @Override\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
306             \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
311                     filter[i] = "All";\r
312                 }\r
313             }\r
314             \r
315             // Modify the filter index\r
316             filter[index] = text;\r
317             graph.claimLiteral(series, jfree.variableFilter, filter, Bindings.STRING_ARRAY);\r
318         }\r
319     }\r
320 }\r