comparison flys-client/src/main/java/de/intevation/flys/client/client/ui/QSegmentedInputPanel.java @ 4116:4ffeccc5b5a1

Initial GUI and state for per-segment Q-input for extreme valua analysis.
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Fri, 12 Oct 2012 15:07:01 +0200
parents
children 03de5c424f95
comparison
equal deleted inserted replaced
4115:0cc2c3d89a9d 4116:4ffeccc5b5a1
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 :

http://dive4elements.wald.intevation.org