teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
teichmann@5861: * Software engineering by Intevation GmbH
teichmann@5861: *
teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3)
teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the
teichmann@5993: * documentation coming with Dive4Elements River for details.
teichmann@5861: */
teichmann@5861:
teichmann@5835: package org.dive4elements.river.client.client.ui;
ingo@243:
ingo@243: import com.google.gwt.core.client.GWT;
ingo@565: import com.google.gwt.i18n.client.NumberFormat;
raimund@2456: import com.google.gwt.user.client.rpc.AsyncCallback;
ingo@243:
felix@5195: import com.smartgwt.client.data.Record;
ingo@246: import com.smartgwt.client.types.TitleOrientation;
ingo@247: import com.smartgwt.client.types.VerticalAlignment;
ingo@602: import com.smartgwt.client.util.SC;
ingo@243: import com.smartgwt.client.widgets.Canvas;
ingo@243: import com.smartgwt.client.widgets.Label;
ingo@255: import com.smartgwt.client.widgets.form.DynamicForm;
ingo@255: import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
ingo@243: import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
christian@4568: import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
christian@4568: import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
ingo@243: import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
felix@5195: import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
felix@5195: import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
felix@5195: import com.smartgwt.client.widgets.grid.events.CellClickEvent;
felix@5195: import com.smartgwt.client.widgets.grid.events.CellClickHandler;
ingo@247: import com.smartgwt.client.widgets.layout.HLayout;
ingo@243: import com.smartgwt.client.widgets.layout.VLayout;
christian@4568: import com.smartgwt.client.widgets.tab.Tab;
raimund@2456: import com.smartgwt.client.widgets.tab.TabSet;
ingo@243:
teichmann@5835: import org.dive4elements.river.client.client.Config;
teichmann@5835: import org.dive4elements.river.client.client.FLYSConstants;
teichmann@5835: import org.dive4elements.river.client.client.services.WQInfoService;
teichmann@5835: import org.dive4elements.river.client.client.services.WQInfoServiceAsync;
teichmann@5835: import org.dive4elements.river.client.client.ui.wq.QDTable;
teichmann@5835: import org.dive4elements.river.client.client.ui.wq.WTable;
teichmann@5835: import org.dive4elements.river.client.shared.model.ArtifactDescription;
teichmann@5835: import org.dive4elements.river.client.shared.model.Data;
teichmann@5835: import org.dive4elements.river.client.shared.model.DataItem;
teichmann@5835: import org.dive4elements.river.client.shared.model.DataList;
teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultData;
teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultDataItem;
teichmann@5835: import org.dive4elements.river.client.shared.model.WQDataItem;
teichmann@5835: import org.dive4elements.river.client.shared.model.WQInfoObject;
teichmann@5835: import org.dive4elements.river.client.shared.model.WQInfoRecord;
ingo@243:
christian@4568: import java.util.ArrayList;
christian@4568: import java.util.HashMap;
christian@4568: import java.util.LinkedHashMap;
christian@4568: import java.util.List;
christian@4568: import java.util.Map;
ingo@246:
ingo@243:
ingo@243: /**
ingo@243: * This UIProvider creates a widget to enter W or Q data for discharge
ingo@243: * longitudinal section computations.
ingo@243: *
ingo@243: * @author Ingo Weinzierl
ingo@243: */
ingo@243: public class WQAdaptedInputPanel
ingo@243: extends AbstractUIProvider
felix@5195: implements ChangeHandler, BlurHandler, FocusHandler
ingo@243: {
christian@4568: private static final long serialVersionUID = -3218827566805476423L;
christian@4568:
felix@5635: /** The message class that provides i18n strings. */
felix@5190: protected FLYSConstants MESSAGE = GWT.create(FLYSConstants.class);
felix@5190:
ingo@2392: public static final String FIELD_WQ_MODE = "wq_isq";
ingo@255: public static final String FIELD_WQ_W = "W";
ingo@255: public static final String FIELD_WQ_Q = "Q";
ingo@246:
ingo@247: public static final String GAUGE_SEPARATOR = ":";
ingo@247:
ingo@247: public static final String GAUGE_PART_SEPARATOR = ";";
ingo@247:
ingo@247: public static final String VALUE_SEPARATOR = ",";
ingo@247:
ingo@255: public static final int ROW_HEIGHT = 20;
ingo@255:
felix@5635: /** The constant field name for choosing w or q mode. */
raimund@2456: public static final String FIELD_WQ = "wq";
raimund@2456:
felix@5635: /** The constant field name for choosing single values or range. */
raimund@2456: public static final String FIELD_MODE = "mode";
raimund@2456:
felix@5635: /** The constant field value for range input mode. */
raimund@2456: public static final String FIELD_MODE_RANGE = "range";
raimund@2456:
felix@5640: /** Service to fetch W/Q MainValues. */
raimund@2456: protected WQInfoServiceAsync wqInfoService =
raimund@2456: GWT.create(WQInfoService.class);
ingo@246:
felix@5635: /** The message class that provides i18n strings. */
ingo@246: protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
ingo@246:
felix@5635: /** Stores the input panels related to their keys. */
ingo@246: protected Map wqranges;
ingo@246:
felix@5527: /** List of doubleArrayPanels shown. */
felix@5526: protected ArrayList doubleArrayPanels;
felix@5526:
felix@5773: /** [startkm,endkm] per gauge in selected range. */
felix@5773: protected double[][] gaugeRanges;
felix@5773:
felix@5773: /** Stores the min/max values for each q range (gauge). */
ingo@565: protected Map qranges;
ingo@565:
felix@5773: /** Stores the min/max values for each w range (gauge). */
ingo@565: protected Map wranges;
ingo@565:
felix@5635: /** The RadioGroupItem that determines the w/q input mode. */
ingo@255: protected DynamicForm modes;
ingo@255:
felix@5773: /** List of wTables in inputhelper section. */
felix@5773: protected List wTables;
raimund@2456:
felix@5773: /** List of QDTables in inputhelper section. */
felix@5773: protected List qdTables;
raimund@2456:
felix@5196: /** Tabs in inputhelper area. */
raimund@2456: protected TabSet tabs;
ingo@246:
felix@5195: /** The currently focussed Input element. */
felix@5195: protected DoubleArrayPanel itemWithFocus;
felix@5195:
ingo@246:
ingo@243: public WQAdaptedInputPanel() {
ingo@246: wqranges = new HashMap();
felix@5526: doubleArrayPanels = new ArrayList();
ingo@565: qranges = new HashMap();
ingo@565: wranges = new HashMap();
felix@5773: wTables = new ArrayList();
felix@5773: qdTables = new ArrayList();
ingo@243: }
ingo@243:
ingo@243:
felix@6666: /** Create labels, canvasses, layouts. */
christian@4568: @Override
ingo@243: public Canvas create(DataList data) {
felix@5773: readGaugeRanges(data);
raimund@2456: initHelperPanel();
raimund@2456:
ingo@243: Canvas submit = getNextButton();
ingo@246: Canvas widget = createWidget(data);
ingo@246: Label label = new Label(MSG.wqadaptedTitle());
ingo@246:
ingo@246: label.setHeight(25);
ingo@243:
ingo@243: VLayout layout = new VLayout();
ingo@243: layout.setMembersMargin(10);
ingo@255: layout.setWidth(350);
ingo@243:
ingo@246: layout.addMember(label);
ingo@246: layout.addMember(widget);
ingo@243: layout.addMember(submit);
ingo@243:
felix@5773: fetchWQData();
felix@5773:
felix@5773: initTableListeners();
felix@5773:
felix@6413: // We actually want the first Q tab to be selected and all
felix@6413: // Q tabs to be enabled. I sense a bug in TabSet here, as
felix@6413: // the code in the W/Q radiogroup-changehandler behaves
felix@6413: // exactly vice versa (enabling Q, selecting tab 0).
felix@6413: enableWTabs();
felix@6413: tabs.selectTab(1);
felix@6413:
ingo@243: return layout;
ingo@243: }
ingo@243:
ingo@243:
felix@5190: /** Inits the helper panel. */
felix@5190: // TODO duplicate in WQInputPanel
raimund@2456: protected void initHelperPanel() {
raimund@2456: tabs = new TabSet();
raimund@2456: tabs.setWidth100();
raimund@2456: tabs.setHeight100();
raimund@2456:
felix@5773: // For each gauge, add two tabs with helper tables.
raimund@2456:
felix@5773: for (int i = 0; i< gaugeRanges.length; i++) {
felix@5773: // Later the tabs title will get adjusted to include gauges name.
felix@5773: // TODO the tabs title becomes rather long through that (i18n).
felix@5773: Tab wTab = new Tab(MESSAGE.wq_table_w());
felix@5773: Tab qTab = new Tab(MESSAGE.wq_table_q());
raimund@2456:
felix@5773: QDTable qdTable = new QDTable();
felix@5773: WTable wTable = new WTable();
felix@5773:
felix@5773: wTables.add(wTable);
felix@5773: qdTables.add(qdTable);
felix@5773:
felix@5773: qdTable.showSelect();
felix@6666: wTable.showSelect();
felix@5773: wTab.setPane(wTable);
felix@5773: qTab.setPane(qdTable);
felix@5773:
felix@5773: tabs.addTab(wTab, i*2+0);
felix@5773: tabs.addTab(qTab, i*2+1);
felix@6413: //tabs.disableTab(i*2+1);
felix@5773: }
raimund@2456:
felix@6271: // Defaults at "Q", first input field.
felix@6271: tabs.selectTab(0);
felix@6271: enableQTabs();
felix@6271:
raimund@2456: helperContainer.addMember(tabs);
raimund@2456: }
raimund@2456:
raimund@2456:
felix@5195: /**
felix@5195: * Initializes the listeners of the WQD tables.
felix@5195: */
felix@5195: // TODO dupe from WQInputPanel
felix@5195: protected void initTableListeners() {
felix@5773: int i = 0;
felix@5773: for (QDTable qdTable: qdTables) {
felix@5773: // Register listener such that values are filled in on click.
felix@5773: final QDTable table = qdTable;
felix@5773: final int fi = i;
felix@5773: CellClickHandler handler = new CellClickHandler() {
felix@5773: @Override
felix@5773: public void onCellClick(CellClickEvent e) {
felix@5773: if (isWMode() || table.isLocked()) {
felix@5773: return;
felix@5773: }
felix@5195:
felix@5773: Record r = e.getRecord();
felix@5773: double val = r.getAttributeAsDouble("value");
felix@5773:
felix@5773: doubleArrayPanels.get(fi).setValues(new double[]{val});
felix@5774: // If a named value for first gauge is chosen, try to find and set
felix@5774: // the values to the other panels too.
felix@5774: if (fi == 0) {
felix@5774: String valueName = r.getAttribute("name");
felix@5774: int oi = 0;
felix@5774: // TODO instead of oi use random access.
felix@5774: for (QDTable otherQDTable: qdTables) {
felix@5774: if (oi == 0) {
felix@5774: oi++;
felix@5774: continue;
felix@5774: }
felix@5774: Double value = otherQDTable.findRecordValue(valueName);
felix@5774: if (value == null) {
felix@6014: SC.warn(MSG.noMainValueAtGauge());
felix@5774: }
felix@5774: else {
felix@5774: doubleArrayPanels.get(oi).setValues(new double[]{value});
felix@5774: }
felix@5774: oi++;
felix@5774: }
felix@5526: }
felix@5774: else {
felix@5774: // Focus next.
felix@5774: if (fi != doubleArrayPanels.size()-1) {
felix@5774: doubleArrayPanels.get(fi+1).focusInItem(1);
felix@5773: }
felix@5774: }
felix@5195: }
felix@5773: };
felix@5195:
felix@5773: qdTable.addCellClickHandler(handler);
felix@5773: i++;
felix@5773: }
felix@6666:
felix@6666: i = 0;
felix@6666: for (WTable wTable: wTables) {
felix@6666: // Register listener such that values are filled in on click.
felix@6666: final WTable table = wTable;
felix@6666: final int fi = i;
felix@6666: CellClickHandler handler = new CellClickHandler() {
felix@6666: @Override
felix@6666: public void onCellClick(CellClickEvent e) {
felix@6666: if (!isWMode() /*|| table.isLocked()*/) {
felix@6666: return;
felix@6666: }
felix@6666:
felix@6666: Record r = e.getRecord();
felix@6666: double val = r.getAttributeAsDouble("value");
felix@6666:
felix@6666: doubleArrayPanels.get(fi).setValues(new double[]{val});
felix@6666: // If a named value for first gauge is chosen, try to find and set
felix@6666: // the values to the other panels too.
felix@6666: if (fi == 0) {
felix@6666: String valueName = r.getAttribute("name");
felix@6666: int oi = 0;
felix@6666: // TODO instead of oi use random access.
felix@6666: for (WTable otherWTable: wTables) {
felix@6666: if (oi == 0) {
felix@6666: oi++;
felix@6666: continue;
felix@6666: }
felix@6666: Double value = otherWTable.findRecordValue(valueName);
felix@6666: if (value == null) {
felix@6666: // TODO: afterwards it freaks out
felix@6666: SC.warn(MSG.noMainValueAtGauge());
felix@6666: }
felix@6666: else {
felix@6666: doubleArrayPanels.get(oi).setValues(new double[]{value});
felix@6666: }
felix@6666: oi++;
felix@6666: }
felix@6666: }
felix@6666: else {
felix@6666: // Focus next.
felix@6666: if (fi != doubleArrayPanels.size()-1) {
felix@6666: doubleArrayPanels.get(fi+1).focusInItem(1);
felix@6666: }
felix@6666: }
felix@6666: }
felix@6666: };
felix@6666:
felix@6666: wTable.addCellClickHandler(handler);
felix@6666: i++;
felix@6666: }
felix@5195: }
felix@5195:
felix@5527:
christian@4568: @Override
ingo@243: public Canvas createOld(DataList dataList) {
ingo@247: List all = dataList.getAll();
ingo@247: Data wqData = getData(all, "wq_values");
ingo@2392: Data wqMode = getData(all, "wq_isq");
felix@5154: boolean isQ = wqMode.getItems()[0].getStringValue().equals("true");
ingo@247: Canvas back = getBackButton(dataList.getState());
ingo@247:
ingo@247: HLayout valLayout = new HLayout();
ingo@247: HLayout modeLayout = new HLayout();
ingo@247: VLayout vlayout = new VLayout();
ingo@247:
ingo@247: Label wqLabel = new Label(dataList.getLabel());
ingo@247: Label modeLabel = new Label("");
ingo@247:
ingo@247: wqLabel.setValign(VerticalAlignment.TOP);
ingo@247:
ingo@247: wqLabel.setWidth(200);
ingo@247: wqLabel.setHeight(25);
ingo@247: modeLabel.setHeight(25);
ingo@247: modeLabel.setWidth(200);
ingo@247:
ingo@247: valLayout.addMember(wqLabel);
felix@5154: valLayout.addMember(createOldWQValues(wqData, isQ));
felix@5154:
ingo@247: valLayout.addMember(back);
ingo@247: modeLayout.addMember(modeLabel);
ingo@247:
ingo@247: vlayout.addMember(valLayout);
ingo@247: vlayout.addMember(modeLayout);
ingo@247:
ingo@247: return vlayout;
ingo@247: }
ingo@247:
ingo@247:
felix@5124: /** Create area showing previously entered w or q data. */
felix@5154: protected Canvas createOldWQValues(Data wqData, boolean isQ) {
ingo@247: VLayout layout = new VLayout();
ingo@247:
ingo@247: DataItem item = wqData.getItems()[0];
ingo@247: String value = item.getStringValue();
ingo@247:
ingo@247: String[] gauges = value.split(GAUGE_SEPARATOR);
ingo@247:
felix@5154: String unit = isQ ? "m³/s" : "cm";
felix@5154:
ingo@247: for (String gauge: gauges) {
ingo@247: HLayout h = new HLayout();
ingo@247:
ingo@247: String[] parts = gauge.split(GAUGE_PART_SEPARATOR);
rrenkert@5104: String[] values = parts[3].split(VALUE_SEPARATOR);
ingo@247:
rrenkert@5104: Label l = new Label(parts[2] + ": ");
ingo@247:
ingo@247: StringBuilder sb = new StringBuilder();
ingo@247: boolean first = true;
ingo@247:
ingo@247: for (String v: values) {
ingo@247: if (!first) {
ingo@247: sb.append(", ");
ingo@247: }
ingo@247:
ingo@247: sb.append(v);
felix@5154: sb.append(" ");
felix@5154: sb.append(unit);
ingo@247:
ingo@247: first = false;
ingo@247: }
ingo@247:
ingo@247: Label v = new Label(sb.toString());
ingo@247:
ingo@247: l.setWidth(65);
ingo@247: v.setWidth(65);
ingo@247:
ingo@247: h.addMember(l);
ingo@247: h.addMember(v);
ingo@247:
ingo@247: layout.addMember(h);
ingo@247: }
ingo@247:
ingo@247: return layout;
ingo@243: }
ingo@243:
ingo@243:
felix@5773: /** Create non-input helper part of the UI. */
ingo@246: protected Canvas createWidget(DataList dataList) {
ingo@246: VLayout layout = new VLayout();
ingo@246:
ingo@255: Canvas mode = createMode(dataList);
ingo@255: Canvas list = createList(dataList);
ingo@255:
ingo@255: DataItem[] items = getWQItems(dataList);
ingo@255: int listHeight = ROW_HEIGHT * items.length;
ingo@255:
ingo@255: mode.setHeight(25);
ingo@255: mode.setWidth(200);
ingo@255:
ingo@255: layout.addMember(mode);
ingo@255: layout.addMember(list);
ingo@255:
ingo@255: layout.setHeight(25 + listHeight);
ingo@255: layout.setWidth(350);
ingo@255:
ingo@519: initUserDefaults(dataList);
ingo@519:
ingo@255: return layout;
ingo@255: }
ingo@255:
ingo@255:
ingo@565: @Override
ingo@565: public List validate() {
ingo@565: if (isWMode()) {
ingo@565: return validateW();
ingo@565: }
ingo@565: else {
ingo@565: return validateQ();
ingo@565: }
ingo@565: }
ingo@565:
felix@5527:
felix@5123: protected List validateRange(Map ranges) {
ingo@565: List errors = new ArrayList();
ingo@565: NumberFormat nf = NumberFormat.getDecimalFormat();
ingo@565:
teichmann@6100: for (Map.Entry entry: wqranges.entrySet()) {
ingo@565:
teichmann@6100: String key = entry.getKey();
teichmann@6100: DoubleArrayPanel dap = entry.getValue();
ingo@602:
ingo@602: if (!dap.validateForm()) {
ingo@602: errors.add(MSG.error_invalid_double_value());
ingo@602: return errors;
ingo@602: }
ingo@602:
felix@5123: double[] mm = ranges.get(key);
ingo@602: if (mm == null) {
ingo@602: SC.warn(MSG.error_read_minmax_values());
ingo@602: continue;
ingo@602: }
ingo@565:
ingo@565: double[] values = dap.getInputValues();
ingo@565: double[] good = new double[values.length];
ingo@565:
ingo@565: int idx = 0;
ingo@565:
teichmann@6100: List tmpErrors = new ArrayList();
ingo@565: for (double value: values) {
ingo@565: if (value < mm[0] || value > mm[1]) {
ingo@565: String tmp = MSG.error_validate_range();
ingo@565: tmp = tmp.replace("$1", nf.format(value));
ingo@565: tmp = tmp.replace("$2", nf.format(mm[0]));
ingo@565: tmp = tmp.replace("$3", nf.format(mm[1]));
ingo@565: tmpErrors.add(tmp);
ingo@565: }
ingo@565: else {
ingo@565: good[idx++] = value;
ingo@565: }
ingo@565: }
ingo@565:
ingo@565: double[] justGood = new double[idx];
ingo@565: for (int i = 0; i < justGood.length; i++) {
ingo@565: justGood[i] = good[i];
ingo@565: }
ingo@565:
ingo@565: if (!tmpErrors.isEmpty()) {
ingo@565: dap.setValues(justGood);
ingo@565:
ingo@565: errors.addAll(tmpErrors);
ingo@565: }
ingo@565: }
ingo@565:
ingo@565: return errors;
ingo@565: }
ingo@565:
ingo@565:
felix@5123: protected List validateW() {
felix@5123: return validateRange(wranges);
felix@5123: }
ingo@565:
ingo@565:
felix@5123: protected List validateQ() {
felix@5123: return validateRange(qranges);
ingo@565: }
ingo@565:
ingo@565:
ingo@519: protected void initUserDefaults(DataList dataList) {
ingo@519: initUserWQValues(dataList);
ingo@519: initUserWQMode(dataList);
ingo@519: }
ingo@519:
ingo@519:
ingo@519: protected void initUserWQMode(DataList dataList) {
ingo@519: List allData = dataList.getAll();
ingo@519:
ingo@519: Data dDef = getData(allData, "wq_mode");
ingo@519: DataItem def = dDef != null ? dDef.getDefault() : null;
ingo@519: String value = def != null ? def.getStringValue() : null;
ingo@519:
ingo@617: if (value != null && value.equals(FIELD_WQ_W)) {
ingo@617: modes.setValue(FIELD_WQ_MODE, FIELD_WQ_W);
ingo@519: }
ingo@519: else {
ingo@617: modes.setValue(FIELD_WQ_MODE, FIELD_WQ_Q);
ingo@519: }
ingo@519: }
ingo@519:
ingo@519:
ingo@519: protected void initUserWQValues(DataList dataList) {
ingo@519: List allData = dataList.getAll();
ingo@519:
ingo@519: Data dDef = getData(allData, "wq_values");
ingo@519: DataItem def = dDef != null ? dDef.getDefault() : null;
ingo@519: String value = def != null ? def.getStringValue() : null;
ingo@519:
ingo@519: if (value == null || value.length() == 0) {
ingo@519: return;
ingo@519: }
ingo@519:
ingo@519: String[] lines = value.split(GAUGE_SEPARATOR);
ingo@519:
ingo@519: if (lines == null || lines.length == 0) {
ingo@519: return;
ingo@519: }
ingo@519:
ingo@519: for (String line: lines) {
ingo@519: String[] cols = line.split(GAUGE_PART_SEPARATOR);
ingo@519: String title = createLineTitle(line);
ingo@519:
ingo@519: if (cols == null || cols.length < 3) {
ingo@519: continue;
ingo@519: }
ingo@519:
ingo@519: String[] strValues = cols[2].split(VALUE_SEPARATOR);
ingo@519: double[] values = new double[strValues.length];
ingo@519:
ingo@519: int idx = 0;
ingo@519:
ingo@519: for (String strValue: strValues) {
ingo@519: try {
ingo@519: values[idx++] = Double.valueOf(strValue);
ingo@519: }
ingo@519: catch (NumberFormatException nfe) {
ingo@519: // do nothing
ingo@519: }
ingo@519: }
ingo@519:
ingo@519: String key = cols[0] + GAUGE_PART_SEPARATOR + cols[1];
ingo@519: DoubleArrayPanel dap = wqranges.get(key);
ingo@560:
ingo@560: if (dap == null) {
ingo@560: continue;
ingo@560: }
ingo@560:
ingo@519: dap.setValues(values);
ingo@519: }
ingo@519: }
ingo@519:
felix@5773: /** Populate Gauge Ranges array. */
felix@5773: private void readGaugeRanges(DataList dataList) {
felix@5773: DataItem[] items = getWQItems(dataList);
felix@5773: gaugeRanges = new double[items.length][2];
teichmann@5993:
felix@5773: int i = 0;
felix@5773:
felix@5773: for (DataItem item: items) {
felix@5773: String[] startEndKm = item.getLabel().split(";");
felix@5773:
felix@5773: gaugeRanges[i][0] = Double.parseDouble(startEndKm[0]);
felix@5773: gaugeRanges[i][1] = Double.parseDouble(startEndKm[1]);
felix@5773: i++;
felix@5773: }
felix@5773: }
felix@5773:
ingo@519:
ingo@255: protected Canvas createList(DataList dataList) {
ingo@255: VLayout layout = new VLayout();
ingo@255:
ingo@255: DataItem[] items = getWQItems(dataList);
ingo@255:
felix@5773: int i = 0;
felix@5773:
ingo@255: for (DataItem item: items) {
felix@5773: String title = item.getLabel(); // of form: 70.5;112.0
rrenkert@5104: String label = item.getStringValue();
felix@5773:
felix@5773: // Rename W and Q tab to include gauges name.
felix@5773: tabs.getTab(i*2).setTitle(tabs.getTab(i*2).getTitle()
felix@5773: + " (" + label + ")");
felix@5773: tabs.getTab(i*2+1).setTitle(tabs.getTab(i*2+1).getTitle()
felix@5773: + " (" + label + ")");
felix@5773:
ingo@255: DoubleArrayPanel dap = new DoubleArrayPanel(
felix@5195: label, null, this, this, TitleOrientation.LEFT);
ingo@255:
ingo@255: wqranges.put(title, dap);
felix@5526: doubleArrayPanels.add(dap);
ingo@565:
ingo@565: if (item instanceof WQDataItem) {
ingo@565: WQDataItem wq = (WQDataItem) item;
ingo@565: double[] mmQ = wq.getQRange();
ingo@565: double[] mmW = wq.getWRange();
ingo@565:
ingo@565: qranges.put(title, mmQ);
ingo@565: wranges.put(title, mmW);
ingo@565: }
ingo@565:
ingo@255: layout.addMember(dap);
felix@5773: i++;
ingo@255: }
ingo@255:
ingo@255: layout.setHeight(items.length * ROW_HEIGHT);
ingo@255:
ingo@255: return layout;
ingo@255: }
ingo@255:
ingo@255:
felix@5154: /** Get items which are not WQ_MODE. */
ingo@255: protected DataItem[] getWQItems(DataList dataList) {
ingo@246: List data = dataList.getAll();
ingo@246:
ingo@246: for (Data d: data) {
ingo@246: String name = d.getLabel();
ingo@246:
ingo@246: if (name.equals(FIELD_WQ_MODE)) {
ingo@246: continue;
ingo@246: }
ingo@246:
ingo@255: return d.getItems();
ingo@246: }
ingo@246:
ingo@255: return null;
ingo@255: }
ingo@255:
ingo@255:
felix@5154: /**
felix@5154: * Create radio button for switching w and q input.
felix@5154: * Radiobutton-change also triggers helper panel tab selection.
felix@5154: */
ingo@255: protected Canvas createMode(DataList dataList) {
ingo@255: RadioGroupItem wq = new RadioGroupItem(FIELD_WQ_MODE);
ingo@255: wq.setShowTitle(false);
ingo@255: wq.setVertical(false);
ingo@255: wq.setWidth(200);
ingo@255:
ingo@255: LinkedHashMap wqValues = new LinkedHashMap();
ingo@255: wqValues.put(FIELD_WQ_W, MSG.wqW());
rrenkert@5104: wqValues.put(FIELD_WQ_Q, MSG.wqQatGauge());
ingo@255:
ingo@255: wq.setValueMap(wqValues);
ingo@255:
ingo@255: modes = new DynamicForm();
ingo@255: modes.setFields(wq);
ingo@255: modes.setWidth(200);
raimund@2456: wq.addChangeHandler(new ChangeHandler() {
christian@4568: @Override
raimund@2456: public void onChange(ChangeEvent e) {
raimund@2456: DynamicForm form = e.getForm();
raimund@2456:
raimund@2456: if(form.getValueAsString(FIELD_WQ_MODE).contains("Q")) {
raimund@2456: tabs.selectTab(0);
felix@5921: enableQTabs();
raimund@2456: }
raimund@2456: else {
raimund@2456: tabs.selectTab(1);
felix@5921: enableWTabs();
raimund@2456: }
raimund@2456: }
raimund@2456: });
raimund@2456:
ingo@255:
ingo@255: LinkedHashMap initial = new LinkedHashMap();
ingo@617: initial.put(FIELD_WQ_MODE, FIELD_WQ_Q);
ingo@255: modes.setValues(initial);
raimund@2456: tabs.selectTab(1);
ingo@255: return modes;
ingo@246: }
ingo@246:
ingo@246:
felix@5921: public void enableWTabs() {
felix@5921: for (int i = 0; i < doubleArrayPanels.size(); i++) {
felix@5921: tabs.disableTab(2*i);
felix@5921: tabs.enableTab(2*i+1);
felix@5921: }
felix@5921: }
felix@5921:
felix@5921:
felix@5921: public void enableQTabs() {
felix@5921: for (int i = 0; i < doubleArrayPanels.size(); i++) {
felix@5921: tabs.enableTab(2*i);
felix@5921: tabs.disableTab(2*i+1);
felix@5921: }
felix@5921: }
felix@5921:
felix@5921:
ingo@246: public String createLineTitle(String key) {
ingo@246: String[] splitted = key.split(";");
ingo@246:
ingo@246: return splitted[0] + " - " + splitted[1];
ingo@246: }
ingo@246:
ingo@246:
christian@4568: @Override
ingo@243: public Data[] getData() {
ingo@246: Data mode = getWQMode();
ingo@246: Data values = getWQValues();
ingo@243:
ingo@246: return new Data[] { mode, values };
ingo@246: }
ingo@246:
ingo@246:
ingo@565: public boolean isWMode() {
ingo@565: String mode = (String) modes.getValue(FIELD_WQ_MODE);
ingo@565:
ingo@565: return FIELD_WQ_W.equals(mode);
ingo@565: }
ingo@565:
ingo@565:
ingo@246: protected Data getWQMode() {
ingo@255: String wqMode = modes.getValueAsString(FIELD_WQ_MODE);
ingo@2392: String value = "false";
ingo@2392: if (wqMode.equals("Q")) {
ingo@2392: value = "true";
ingo@2392: }
ingo@2392: DataItem item = new DefaultDataItem("wq_isq", "wq_isq", value);
ingo@243: Data mode = new DefaultData(
ingo@2392: "wq_isq", null, null, new DataItem[] { item });
ingo@243:
ingo@246: return mode;
ingo@246: }
ingo@246:
ingo@246:
ingo@246: protected Data getWQValues() {
ingo@246: String wqvalue = null;
ingo@246:
teichmann@6100: for (Map.Entry entry: wqranges.entrySet()) {
teichmann@6100: String key = entry.getKey();
teichmann@6100: DoubleArrayPanel dap = entry.getValue();
rrenkert@5104: String label = dap.getItemTitle();
ingo@246:
ingo@246: double[] values = dap.getInputValues();
ingo@246: if (wqvalue == null) {
rrenkert@5104: wqvalue = createValueString(key + ";" + label, values);
ingo@246: }
ingo@246: else {
rrenkert@5104: wqvalue += GAUGE_SEPARATOR + createValueString(key + ";" + label, values);
ingo@246: }
ingo@246: }
ingo@246:
ingo@243: DataItem valueItem = new DefaultDataItem(
ingo@246: "wq_values", "wq_values", wqvalue);
ingo@243: Data values = new DefaultData(
ingo@243: "wq_values", null, null, new DataItem[] { valueItem });
ingo@243:
ingo@246: return values;
ingo@246: }
ingo@246:
ingo@246:
ingo@246: protected String createValueString(String key, double[] values) {
ingo@246: StringBuilder sb = new StringBuilder();
ingo@246:
ingo@246: boolean first = true;
ingo@246:
ingo@246: for (double value: values) {
ingo@246: if (!first) {
ingo@246: sb.append(",");
ingo@246: }
ingo@246:
ingo@246: sb.append(Double.toString(value));
ingo@246:
ingo@246: first = false;
ingo@246: }
ingo@246:
ingo@246: return key + ";" + sb.toString();
ingo@243: }
ingo@243:
ingo@243:
christian@4568: @Override
ingo@243: public void onChange(ChangeEvent event) {
ingo@243: // TODO IMPLEMENT ME
ingo@243: }
ingo@243:
ingo@243:
felix@5773: /** Store the currently focussed DoubleArrayPanel and focus helper tab. */
felix@5195: @Override
felix@5195: public void onFocus(FocusEvent event) {
felix@5195: itemWithFocus = (DoubleArrayPanel) event.getForm();
felix@5773: // Switch to respective tab.
felix@5773: // TODO which makes a focus loss
felix@5773: int inputIndex = doubleArrayPanels.indexOf(itemWithFocus);
felix@5773: tabs.selectTab(inputIndex*2 + (isWMode() ? 0 : 1));
felix@5195: }
felix@5195:
felix@5195:
christian@4568: @Override
ingo@243: public void onBlur(BlurEvent event) {
ingo@246: DoubleArrayPanel dap = (DoubleArrayPanel) event.getForm();
ingo@246: dap.validateForm(event.getItem());
ingo@243: }
raimund@2456:
raimund@2456:
felix@5773: /** Get the WQD data from service and stuck them up that tables. */
raimund@2456: protected void fetchWQData() {
raimund@2456: Config config = Config.getInstance();
raimund@2456: String locale = config.getLocale ();
raimund@2456:
raimund@2456: ArtifactDescription adescr = artifact.getArtifactDescription();
raimund@2456: DataList[] data = adescr.getOldData();
raimund@2456:
raimund@2456: double[] mm = getMinMaxKM(data);
raimund@2456: String river = getRiverName(data);
raimund@2456:
felix@5773: int i = 0;
raimund@2456:
felix@5773: // Get Data for respective gauge.
felix@5773: for (double[] range : gaugeRanges){
felix@5773: // Gauge ranges overlap, move start and end a bit closer to each other.
felix@5773: final double rDiff = (range[1] - range[0]) / 10d;
felix@5773: final int fi = i;
felix@5773: wqInfoService.getWQInfo(locale, river, range[0]+rDiff, range[1]-rDiff,
felix@5773: new AsyncCallback() {
felix@5773: @Override
felix@5773: public void onFailure(Throwable caught) {
felix@5773: GWT.log("Could not recieve wq informations.");
felix@5773: SC.warn(caught.getMessage());
raimund@2456: }
raimund@2456:
felix@5773: @Override
felix@5773: public void onSuccess(WQInfoObject[] wqi) {
felix@5773: int num = wqi != null ? wqi.length :0;
felix@5773: GWT.log("Received " + num + " wq informations (" + fi + ".");
felix@5773:
felix@5773: if (num == 0) {
felix@5773: return;
felix@5773: }
felix@5773:
felix@5773: addWQInfo(wqi, fi);
felix@5773: }
raimund@2456: }
felix@5773: );
felix@5773: i++;
felix@5773: }
raimund@2456: }
raimund@2456:
raimund@2456:
felix@5773: /** Add Info to helper table for gauge at index gaugeIdx. */
felix@5773: protected void addWQInfo (WQInfoObject[] wqi, int gaugeIdx) {
raimund@2456: for(WQInfoObject wi: wqi) {
raimund@2456: WQInfoRecord rec = new WQInfoRecord(wi);
raimund@2456:
raimund@2456: if (wi.getType().equals("W")) {
felix@5773: wTables.get(gaugeIdx).addData(rec);
raimund@2456: }
raimund@2456: else {
felix@5773: qdTables.get(gaugeIdx).addData(rec);
raimund@2456: }
raimund@2456: }
raimund@2456: }
raimund@2456:
raimund@2456:
raimund@2456: /**
raimund@2456: * Determines the min and max kilometer value selected in a former state. A
raimund@2456: * bit silly, but we need to run over each value of the "old data" to find
raimund@2456: * such values because it is not available here.
raimund@2456: *
raimund@2456: * @param data The DataList which contains the whole data inserted for the
raimund@2456: * current artifact.
raimund@2456: *
raimund@2456: * @return a double array with [min, max].
raimund@2456: */
raimund@2456: protected double[] getMinMaxKM(DataList[] data) {
raimund@2456: ArtifactDescription adesc = artifact.getArtifactDescription();
raimund@2456: return adesc.getKMRange();
raimund@2456: }
raimund@2456:
raimund@2456:
raimund@2456: /**
raimund@2456: * Returns the name of the selected river.
raimund@2456: *
raimund@2456: * @param data The DataList with all data.
raimund@2456: *
raimund@2456: * @return the name of the current river.
raimund@2456: */
raimund@2456: protected String getRiverName(DataList[] data) {
raimund@2456: ArtifactDescription adesc = artifact.getArtifactDescription();
raimund@2456: return adesc.getRiver();
raimund@2456: }
ingo@243: }
ingo@243: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :