com.mecatran.otp.gwt.client.view.PrintWidgetWindowImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.mecatran.otp.gwt.client.view.PrintWidgetWindowImpl.java

Source

/* -------------------------------------------------------------------------
OpenTripPlanner GWT Client
Copyright (C) 2015 Mecatran - info@mecatran.com
    
This program 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 program 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 program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   ------------------------------------------------------------------------- */
package com.mecatran.otp.gwt.client.view;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.mecatran.otp.gwt.client.i18n.I18nUtils;
import com.mecatran.otp.gwt.client.model.ItineraryBean;
import com.mecatran.otp.gwt.client.model.ItineraryLegBean;
import com.mecatran.otp.gwt.client.model.ItineraryRoadLegBean;
import com.mecatran.otp.gwt.client.model.ItineraryRoadStepBean;
import com.mecatran.otp.gwt.client.model.ItineraryTransitLegBean;
import com.mecatran.otp.gwt.client.model.TransitRouteBean;
import com.mecatran.otp.gwt.client.model.Wgs84LatLonBean;
import com.mecatran.otp.gwt.client.utils.FormatUtils;
import com.mecatran.otp.gwt.client.utils.PolylineEncoder;

/*
 * TODO Use html templating?
 */
public class PrintWidgetWindowImpl implements PrintWidget {

    private PrintWidgetListener printWidgetListener;

    private String printCss = "";

    public PrintWidgetWindowImpl(String customCssUrl) {
        if (customCssUrl != null)
            downloadPrintCss(customCssUrl);
    }

    @Override
    public Widget getAsWidget() {
        return null;
    }

    @Override
    public void setPrintWidgetListener(PrintWidgetListener printWidgetListener) {
        this.printWidgetListener = printWidgetListener;
    }

    @Override
    public void printItinerary(ItineraryBean itinerary) {
        FlowPanel rootPanel = new FlowPanel();

        /* Compute some values */
        int nTransfers = 0;
        long walkDistanceMeter = 0;
        long bikeDistanceMeter = 0;
        for (ItineraryLegBean leg : itinerary.getLegs()) {
            switch (leg.getTravelType()) {
            case ROAD:
                switch (leg.getAsRoadLeg().getMode()) {
                case BICYCLE:
                case BICYCLE_RENTAL:
                    bikeDistanceMeter += leg.getAsRoadLeg().getDistanceMeters();
                    break;
                case WALK:
                    walkDistanceMeter += leg.getAsRoadLeg().getDistanceMeters();
                    break;
                default:
                    // pass
                }
                break;
            case TRANSIT:
                nTransfers++;
                break;
            }
        }

        /* Display summary */
        rootPanel.add(new HTML("<h1>"
                + I18nUtils.tr("print.itinerary.header", itinerary.getStartAddress(), itinerary.getEndAddress())
                + "</h1>"));
        rootPanel.add(new HTML(I18nUtils.tr("print.summary.departure",
                FormatUtils.formatDateTime(itinerary.getDepartureTime()), itinerary.getStartAddress())));
        rootPanel.add(new HTML(I18nUtils.tr("print.summary.arrival",
                FormatUtils.formatDateTime(itinerary.getArrivalTime()), itinerary.getEndAddress())));
        rootPanel.add(new HTML(
                I18nUtils.tr("print.summary.duration", FormatUtils.formatDuration(itinerary.getDurationSeconds()),
                        FormatUtils.formatDistance(itinerary.getDistanceMeters()))));
        StringBuffer infoHtml = new StringBuffer();
        if (nTransfers > 0) {
            infoHtml.append(I18nUtils.tr("print.summary.transfers", nTransfers - 1)).append(", ");
        }
        if (walkDistanceMeter > 0) {
            infoHtml.append(
                    I18nUtils.tr("print.summary.walk.distance", FormatUtils.formatDistance(walkDistanceMeter)))
                    .append(", ");
        }
        if (bikeDistanceMeter > 0) {
            infoHtml.append(
                    I18nUtils.tr("print.summary.bike.distance", FormatUtils.formatDistance(bikeDistanceMeter)))
                    .append(", ");
        }
        // Remove last comma
        if (infoHtml.length() > 0)
            infoHtml.setLength(infoHtml.length() - 2);
        rootPanel.add(new HTML(infoHtml.toString()));

        rootPanel.add(new HTML("<h2>" + I18nUtils.tr("print.itinerary.details.header") + "</h2>"));
        /* Departure */
        rootPanel.add(new HTML(
                "<h3>" + I18nUtils.tr("print.step.depart", FormatUtils.formatTime(itinerary.getDepartureTime()),
                        FormatUtils.formatAddress(itinerary.getStartAddress())) + "</h3>"));
        /* Details */
        for (ItineraryLegBean leg : itinerary.getLegs()) {
            switch (leg.getTravelType()) {
            case ROAD:
                rootPanel.add(getRoadDetails((ItineraryRoadLegBean) leg));
                break;
            case TRANSIT:
                rootPanel.add(getTransitDetails((ItineraryTransitLegBean) leg));
                break;
            default:
                throw new IllegalArgumentException("Unsupported leg type: " + leg.getTravelType());
            }
        }
        /* Arrival */
        rootPanel.add(new HTML(
                "<h3>" + I18nUtils.tr("print.step.arrival", FormatUtils.formatTime(itinerary.getArrivalTime()),
                        FormatUtils.formatAddress(itinerary.getEndAddress())) + "</h3>"));

        openWindow(rootPanel.getElement());
    }

    private void downloadPrintCss(String cssUrl) {
        RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, cssUrl);
        try {
            requestBuilder.sendRequest(null, new RequestCallback() {

                @Override
                public void onResponseReceived(Request request, Response response) {
                    printCss = response.getText();
                }

                @Override
                public void onError(Request request, Throwable exception) {
                }
            });
        } catch (RequestException e) {
        }
    }

    private void openWindow(Element rootElement) {
        /* This is the hackish area ... */
        BodyElement printBody = openWindow(I18nUtils.tr("print.button"), printCss);
        printBody.getOwnerDocument().getElementById("printarea").appendChild(rootElement);
    }

    /**
     * Implementation note: Including a CSS as script with href in the HTML
     * document below does not work. We need to include the CSS inline,
     * pre-downloaded.
     * 
     * @param printLabel
     * @param cssContent
     *            CSS CONTENT, not URL.
     * @return
     */
    public static native BodyElement openWindow(String printLabel, String cssContent) /*-{
                                                                                      var win = window.open("", "win", "width=940,height=400,status=1,resizeable=1,scrollbars=1");
                                                                                      win.document.open("text/html", "replace");
                                                                                      win.document.write("<html><head><style>\n" + cssContent
                                                                                      + "\n</style></head><body><div><button onclick='window.print()'>" + printLabel
                                                                                      + "</button></div><div id='printarea'/></body></html>");
                                                                                      win.document.close();
                                                                                      win.focus();
                                                                                      return win.document.body;
                                                                                      }-*/;

    private Widget getRoadDetails(ItineraryRoadLegBean leg) {
        FlowPanel line = new FlowPanel();
        // Main instruction
        line.add(
                new HTML("<h3>" + leg.getInstructions() + " (" + FormatUtils.formatDistance(leg.getDistanceMeters())
                        + " - " + FormatUtils.formatDuration(leg.getDurationSeconds()) + ")</h3>"));

        // Steps
        StringBuilder stepsHtml = new StringBuilder();
        stepsHtml.append("<ul>");
        for (ItineraryRoadStepBean step : leg.getRoadSteps()) {
            if (step.getInstructions() == null) {
                // Can happen in case of transfers between two transit legs
                continue;
            }
            stepsHtml
                    .append("<li>").append(step.getInstructions()).append(
                            (step.getDistanceMeters() >= 5
                                    ? " (" + FormatUtils.formatDistance(step.getDistanceMeters()) + " - "
                                            + FormatUtils.formatDuration(step.getDurationSeconds()) + ")"
                                    : ""))
                    .append("</li>");
        }

        // Map
        StringBuilder mapsHtml = new StringBuilder();
        if (leg.getPath() != null && leg.getPath().length > 0) {
            for (String url : getMapUrl(leg.getPath())) {
                mapsHtml.append("<img style='width: 8cm' src='").append(url).append("'><br/><hr/>");
            }
        }
        // Table
        StringBuilder tableHtml = new StringBuilder();
        tableHtml.append("<table><tr><td>").append(mapsHtml.toString()).append("</td><td>")
                .append(stepsHtml.toString()).append("</td></tr></table>");
        line.add(new HTML(tableHtml.toString()));
        return line;
    }

    private Widget getTransitDetails(ItineraryTransitLegBean leg) {
        FlowPanel line = new FlowPanel();
        TransitRouteBean route = leg.getRoute();
        String codeHtml = "<b><span class='route-code' style='color:" + route.getForegroundColor()
                + "; background-color:" + route.getBackgroundColor() + "'>&nbsp;" + route.getCode()
                + "&nbsp;</span></b>";
        line.add(new HTML("<h3>" + I18nUtils.tr("print.take.the.route", codeHtml,
                FormatUtils.formatTime(leg.getDepartureTime()), leg.getDepartureStop().getName(), leg.getHeadsign())
                + "</h3>"));
        line.add(new HTML("<h3>" + I18nUtils.tr("print.hop.off",
                "<span class='time'>" + FormatUtils.formatTime(leg.getArrivalTime()) + "</span>",
                leg.getArrivalStop().getName()) + "\"</h3>"));
        return line;
    }

    private List<String> getMapUrl(Wgs84LatLonBean[] path) {
        final int MAP_PATH_SIZE = 100;
        NumberFormat dec5Format = NumberFormat.getFormat("#.00000");
        List<String> retval = new ArrayList<String>();
        int n = (path.length - 1) / MAP_PATH_SIZE + 1;
        int m = path.length / n + 1;
        int js = 0;
        for (int i = 0; i < n; i++) {
            StringBuilder urlBuilder = new StringBuilder();
            int je = js + m;
            if (je > path.length)
                je = path.length;
            boolean start = i == 0;
            boolean end = je == path.length;
            urlBuilder.append(
                    "http://maps.googleapis.com/maps/api/staticmap?sensor=false&scale=2&size=800x800&maptype=roadmap");
            if (start)
                urlBuilder.append("&markers=").append(dec5Format.format(path[0].getLat())).append(",")
                        .append(dec5Format.format(path[0].getLon()));
            if (end && !start)
                urlBuilder.append("&markers=");
            else
                urlBuilder.append("|");
            if (end)
                urlBuilder.append(dec5Format.format(path[path.length - 1].getLat())).append(",")
                        .append(dec5Format.format(path[path.length - 1].getLon()));
            urlBuilder.append("&path=color:blue|enc:");
            Wgs84LatLonBean[] subPath = new Wgs84LatLonBean[je - js];
            // GWT does not have Arrays.copyOfRange() ...
            for (int k = js; k < je; k++) {
                subPath[k - js] = path[k];
            }
            urlBuilder.append(PolylineEncoder.encode(subPath));
            retval.add(urlBuilder.toString());
            js = je;
        }
        assert (js == path.length);
        return retval;
    }
}