view flys-client/src/main/java/de/intevation/flys/client/client/ui/chart/ManualPointsEditor.java @ 1561:3cf3cd8dd92d

Made manual points edit- and removable. flys-client/trunk@3807 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Fri, 27 Jan 2012 15:24:04 +0000
parents 9ad19e31d149
children af29d43cf4da
line wrap: on
line source
package de.intevation.flys.client.client.ui.chart;

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.json.client.JSONString;
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.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.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.types.ListGridFieldType;

import com.smartgwt.client.widgets.form.DynamicForm;

import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;

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.Collection;
import de.intevation.flys.client.shared.model.CollectionItem;
import de.intevation.flys.client.client.utils.DoubleValidator;

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.client.event.RedrawRequestHandler;
import de.intevation.flys.client.client.event.RedrawRequestEvent;
import de.intevation.flys.client.client.event.RedrawRequestEvent.Type;


/**
 * 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).

    /** When we chaged something, we need a RedrawRequest(Handler). */
    protected RedrawRequestHandler redrawRequestHandler;

    /** 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,
        RedrawRequestHandler handler
    ) {
        this.collection = collection;
        this.redrawRequestHandler = handler;
        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(MSG.addpoints());
        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);

        // TODO refactor.
        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();

                    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()));
                            data.set(2, new JSONString(point.getName()));

                            list.set(idx, data);
                            idx++;
                        }
                        else {
                            JSONArray data = new JSONArray();

                            // TODO better get double directly (via cell-formatter etc)
                            // TODO finalize the X, Y etc.
                            String xString = record.getAttributeAsString("X");
                            String yString = record.getAttributeAsString("Y");
                            String nameString = record.getAttributeAsString("name");
                            if (nameString == null || nameString.equals("")) {
                                nameString = xString + "/" + yString;
                            }

                            data.set(0, new JSONNumber(Double.valueOf(xString)));
                            data.set(1, new JSONNumber(Double.valueOf(yString)));
                            data.set(2, new JSONString(nameString));

                            list.set(idx, data);
                            idx++;
                        }
                    }

                    // 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 ");
                                redrawRequestHandler.onRedrawRequest(
                                    new RedrawRequestEvent());
                                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);

        VLayout layout = new VLayout();
        listGrid = new ListGrid();
        listGrid.setWidth100();
        listGrid.setHeight(200);
        listGrid.setCanSort(false);
        listGrid.setCanEdit(true);
        listGrid.setShowHeaderContextMenu(false);

        // TODO X and Y Header depend on the current chart and axis (e.g. W[nn+m])
        // collection.getSettings(outputName).getSettings -> Propertie -> "axis" -> "label"
        ListGridField xField = new ListGridField("X", "X");
        xField.setType(ListGridFieldType.FLOAT);
        ListGridField yField = new ListGridField("Y", "Y");
        yField.setType(ListGridFieldType.FLOAT);
        ListGridField nameField = new ListGridField("name",
            MSG.pointname());
        final ListGridField removeField  =
            new ListGridField("_removeRecord", MSG.removepoint()){{
                setType(ListGridFieldType.ICON);
                setIcon(GWT.getHostPageBaseURL() + MSG.removeFeature());
                setCanEdit(false);
                setCanFilter(false);
                setCanSort(false);
                setCanGroupBy(false);
                setCanFreeze(false);
                setWidth(25);
        }};

        listGrid.setFields(new ListGridField[] {xField, yField,
            nameField, removeField});

        listGrid.addRecordClickHandler(new RecordClickHandler() {
                public void onRecordClick(final RecordClickEvent event) {
                    // Just handle remove-clicks
                    if(!event.getField().getName().equals(removeField.getName())) {
                        return;
                    }    
                    event.getViewer().removeData(event.getRecord());
                }
            });

        // 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 {
            // TODO proper log
            System.out.println("No item found for " + uuid);
        }

        IButton button = new IButton(MSG.newpoint());
        button.setTop(250);
        button.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                listGrid.startEditingNew();
            }
        });

        layout.addMember(listGrid);
        layout.addMember(button);

        addItem(layout);

        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);
        JSONString s = (JSONString) jsonArray.get(2);
        return new PointRecord(x.doubleValue(), y.doubleValue(), s.stringValue());
    }


    /** Add a ManualPointArtifact to Collection. */
    public void addArtifactCreateUI() {
        final Label standByLabel = new Label(MSG.standby());
        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";
        protected static final String ATTRIBUTE_NAME = "name";
        protected static final String ATTRIBUTE_ACTIVE = "active";

        private PointRecord() {;}

        public PointRecord(double x, double y, String name) {
            setName(name);
            setX(x);
            setY(y);
        }

        public void setActive(boolean b) {
            setAttribute(ATTRIBUTE_ACTIVE, b);
        }

        public boolean isActive() {
            return getAttributeAsBoolean(ATTRIBUTE_ACTIVE);
        }

        public void setName(String name) {
            setAttribute(ATTRIBUTE_NAME, name);
        }

        public String getName() {
            return getAttributeAsString(ATTRIBUTE_NAME);
        }

        public void setX(double x) {
            setAttribute(ATTRIBUTE_X, x);
        }

        public void setY(double y) {
            setAttribute(ATTRIBUTE_Y, y);
        }

        public double getX() {
            return getAttributeAsDouble(ATTRIBUTE_X);
        }

        public double getY() {
            return getAttributeAsDouble(ATTRIBUTE_Y);
        }
    }


    // TODO validate entered values (CellFormatter).
    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