raimund@238: package de.intevation.flys.client.client.ui;
raimund@238:
ingo@563: import java.util.ArrayList;
raimund@238: import java.util.List;
raimund@1534: import java.util.LinkedHashMap;
raimund@238:
raimund@238: import com.google.gwt.core.client.GWT;
ingo@563: import com.google.gwt.i18n.client.NumberFormat;
raimund@238:
ingo@563: import com.smartgwt.client.util.SC;
raimund@238: import com.smartgwt.client.widgets.Canvas;
raimund@238: import com.smartgwt.client.widgets.Label;
raimund@1534: import com.smartgwt.client.widgets.form.DynamicForm;
raimund@238: import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
raimund@238: import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
raimund@238: import com.smartgwt.client.widgets.form.fields.FormItem;
raimund@1534: import com.smartgwt.client.widgets.form.fields.SelectItem;
raimund@1567: import com.smartgwt.client.widgets.form.fields.StaticTextItem;
raimund@1534: import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
raimund@1534: import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
raimund@1534:
raimund@238: import com.smartgwt.client.widgets.layout.HLayout;
raimund@238: import com.smartgwt.client.widgets.layout.VLayout;
raimund@238: import com.smartgwt.client.widgets.grid.ListGrid;
raimund@238: import com.smartgwt.client.widgets.grid.ListGridField;
raimund@906: import com.smartgwt.client.widgets.grid.ListGridRecord;
raimund@906:
raimund@238: import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
raimund@238: import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
raimund@906: import com.smartgwt.client.widgets.grid.CellFormatter;
raimund@238:
raimund@863: import com.smartgwt.client.data.Criteria;
raimund@1538: import com.smartgwt.client.data.Criterion;
raimund@1538: import com.smartgwt.client.data.AdvancedCriteria;
raimund@1538: import com.smartgwt.client.types.OperatorId;
raimund@1567: import com.smartgwt.client.types.Alignment;
raimund@1538:
raimund@863: import com.smartgwt.client.data.Record;
raimund@238: import com.smartgwt.client.types.ListGridFieldType;
raimund@238:
raimund@238: import de.intevation.flys.client.shared.model.Data;
raimund@238: import de.intevation.flys.client.shared.model.DataItem;
raimund@238: import de.intevation.flys.client.shared.model.DataList;
raimund@238: import de.intevation.flys.client.shared.model.DefaultData;
raimund@238: import de.intevation.flys.client.shared.model.DefaultDataItem;
raimund@238: import de.intevation.flys.client.shared.model.DistanceInfoObject;
raimund@238: import de.intevation.flys.client.shared.model.ArtifactDescription;
raimund@238:
raimund@238: import de.intevation.flys.client.client.services.DistanceInfoService;
raimund@238: import de.intevation.flys.client.client.services.DistanceInfoServiceAsync;
raimund@238: import de.intevation.flys.client.client.FLYSConstants;
raimund@238: import de.intevation.flys.client.client.Config;
raimund@863: import de.intevation.flys.client.client.ui.range.DistanceInfoDataSource;
raimund@863: import de.intevation.flys.client.client.event.FilterHandler;
raimund@863: import de.intevation.flys.client.client.event.StringFilterEvent;
raimund@1534: import de.intevation.flys.client.client.event.RangeFilterEvent;
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * This UIProvider creates a widget to enter locations.
raimund@238: *
raimund@238: * @author Raimund Renkert
raimund@238: */
raimund@238: public class SingleLocationPanel
raimund@238: extends AbstractUIProvider
raimund@863: implements FilterHandler
raimund@238: {
felix@1585: /** The DistanceInfoService used to retrieve locations about rivers. */
raimund@238: protected DistanceInfoServiceAsync distanceInfoService =
raimund@238: GWT.create(DistanceInfoService.class);
raimund@238:
felix@1585: /** A container that will contain the location or the distance panel. */
raimund@238: protected HLayout container;
raimund@238:
felix@1585: /** The minimal value that the user is allowed to enter. */
ingo@563: protected double min;
ingo@563:
felix@1585: /** The maximal value that the user is allowed to enter. */
ingo@563: protected double max;
ingo@563:
felix@1585: /** The values entered in the location mode. */
raimund@238: protected double[] values;
raimund@238:
felix@1585: /** The input panel for locations. */
raimund@238: protected DoubleArrayPanel locationPanel;
raimund@238:
felix@1585: /** The locations table. */
raimund@238: protected ListGrid locationTable;
raimund@238:
raimund@238: /** The table data. */
raimund@238: protected DistanceInfoObject[] tableData;
raimund@238:
felix@1585: /** Text to show number of matched items when filtered. */
raimund@1567: protected StaticTextItem filterResultCount;
raimund@1567:
felix@1586: /** Name of the data item that keeps locations. */
felix@1586: protected String DATA_ITEM_NAME = "ld_locations";
felix@1586:
felix@1586:
raimund@238: /**
raimund@238: * Creates a new LocationDistancePanel instance.
raimund@238: */
raimund@238: public SingleLocationPanel() {
raimund@238: locationTable = new ListGrid();
raimund@284: locationTable.setShowHeaderContextMenu(false);
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * This method creates a widget that contains a label, a panel with
raimund@238: * checkboxes to switch the input mode between location and distance input,
felix@1585: * and a mode specific panel.
raimund@238: *
raimund@238: * @param data The data that might be inserted.
raimund@238: *
raimund@238: * @return a panel.
raimund@238: */
felix@1586: @Override
raimund@238: public Canvas create(DataList data) {
raimund@238: VLayout layout = new VLayout();
raimund@238: layout.setMembersMargin(10);
raimund@238:
felix@1586: Label label = new Label(MSG.location ());
raimund@238: Canvas widget = createWidget(data);
raimund@238: Canvas submit = getNextButton();
raimund@238:
ingo@519: initDefaults(data);
ingo@519:
raimund@238: createLocationTable();
raimund@238:
raimund@238: widget.setHeight(50);
raimund@238: label.setHeight(25);
raimund@238:
raimund@238: layout.addMember(label);
raimund@238: layout.addMember(widget);
raimund@238: layout.addMember(submit);
raimund@238:
raimund@238: return layout;
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * This method creates a table that contains the location values.
raimund@238: */
raimund@238: protected void createLocationTable() {
sascha@568: GWT.log("---------- I WAS HERE ---------");
raimund@1399:
raimund@1399: String baseUrl = GWT.getHostPageBaseURL();
raimund@1399:
raimund@272: locationTable.setWidth100();
raimund@238: locationTable.setShowRecordComponents(true);
raimund@238: locationTable.setShowRecordComponentsByCell(true);
raimund@272: locationTable.setHeight100();
felix@1586: locationTable.setEmptyMessage(MSG.empty_filter());
raimund@876: locationTable.setCanReorderFields(false);
raimund@238:
raimund@238: ListGridField addLocation = new ListGridField ("", "");
raimund@238: addLocation.setType (ListGridFieldType.ICON);
sascha@568: addLocation.setWidth (20);
raimund@238: addLocation.addRecordClickHandler (new RecordClickHandler () {
raimund@238: public void onRecordClick (RecordClickEvent e) {
raimund@863: Record record = e.getRecord();
raimund@238: double[] selected = new double[1];
raimund@863: try {
raimund@863: selected[0] =
raimund@863: Double.parseDouble(record.getAttribute("from"));
raimund@863: }
raimund@863: catch(NumberFormatException nfe) {
raimund@863: // Is there anything else to do here?
raimund@863: }
raimund@238: setLocationValues(selected);
raimund@238: }
raimund@238: });
felix@1586: addLocation.setCellIcon (baseUrl + MSG.markerGreen());
raimund@238:
raimund@238: ListGridField ldescr = new ListGridField("description",
felix@1586: MSG.description());
raimund@238: ldescr.setType(ListGridFieldType.TEXT);
raimund@238: ldescr.setWidth("*");
raimund@238: ListGridField lside = new ListGridField("riverside",
felix@1586: MSG.riverside());
raimund@238: lside.setType(ListGridFieldType.TEXT);
raimund@886: lside.setWidth("10%");
sascha@568:
felix@1586: ListGridField loc = new ListGridField("from", MSG.location());
raimund@906: loc.setCellFormatter(new CellFormatter() {
raimund@906: public String format(
raimund@906: Object value,
raimund@906: ListGridRecord record,
raimund@906: int rowNum, int colNum) {
raimund@906: if (value == null) return null;
raimund@906: try {
raimund@906: NumberFormat nf;
raimund@906: double v = Double.parseDouble((String)value);
raimund@906: nf = NumberFormat.getFormat("###0.00##");
raimund@906: return nf.format(v);
raimund@906: }
raimund@906: catch (Exception e) {
raimund@906: return value.toString();
raimund@906: }
raimund@906: }
raimund@906: }
raimund@906: );
raimund@903: loc.setType(ListGridFieldType.FLOAT);
raimund@906:
raimund@886: loc.setWidth("10%");
sascha@568:
sascha@568: ListGridField bottom =
felix@1586: new ListGridField("bottom", MSG.bottom_edge());
sascha@568: bottom.setType(ListGridFieldType.TEXT);
raimund@886: bottom.setWidth("10%");
sascha@568:
sascha@568: ListGridField top =
felix@1586: new ListGridField("top", MSG.top_edge());
sascha@568: top.setType(ListGridFieldType.TEXT);
raimund@886: top.setWidth("10%");
sascha@568:
sascha@568: locationTable.setFields(
sascha@568: addLocation, ldescr, loc, lside, bottom, top);
raimund@238: }
raimund@238:
raimund@238:
felix@1586: /**
felix@1586: * This method creates a Canvas element showing the old Data objects in the
felix@1586: * DataList data.
felix@1586: */
raimund@238: public Canvas createOld(DataList dataList) {
raimund@238: List items = dataList.getAll();
felix@1586: Data dLocation = getData(items, DATA_ITEM_NAME);
raimund@242: DataItem[] loc = dLocation.getItems();
raimund@238:
raimund@238: HLayout layout = new HLayout();
raimund@238: layout.setWidth("400px");
raimund@238:
felix@1586: Label label = new Label(dataList.getLabel());
raimund@238: label.setWidth("200px");
raimund@238:
raimund@238: Canvas back = getBackButton(dataList.getState());
raimund@238:
raimund@242: Label selected = new Label(loc[0].getLabel());
raimund@238: selected.setWidth("130px");
raimund@238:
raimund@238: layout.addMember(label);
raimund@238: layout.addMember(selected);
raimund@238: layout.addMember(back);
raimund@238:
raimund@238: return layout;
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * This method reads the default values defined in the DataItems of the Data
raimund@238: * objects in list.
raimund@238: *
raimund@238: * @param list The DataList container that stores the Data objects.
raimund@238: */
raimund@238: protected void initDefaults(DataList list) {
ingo@519: Data data = list.get(0);
ingo@519:
ingo@519: if (data == null) {
ingo@519: return;
ingo@519: }
ingo@519:
ingo@563: DataItem[] items = data.getItems();
ingo@563: DataItem iMin = getDataItem(items, "min");
ingo@563: DataItem iMax = getDataItem(items, "max");
ingo@563:
ingo@563: try {
ingo@563: min = Double.parseDouble(iMin.getStringValue());
ingo@563: max = Double.parseDouble(iMax.getStringValue());
ingo@563: }
ingo@563: catch (NumberFormatException nfe) {
felix@1586: SC.warn(MSG.error_read_minmax_values());
ingo@563: min = -Double.MAX_VALUE;
ingo@563: max = Double.MAX_VALUE;
ingo@563: }
ingo@563:
ingo@519: DataItem def = data.getDefault();
ingo@519: String value = def.getStringValue();
ingo@519:
ingo@519: try {
ingo@519: double d = Double.parseDouble(value);
ingo@519: setLocationValues(new double[] { d } );
ingo@519: }
ingo@519: catch (NumberFormatException nfe) {
ingo@519: // could not parse, dont know what to do else
ingo@519: }
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
felix@1586: * This method grabs the Data with name name from the list and
raimund@238: * returns it.
raimund@238: *
raimund@238: * @param items A list of Data.
raimund@238: * @param name The name of the Data that we are searching for.
raimund@238: *
raimund@238: * @return the Data with the name name.
raimund@238: */
felix@1586: @Override
raimund@238: protected Data getData(List data, String name) {
raimund@238: for (Data d: data) {
raimund@238: if (name.equals(d.getLabel())) {
raimund@238: return d;
raimund@238: }
raimund@238: }
raimund@238:
raimund@238: return null;
raimund@238: }
raimund@238:
raimund@238:
raimund@238: protected Canvas createWidget(DataList data) {
raimund@238: VLayout layout = new VLayout();
raimund@238: container = new HLayout();
raimund@238:
felix@1586: // The initial view will display the location input mode.
raimund@238: locationPanel = new DoubleArrayPanel(
felix@1586: MSG.unitLocation(),
felix@1586: getLocationValues(),
felix@1586: new BlurHandler(){public void onBlur(BlurEvent be) {}});
raimund@863:
raimund@863: locationTable.setAutoFetchData(true);
raimund@863:
raimund@238: container.addMember(locationPanel);
raimund@238:
raimund@238: layout.addMember(container);
raimund@238:
raimund@238: container.setMembersMargin(30);
raimund@238:
felix@1586: filterResultCount = new StaticTextItem(MSG.resultCount());
raimund@1567: filterResultCount.setTitleAlign(Alignment.LEFT);
raimund@1567: filterResultCount.setTitleStyle("color: #000");
raimund@1567:
raimund@1534: final TableFilter filter = new TableFilter();
raimund@863: filter.setHeight("30px");
raimund@863: filter.addFilterHandler(this);
raimund@863:
raimund@1534: final RangeTableFilter filterRange = new RangeTableFilter();
raimund@1534: filterRange.setHeight("30px");
raimund@1534: filterRange.addFilterHandler(this);
raimund@1534: filterRange.setVisible(false);
raimund@1534:
raimund@1534: SelectItem filterCriteria = new SelectItem();
raimund@1534: filterCriteria.setShowTitle(false);
raimund@1534: filterCriteria.setWidth(100);
raimund@1534: filterCriteria.addChangedHandler(new ChangedHandler() {
raimund@1534: public void onChanged(ChangedEvent e) {
raimund@1534: if(e.getValue().toString().equals("range")) {
raimund@1534: filterRange.setVisible(true);
raimund@1534: filter.setVisible(false);
raimund@1534: filter.clear();
raimund@1567: filterResultCount.setValue("");
raimund@1534: }
raimund@1534: else {
raimund@1534: filterRange.setVisible(false);
raimund@1534: filterRange.clear();
raimund@1534: filter.setVisible(true);
raimund@1567: filterResultCount.setValue("");
raimund@1534: }
raimund@1534: }
raimund@1534: });
raimund@1534:
raimund@1534: LinkedHashMap filterMap =
raimund@1534: new LinkedHashMap();
felix@1586: filterMap.put("description", MSG.description());
felix@1586: filterMap.put("range", MSG.range());
raimund@1534: filterCriteria.setValueMap(filterMap);
raimund@1534: filterCriteria.setValue("description");
raimund@1534:
raimund@1534: DynamicForm form = new DynamicForm();
raimund@1534: form.setFields(filterCriteria);
raimund@1534:
raimund@1567: DynamicForm form2 = new DynamicForm();
raimund@1567: form2.setFields(filterResultCount);
raimund@1567:
raimund@1534: HLayout filterLayout = new HLayout();
raimund@1534: filterLayout.addMember(form);
raimund@1534: filterLayout.addMember(filter);
raimund@1534: filterLayout.addMember(filterRange);
raimund@1534:
ingo@788: helperContainer.addMember(locationTable);
raimund@1534: helperContainer.addMember(filterLayout);
raimund@1567: helperContainer.addMember(form2);
raimund@238: createInputPanel();
raimund@238: return layout;
raimund@238: }
raimund@238:
felix@1586:
felix@1586: @Override
raimund@863: public void onFilterCriteriaChanged(StringFilterEvent event) {
raimund@863: String search = event.getFilter();
raimund@863:
raimund@863: if (search != null && search.length() > 0) {
raimund@863: Criteria c = new Criteria("description", search);
raimund@863: locationTable.filterData(c);
raimund@1567: filterResultCount.setValue(locationTable.getRecords().length);
raimund@863: }
raimund@863: else {
raimund@863: // TODO Remove filter
raimund@863: }
raimund@863: }
raimund@238:
raimund@1534:
felix@1586: @Override
raimund@1534: public void onFilterCriteriaChanged(RangeFilterEvent event) {
raimund@1538: Float from = event.getFrom() - 0.001f;
raimund@1538: Float to = event.getTo() + 0.001f;
raimund@1538:
raimund@1538: Criterion combinedFilter = null;
raimund@1538: if (from.equals(Float.NaN) && to.equals(Float.NaN)) {
raimund@1538: locationTable.clearCriteria();
raimund@1567: filterResultCount.setValue("");
raimund@1567: return;
raimund@1538: }
raimund@1538: else if (from.equals(Float.NaN)) {
raimund@1538: combinedFilter =
raimund@1538: new Criterion("from", OperatorId.LESS_OR_EQUAL, to);
raimund@1538: }
raimund@1538: else if (to.equals(Float.NaN)) {
raimund@1538: combinedFilter =
raimund@1538: new Criterion("from", OperatorId.GREATER_OR_EQUAL, from);
raimund@1538: }
raimund@1538: else {
raimund@1538: combinedFilter =
raimund@1538: new AdvancedCriteria(OperatorId.AND, new Criterion[] {
raimund@1538: new Criterion("from", OperatorId.GREATER_OR_EQUAL, from),
raimund@1538: new Criterion("from", OperatorId.LESS_OR_EQUAL, to)
raimund@1538: });
raimund@1538: }
raimund@1538: locationTable.filterData(combinedFilter);
raimund@1567: filterResultCount.setValue(locationTable.getRecords().length);
raimund@1534: }
raimund@1534:
raimund@1534:
ingo@563: @Override
ingo@563: public List validate() {
ingo@563: List errors = new ArrayList();
ingo@563: NumberFormat nf = NumberFormat.getDecimalFormat();
ingo@563:
ingo@563: saveLocationValues(locationPanel);
ingo@563:
ingo@563: if (!locationPanel.validateForm()) {
felix@1586: errors.add(MSG.wrongFormat());
ingo@563: return errors;
ingo@563: }
ingo@563:
ingo@563: double[] values = getLocationValues();
ingo@563: double[] good = new double[values.length];
ingo@563: int idx = 0;
ingo@563:
raimund@907: if (values.length > 1) {
felix@1586: errors.add(MSG.too_many_values());
raimund@907: }
raimund@907:
ingo@563: for (double value: values) {
ingo@563: if (value < min || value > max) {
felix@1586: String tmp = MSG.error_validate_range();
ingo@563: tmp = tmp.replace("$1", nf.format(value));
ingo@563: tmp = tmp.replace("$2", nf.format(min));
ingo@563: tmp = tmp.replace("$3", nf.format(max));
ingo@563: errors.add(tmp);
ingo@563: }
ingo@563: else {
ingo@563: good[idx++] = value;
ingo@563: }
ingo@563: }
ingo@563:
ingo@563: double[] justGood = new double[idx];
ingo@563: for (int i = 0; i < justGood.length; i++) {
ingo@563: justGood[i] = good[i];
ingo@563: }
ingo@563:
ingo@563: if (!errors.isEmpty()) {
ingo@563: locationPanel.setValues(justGood);
ingo@563: }
ingo@563:
ingo@563: return errors;
ingo@563: }
ingo@563:
ingo@563:
felix@1586: /** Create simple DefaultData with single DataItem inside. */
felix@1586: public DefaultData createDataArray(String name, String value) {
felix@1586: DataItem item = new DefaultDataItem(
felix@1586: name,
felix@1586: name,
felix@1586: value);
felix@1586:
felix@1586: return new DefaultData(name,
felix@1586: null,
felix@1586: null,
felix@1586: new DataItem[] {item});
felix@1586: }
felix@1586:
felix@1586:
raimund@238: /**
raimund@238: * This method returns the selected data.
raimund@238: *
raimund@238: * @return the selected/inserted data.
raimund@238: */
raimund@238: public Data[] getData() {
raimund@242: saveLocationValues(locationPanel);
raimund@238: double[] values = getLocationValues();
ingo@1387: Data[] data = new Data[values.length+1];
felix@1586:
raimund@238: for (int i = 0; i < values.length; i++) {
felix@1586: data[i] = createDataArray(DATA_ITEM_NAME,
raimund@238: Double.valueOf(values[i]).toString());
raimund@238: }
felix@1586: data[values.length] = createDataArray("ld_mode", "locations");
ingo@1387:
raimund@238: return data;
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * Validates and stores all values entered in the location mode.
raimund@238: *
raimund@238: * @param p The DoubleArrayPanel.
raimund@238: */
raimund@238: protected void saveLocationValues(DoubleArrayPanel p) {
raimund@238: FormItem[] formItems = p.getFields();
raimund@238:
raimund@238: for (FormItem item: formItems) {
raimund@238: if (item.getFieldName().equals(DoubleArrayPanel.FIELD_NAME)) {
raimund@238: saveLocationValue(p, item);
raimund@238: }
raimund@238: }
raimund@238: }
raimund@238:
raimund@238:
raimund@238: /**
raimund@238: * Validates and stores a value entered in the location mode.
raimund@238: *
raimund@238: * @param p The DoubleArrayPanel.
raimund@238: * @param item The item that needs to be validated.
raimund@238: */
raimund@238: protected void saveLocationValue(DoubleArrayPanel p, FormItem item) {
raimund@238: if (p.validateForm(item)) {
raimund@238: setLocationValues(p.getInputValues(item));
raimund@238: }
raimund@238: }
raimund@238:
raimund@238:
raimund@238: protected void createInputPanel() {
raimund@238: Config config = Config.getInstance();
raimund@238: String url = config.getServerUrl();
raimund@238: String river = "";
raimund@238:
raimund@238: ArtifactDescription adescr = artifact.getArtifactDescription();
raimund@238: DataList[] data = adescr.getOldData();
raimund@238:
felix@1586: // Try to find a "river" data item to set the source for the
felix@1586: // list grid.
raimund@238: if (data != null && data.length > 0) {
raimund@238: for (int i = 0; i < data.length; i++) {
raimund@238: DataList dl = data[i];
raimund@1526: if (dl.getState().equals("state.winfo.river") ||
raimund@1526: dl.getState().equals("state.chart.river")) {
raimund@238: for (int j = 0; j < dl.size(); j++) {
raimund@238: Data d = dl.get(j);
raimund@238: DataItem[] di = d.getItems();
raimund@238: if (di != null && di.length == 1) {
raimund@238: river = d.getItems()[0].getStringValue();
sascha@276: break;
raimund@238: }
raimund@238: }
raimund@238: }
raimund@238: }
raimund@238: }
raimund@238:
raimund@863: locationTable.setDataSource(new DistanceInfoDataSource(
raimund@863: url, river, "locations"));
raimund@238: }
raimund@238:
raimund@238:
felix@1586: /** Get the location values. */
raimund@238: protected double[] getLocationValues() {
raimund@238: return values;
raimund@238: }
raimund@238:
raimund@238:
felix@1586: /** Sets Location values and updates the panel. */
raimund@238: protected void setLocationValues(double[] values) {
raimund@238: this.values = values;
raimund@238: locationPanel.setValues(values);
raimund@238: }
raimund@238: }
raimund@238: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :