es.emergya.ui.gis.popups.RouteDialog.java Source code

Java tutorial

Introduction

Here is the source code for es.emergya.ui.gis.popups.RouteDialog.java

Source

/*
 * Copyright (C) 2010, Emergya (http://www.emergya.es)
 *
 * @author <a href="mailto:jlrodriguez@emergya.es">Juan Lus Rodrguez</a>
 * @author <a href="mailto:marias@emergya.es">Mara Arias</a>
 *
 * This file is part of GoFleet
 *
 * This software is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As a special exception, if you link this library with other files to
 * produce an executable, this library does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * This exception does not however invalidate any other reasons why the
 * executable file might be covered by the GNU General Public License.
 */
package es.emergya.ui.gis.popups;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.util.ConcurrentModificationException;
import java.util.LinkedList;
import java.util.List;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingWorker;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.gofleet.context.GoClassLoader;
import org.gofleet.context.GoWired;
import org.gofleet.internacionalization.I18n;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.mappaint.LineElemStyle;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;

import es.emergya.bbdd.dao.RoutingHome;
import es.emergya.cliente.constants.LogicConstants;
import es.emergya.consultas.RoutingConsultas;
import es.emergya.geo.util.UTM;
import es.emergya.ui.SpringUtilities;
import es.emergya.ui.base.BasicWindow;
import es.emergya.ui.gis.CustomMapView;

public class RouteDialog extends JFrame implements ActionListener {

    static final Log log = LogFactory.getLog(RouteDialog.class);
    private static RouteDialog instance;
    private LatLon from, to;
    private JTextField fx, fy, tx, ty;
    JLabel notification;
    JLabel progressIcon;
    Icon iconTransparente;
    Icon iconEnviando;
    JButton search, clear;
    CustomMapView view;
    OsmDataLayer route;
    private static final Log LOG = LogFactory.getLog(RouteDialog.class);

    @GoWired
    public I18n i18n;

    /**
     * @return the i18n
     */
    public I18n getI18n() {
        return i18n;
    }

    /**
     * @param i18n
     *            the i18n to set
     */
    public void setI18n(I18n i18n) {
        this.i18n = i18n;
    }

    private RouteDialog() {
        super();
        setAlwaysOnTop(true);
        setResizable(false);
        iconTransparente = LogicConstants.getIcon("48x48_transparente");
        iconEnviando = LogicConstants.getIcon("anim_calculando");
        try {
            route = new OsmDataLayer(new DataSet(), "route", File.createTempFile("route", "route"));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                clear.doClick();
                setVisible(false);
            }
        });
        setTitle(i18n.getString("window.route.titleBar"));
        setMinimumSize(new Dimension(400, 200));
        try {
            setIconImage(((BasicWindow) GoClassLoader.getGoClassLoader().load(BasicWindow.class)).getFrame()
                    .getIconImage());
        } catch (Throwable e) {
            LOG.error("There is no icon image", e);
        }

        JPanel base = new JPanel();
        base.setBackground(Color.WHITE);
        base.setLayout(new BoxLayout(base, BoxLayout.Y_AXIS));

        // Icono del titulo
        JPanel title = new JPanel(new FlowLayout(FlowLayout.LEADING));
        title.setOpaque(false);
        final JLabel labelTitle = new JLabel(i18n.getString("window.route.title"),
                LogicConstants.getIcon("tittleventana_icon_calcularruta"), JLabel.LEFT);
        labelTitle.setFont(LogicConstants.deriveBoldFont(12.0f));
        title.add(labelTitle);
        base.add(title);

        JPanel content = new JPanel(new SpringLayout());
        content.setOpaque(false);

        // Coordenadas
        content.add(new JLabel(i18n.getString("window.route.origen"), JLabel.LEFT));
        JPanel coords = new JPanel(new GridLayout(1, 2));
        coords.setOpaque(false);
        fx = new JTextField(8);
        fx.setEditable(false);
        fy = new JTextField(8);
        fy.setEditable(false);
        coords.add(fy);
        coords.add(fx);
        content.add(coords);
        content.add(new JLabel(i18n.getString("window.route.destino"), JLabel.LEFT));
        JPanel coords2 = new JPanel(new GridLayout(1, 2));
        coords2.setOpaque(false);
        tx = new JTextField(8);
        tx.setEditable(false);
        ty = new JTextField(8);
        ty.setEditable(false);
        coords2.add(ty);
        coords2.add(tx);
        content.add(coords2);

        SpringUtilities.makeCompactGrid(content, 2, 2, 6, 6, 6, 6);
        base.add(content);

        // Area para mensajes
        JPanel notificationArea = new JPanel();
        notificationArea.setOpaque(false);
        notification = new JLabel("PLACEHOLDER");
        notification.setForeground(Color.WHITE);
        notificationArea.add(notification);
        base.add(notificationArea);

        JPanel buttons = new JPanel();
        buttons.setOpaque(false);
        buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
        search = new JButton(i18n.getString("window.route.calcular"),
                LogicConstants.getIcon("ventanacontextual_button_calcularruta"));
        search.addActionListener(this);
        buttons.add(search);
        clear = new JButton(i18n.getString("window.route.limpiar"), LogicConstants.getIcon("button_limpiar"));
        clear.addActionListener(this);
        buttons.add(clear);
        buttons.add(Box.createHorizontalGlue());
        progressIcon = new JLabel(iconTransparente);
        buttons.add(progressIcon);
        buttons.add(Box.createHorizontalGlue());
        JButton cancel = new JButton(i18n.getString("Buttons.cancel"), LogicConstants.getIcon("button_cancel"));
        cancel.addActionListener(this);
        buttons.add(cancel);
        base.add(buttons);
        getContentPane().add(base);
        pack();
        int x;
        int y;

        Container myParent;
        try {
            myParent = ((BasicWindow) GoClassLoader.getGoClassLoader().load(BasicWindow.class)).getFrame()
                    .getContentPane();
            java.awt.Point topLeft = myParent.getLocationOnScreen();
            Dimension parentSize = myParent.getSize();

            Dimension mySize = getSize();

            if (parentSize.width > mySize.width)
                x = ((parentSize.width - mySize.width) / 2) + topLeft.x;
            else
                x = topLeft.x;

            if (parentSize.height > mySize.height)
                y = ((parentSize.height - mySize.height) / 2) + topLeft.y;
            else
                y = topLeft.y;

            setLocation(x, y);
        } catch (Throwable e1) {
            LOG.error("There is no basic window!", e1);
        }
    }

    /**
     * @param from
     *            the from to set
     */
    public void setFrom(LatLon from) {
        if (from != null) {
            this.from = from;
            if (LogicConstants.get("FORMATO_COORDENADAS_MAPA", "UTM").equals(LogicConstants.COORD_UTM)) {
                UTM u = new UTM(LogicConstants.getInt("ZONA_UTM"));
                EastNorth enf = u.latlon2eastNorth(from);
                fy.setText(String.valueOf(enf.getX()));
                fx.setText(String.valueOf(enf.getY()));
            } else {
                fx.setText(String.valueOf(from.getX()));
                fy.setText(String.valueOf(from.getY()));
            }
        }
    }

    /**
     * @param to
     *            the to to set
     */
    public void setTo(LatLon to) {
        if (to != null) {
            this.to = to;
            if (LogicConstants.get("FORMATO_COORDENADAS_MAPA", "UTM").equals(LogicConstants.COORD_UTM)) {
                // mirar LogicConstants.transform(Point geom, final String
                // sourceSRID, final String targetSRID)
                UTM u = new UTM(LogicConstants.getInt("ZONA_UTM"));
                EastNorth ent = u.latlon2eastNorth(to);
                ty.setText(String.valueOf(ent.getX()));
                tx.setText(String.valueOf(ent.getY()));
            } else {
                tx.setText(String.valueOf(to.getX()));
                ty.setText(String.valueOf(to.getY()));
            }
        }
    }

    public void showRouteDialog(LatLon from, LatLon to, CustomMapView view) {
        JFrame f = getRouteDialog(from, to, view);
        f.setVisible(true);
        f.setExtendedState(JFrame.NORMAL);
        f.requestFocus();
    }

    public JFrame getRouteDialog(LatLon from, LatLon to, CustomMapView view) {
        if (instance == null) {
            instance = new RouteDialog();
        }
        instance.view = view;

        instance.setFrom(from);
        instance.setTo(to);
        if (instance.from == null || instance.to == null) {
            instance.notification.setText(i18n.getString("progress.route.nopoints"));
            instance.notification.setForeground(Color.RED);

            instance.search.setEnabled(false);
        } else {
            instance.notification.setForeground(Color.WHITE);
            // instance.notification.setText("");
            instance.search.setEnabled(true);
        }
        if (instance.from == null && instance.to == null) {
            instance.clear.setEnabled(false);
        } else {
            instance.clear.setEnabled(true);
        }

        return instance;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(search)) {
            notification.setForeground(Color.WHITE);
            notification.updateUI();
            progressIcon.setIcon(iconEnviando);
            search.setEnabled(false);
            clear.setEnabled(false);
            new SwingWorker<Boolean, Object>() {
                List<Way> route = null;

                protected void done() {
                    if (route != null && route.size() > 0) {
                        setRoute(route);
                    } else {
                        notification.setText(i18n.getString("window.route.notification.noRoute"));
                        notification.setForeground(Color.RED);
                    }
                    progressIcon.setIcon(iconTransparente);
                    clear.setEnabled(true);
                    search.setEnabled(true);
                    notification.updateUI();
                }

                @Override
                protected Boolean doInBackground() throws Exception {
                    try {
                        route = getRoute();
                        return true;
                    } catch (Throwable t) {
                        log.error("Error al calcular la ruta", t);
                        notification.setText(i18n.getString("progress.route.error"));
                        notification.setForeground(Color.RED);
                        return false;
                    }
                }

            }.execute();

        } else {
            from = null;
            fx.setText("");
            fy.setText("");
            to = null;
            tx.setText("");
            ty.setText("");
            search.setEnabled(false);
            clear.setEnabled(false);

            clearRoute();
            instance.notification.setText(i18n.getString("progress.route.nopoints"));
            instance.notification.setForeground(Color.RED);
            notification.updateUI();
            if (!e.getSource().equals(clear)) {
                setVisible(false);
            }
        }
    }

    private void setRoute(List<Way> ways) {
        clearRoute();
        LineElemStyle ls = new LineElemStyle();
        ls.color = Color.decode(LogicConstants.get("WAY_COLOR"));
        ls.width = Integer.parseInt(LogicConstants.get("WAY_WIDTH"));
        for (Way way : ways) {
            route.data.ways.add(way);
            way.mappaintStyle = ls;
        }
        route.visible = true;
        view.addLayer(route, false);
        view.repaint();
    }

    private void clearRoute() {
        route.data.nodes.clear();
        route.data.ways.clear();
        Layer capaABorrar = null;
        try {
            for (Layer l : view.getAllLayers()) {
                if (l.name.equals(route.name)) {
                    capaABorrar = l;
                    break;
                }
            }
            if (capaABorrar != null) {
                view.removeLayer(capaABorrar);
            }
        } catch (ConcurrentModificationException cme) {
            log.error("Error eliminado la capa de rutas.", cme);
        }
        view.repaint();
    }

    private List<Way> getRoute() throws Throwable {
        LinkedList<Way> res = new LinkedList<Way>();
        GeometryFactory f = new GeometryFactory();
        Point origen = f.createPoint(new Coordinate(from.lon(), from.lat()));
        Point destino = f.createPoint(new Coordinate(to.lon(), to.lat()));

        destino.setSRID(4326);
        origen.setSRID(4326);

        log.debug("getRoute() from " + origen + " to " + destino);

        CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326");
        CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:" + RoutingHome.SRID);
        MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
        origen = (Point) JTS.transform(origen, transform).getCentroid();
        destino = (Point) JTS.transform(destino, transform).getCentroid();

        MultiLineString mls = RoutingConsultas.calculateRoute(origen, destino);
        if (mls != null) {
            for (int i = 0; i < mls.getNumGeometries(); i++) {
                Way way = new Way();
                for (Coordinate coordenada : ((LineString) mls.getGeometryN(i)).getCoordinates()) {
                    Point p = f.createPoint(coordenada);
                    p = (Point) JTS.transform(p, CRS.findMathTransform(targetCRS, sourceCRS));
                    LatLon ll = new LatLon(p.getY(), p.getX());
                    way.addNode(new Node(ll));
                    // if (log.isTraceEnabled())
                    // BasicWindow.showOnMap(ll, 1);
                }
                res.add(way);
            }
        }

        if (log.isTraceEnabled())
            log.trace("Ruta obtenida: " + res);

        return res;
    }
}