changeset 1545:2f0150f21e77

Added basic UI to enter manual points. flys-client/trunk@3773 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Thu, 26 Jan 2012 13:27:19 +0000
parents 2b3d02626823
children 5c6a5832bde5
files flys-client/ChangeLog flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartOutputTab.java flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartToolbar.java flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ManualPointsEditor.java
diffstat 4 files changed, 466 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/flys-client/ChangeLog	Thu Jan 26 13:24:17 2012 +0000
+++ b/flys-client/ChangeLog	Thu Jan 26 13:27:19 2012 +0000
@@ -1,3 +1,18 @@
+2012-01-26  Felix Wolfsteller <felix.wolfsteller@intevation.de>
+
+	Added basic UI to enter 'manual points'.
+
+	* src/main/java/de/intevation/flys/client/client/ui/chart/ManualPointsEditor.java:
+	  New. UI to enter and modify manual points.
+
+	* src/main/java/de/intevation/flys/client/client/ui/chart/ChartToolbar.java:
+	  Modified constructor to avoid passing unused parameters, instantiate
+	  ManualPointsEditor on users command.
+
+	* src/main/java/de/intevation/flys/client/client/ui/chart/ChartOutputTab.java:
+	  Reflect change in ChartToolbars constructor.
+	  (getView): New.
+
 2012-01-26  Felix Wolfsteller <felix.wolfsteller@intevation.de>
 
 	In preparation of 'manual points' feature, opened Collection
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartOutputTab.java	Thu Jan 26 13:24:17 2012 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartOutputTab.java	Thu Jan 26 13:27:19 2012 +0000
@@ -42,6 +42,8 @@
 
 
 /**
+ * Tab representing and showing one Chart-output.
+ *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
 public class ChartOutputTab
@@ -149,7 +151,7 @@
         //right.addChild(createChartPanel());
         left.addChild(ctp);
 
-        tbarPanel = new ChartToolbar(collectionView, this);
+        tbarPanel = new ChartToolbar(this);
         vLayout.addMember(tbarPanel);
         vLayout.addMember(hLayout);
 
@@ -626,5 +628,11 @@
     protected double[] getZoomValues() {
         return zoom;
     }
+
+
+    /** Return the 'parent' CollectionView. */
+    public CollectionView getView() {
+        return this.view;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartToolbar.java	Thu Jan 26 13:24:17 2012 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ChartToolbar.java	Thu Jan 26 13:27:19 2012 +0000
@@ -54,7 +54,8 @@
     protected PanControl panControl;
 
 
-    public ChartToolbar(CollectionView view, ChartOutputTab chartTab) {
+    /** @param chartTab Output-Tab on which this toolbar is located. */
+    public ChartToolbar(ChartOutputTab chartTab) {
         super(chartTab);
 
         this.chartTab   = chartTab;
@@ -208,8 +209,7 @@
 
     /** Open editor for custom points. */
     protected void openPointWindow() {
-
-        // TBD   
+        new ManualPointsEditor(chartTab.getView().getCollection()).show();
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ManualPointsEditor.java	Thu Jan 26 13:27:19 2012 +0000
@@ -0,0 +1,439 @@
+package de.intevation.flys.client.client.ui.chart;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONNumber;
+import com.google.gwt.json.client.JSONParser;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Window;
+import com.smartgwt.client.widgets.tab.TabSet;
+import com.smartgwt.client.widgets.tab.Tab;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.IButton;
+import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.CheckboxItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+
+import com.smartgwt.client.types.Alignment;
+
+import de.intevation.flys.client.shared.model.Artifact;
+
+import de.intevation.flys.client.client.Config;
+import de.intevation.flys.client.client.FLYSConstants;
+import de.intevation.flys.client.shared.model.Property;
+import de.intevation.flys.client.shared.model.PropertyGroup;
+import de.intevation.flys.client.shared.model.PropertySetting;
+import de.intevation.flys.client.shared.model.BooleanProperty;
+import de.intevation.flys.client.shared.model.DoubleProperty;
+import de.intevation.flys.client.shared.model.IntegerProperty;
+import de.intevation.flys.client.shared.model.StringProperty;
+import de.intevation.flys.client.shared.model.Settings;
+import de.intevation.flys.client.shared.model.OutputSettings;
+import de.intevation.flys.client.shared.model.Collection;
+import de.intevation.flys.client.shared.model.CollectionItem;
+import de.intevation.flys.client.client.utils.IntegerValidator;
+import de.intevation.flys.client.client.utils.DoubleValidator;
+
+import de.intevation.flys.client.client.services.CollectionAttributeService;
+import de.intevation.flys.client.client.services.CollectionAttributeServiceAsync;
+import de.intevation.flys.client.client.services.LoadArtifactService;
+import de.intevation.flys.client.client.services.LoadArtifactServiceAsync;
+import de.intevation.flys.client.client.services.FeedService;
+import de.intevation.flys.client.client.services.FeedServiceAsync;
+
+import de.intevation.flys.client.shared.model.Data;
+import de.intevation.flys.client.shared.model.DefaultArtifact;
+import de.intevation.flys.client.shared.model.DefaultData;
+import de.intevation.flys.client.shared.model.Recommendation;
+import de.intevation.flys.client.shared.model.Recommendation.Facet;
+import de.intevation.flys.client.shared.model.Recommendation.Filter;
+
+
+/**
+ * UI to enter point data and save it to an PointArtifact.
+ */
+public class ManualPointsEditor
+extends      Window
+implements   ClickHandler
+{
+    /** The interface that provides i18n messages. */
+    protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
+
+    /** Name of the main data item to be fed. */
+    public static final String POINT_DATA = "manualpoints.data";
+    // TODO with separate point sets in multiple diagrams, we might need
+    //      different POINT_DATA-names (e.g. one per diagram).
+
+    protected CollectionAttributeServiceAsync updater =
+        GWT.create(CollectionAttributeService.class);
+
+    /** The collection */
+    protected Collection collection;
+
+    /** The listGrid showing point entries. */
+    protected ListGrid listGrid;
+
+    /** Service handle to clone and add artifacts to collection. */
+    LoadArtifactServiceAsync loadArtifactService = GWT.create(
+            de.intevation.flys.client.client.services.LoadArtifactService.class);
+
+    /** Service to feed the artifact with new point-data. */
+    FeedServiceAsync feedService = GWT.create(
+        de.intevation.flys.client.client.services.FeedService.class);
+
+    /** UUID of artifact to feed. */
+    protected String uuid;
+
+
+    /**
+     * Setup editor dialog.
+     * @param collection The collection to use.
+     */
+    public ManualPointsEditor(Collection collection) {
+        this.collection = collection;
+        init();
+    }
+
+
+    /** Searches collection for first artifact to serve (manual) point data. */
+    public String findManualPointsUUID() {
+        // TODO Need to be more picky (different points in different diagrams)
+        int size = collection.getItemLength();
+
+        for (int i = 0; i < size; i++) {
+            CollectionItem item = collection.getItem(i);
+            String dataValue = (String) item.getData().get(POINT_DATA);
+            if (dataValue != null) {
+                // Found it.
+                uuid = item.identifier();
+                return uuid;
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Initialize the editor window and its components.
+     */
+    protected void init() {
+        setTitle("Add Points");
+        //TODO MSG.properties());
+        setCanDragReposition(true);
+        setCanDragResize(true);
+
+        // If no manualpoints artifact found, create it now. 
+        if(findManualPointsUUID() == null) {
+            addArtifactCreateUI();
+        }
+        else {
+            createUI();
+        }
+    }
+
+    /** Create and setup/add the ui. */
+    public void createUI() {
+        Config config = Config.getInstance();
+
+        Button accept = new Button(MSG.label_ok());
+        Button cancel = new Button(MSG.label_cancel());
+        cancel.addClickHandler(this);
+        accept.addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent e) {
+                if(isDialogValid()) {
+                    // Feed JSON-encoded content of listgrid.
+                    String jsonString = "";
+                    int idx = 0;
+                    JSONArray list = new JSONArray();
+
+                    // TODO also need name attribute
+                    for(ListGridRecord record : listGrid.getRecords()) {
+                        if (record instanceof PointRecord) {
+                            JSONArray data = new JSONArray();
+
+                            PointRecord point = (PointRecord) record;
+                            data.set(0, new JSONNumber(point.getX()));
+                            data.set(1, new JSONNumber(point.getY()));
+
+                            list.set(idx, data);
+                            idx++;
+                        }
+                        else {
+                            JSONArray data = new JSONArray();
+
+                            // TODO better get double directly (via cell-formatter etc)
+                            String xString = record.getAttributeAsString("X");
+                            String yString = record.getAttributeAsString("Y");
+
+                            data.set(0, new JSONNumber(Double.valueOf(xString)));
+                            data.set(1, new JSONNumber(Double.valueOf(yString)));
+
+                            list.set(idx, data);
+                            idx++;
+                        }
+                    }
+
+                    // TODO lock UI until feed succeeded/failed.
+
+                    // Feed list.toString to respective artifact.
+                    Data[] feedData = new Data[] {
+                        DefaultData.createSimpleStringData(POINT_DATA,
+                            list.toString())
+                    };
+                    feedService.feed(
+                        Config.getInstance().getLocale(),
+                        new DefaultArtifact(uuid, "TODO:hash"),
+                        feedData,
+                        new AsyncCallback<Artifact>() {
+                            public void onFailure(Throwable caught) {
+                                GWT.log("Could not feed artifact with points.");
+                                SC.warn(MSG.getString(caught.getMessage()));
+                                enable();
+                            }
+                            public void onSuccess(Artifact fartifact) {
+                                GWT.log("Successfully set points ");
+                                // TODO refresh view
+                                //requestRedraw();
+                                //updateCollection();
+                                //updateGrid();
+                                //enable();
+                                destroy();
+                            }
+                        });
+                }
+                else {
+                    GWT.log("Dialog not valid");
+                    SC.warn(MSG.error_dialog_not_valid());
+                }
+            }
+        });
+
+        HLayout buttons = new HLayout();
+        buttons.addMember(accept);
+        buttons.addMember(cancel);
+        buttons.setAlign(Alignment.CENTER);
+        buttons.setHeight(30);
+
+        HLayout newPointLayout = new HLayout();
+        DynamicForm newPointForm = createNewPointForm();
+        newPointLayout.addMember(newPointForm);
+
+        VLayout layout = new VLayout();
+        listGrid = new ListGrid();
+        listGrid.setWidth100();
+        listGrid.setHeight(200);
+        final ListGridField xField = new ListGridField("X", "X");
+        final ListGridField yField = new ListGridField("Y", "Y");
+        final ListGridField nameField = new ListGridField("name", "name");
+        final ListGridField removeField = new ListGridField("remove", "remove");
+        listGrid.setFields(new ListGridField[] {xField, yField, removeField});
+
+        // Find the artifacts uuid.
+        findManualPointsUUID();
+        CollectionItem item = collection.getItem(uuid);
+
+        // Add points to grid.
+        if (item != null) {
+            String jsonData = item.getData().get(POINT_DATA);
+            JSONArray jsonArray = (JSONArray) JSONParser.parse(jsonData);
+            for (int i = 0; i < jsonArray.size(); i++) {
+                JSONArray point = (JSONArray) jsonArray.get(i);
+                listGrid.addData(pointRecordFromJSON(point));
+            }
+        }
+        else {
+            System.out.println("No item found for " + uuid);
+        }
+
+        layout.addMember(listGrid);
+
+        addItem(layout);
+        IButton button = new IButton("Edit New");
+        button.setTop(250);
+        button.addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent event) {
+                listGrid.startEditingNew();
+            }
+        });
+        addItem(button);
+        addItem(buttons);
+        setWidth(380);
+        setHeight(470);
+        centerInPage();
+    }
+
+
+    /** From a JSON-encoded point, create a PointRecord. */
+    public PointRecord pointRecordFromJSON(JSONArray jsonArray) {
+        JSONNumber x = (JSONNumber) jsonArray.get(0);
+        JSONNumber y = (JSONNumber) jsonArray.get(1);
+        return new PointRecord(x.doubleValue(), y.doubleValue());
+    }
+
+
+    /** Add a ManualPointArtifact to Collection. */
+    public void addArtifactCreateUI() {
+        // TODO MSG:/i18n
+        final Label standByLabel = new Label("Creating artifact, these are not the droids");
+        addItem(standByLabel);
+
+        setWidth(380);
+        setHeight(470);
+        centerInPage();
+
+        Config config = Config.getInstance();
+        String locale = config.getLocale();
+    
+        loadArtifactService.load(
+            this.collection,
+            new Recommendation("manualpoints", ""),
+            "manualpoints",
+            locale,
+            new AsyncCallback<Artifact>() {
+                public void onFailure(Throwable caught) {
+                    GWT.log("Creating manualpoint artifact failed!");
+                }
+                public void onSuccess(Artifact artifact) {
+                    GWT.log("Successfully created artifact.");
+                    removeItem(standByLabel);
+                    uuid = artifact.getUuid();
+                    createUI();
+                }
+            });
+    }
+
+
+    /**
+     * This method is called when the user aborts point editing.
+     * @param event The event.
+     */
+    public void onClick(ClickEvent event) {
+        this.destroy();
+    }
+
+
+    /** Simple record to store points. */
+    public class PointRecord extends ListGridRecord {
+        protected static final String ATTRIBUTE_X = "X";
+        protected static final String ATTRIBUTE_Y = "Y";
+
+        double x;
+        double y;
+
+        private PointRecord() {;}
+
+        public PointRecord(double x, double y) {
+            setX(x);
+            setY(y);
+        }
+
+        public void setX(double x) {
+            this.x = x;
+            setAttribute(ATTRIBUTE_X, getX());
+        }
+
+        public void setY(double y) {
+            this.y = y;
+            setAttribute(ATTRIBUTE_Y, getY());
+        }
+
+        public double getX() {
+            return this.x;
+        }
+
+        public double getY() {
+            return this.y;
+        }
+    }
+
+
+    // TODO cleanup. We need code similar to the following.
+
+    /*
+    protected void updateCollection() {
+        final Config config = Config.getInstance();
+        final String loc    = config.getLocale();
+
+        GWT.log("PropertiesEditor.updateCollection via RPC now");
+
+        Settings s = settings;
+        collection.addSettings(this.tab.getOutputName(), s);
+        updater.update(collection, loc, new AsyncCallback<Collection>() {
+            public void onFailure(Throwable caught) {
+                GWT.log("Could not update collection attributes.");
+                SC.warn(MSG.getString(caught.getMessage()));
+            }
+            public void onSuccess(Collection collection) {
+                updateChartTab();
+            }
+        });
+    }
+
+/*
+    protected void updateChartTab() {
+        this.tab.updateChartInfo();
+        this.tab.updateChartPanel();
+        this.destroy();
+    }
+*/
+
+    protected boolean isDialogValid() {
+        boolean valid = true;
+        /*
+        for (int i = 0; i < tabs.getNumTabs(); i++) {
+            Tab t = tabs.getTab(i);
+            Canvas container = t.getPane();
+            Canvas[] children = container.getChildren();
+            for (Canvas c: children) {
+                valid = validateCanvas(c);
+                if(!valid) {
+                    return valid;
+                }
+            }
+        }
+        */
+        return valid;
+    }
+
+
+    protected boolean validateCanvas(Canvas c) {
+        boolean valid = true;
+        if(c instanceof DynamicForm) {
+            DynamicForm f = (DynamicForm) c;
+            return !f.hasErrors();
+        }
+        else if(c.getChildren().length > 0) {
+            for (Canvas child: c.getChildren()) {
+                valid = validateCanvas(child);
+                if(!valid) {
+                    return valid;
+                }
+            }
+        }
+        return valid;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org