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 :