Package org.locationtech.udig.printing.model.impl

Source Code of org.locationtech.udig.printing.model.impl.MapGraphicBoxPrinter

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.printing.model.impl;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;

import org.locationtech.udig.catalog.CatalogPlugin;
import org.locationtech.udig.catalog.ID;
import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.catalog.URLUtils;
import org.locationtech.udig.core.Pair;
import org.locationtech.udig.mapgraphic.MapGraphicChooserDialog;
import org.locationtech.udig.mapgraphic.internal.MapGraphicRenderer;
import org.locationtech.udig.mapgraphic.internal.MapGraphicResource;
import org.locationtech.udig.mapgraphic.internal.MapGraphicService;
import org.locationtech.udig.mapgraphic.style.LocationStyleContent;
import org.locationtech.udig.printing.model.AbstractBoxPrinter;
import org.locationtech.udig.printing.model.Box;
import org.locationtech.udig.printing.model.BoxPrinter;
import org.locationtech.udig.printing.model.Page;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.ILayerListener;
import org.locationtech.udig.project.IProjectElement;
import org.locationtech.udig.project.LayerEvent;
import org.locationtech.udig.project.internal.Layer;
import org.locationtech.udig.project.internal.LayerDecorator;
import org.locationtech.udig.project.internal.LayerFactory;
import org.locationtech.udig.project.internal.Map;
import org.locationtech.udig.project.internal.ProjectFactory;
import org.locationtech.udig.project.internal.render.CompositeRenderContext;
import org.locationtech.udig.project.internal.render.RenderContext;
import org.locationtech.udig.project.internal.render.ViewportModel;
import org.locationtech.udig.project.internal.render.impl.CompositeRenderContextImpl;
import org.locationtech.udig.project.internal.render.impl.ScaleUtils;
import org.locationtech.udig.project.ui.ApplicationGIS;
import org.locationtech.udig.project.ui.BoundsStrategy;
import org.locationtech.udig.project.ui.UDIGEditorInput;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.geotools.geometry.jts.ReferencedEnvelope;

/**
* Allows a Map graphic to be embedded into a box separate from the MapBox.
*
* @author jesse
* @since 1.1.0
*/
public class MapGraphicBoxPrinter extends AbstractBoxPrinter {

    private static final int DEFAULTDPI = 90;
    private int usedDpi = 90;
    private float scaleFactor = Float.NaN;

    private static final Layer NULL = new LayerDecorator(null);

    private Layer layer;
    private String warning;

    private ILayerListener layerListener = new ILayerListener(){

        public void refresh( LayerEvent event ) {
            setDirty(true);
        }

    };
    private boolean inPreviewMode;

    public MapGraphicBoxPrinter() {
        System.out.println();
    }

    public MapGraphicBoxPrinter( Page page ) {
        if (page != null) {
            scaleFactor = (float) page.getSize().width / (float) page.getPaperSize().height;
        }
    }

    public void draw( Graphics2D graphics, IProgressMonitor monitor ) {
        super.draw(graphics, monitor);
        if (Float.isNaN(scaleFactor)) {
            List<Box> boxes = getBox().getPage().getBoxes();
            for( Box box : boxes ) {
                Object adapter = box.getBoxPrinter().getAdapter(Map.class);
                if (adapter != null) {
                    scaleFactor = (float) box.getSize().width / (float) box.getPaperSize().height;
                    break;
                }
            }
        }

        if (warning != null) {
            drawWarning(graphics, warning);
            return;
        }

        if (layer == null) {
            queryForMapGraphic();
        }

        if (layer == null) {
            drawWarning(graphics, "Loading...");
        } else if (layer == NULL) {
            drawWarning(graphics, "A Decorator needs to be selected");
        } else {
            drawGraphic(graphics, monitor);
        }

    }

    /**
     * Draws the graphic.
     */
    private void drawGraphic( Graphics2D graphics, IProgressMonitor monitor ) {
        Pair<Map, Pair<Dimension, Double>> info = findMap();

        if (info == null) {
            drawWarning(graphics, "A map needs to be added to this page");
        }

        List<Layer> layers = info.getLeft().getLayersInternal();
        org.eclipse.draw2d.geometry.Dimension size = getBox().getSize();
        Rectangle rect = new Rectangle(size.width - 1, size.height - 1);
        layer.getStyleBlackboard().put(LocationStyleContent.ID, rect);
        layers.add(layer);

        MapGraphicRenderer renderer = new MapGraphicRenderer();
        CompositeRenderContext toUseForRendering = createRenderContext(info, layer);
        renderer.setContext(toUseForRendering);

        renderer.render(graphics, monitor);
    }

    public void createPreview( Graphics2D graphics, IProgressMonitor monitor ) {
        inPreviewMode = true;
        draw(graphics, monitor);
        setDirty(false);
        inPreviewMode = false;
    }

    private CompositeRenderContext createRenderContext( Pair<Map, Pair<Dimension, Double>> info,
            Layer layer ) {
        Map map = info.getLeft();
        Dimension size = info.getRight().getLeft();
        double scale = info.getRight().getRight();

        ViewportModel viewportModel = map.getViewportModelInternal();
        ReferencedEnvelope bounds = (ReferencedEnvelope) viewportModel.getBounds();
        BoundsStrategy boundsStrategy = new BoundsStrategy(scale);

        RenderContext context = null;
        if (inPreviewMode && !Float.isNaN(scaleFactor)) {
            float dpiFloat = (float) DEFAULTDPI * scaleFactor;
            context = ApplicationGIS.configureMapForRendering(map, size, (int) dpiFloat,
                    boundsStrategy, bounds);
        } else {
            context = ApplicationGIS.configureMapForRendering(map, size, DEFAULTDPI,
                    boundsStrategy, bounds);
        }

        context.setLayerInternal(layer);
        context.setGeoResourceInternal(layer.getGeoResource());

        CompositeRenderContext toUseForRendering = new CompositeRenderContextImpl();
        toUseForRendering.addContexts(Collections.singleton(context));
        toUseForRendering.setRenderManagerInternal(context.getRenderManagerInternal());
        toUseForRendering.setMapInternal(context.getMapInternal());
        return toUseForRendering;
    }

    /**
     * @return Pair<CopyOfMap, Pair<MapBoxSize,ScaleDenominator>>
     */
    private Pair<Map, Pair<Dimension, Double>> findMap() {
        List<Box> boxes = getBox().getPage().getBoxes();
        for( Box box : boxes ) {
            if (box.getBoxPrinter() instanceof MapBoxPrinter) {
                MapBoxPrinter mapBoxPrinter = ((MapBoxPrinter) box.getBoxPrinter());
                Map map = mapBoxPrinter.getMap();
                Map copy = (Map) EcoreUtil.copy(map);

                // we need the original map and its box to correctly calculate the
                // scale so we must do it now
                Dimension size = new Dimension(box.getSize().width, box.getSize().height);
                ViewportModel viewportModel = map.getViewportModelInternal();

                ReferencedEnvelope bounds = (ReferencedEnvelope) viewportModel.getBounds();

                double scale = ScaleUtils.calculateScaleDenominator(bounds, size, 90);

                Pair<Dimension, Double> details = new Pair<Dimension, Double>(size, scale);
                return new Pair<Map, Pair<Dimension, Double>>(copy, details);
            }
        }
        return null;
    }

    /**
     * Warns the user that a MapGraphic needs to be set
     */
    private void drawWarning( Graphics2D graphics, String message ) {
        graphics.setColor(Color.BLACK);
        int height = graphics.getFontMetrics().getHeight();

        int base = (getBox().getSize().height - height) / 2 + height;

        graphics.drawString(message, 0, base);

    }

    @Override
    public void save( IMemento memento ) {
        memento.putTextData(URLUtils.urlToString(layer.getID(), false));
    }

    @Override
    public void load( IMemento memento ) {
        String url = memento.getTextData();

        try {
            IGeoResource resource = CatalogPlugin.getDefault().getLocalCatalog().getById(
                    IGeoResource.class, new ID(new URL(MapGraphicService.SERVICE_URL, url)),
                    new NullProgressMonitor());
            setMapGraphic((MapGraphicResource) resource);
        } catch (IOException e) {
            // uh oh must be missing a plugin
            setMissingResourceWarning();
        }
    }

    private void setMissingResourceWarning() {
        warning = "The map graphic is missing from your installation, talk to the creator of this page and make sure you have the correct plugins.";
    }

    private void queryForMapGraphic() {
        final Display display = findDisplay();
        display.asyncExec(new Runnable(){
            public void run() {
                MapGraphicChooserDialog dialog = new MapGraphicChooserDialog(display
                        .getActiveShell(), false);
                dialog.open();
                if (dialog.getSelectedResources().isEmpty()) {
                    layer = NULL;
                } else {
                    IGeoResource resource = dialog.getSelectedResources().get(0);
                    setMapGraphic((MapGraphicResource) resource);
                }
                setDirty(true);

            }
        });
    }

    private Display findDisplay() {
        Display display = Display.getCurrent();
        if (display == null) {
            display = PlatformUI.getWorkbench().getDisplay();
        }
        return display;
    }

    public String getExtensionPointID() {
        return "org.locationtech.udig.printing.ui.standardBoxes"; //$NON-NLS-1$
    }

    public void setMapGraphic( MapGraphicResource resource ) {
        LayerFactory factory = ProjectFactory.eINSTANCE.createLayerFactory();
        try {
            if (layer != null) {
                layer.removeListener(layerListener);
            }
            layer = factory.createLayer(resource);
            layer.addListener(layerListener);
        } catch (IOException e) {
            setMissingResourceWarning();
        }
        setDirty(true);
    }

    @SuppressWarnings("unchecked")
    public Object getAdapter( Class adapter ) {
        if (adapter.isAssignableFrom(ILayer.class)) {
            return layer;
        }
        if (adapter.isAssignableFrom(IGeoResource.class)) {
            return getMapGraphic();
        }
        return Platform.getAdapterManager().getAdapter(this, adapter);
    }

    public MapGraphicResource getMapGraphic() {
        try {
            if (layer != null) {
                return layer.getResource(MapGraphicResource.class, new NullProgressMonitor());
            } else {
                return null;
            }
        } catch (IOException e) {
            // won't happen
            throw new RuntimeException(e);
        }
    }

    public void setStyleBlackboardKey( String key, Object value ) {
        if (layer == null) {
            throw new IllegalStateException(
                    "Please set the map graphic before calling this method."); //$NON-NLS-1$
        }
        layer.getStyleBlackboard().put(key, value);
    }

    /**
     * Returns the layer contained in the box
     *
     * @return the layer contained in the box
     */
    public Layer getLayer() {
        return layer;
    }

}
TOP

Related Classes of org.locationtech.udig.printing.model.impl.MapGraphicBoxPrinter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.