Mercurial > dive4elements > river
comparison flys-client/src/main/java/de/intevation/flys/client/client/ui/QSegmentedInputPanel.java @ 4133:c722c08cf502
Merged heads.
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Mon, 15 Oct 2012 09:31:50 +0200 |
parents | 4ffeccc5b5a1 |
children | 03de5c424f95 |
comparison
equal
deleted
inserted
replaced
4132:f6c73ee1b7f1 | 4133:c722c08cf502 |
---|---|
1 package de.intevation.flys.client.client.ui; | |
2 | |
3 import java.util.ArrayList; | |
4 import java.util.HashMap; | |
5 import java.util.Iterator; | |
6 import java.util.LinkedHashMap; | |
7 import java.util.List; | |
8 import java.util.Map; | |
9 | |
10 import com.google.gwt.core.client.GWT; | |
11 import com.google.gwt.i18n.client.NumberFormat; | |
12 import com.google.gwt.user.client.rpc.AsyncCallback; | |
13 | |
14 import com.smartgwt.client.types.TitleOrientation; | |
15 import com.smartgwt.client.types.VerticalAlignment; | |
16 import com.smartgwt.client.util.SC; | |
17 import com.smartgwt.client.widgets.Canvas; | |
18 import com.smartgwt.client.widgets.Label; | |
19 import com.smartgwt.client.widgets.form.DynamicForm; | |
20 import com.smartgwt.client.widgets.form.fields.RadioGroupItem; | |
21 import com.smartgwt.client.widgets.form.fields.events.BlurHandler; | |
22 import com.smartgwt.client.widgets.form.fields.events.BlurEvent; | |
23 import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; | |
24 import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; | |
25 import com.smartgwt.client.widgets.layout.HLayout; | |
26 import com.smartgwt.client.widgets.layout.VLayout; | |
27 import com.smartgwt.client.widgets.tab.TabSet; | |
28 import com.smartgwt.client.widgets.tab.Tab; | |
29 | |
30 import de.intevation.flys.client.shared.model.Data; | |
31 import de.intevation.flys.client.shared.model.DataItem; | |
32 import de.intevation.flys.client.shared.model.DataList; | |
33 import de.intevation.flys.client.shared.model.DefaultData; | |
34 import de.intevation.flys.client.shared.model.DefaultDataItem; | |
35 import de.intevation.flys.client.shared.model.WQDataItem; | |
36 import de.intevation.flys.client.shared.model.WQInfoObject; | |
37 import de.intevation.flys.client.shared.model.WQInfoRecord; | |
38 import de.intevation.flys.client.shared.model.ArtifactDescription; | |
39 | |
40 | |
41 import de.intevation.flys.client.client.FLYSConstants; | |
42 import de.intevation.flys.client.client.Config; | |
43 import de.intevation.flys.client.client.services.WQInfoService; | |
44 import de.intevation.flys.client.client.services.WQInfoServiceAsync; | |
45 import de.intevation.flys.client.client.ui.wq.WTable; | |
46 import de.intevation.flys.client.client.ui.wq.QDTable; | |
47 | |
48 | |
49 /** | |
50 * This UIProvider creates a widget to enter Q values per segment. | |
51 */ | |
52 public class QSegmentedInputPanel | |
53 extends AbstractUIProvider | |
54 implements ChangeHandler, BlurHandler | |
55 { | |
56 public static final String FIELD_WQ_MODE = "wq_isq"; | |
57 public static final String FIELD_WQ_Q = "Q"; | |
58 | |
59 public static final String GAUGE_SEPARATOR = ":"; | |
60 | |
61 public static final String GAUGE_PART_SEPARATOR = ";"; | |
62 | |
63 public static final String VALUE_SEPARATOR = ","; | |
64 | |
65 public static final int ROW_HEIGHT = 20; | |
66 | |
67 /** The constant field name for choosing single values or range.*/ | |
68 public static final String FIELD_MODE = "mode"; | |
69 | |
70 /** The constant field value for range input mode.*/ | |
71 public static final String FIELD_MODE_RANGE = "range"; | |
72 | |
73 protected WQInfoServiceAsync wqInfoService = | |
74 GWT.create(WQInfoService.class); | |
75 | |
76 /** The message class that provides i18n strings.*/ | |
77 protected FLYSConstants MSG = GWT.create(FLYSConstants.class); | |
78 | |
79 /** Stores the input panels related to their keys.*/ | |
80 protected Map<String, DoubleArrayPanel> wqranges; | |
81 | |
82 /** Stores the min/max values for each q range.*/ | |
83 protected Map<String, double[]> qranges; | |
84 | |
85 protected QDTable qdTable; | |
86 | |
87 protected WTable wTable; | |
88 | |
89 protected TabSet tabs; | |
90 | |
91 | |
92 public QSegmentedInputPanel() { | |
93 wqranges = new HashMap<String, DoubleArrayPanel>(); | |
94 qranges = new HashMap<String, double[]>(); | |
95 qdTable = new QDTable(); | |
96 wTable = new WTable(); | |
97 } | |
98 | |
99 | |
100 /** Create main UI Canvas. */ | |
101 public Canvas create(DataList data) { | |
102 initHelperPanel(); | |
103 | |
104 Canvas submit = getNextButton(); | |
105 Canvas widget = createWidget(data); | |
106 Label label = new Label(MSG.wqadaptedTitle()); | |
107 | |
108 label.setHeight(25); | |
109 | |
110 VLayout layout = new VLayout(); | |
111 layout.setMembersMargin(10); | |
112 layout.setWidth(350); | |
113 | |
114 layout.addMember(label); | |
115 layout.addMember(widget); | |
116 layout.addMember(submit); | |
117 | |
118 return layout; | |
119 } | |
120 | |
121 | |
122 protected void initHelperPanel() { | |
123 tabs = new TabSet(); | |
124 tabs.setWidth100(); | |
125 tabs.setHeight100(); | |
126 | |
127 // TODO i18n | |
128 Tab qTab = new Tab("Q / D"); | |
129 | |
130 qTab.setPane(qdTable); | |
131 qdTable.hideIconFields(); | |
132 | |
133 tabs.addTab(qTab, 1); | |
134 | |
135 helperContainer.addMember(tabs); | |
136 | |
137 // TODO Q only would suffice. | |
138 fetchWQData(); | |
139 } | |
140 | |
141 | |
142 /** Create display for passive mode. */ | |
143 public Canvas createOld(DataList dataList) { | |
144 List<Data> all = dataList.getAll(); | |
145 Data wqData = getData(all, "ranges"); | |
146 | |
147 Canvas back = getBackButton(dataList.getState()); | |
148 | |
149 HLayout valLayout = new HLayout(); | |
150 VLayout vlayout = new VLayout(); | |
151 Label wqLabel = new Label(dataList.getLabel()); | |
152 | |
153 wqLabel.setValign(VerticalAlignment.TOP); | |
154 | |
155 wqLabel.setWidth(200); | |
156 wqLabel.setHeight(25); | |
157 | |
158 valLayout.addMember(wqLabel); | |
159 valLayout.addMember(createOldWQValues(wqData)); | |
160 valLayout.addMember(back); | |
161 | |
162 vlayout.addMember(valLayout); | |
163 | |
164 return vlayout; | |
165 } | |
166 | |
167 | |
168 /** Create canvas showing previously entered values. */ | |
169 protected Canvas createOldWQValues(Data wqData) { | |
170 VLayout layout = new VLayout(); | |
171 | |
172 //TODO: Sort by first field, numerically. | |
173 | |
174 DataItem item = wqData.getItems()[0]; | |
175 String value = item.getStringValue(); | |
176 | |
177 String[] gauges = value.split(GAUGE_SEPARATOR); | |
178 | |
179 for (String gauge: gauges) { | |
180 HLayout h = new HLayout(); | |
181 | |
182 String[] parts = gauge.split(GAUGE_PART_SEPARATOR); | |
183 String[] values = parts[2].split(VALUE_SEPARATOR); | |
184 | |
185 Label l = new Label(parts[0] + " - " + parts[1] + ": "); | |
186 | |
187 StringBuilder sb = new StringBuilder(); | |
188 boolean first = true; | |
189 | |
190 for (String v: values) { | |
191 if (!first) { | |
192 sb.append(", "); | |
193 } | |
194 | |
195 sb.append(v); | |
196 | |
197 first = false; | |
198 } | |
199 | |
200 Label v = new Label(sb.toString()); | |
201 | |
202 l.setWidth(65); | |
203 v.setWidth(65); | |
204 | |
205 h.addMember(l); | |
206 h.addMember(v); | |
207 | |
208 layout.addMember(h); | |
209 } | |
210 | |
211 return layout; | |
212 } | |
213 | |
214 | |
215 protected Canvas createWidget(DataList dataList) { | |
216 VLayout layout = new VLayout(); | |
217 | |
218 Canvas list = createList(dataList); | |
219 | |
220 DataItem[] items = getWQItems(dataList); | |
221 int listHeight = ROW_HEIGHT * items.length; | |
222 | |
223 layout.addMember(list); | |
224 | |
225 layout.setHeight(25 + listHeight); | |
226 layout.setWidth(350); | |
227 | |
228 return layout; | |
229 } | |
230 | |
231 | |
232 @Override | |
233 public List<String> validate() { | |
234 List<String> errors = new ArrayList<String>(); | |
235 NumberFormat nf = NumberFormat.getDecimalFormat(); | |
236 | |
237 Iterator<String> iter = wqranges.keySet().iterator(); | |
238 | |
239 while (iter.hasNext()) { | |
240 List<String> tmpErrors = new ArrayList<String>(); | |
241 | |
242 String key = iter.next(); | |
243 DoubleArrayPanel dap = wqranges.get(key); | |
244 | |
245 if (!dap.validateForm()) { | |
246 errors.add(MSG.error_invalid_double_value()); | |
247 return errors; | |
248 } | |
249 | |
250 double[] mm = qranges.get(key); | |
251 if (mm == null) { | |
252 SC.warn(MSG.error_read_minmax_values()); | |
253 continue; | |
254 } | |
255 | |
256 double[] values = dap.getInputValues(); | |
257 // might geht npe here if one field not filled | |
258 double[] good = new double[values.length]; | |
259 | |
260 int idx = 0; | |
261 | |
262 for (double value: values) { | |
263 if (value < mm[0] || value > mm[1]) { | |
264 String tmp = MSG.error_validate_range(); | |
265 tmp = tmp.replace("$1", nf.format(value)); | |
266 tmp = tmp.replace("$2", nf.format(mm[0])); | |
267 tmp = tmp.replace("$3", nf.format(mm[1])); | |
268 tmpErrors.add(tmp); | |
269 } | |
270 else { | |
271 good[idx++] = value; | |
272 } | |
273 } | |
274 | |
275 double[] justGood = new double[idx]; | |
276 for (int i = 0; i < justGood.length; i++) { | |
277 justGood[i] = good[i]; | |
278 } | |
279 | |
280 if (!tmpErrors.isEmpty()) { | |
281 dap.setValues(justGood); | |
282 | |
283 errors.addAll(tmpErrors); | |
284 } | |
285 } | |
286 | |
287 return errors; | |
288 } | |
289 | |
290 | |
291 protected Canvas createList(DataList dataList) { | |
292 VLayout layout = new VLayout(); | |
293 | |
294 DataItem[] items = getWQItems(dataList); | |
295 | |
296 for (DataItem item: items) { | |
297 String title = item.getLabel(); | |
298 | |
299 DoubleArrayPanel dap = new DoubleArrayPanel( | |
300 createLineTitle(title), null, this, TitleOrientation.LEFT); | |
301 | |
302 wqranges.put(title, dap); | |
303 | |
304 if (item instanceof WQDataItem) { | |
305 WQDataItem wq = (WQDataItem) item; | |
306 double[] mmQ = wq.getQRange(); | |
307 double[] mmW = wq.getWRange(); | |
308 | |
309 qranges.put(title, mmQ); | |
310 } | |
311 | |
312 layout.addMember(dap); | |
313 } | |
314 | |
315 layout.setHeight(items.length * ROW_HEIGHT); | |
316 | |
317 return layout; | |
318 } | |
319 | |
320 | |
321 protected DataItem[] getWQItems(DataList dataList) { | |
322 List<Data> data = dataList.getAll(); | |
323 | |
324 for (Data d: data) { | |
325 String name = d.getLabel(); | |
326 | |
327 // TODO to be gone | |
328 if (name.equals(FIELD_WQ_MODE)) { | |
329 continue; | |
330 } | |
331 | |
332 return d.getItems(); | |
333 } | |
334 | |
335 return null; | |
336 } | |
337 | |
338 | |
339 | |
340 public String createLineTitle(String key) { | |
341 String[] splitted = key.split(";"); | |
342 | |
343 return splitted[0] + " - " + splitted[1]; | |
344 } | |
345 | |
346 | |
347 public Data[] getData() { | |
348 Data values = getWQValues(); | |
349 | |
350 return new Data[] { values }; | |
351 } | |
352 | |
353 | |
354 protected Data getWQValues() { | |
355 String wqvalue = null; | |
356 | |
357 Iterator<String> iter = wqranges.keySet().iterator(); | |
358 while (iter.hasNext()) { | |
359 String key = iter.next(); | |
360 DoubleArrayPanel dap = wqranges.get(key); | |
361 | |
362 double[] values = dap.getInputValues(); | |
363 if (wqvalue == null) { | |
364 wqvalue = createValueString(key, values); | |
365 } | |
366 else { | |
367 wqvalue += GAUGE_SEPARATOR + createValueString(key, values); | |
368 } | |
369 } | |
370 | |
371 // TODO probably ranges | |
372 DataItem valueItem = new DefaultDataItem( | |
373 "ranges", "ranges", wqvalue); | |
374 Data values = new DefaultData( | |
375 "ranges", null, null, new DataItem[] { valueItem }); | |
376 | |
377 return values; | |
378 } | |
379 | |
380 | |
381 protected String createValueString(String key, double[] values) { | |
382 StringBuilder sb = new StringBuilder(); | |
383 | |
384 boolean first = true; | |
385 | |
386 for (double value: values) { | |
387 if (!first) { | |
388 sb.append(","); | |
389 } | |
390 | |
391 sb.append(Double.toString(value)); | |
392 | |
393 first = false; | |
394 } | |
395 | |
396 return key + ";" + sb.toString(); | |
397 } | |
398 | |
399 | |
400 public void onChange(ChangeEvent event) { | |
401 // TODO IMPLEMENT ME | |
402 } | |
403 | |
404 | |
405 public void onBlur(BlurEvent event) { | |
406 DoubleArrayPanel dap = (DoubleArrayPanel) event.getForm(); | |
407 dap.validateForm(event.getItem()); | |
408 } | |
409 | |
410 | |
411 protected void fetchWQData() { | |
412 Config config = Config.getInstance(); | |
413 String locale = config.getLocale (); | |
414 | |
415 ArtifactDescription adescr = artifact.getArtifactDescription(); | |
416 DataList[] data = adescr.getOldData(); | |
417 | |
418 double[] mm = getMinMaxKM(data); | |
419 String river = getRiverName(data); | |
420 | |
421 wqInfoService.getWQInfo(locale, river, mm[0], mm[0], | |
422 new AsyncCallback<WQInfoObject[]>() { | |
423 public void onFailure(Throwable caught) { | |
424 GWT.log("Could not recieve wq informations."); | |
425 SC.warn(caught.getMessage()); | |
426 } | |
427 | |
428 public void onSuccess(WQInfoObject[] wqi) { | |
429 int num = wqi != null ? wqi.length :0; | |
430 GWT.log("Recieved " + num + " wq informations."); | |
431 | |
432 if (num == 0) { | |
433 return; | |
434 } | |
435 | |
436 addWQInfo(wqi); | |
437 | |
438 } | |
439 } | |
440 ); | |
441 } | |
442 | |
443 | |
444 protected void addWQInfo (WQInfoObject[] wqi) { | |
445 for(WQInfoObject wi: wqi) { | |
446 WQInfoRecord rec = new WQInfoRecord(wi); | |
447 | |
448 if (wi.getType().equals("W")) { | |
449 wTable.addData(rec); | |
450 } | |
451 else { | |
452 qdTable.addData(rec); | |
453 } | |
454 } | |
455 } | |
456 | |
457 | |
458 /** | |
459 * Determines the min and max kilometer value selected in a former state. A | |
460 * bit silly, but we need to run over each value of the "old data" to find | |
461 * such values because it is not available here. | |
462 * | |
463 * @param data The DataList which contains the whole data inserted for the | |
464 * current artifact. | |
465 * | |
466 * @return a double array with [min, max]. | |
467 */ | |
468 protected double[] getMinMaxKM(DataList[] data) { | |
469 ArtifactDescription adesc = artifact.getArtifactDescription(); | |
470 return adesc.getKMRange(); | |
471 } | |
472 | |
473 | |
474 /** | |
475 * Returns the name of the selected river. | |
476 * | |
477 * @param data The DataList with all data. | |
478 * | |
479 * @return the name of the current river. | |
480 */ | |
481 protected String getRiverName(DataList[] data) { | |
482 ArtifactDescription adesc = artifact.getArtifactDescription(); | |
483 return adesc.getRiver(); | |
484 } | |
485 } | |
486 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |