felix@1545: package de.intevation.flys.client.client.ui.chart; felix@1545: raimund@1569: import java.util.List; raimund@1569: felix@1545: import com.google.gwt.json.client.JSONArray; felix@1563: import com.google.gwt.json.client.JSONBoolean; felix@1545: import com.google.gwt.json.client.JSONNumber; felix@1545: import com.google.gwt.json.client.JSONParser; felix@1553: import com.google.gwt.json.client.JSONString; felix@1545: import com.google.gwt.core.client.GWT; felix@1545: import com.google.gwt.user.client.rpc.AsyncCallback; felix@1545: felix@1545: import com.smartgwt.client.util.SC; felix@1545: import com.smartgwt.client.widgets.Window; felix@1545: import com.smartgwt.client.widgets.layout.VLayout; felix@1545: import com.smartgwt.client.widgets.layout.HLayout; felix@1545: import com.smartgwt.client.widgets.IButton; felix@1545: import com.smartgwt.client.widgets.Button; felix@1545: import com.smartgwt.client.widgets.Label; felix@1545: import com.smartgwt.client.widgets.grid.ListGrid; felix@1545: import com.smartgwt.client.widgets.grid.ListGridField; felix@1545: import com.smartgwt.client.widgets.grid.ListGridRecord; felix@1561: import com.smartgwt.client.widgets.grid.events.RecordClickEvent; felix@1561: import com.smartgwt.client.widgets.grid.events.RecordClickHandler; felix@1553: import com.smartgwt.client.types.ListGridFieldType; felix@1562: import com.smartgwt.client.widgets.grid.CellFormatter; felix@1562: import com.google.gwt.i18n.client.NumberFormat; felix@1545: raimund@1604: import com.smartgwt.client.widgets.grid.CellEditValueParser; raimund@1604: import com.smartgwt.client.widgets.grid.CellEditValueFormatter; felix@1545: import com.smartgwt.client.widgets.events.ClickEvent; felix@1545: import com.smartgwt.client.widgets.events.ClickHandler; felix@1545: felix@1545: import com.smartgwt.client.types.Alignment; felix@1545: felix@1545: import de.intevation.flys.client.shared.model.Artifact; felix@1545: felix@1545: import de.intevation.flys.client.client.Config; felix@1545: import de.intevation.flys.client.client.FLYSConstants; felix@1545: import de.intevation.flys.client.shared.model.Collection; felix@1545: import de.intevation.flys.client.shared.model.CollectionItem; felix@1545: felix@1545: import de.intevation.flys.client.client.services.LoadArtifactService; felix@1545: import de.intevation.flys.client.client.services.LoadArtifactServiceAsync; felix@1545: import de.intevation.flys.client.client.services.FeedService; felix@1545: import de.intevation.flys.client.client.services.FeedServiceAsync; felix@1545: felix@1545: import de.intevation.flys.client.shared.model.Data; felix@1545: import de.intevation.flys.client.shared.model.DefaultArtifact; felix@1545: import de.intevation.flys.client.shared.model.DefaultData; felix@1545: import de.intevation.flys.client.shared.model.Recommendation; raimund@1569: import de.intevation.flys.client.shared.model.Settings; raimund@1569: import de.intevation.flys.client.shared.model.Property; raimund@1569: import de.intevation.flys.client.shared.model.PropertyGroup; raimund@1569: import de.intevation.flys.client.shared.model.StringProperty; felix@1545: felix@1549: import de.intevation.flys.client.client.event.RedrawRequestHandler; felix@1549: import de.intevation.flys.client.client.event.RedrawRequestEvent; felix@1549: felix@1545: felix@1545: /** felix@1545: * UI to enter point data and save it to an PointArtifact. felix@1545: */ felix@1545: public class ManualPointsEditor felix@1545: extends Window felix@1545: implements ClickHandler felix@1545: { felix@1545: /** The interface that provides i18n messages. */ felix@1545: protected FLYSConstants MSG = GWT.create(FLYSConstants.class); felix@1545: felix@2924: /** Part of name of the main data item to be fed. */ felix@1545: public static final String POINT_DATA = "manualpoints.data"; felix@1545: felix@1549: /** When we chaged something, we need a RedrawRequest(Handler). */ felix@1549: protected RedrawRequestHandler redrawRequestHandler; felix@1545: felix@1545: /** The collection */ felix@1545: protected Collection collection; felix@1545: felix@1545: /** The listGrid showing point entries. */ felix@1545: protected ListGrid listGrid; felix@1545: felix@1545: /** Service handle to clone and add artifacts to collection. */ felix@1545: LoadArtifactServiceAsync loadArtifactService = GWT.create( felix@1545: de.intevation.flys.client.client.services.LoadArtifactService.class); felix@1545: felix@1545: /** Service to feed the artifact with new point-data. */ felix@1545: FeedServiceAsync feedService = GWT.create( felix@1545: de.intevation.flys.client.client.services.FeedService.class); felix@1545: felix@1545: /** UUID of artifact to feed. */ felix@1545: protected String uuid; felix@1545: felix@1568: /** Name of the outputmode, important when feeding data. */ felix@1568: protected String outputModeName; felix@1568: felix@2924: /** Name of the point data item. */ felix@2924: protected String pointDataItemName; felix@2924: felix@1545: felix@1545: /** felix@1545: * Setup editor dialog. felix@1545: * @param collection The collection to use. felix@1545: */ felix@1549: public ManualPointsEditor(Collection collection, felix@1568: RedrawRequestHandler handler, String outputModeName felix@1549: ) { felix@1545: this.collection = collection; felix@1549: this.redrawRequestHandler = handler; felix@1568: this.outputModeName = outputModeName; felix@2924: this.pointDataItemName = outputModeName + "." + POINT_DATA; felix@1545: init(); felix@1545: } felix@1545: felix@1545: felix@1545: /** Searches collection for first artifact to serve (manual) point data. */ felix@1545: public String findManualPointsUUID() { felix@1545: // TODO Need to be more picky (different points in different diagrams) felix@1545: int size = collection.getItemLength(); felix@1545: felix@1545: for (int i = 0; i < size; i++) { felix@1545: CollectionItem item = collection.getItem(i); felix@2924: String dataValue = (String) item.getData().get(pointDataItemName); felix@1545: if (dataValue != null) { felix@1545: // Found it. felix@1545: uuid = item.identifier(); felix@1545: return uuid; felix@1545: } felix@1545: } felix@1545: felix@1545: return null; felix@1545: } felix@1545: felix@1545: felix@1545: /** felix@1545: * Initialize the editor window and its components. felix@1545: */ felix@1545: protected void init() { felix@1553: setTitle(MSG.addpoints()); felix@1545: setCanDragReposition(true); felix@1545: setCanDragResize(true); felix@1545: sascha@2905: // If no manualpoints artifact found, create it now. felix@1545: if(findManualPointsUUID() == null) { felix@1545: addArtifactCreateUI(); felix@1545: } felix@1545: else { felix@1545: createUI(); felix@1545: } felix@1545: } felix@1545: felix@1547: felix@1545: /** Create and setup/add the ui. */ felix@1545: public void createUI() { felix@1545: Config config = Config.getInstance(); felix@1545: felix@1545: Button accept = new Button(MSG.label_ok()); felix@1545: Button cancel = new Button(MSG.label_cancel()); felix@1545: cancel.addClickHandler(this); felix@1561: felix@1545: accept.addClickHandler(new ClickHandler() { felix@1545: public void onClick(ClickEvent e) { felix@1563: okClicked(); felix@1545: } felix@1545: }); felix@1545: felix@1545: HLayout buttons = new HLayout(); felix@1545: buttons.addMember(accept); felix@1545: buttons.addMember(cancel); felix@1545: buttons.setAlign(Alignment.CENTER); felix@1545: buttons.setHeight(30); felix@1545: felix@1545: VLayout layout = new VLayout(); felix@1545: listGrid = new ListGrid(); felix@1545: listGrid.setWidth100(); raimund@1570: listGrid.setHeight("*"); felix@1561: listGrid.setCanSort(false); felix@1561: listGrid.setCanEdit(true); felix@1561: listGrid.setShowHeaderContextMenu(false); felix@1561: felix@1563: CellFormatter doubleFormat = new CellFormatter() { felix@1562: public String format(Object value, ListGridRecord record, int rowNum, int colNum) { felix@1562: if(value != null) { raimund@1604: NumberFormat nf = NumberFormat.getDecimalFormat(); felix@1562: try { raimund@1604: double d = Double.valueOf(value.toString()).doubleValue(); raimund@1604: return nf.format(d); felix@1562: } catch (Exception e) { felix@1562: return value.toString(); felix@1562: } felix@1562: } else { felix@1562: return null; felix@1562: } felix@1563: }}; felix@1563: raimund@1604: CellEditValueParser cevp = new CellEditValueParser() { raimund@1604: public Object parse(Object value, ListGridRecord record, int rowNum, int colNum) { felix@2461: if (value == null) felix@2461: return null; raimund@1604: try { raimund@1604: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@1604: double d = nf.parse(value.toString()); raimund@1604: return (new Double(d)).toString(); raimund@1604: } raimund@1604: catch(NumberFormatException nfe) { raimund@1604: return value; raimund@1604: } raimund@1604: } raimund@1604: }; raimund@1604: raimund@1604: CellEditValueFormatter cevf = new CellEditValueFormatter() { raimund@1604: public Object format(Object value, ListGridRecord record, int rowNum, int colNum) { felix@2482: if (value == null) { felix@2482: return ""; felix@2482: } raimund@1604: NumberFormat nf = NumberFormat.getDecimalFormat(); raimund@1604: try { raimund@1604: double d = Double.valueOf(value.toString()).doubleValue(); raimund@1604: return nf.format(d); raimund@1604: } raimund@1604: catch(NumberFormatException nfe) { raimund@1604: return value; raimund@1604: } raimund@1604: } raimund@1604: }; raimund@1604: raimund@1569: // Use X and Y as default fallback. raimund@1569: String xAxis = "X"; raimund@1569: String yAxis = "Y"; felix@1563: raimund@1569: // Get header text from collection settings. raimund@1569: Settings settings = this.collection.getSettings(outputModeName); raimund@1569: List axes = settings.getSettings("axes"); raimund@1569: if(axes != null) { raimund@1569: for (Property p: axes) { raimund@1569: PropertyGroup pg = (PropertyGroup)p; raimund@1569: StringProperty id = raimund@1569: (StringProperty)pg.getPropertyByName("id"); raimund@1569: if(id.getValue().equals("X")) { raimund@1569: StringProperty name = raimund@1569: (StringProperty)pg.getPropertyByName("label"); raimund@1569: xAxis = name.getValue(); raimund@1569: } raimund@1569: else if (yAxis.equals("Y")) { raimund@1569: StringProperty name = raimund@1569: (StringProperty)pg.getPropertyByName("label"); raimund@1569: yAxis = name.getValue(); raimund@1569: } raimund@1569: } raimund@1569: } raimund@1569: ListGridField xField = raimund@1569: new ListGridField(PointRecord.ATTRIBUTE_X, xAxis); felix@1563: xField.setType(ListGridFieldType.FLOAT); felix@1563: xField.setCellFormatter(doubleFormat); raimund@1604: xField.setEditValueParser(cevp); raimund@1604: xField.setEditValueFormatter(cevf); raimund@1604: felix@1563: raimund@1569: ListGridField yField = raimund@1569: new ListGridField(PointRecord.ATTRIBUTE_Y, yAxis); felix@1553: yField.setType(ListGridFieldType.FLOAT); felix@1563: yField.setCellFormatter(doubleFormat); raimund@1604: yField.setEditValueParser(cevp); raimund@1604: yField.setEditValueFormatter(cevf); felix@1563: felix@1562: ListGridField nameField = new ListGridField(PointRecord.ATTRIBUTE_NAME, felix@1553: MSG.pointname()); felix@1561: final ListGridField removeField = felix@1561: new ListGridField("_removeRecord", MSG.removepoint()){{ felix@1561: setType(ListGridFieldType.ICON); felix@1561: setIcon(GWT.getHostPageBaseURL() + MSG.removeFeature()); felix@1561: setCanEdit(false); felix@1561: setCanFilter(false); felix@1561: setCanSort(false); felix@1561: setCanGroupBy(false); felix@1561: setCanFreeze(false); felix@1561: setWidth(25); felix@1561: }}; felix@1561: felix@1563: ListGridField activeField = new ListGridField( felix@1563: PointRecord.ATTRIBUTE_ACTIVE, MSG.selection()); felix@1563: activeField.setType(ListGridFieldType.BOOLEAN); felix@1564: activeField.setDefaultValue(true); felix@1563: felix@1563: listGrid.setFields(new ListGridField[] {activeField, xField, yField, felix@1553: nameField, removeField}); felix@1545: felix@1561: listGrid.addRecordClickHandler(new RecordClickHandler() { felix@1561: public void onRecordClick(final RecordClickEvent event) { felix@1561: // Just handle remove-clicks felix@1561: if(!event.getField().getName().equals(removeField.getName())) { felix@1561: return; sascha@2905: } felix@1561: event.getViewer().removeData(event.getRecord()); felix@1561: } felix@1561: }); felix@1561: felix@1545: // Find the artifacts uuid. felix@1545: findManualPointsUUID(); felix@1545: CollectionItem item = collection.getItem(uuid); felix@1545: felix@1545: // Add points to grid. felix@1545: if (item != null) { felix@2924: // TODO store this from findPointUUID instead (we touched these). felix@2924: String jsonData = item.getData().get(pointDataItemName); felix@1545: JSONArray jsonArray = (JSONArray) JSONParser.parse(jsonData); felix@1545: for (int i = 0; i < jsonArray.size(); i++) { felix@1545: JSONArray point = (JSONArray) jsonArray.get(i); felix@1545: listGrid.addData(pointRecordFromJSON(point)); felix@1545: } felix@1545: } felix@1545: else { felix@1553: // TODO proper log felix@1545: System.out.println("No item found for " + uuid); felix@1545: } felix@1545: felix@1553: IButton button = new IButton(MSG.newpoint()); felix@1545: button.setTop(250); felix@1545: button.addClickHandler(new ClickHandler() { felix@1545: public void onClick(ClickEvent event) { felix@1545: listGrid.startEditingNew(); felix@1545: } felix@1545: }); felix@1553: felix@1553: layout.addMember(listGrid); felix@1553: layout.addMember(button); felix@1553: felix@1553: addItem(layout); felix@1553: felix@1545: addItem(buttons); felix@1545: setWidth(380); felix@1545: setHeight(470); felix@1545: centerInPage(); felix@1545: } felix@1545: felix@1545: felix@1563: /** Create JSON representation of the points present in the list grid. */ felix@1563: protected JSONArray jsonArrayFromListGrid() { felix@1563: JSONArray list = new JSONArray(); felix@1563: int idx = 0; felix@1563: felix@1563: for(ListGridRecord record : listGrid.getRecords()) { felix@1563: if (record instanceof PointRecord) { felix@1563: JSONArray data = new JSONArray(); felix@1563: felix@1563: PointRecord point = (PointRecord) record; felix@1563: data.set(0, new JSONNumber(point.getX())); felix@1563: data.set(1, new JSONNumber(point.getY())); felix@1563: data.set(2, new JSONString(point.getName())); felix@1563: data.set(3, JSONBoolean.getInstance(point.isActive())); felix@1563: felix@1563: list.set(idx, data); felix@1563: idx++; felix@1563: } felix@1563: else { felix@1563: JSONArray data = new JSONArray(); felix@1563: felix@1565: String nameString = record.getAttributeAsString(PointRecord.ATTRIBUTE_NAME); felix@1563: // Apply default name if none set. felix@1563: if (nameString == null || nameString.equals("")) { felix@1563: String xString = record.getAttributeAsString( felix@1563: PointRecord.ATTRIBUTE_X); felix@1563: String yString = record.getAttributeAsString( felix@1563: PointRecord.ATTRIBUTE_Y); felix@1563: nameString = xString + "/" + yString; felix@1563: } felix@1563: felix@1563: data.set(0, new JSONNumber(record. felix@1563: getAttributeAsDouble(PointRecord.ATTRIBUTE_X))); felix@1563: data.set(1, new JSONNumber(record. felix@1563: getAttributeAsDouble(PointRecord.ATTRIBUTE_Y))); felix@1563: data.set(2, new JSONString(nameString)); felix@1563: data.set(3, JSONBoolean.getInstance(record.getAttributeAsBoolean( felix@1563: PointRecord.ATTRIBUTE_ACTIVE))); felix@1563: felix@1563: list.set(idx, data); felix@1563: idx++; felix@1563: } felix@1563: } felix@1563: return list; felix@1563: } felix@1563: felix@1563: felix@1563: /** felix@1563: * Called when OK Button was clicked. Then, if entered values are valid, felix@1563: * fire a RedrawRequest and destroy. felix@1563: */ felix@1563: protected void okClicked() { felix@1563: if(isDialogValid()) { felix@1563: // Feed JSON-encoded content of listgrid. felix@1563: JSONArray list = jsonArrayFromListGrid(); felix@1563: felix@1563: Data[] feedData = new Data[] { felix@2924: DefaultData.createSimpleStringData(pointDataItemName, felix@1563: list.toString()) felix@1563: }; felix@1563: felix@1563: feedService.feed( felix@1563: Config.getInstance().getLocale(), felix@1563: new DefaultArtifact(uuid, "TODO:hash"), felix@1563: feedData, felix@1563: new AsyncCallback() { felix@1563: public void onFailure(Throwable caught) { felix@1563: GWT.log("Could not feed artifact with points."); felix@1563: SC.warn(MSG.getString(caught.getMessage())); felix@1563: enable(); felix@1563: } felix@1563: public void onSuccess(Artifact fartifact) { felix@1563: GWT.log("Successfully set points "); felix@1563: redrawRequestHandler.onRedrawRequest( felix@1563: new RedrawRequestEvent()); felix@1563: destroy(); felix@1563: } felix@1563: }); felix@1563: } felix@1563: else { felix@1563: GWT.log("Dialog not valid"); felix@1563: SC.warn(MSG.error_dialog_not_valid()); felix@1563: } felix@1563: } felix@1563: felix@1563: felix@1545: /** From a JSON-encoded point, create a PointRecord. */ felix@1545: public PointRecord pointRecordFromJSON(JSONArray jsonArray) { felix@1563: JSONNumber x = (JSONNumber) jsonArray.get(0); felix@1563: JSONNumber y = (JSONNumber) jsonArray.get(1); felix@1563: JSONString s = (JSONString) jsonArray.get(2); felix@1563: JSONBoolean b = (JSONBoolean) jsonArray.get(3); felix@1563: felix@1563: return new PointRecord(b.booleanValue(), x.doubleValue(), felix@1563: y.doubleValue(), s.stringValue()); felix@1545: } felix@1545: felix@1545: felix@1545: /** Add a ManualPointArtifact to Collection. */ felix@1545: public void addArtifactCreateUI() { felix@1553: final Label standByLabel = new Label(MSG.standby()); felix@1545: addItem(standByLabel); felix@1545: felix@1545: setWidth(380); felix@1545: setHeight(470); felix@1545: centerInPage(); felix@1545: felix@1545: Config config = Config.getInstance(); felix@1545: String locale = config.getLocale(); sascha@2905: felix@1545: loadArtifactService.load( felix@1545: this.collection, felix@1545: new Recommendation("manualpoints", ""), felix@1545: "manualpoints", felix@1545: locale, felix@1545: new AsyncCallback() { felix@1545: public void onFailure(Throwable caught) { felix@1545: GWT.log("Creating manualpoint artifact failed!"); felix@1545: } felix@1545: public void onSuccess(Artifact artifact) { felix@1545: GWT.log("Successfully created artifact."); felix@1545: removeItem(standByLabel); felix@1545: uuid = artifact.getUuid(); felix@1545: createUI(); felix@1545: } felix@1545: }); felix@1545: } felix@1545: felix@1545: felix@1545: /** felix@1545: * This method is called when the user aborts point editing. felix@1545: * @param event The event. felix@1545: */ felix@1545: public void onClick(ClickEvent event) { felix@1545: this.destroy(); felix@1545: } felix@1545: felix@1545: felix@1545: /** Simple record to store points. */ felix@1545: public class PointRecord extends ListGridRecord { felix@1545: protected static final String ATTRIBUTE_X = "X"; felix@1545: protected static final String ATTRIBUTE_Y = "Y"; felix@1553: protected static final String ATTRIBUTE_NAME = "name"; felix@1561: protected static final String ATTRIBUTE_ACTIVE = "active"; felix@1545: felix@1545: private PointRecord() {;} felix@1545: felix@1563: public PointRecord(boolean b, double x, double y, String name) { felix@1563: setActive(b); felix@1553: setName(name); felix@1545: setX(x); felix@1545: setY(y); felix@1545: } felix@1545: felix@1561: public void setActive(boolean b) { felix@1561: setAttribute(ATTRIBUTE_ACTIVE, b); felix@1561: } felix@1561: felix@1561: public boolean isActive() { felix@1561: return getAttributeAsBoolean(ATTRIBUTE_ACTIVE); felix@1561: } felix@1561: felix@1553: public void setName(String name) { felix@1561: setAttribute(ATTRIBUTE_NAME, name); felix@1553: } felix@1553: felix@1553: public String getName() { felix@1561: return getAttributeAsString(ATTRIBUTE_NAME); felix@1553: } felix@1553: felix@1545: public void setX(double x) { felix@1561: setAttribute(ATTRIBUTE_X, x); felix@1545: } felix@1545: felix@1545: public void setY(double y) { felix@1561: setAttribute(ATTRIBUTE_Y, y); felix@1545: } felix@1545: felix@1545: public double getX() { felix@1561: return getAttributeAsDouble(ATTRIBUTE_X); felix@1545: } felix@1545: felix@1545: public double getY() { felix@1561: return getAttributeAsDouble(ATTRIBUTE_Y); felix@1545: } felix@1545: } felix@1545: felix@1545: felix@1565: /** Return false if x or y attribute is missing. */ felix@1545: protected boolean isDialogValid() { felix@1545: boolean valid = true; felix@1565: for (ListGridRecord record : listGrid.getRecords()) { felix@1565: if (record.getAttributeAsDouble(PointRecord.ATTRIBUTE_X) == null felix@1565: || record.getAttributeAsDouble(PointRecord.ATTRIBUTE_Y) == null) { felix@1565: return false; felix@1545: } felix@1545: } raimund@1604: if (listGrid.hasErrors()) { raimund@1604: valid = false; raimund@1604: } felix@1545: return valid; felix@1545: } felix@1545: } felix@1545: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :