Package org.locationtech.udig.project.internal.render.impl

Source Code of org.locationtech.udig.project.internal.render.impl.ViewportModelImpl

/**
* <copyright></copyright> $Id$
*/
package org.locationtech.udig.project.internal.render.impl;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;

import org.locationtech.udig.aoi.IAOIService;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.IMap;
import org.locationtech.udig.project.internal.Map;
import org.locationtech.udig.project.internal.ProjectPackage;
import org.locationtech.udig.project.internal.render.RenderFactory;
import org.locationtech.udig.project.internal.ProjectPlugin;
import org.locationtech.udig.project.internal.render.RenderManager;
import org.locationtech.udig.project.internal.render.RenderPackage;
import org.locationtech.udig.project.internal.render.ViewportModel;
import org.locationtech.udig.project.preferences.PreferenceConstants;
import org.locationtech.udig.project.render.IViewportModelListener;
import org.locationtech.udig.project.render.ViewportModelEvent;
import org.locationtech.udig.project.render.ViewportModelEvent.EventType;
import org.locationtech.udig.project.render.displayAdapter.IMapDisplay;
import org.locationtech.udig.project.render.displayAdapter.MapDisplayEvent;
import org.locationtech.udig.ui.PlatformGIS;
import org.locationtech.udig.ui.ProgressManager;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.emf.ecore.util.EDataTypeUniqueEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Display;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.joda.time.DateTime;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

/**
* TODO Purpose of org.locationtech.udig.project.internal.render.impl
* <p>
* </p>
*
* @author Jesse
* @since 1.0.0
* @generated
*/
public class ViewportModelImpl extends EObjectImpl implements ViewportModel {
    /**
     * The default value of the '{@link #getCRS() <em>CRS</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getCRS()
     * @generated
     * @ordered
     */
    protected static final CoordinateReferenceSystem CRS_EDEFAULT = null;

    /**
     * The cached value of the '{@link #getCRS() <em>CRS</em>}' attribute. <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     *
     * @see #getCRS()
     * @generated NOT
     * @ordered
     */
    protected CoordinateReferenceSystem cRS = DEFAULT_CRS;

    /**
     * This is true if the CRS attribute has been set. <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated false
     * @ordered
     */
    protected boolean cRSESet = false;

    /**
     * The default value of the '{@link #getBounds() <em>Bounds</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getBounds()
     * @generated NOT
     * @ordered
     */
    protected static final ReferencedEnvelope BOUNDS_EDEFAULT = NIL_BBOX; //$NON-NLS-1$

    /**
     * The cached value of the '{@link #getBounds() <em>Bounds</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getBounds()
     * @generated NOT
     * @ordered
     */
    protected ReferencedEnvelope bounds = BOUNDS_EDEFAULT;

    /**
     * The default value of the '{@link #getCenter() <em>Center</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getCenter()
     * @generated
     * @ordered
     */
    protected static final Coordinate CENTER_EDEFAULT = null;

    /**
     * The default value of the '{@link #getHeight() <em>Height</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getHeight()
     * @generated
     * @ordered
     */
    protected static final double HEIGHT_EDEFAULT = 0.0;

    /**
     * The default value of the '{@link #getWidth() <em>Width</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getWidth()
     * @generated
     * @ordered
     */
    protected static final double WIDTH_EDEFAULT = 0.0;

    /**
     * The default value of the '{@link #getAspectRatio() <em>Aspect Ratio</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getAspectRatio()
     * @generated
     * @ordered
     */
    protected static final double ASPECT_RATIO_EDEFAULT = 0.0;

    /**
     * The default value of the '{@link #getPixelSize() <em>Pixel Size</em>}' attribute. <!--
     * begin-user-doc --> <!-- end-user-doc -->
     *
     * @see #getPixelSize()
     * @generated
     * @ordered
     */
    protected static final Coordinate PIXEL_SIZE_EDEFAULT = null;

    /**
     * The cached value of the '{@link #getRenderManagerInternal() <em>Render Manager Internal</em>}' reference.
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @see #getRenderManagerInternal()
     * @generated
     * @ordered
     */
    protected RenderManager renderManagerInternal;

    /**
     * The cached value of the '{@link #getPreferredScaleDenominators() <em>Preferred Scale Denominators</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getPreferredScaleDenominators()
     * @generated
     * @ordered
     */
    protected SortedSet<Double> preferredScaleDenominators;

    private SortedSet<Double> defaultScaleDenominators = null;

    /**
     * The cached value of the '{@link #getAvailableTimesteps() <em>Available Timesteps</em>}' attribute list.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getAvailableTimesteps()
     * @generated
     * @ordered
     */
    protected EList<DateTime> availableTimesteps;

    /**
     * The default value of the '{@link #getCurrentTimestep() <em>Current Timestep</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getCurrentTimestep()
     * @generated
     * @ordered
     */
    protected static final DateTime CURRENT_TIMESTEP_EDEFAULT = null;

    /**
     * The cached value of the '{@link #getCurrentTimestep() <em>Current Timestep</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getCurrentTimestep()
     * @generated
     * @ordered
     */
    protected DateTime currentTimestep = CURRENT_TIMESTEP_EDEFAULT;

    /**
     * The cached value of the '{@link #getAvailableElevation() <em>Available Elevation</em>}' attribute list.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getAvailableElevation()
     * @generated
     * @ordered
     */
    protected EList<Double> availableElevation;

    /**
     * The default value of the '{@link #getCurrentElevation() <em>Current Elevation</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getCurrentElevation()
     * @generated
     * @ordered
     */
    protected static final Double CURRENT_ELEVATION_EDEFAULT = null;

    /**
     * The cached value of the '{@link #getCurrentElevation() <em>Current Elevation</em>}' attribute.
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @see #getCurrentElevation()
     * @generated
     * @ordered
     */
    protected Double currentElevation = CURRENT_ELEVATION_EDEFAULT;

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    protected ViewportModelImpl() {
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    protected EClass eStaticClass() {
        return RenderPackage.Literals.VIEWPORT_MODEL;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public CoordinateReferenceSystem getCRS() {
        return cRS;
    }

    public void setCRS(CoordinateReferenceSystem newCRS) {
        double scale = getScaleDenominator();
        if (newCRS == null)
            throw new IllegalArgumentException("A CRS cannot be null"); //$NON-NLS-1$
        if (newCRS.equals(cRS))
            return;
        CoordinateReferenceSystem oldCRS = getCRS();
        if (getBounds().isNull() || !validState()) {
            setCRSGen(newCRS);

        } else {
            Coordinate center = getCenter();
            DirectPosition2D position = new DirectPosition2D(oldCRS, center.x, center.y);
            try {
                eSetDeliver(false);
                cRS = newCRS;
                bounds = new ReferencedEnvelope(bounds, cRS);
                if (oldCRS != DefaultEngineeringCRS.GENERIC_2D
                        && oldCRS != DefaultEngineeringCRS.GENERIC_3D
                        && oldCRS != DefaultEngineeringCRS.CARTESIAN_2D
                        && oldCRS != DefaultEngineeringCRS.CARTESIAN_3D) {
                    MathTransform transform = CRS.findMathTransform(oldCRS, newCRS, true);
                    DirectPosition newCenter = transform
                            .transform(position, new DirectPosition2D());
                    setCenter(new Coordinate(newCenter.getOrdinate(0), newCenter.getOrdinate(1)));
                    setScale(scale);
                }
            } catch (FactoryException e) {
                throw (RuntimeException) new RuntimeException().initCause(e);
            } catch (MismatchedDimensionException e) {
                throw (RuntimeException) new RuntimeException().initCause(e);
            } catch (TransformException e) {
                throw (RuntimeException) new RuntimeException().initCause(e);
            } finally {
                eSetDeliver(true);
                // Now that the scale is correct, use setCRSGen to correctly fire events
                cRS = oldCRS;

                setCRSGen(newCRS);
                notifyListeners(new ViewportModelEvent(this, EventType.CRS, newCRS, oldCRS));
            }
        }
    }

    /**
     * @generated
     */
    public void setCRSGen(CoordinateReferenceSystem newCRS) {
        CoordinateReferenceSystem oldCRS = cRS;
        cRS = newCRS;
        boolean oldCRSESet = cRSESet;
        cRSESet = true;
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__CRS, oldCRS, cRS, !oldCRSESet));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void unsetCRS() {
        CoordinateReferenceSystem oldCRS = cRS;
        boolean oldCRSESet = cRSESet;
        cRS = getDefaultCRS();
        cRSESet = false;
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.UNSET,
                    RenderPackage.VIEWPORT_MODEL__CRS, oldCRS, getDefaultCRS(), oldCRSESet));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public boolean isSetCRS() {
        return cRSESet;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public synchronized ReferencedEnvelope getBounds() {
        if (bounds == null) {
            return getMapInternal().getBounds(ProgressManager.instance().get());
        }

        return bounds;
    }

    public void setBounds(ReferencedEnvelope newBounds) {
        setBounds(newBounds, false);
    }

    public void setBounds(ReferencedEnvelope newBounds, boolean forceContainBBoxZoom) {
        setCRS(newBounds.getCoordinateReferenceSystem());
        setBoundsInternal(newBounds, forceContainBBoxZoom);
    }

    public void setBounds(Envelope newBounds) {
        setBoundsInternal(newBounds, false);
    }

    public void setBoundsInternal(Envelope newBounds, boolean forceContainBBoxZoom) {
        Envelope finalBounds = newBounds;
        if (getDefaultPreferredScaleDenominators() != getPreferredScaleDenominators()
                && validState()) {
            IMapDisplay mapDisplay = getRenderManagerInternal().getMapDisplay();
            ReferencedEnvelope referenced;
            if (newBounds instanceof ReferencedEnvelope) {
                referenced = (ReferencedEnvelope) newBounds;
            } else {
                referenced = new ReferencedEnvelope(newBounds, getCRS());
            }
            double scale = ScaleUtils.calculateScaleDenominator(referenced,
                    mapDisplay.getDisplaySize(), mapDisplay.getDPI());
            scale = ScaleUtils.calculateClosestScale(getPreferredScaleDenominators(), scale,
                    ScaleUtils.zoomClosenessPreference());

            finalBounds = ScaleUtils.calculateBoundsFromScale(scale, mapDisplay.getDisplaySize(),
                    mapDisplay.getDPI(), referenced);
            if (forceContainBBoxZoom && !finalBounds.contains(newBounds)) {
                Iterator<Double> tail = getPreferredScaleDenominators().tailSet(scale).iterator();
                // the tail will include scale because scale is one of the elements in the set.  So drop that
                tail.next();
                Double nextLargest = tail.next();
                if (nextLargest != null) {
                    finalBounds = ScaleUtils.calculateBoundsFromScale(nextLargest,
                            mapDisplay.getDisplaySize(), mapDisplay.getDPI(), referenced);
                }
            }
        }

        Envelope oldBounds = bounds == null ? new Envelope() : bounds;
        if (!getBounds().isNull() && !Double.isNaN(getAspectRatio())
                && !Double.isNaN(finalBounds.getWidth()) && !Double.isNaN(finalBounds.getHeight())) {
            double nRatio = finalBounds.getWidth() / finalBounds.getHeight();
            if (Double.isNaN(nRatio))
                nRatio = 0.0;
            double dRatio = getAspectRatio();
            if (validState() && Math.abs(nRatio - dRatio) > ACCURACY) {
                // Returning the same newBounds box is ok, but sometimes causes an infinite loop if
                // zoomToBox's calculations don't affect the size. Making this arbitrary change to
                // the
                // x-axis solves the problem.
                final double arbitraryChange = 2 * 0.0000001;
                finalBounds.init(finalBounds.getMinX() - (arbitraryChange),
                        (finalBounds.getMaxX() + arbitraryChange), finalBounds.getMinY(),
                        finalBounds.getMaxY());

                zoomToBox(finalBounds);
                return;
            }
        }
        bounds = new ReferencedEnvelope(finalBounds, getCRS());
        fireNotification(oldBounds);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public Coordinate getCenter() {
        return new Coordinate(bounds.getMinX() + bounds.getWidth() / 2, bounds.getMinY()
                + bounds.getHeight() / 2);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void setCenter(Coordinate newCenter) {
        // Coordinate center=getCenter();
        double dw = getBounds().getWidth() / 2, dh = getBounds().getHeight() / 2;
        setBounds(new Envelope(newCenter.x - dw, newCenter.x + dw, newCenter.y - dh, newCenter.y
                + dh));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public double getHeight() {
        return bounds.getHeight();
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void setHeight(double newHeight) {
        zoom(getHeight() / newHeight);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public double getWidth() {
        return getBounds().getWidth();
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void setWidth(double newWidth) {
        zoom(getWidth() / newWidth);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public double getAspectRatio() {
        if (!validState())
            return Double.NaN;
        return getRenderManagerInternal().getMapDisplay().getWidth()
                / (double) getRenderManagerInternal().getMapDisplay().getHeight();
    }

    /**
     * TODO summary sentence for validState ...
     *
     * @return validState
     */
    private boolean validState() {
        return getRenderManagerInternal() != null
                && getRenderManagerInternal().getMapDisplay() != null
                && getRenderManagerInternal().getMapDisplay().getDisplaySize() != null
                && getRenderManagerInternal().getMapDisplay().getWidth() > 0
                && getRenderManagerInternal().getMapDisplay().getHeight() > 0;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public Map getMapInternal() {
        if (eContainerFeatureID() != RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL)
            return null;
        return (Map) eContainer();
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public NotificationChain basicSetMapInternal(Map newMapInternal, NotificationChain msgs) {
        msgs = eBasicSetContainer((InternalEObject) newMapInternal,
                RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL, msgs);
        return msgs;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public void setMapInternalGen(Map newMapInternal) {
        if (newMapInternal != eInternalContainer()
                || (eContainerFeatureID() != RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL && newMapInternal != null)) {
            if (EcoreUtil.isAncestor(this, newMapInternal))
                throw new IllegalArgumentException(
                        "Recursive containment not allowed for " + toString()); //$NON-NLS-1$
            NotificationChain msgs = null;
            if (eInternalContainer() != null)
                msgs = eBasicRemoveFromContainer(msgs);
            if (newMapInternal != null)
                msgs = ((InternalEObject) newMapInternal).eInverseAdd(this,
                        ProjectPackage.MAP__VIEWPORT_MODEL_INTERNAL, Map.class, msgs);
            msgs = basicSetMapInternal(newMapInternal, msgs);
            if (msgs != null)
                msgs.dispatch();
        } else if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL, newMapInternal, newMapInternal));
    }

    boolean viewer = false;

    // can't expect to great of accuracy since ASPECT RATIO is based on ints
    private static final double ACCURACY = 0.0001;

    private boolean initialized;

    /**
     * @return Returns the viewer.
     * @uml.property name="viewer"
     */
    public boolean isViewer() {
        return viewer;
    }

    /**
     * @param viewer The viewer to set.
     * @uml.property name="viewer"
     */
    public void setViewer(boolean viewer) {
        this.viewer = viewer;
    }

    /**
     * @see org.locationtech.udig.project.internal.render.RenderManager#setMap(IMap)
     */
    public void setMapInternal(Map newMap) {
        if (isViewer()) {
            eBasicSetContainer((InternalEObject) newMap, RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL);
        } else
            setMapInternalGen(newMap);
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public RenderManager getRenderManagerInternal() {
        return renderManagerInternal;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public NotificationChain basicSetRenderManagerInternal(RenderManager newRenderManagerInternal,
            NotificationChain msgs) {
        RenderManager oldRenderManagerInternal = renderManagerInternal;
        renderManagerInternal = newRenderManagerInternal;
        if (eNotificationRequired()) {
            ENotificationImpl notification = new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL,
                    oldRenderManagerInternal, newRenderManagerInternal);
            if (msgs == null)
                msgs = notification;
            else
                msgs.add(notification);
        }
        return msgs;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    public void setRenderManagerInternal(RenderManager newRenderManagerInternal) {
        if (newRenderManagerInternal != renderManagerInternal) {
            NotificationChain msgs = null;
            if (renderManagerInternal != null)
                msgs = ((InternalEObject) renderManagerInternal).eInverseRemove(this,
                        RenderPackage.RENDER_MANAGER__VIEWPORT_MODEL_INTERNAL, RenderManager.class,
                        msgs);
            if (newRenderManagerInternal != null)
                msgs = ((InternalEObject) newRenderManagerInternal).eInverseAdd(this,
                        RenderPackage.RENDER_MANAGER__VIEWPORT_MODEL_INTERNAL, RenderManager.class,
                        msgs);
            msgs = basicSetRenderManagerInternal(newRenderManagerInternal, msgs);
            if (msgs != null)
                msgs.dispatch();
        } else if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL,
                    newRenderManagerInternal, newRenderManagerInternal));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public Coordinate getPixelSize() {
        return new Coordinate(getXPixelToWorldScale(), getYPixelToWorldScale());
    }

    private double getXPixelToWorldScale() {
        if (!validState())
            return Double.NaN;
        return getWidth() / getRenderManagerInternal().getMapDisplay().getWidth();
    }

    private double getYPixelToWorldScale() {
        if (!validState())
            return Double.NaN;
        return getHeight() / getRenderManagerInternal().getMapDisplay().getHeight();
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void setBounds(double minx, double maxx, double miny, double maxy) {
        setBounds(new Envelope(minx, maxx, miny, maxy));
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public AffineTransform worldToScreenTransform() {
        if (!validState())
            return null;
        // set up the affine transform and calculate scale values
        return worldToScreenTransform(getBounds(), getRenderManagerInternal().getMapDisplay()
                .getDisplaySize());
    }

    /**
     * @see ViewportModel#worldToScreenTransform(Envelope, Dimension)
     */
    public AffineTransform worldToScreenTransform(Envelope mapExtent, Dimension screenSize) {
        if (!validState())
            return null;

        return ScaleUtils.worldToScreenTransform(mapExtent, screenSize);
    }

    public Point worldToPixel(Coordinate coord) {
        if (!validState())
            return null;
        return ScaleUtils.worldToPixel(coord, getBounds(), getRenderManagerInternal()
                .getMapDisplay().getDisplaySize());
    }

    public Coordinate pixelToWorld(int x, int y) {
        if (!validState())
            return null;

        return ScaleUtils.pixelToWorld(x, y, getBounds(), getRenderManagerInternal()
                .getMapDisplay().getDisplaySize());
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public ViewportModel panUsingScreenCoords(int xpixels, int ypixels) {
        if (!validState())
            return this;
        panUsingWorldCoords(xpixels * getXPixelToWorldScale(), -ypixels * getYPixelToWorldScale());
        return this;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public ViewportModel panUsingWorldCoords(double x, double y) {
        Envelope bounds = getBounds();
        setBounds(bounds.getMinX() + x, bounds.getMaxX() + x, bounds.getMinY() + y,
                bounds.getMaxY() + y);
        return this;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public ViewportModel zoom(double zoom) {
        Coordinate center = getCenter();
        zoom(zoom, center);
        return this;
    }

    public ViewportModel zoom(double zoom, Coordinate fixedPoint) {
        if (fixedPoint == null) {
            fixedPoint = getCenter();
        }
        double effectiveZoom = zoom;
        AffineTransform transformer = ScaleUtils.createScaleTransformWithFixedPoint(effectiveZoom,
                fixedPoint);
        ReferencedEnvelope srcEnvelope = getBounds();
        Envelope transformedEnvelope = ScaleUtils.transformEnvelope(srcEnvelope, transformer);
        setBounds(transformedEnvelope);
        return this;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void zoomToExtent() {
        try {
            if (!validState())
                return;

            ReferencedEnvelope bounds2 = new ReferencedEnvelope(getCRS());

            // check the limit service
            IAOIService aOIService = PlatformGIS.getAOIService();
            ReferencedEnvelope extent = aOIService.getExtent();

            if (extent != null && !extent.isNull() && !extent.isEmpty()) {
                bounds2 = new ReferencedEnvelope(extent);
            } else {
                boolean hasVisibleLayer = false;
                // search the map for visible layers and construct a bounds from those layers.
                // otherwise default to what the map's extent is.
                List<ILayer> layers = getMap().getMapLayers();
                for (ILayer layer : layers) {
                    ReferencedEnvelope layerBounds = layer.getBounds(ProgressManager.instance()
                            .get(), getCRS());
                    if (layer.isVisible() && !layerBounds.isNull()) {
                        hasVisibleLayer = true;
                        // consider zooming in (or zooming out) to a scale the layer is visible
                        ReferencedEnvelope fitted = ScaleUtils.fitToMinAndMax(layerBounds, layer);
                        if (fitted.getCoordinateReferenceSystem() == bounds2
                                .getCoordinateReferenceSystem()) {
                            bounds2.expandToInclude(fitted);
                        } else if (bounds2.getCoordinateReferenceSystem() == layerBounds
                                .getCoordinateReferenceSystem()) {
                            // We have a small problem here? Should do the fitting
                            // before transform to viewport CRS

                            // use layerBounds which should match
                            bounds2.expandToInclude(layerBounds);
                        } else {
                            // ignore as it probably does not have a CRS
                        }
                    }
                }
                if (!hasVisibleLayer) {
                    bounds2 = getMap().getBounds(ProgressManager.instance().get());
                }
            }

            if (bounds2.getCoordinateReferenceSystem() == null || getCRS() == null
                    || bounds2.getCoordinateReferenceSystem().equals(getCRS())) {
                zoomToBox(bounds2);
            } else {
                MathTransform transform = null;
                transform = CRS.findMathTransform(bounds2.getCoordinateReferenceSystem(), getCRS(),
                        true);
                zoomToBox(JTS.transform(bounds2, transform));
            }

        } catch (FactoryException e) {
            zoomToBox(new Envelope(-180, 180, -90, 90));
        } catch (TransformException e) {
            zoomToBox(new Envelope(-180, 180, -90, 90));
        }
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     * @generated
     */
    @Override
    public String toString() {
        if (eIsProxy())
            return super.toString();

        StringBuffer result = new StringBuffer(super.toString());
        result.append(" (cRS: "); //$NON-NLS-1$
        if (cRSESet)
            result.append(cRS);
        else
            result.append("<unset>"); //$NON-NLS-1$
        result.append(", bounds: "); //$NON-NLS-1$
        result.append(bounds);
        result.append(", preferredScaleDenominators: "); //$NON-NLS-1$
        result.append(preferredScaleDenominators);
        result.append(", availableTimesteps: "); //$NON-NLS-1$
        result.append(availableTimesteps);
        result.append(", currentTimestep: "); //$NON-NLS-1$
        result.append(currentTimestep);
        result.append(", availableElevation: "); //$NON-NLS-1$
        result.append(availableElevation);
        result.append(", currentElevation: "); //$NON-NLS-1$
        result.append(currentElevation);
        result.append(')');
        return result.toString();
    }

    /**
     * @see org.locationtech.udig.project.render.displayAdapter.IMapDisplayListener#sizeChanged(org.locationtech.udig.project.render.displayAdapter.MapDisplayEvent)
     */
    public void sizeChanged(final MapDisplayEvent event) {
        if (event.getSize().width < 1 || event.getSize().height < 1)
            return;

        Runnable handler = new Runnable() {
            public void run() {
                Envelope oldBounds = getBounds();

                if (newSizeIsSmaller(event)) {
                    calculateNewBounds(event, oldBounds);
                    return;
                }

                if (oldBounds.isNull()) {
                    zoomToExtent();
                } else {
                    if (oldSizeIsValid(event)) {
                        calculateNewBounds(event, oldBounds);
                        fireNotification(oldBounds);
                    } else {
                        zoomToBox(getBounds());
                    }
                }
            }
        };

        if (Display.getCurrent() != null) {
            Thread thread = new Thread(handler);
            thread.setDaemon(true);
            thread.start();
        } else {
            handler.run();
        }
    }

    private void fireNotification(Envelope oldBounds) {
        if (eNotificationRequired()) {
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__BOUNDS, oldBounds, bounds));

            //notifyListeners(new ViewportModelEvent(this, EventType.CRS, bounds, oldBounds));
            notifyListeners(new ViewportModelEvent(this, EventType.BOUNDS, bounds, oldBounds));
        }
    }

    private void calculateNewBounds(MapDisplayEvent event, Envelope oldBounds) {
        double oldXscale = getWidth() / event.getOldSize().width;
        double oldYscale = getHeight() / event.getOldSize().height;
        double minx = oldBounds.getMinX();
        double maxy = oldBounds.getMaxY();
        double maxx = minx + (event.getSize().width * oldXscale);
        double miny = maxy - (event.getSize().height * oldYscale);
        this.bounds = new ReferencedEnvelope(minx, maxx, miny, maxy, getCRS());
    }

    private boolean oldSizeIsValid(MapDisplayEvent event) {
        return event.getOldSize() != null && event.getOldSize().width != 0
                && event.getOldSize().height != 0;
    }

    private boolean newSizeIsSmaller(MapDisplayEvent event) {
        if (event.getOldSize() == null)
            return false;
        return event.getOldSize().width > event.getSize().width
                && event.getOldSize().height > event.getSize().height;
    }

    /**
     * @see org.locationtech.udig.project.internal.render.ViewportModel#zoomToBox(com.vividsolutions.jts.geom.Envelope)
     */
    public void zoomToBox(Envelope newbbox) {
        setInitialized(true);
        if (Math.abs(newbbox.getWidth() / newbbox.getHeight() - this.getAspectRatio()) > ACCURACY) {
            IMapDisplay display = this.getRenderManagerInternal().getMapDisplay();
            double scaley = newbbox.getHeight() / display.getHeight();
            double scalex = newbbox.getWidth() / display.getWidth();
            double scale;
            if (scalex > scaley)
                scale = scalex;
            else
                scale = scaley;

            double height = display.getHeight() * scale;
            double width = display.getWidth() * scale;

            double dw = width / 2, dh = height / 2;
            Envelope mapBounds = newbbox;
            double x = (mapBounds.getMaxX() + mapBounds.getMinX()) / 2;
            double y = (mapBounds.getMaxY() + mapBounds.getMinY()) / 2;
            newbbox.init(x - dw, x + dw, y - dh, y + dh);
        }
        this.setBounds(newbbox);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID,
            NotificationChain msgs) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            if (eInternalContainer() != null)
                msgs = eBasicRemoveFromContainer(msgs);
            return basicSetMapInternal((Map) otherEnd, msgs);
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            if (renderManagerInternal != null)
                msgs = ((InternalEObject) renderManagerInternal).eInverseRemove(this,
                        RenderPackage.RENDER_MANAGER__VIEWPORT_MODEL_INTERNAL, RenderManager.class,
                        msgs);
            return basicSetRenderManagerInternal((RenderManager) otherEnd, msgs);
        }
        return super.eInverseAdd(otherEnd, featureID, msgs);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID,
            NotificationChain msgs) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            return basicSetMapInternal(null, msgs);
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            return basicSetRenderManagerInternal(null, msgs);
        }
        return super.eInverseRemove(otherEnd, featureID, msgs);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public NotificationChain eBasicRemoveFromContainerFeature(NotificationChain msgs) {
        switch (eContainerFeatureID()) {
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            return eInternalContainer().eInverseRemove(this,
                    ProjectPackage.MAP__VIEWPORT_MODEL_INTERNAL, Map.class, msgs);
        }
        return super.eBasicRemoveFromContainerFeature(msgs);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public Object eGet(int featureID, boolean resolve, boolean coreType) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__CRS:
            return getCRS();
        case RenderPackage.VIEWPORT_MODEL__BOUNDS:
            return getBounds();
        case RenderPackage.VIEWPORT_MODEL__CENTER:
            return getCenter();
        case RenderPackage.VIEWPORT_MODEL__HEIGHT:
            return getHeight();
        case RenderPackage.VIEWPORT_MODEL__WIDTH:
            return getWidth();
        case RenderPackage.VIEWPORT_MODEL__ASPECT_RATIO:
            return getAspectRatio();
        case RenderPackage.VIEWPORT_MODEL__PIXEL_SIZE:
            return getPixelSize();
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            return getMapInternal();
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            return getRenderManagerInternal();
        case RenderPackage.VIEWPORT_MODEL__PREFERRED_SCALE_DENOMINATORS:
            return getPreferredScaleDenominators();
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_TIMESTEPS:
            return getAvailableTimesteps();
        case RenderPackage.VIEWPORT_MODEL__CURRENT_TIMESTEP:
            return getCurrentTimestep();
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_ELEVATION:
            return getAvailableElevation();
        case RenderPackage.VIEWPORT_MODEL__CURRENT_ELEVATION:
            return getCurrentElevation();
        }
        return super.eGet(featureID, resolve, coreType);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @SuppressWarnings("unchecked")
    @Override
    public void eSet(int featureID, Object newValue) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__CRS:
            setCRS((CoordinateReferenceSystem) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__BOUNDS:
            setBounds((ReferencedEnvelope) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__CENTER:
            setCenter((Coordinate) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__HEIGHT:
            setHeight((Double) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__WIDTH:
            setWidth((Double) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            setMapInternal((Map) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            setRenderManagerInternal((RenderManager) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__PREFERRED_SCALE_DENOMINATORS:
            setPreferredScaleDenominators((SortedSet<Double>) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_TIMESTEPS:
            getAvailableTimesteps().clear();
            getAvailableTimesteps().addAll((Collection<? extends DateTime>) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__CURRENT_TIMESTEP:
            setCurrentTimestep((DateTime) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_ELEVATION:
            getAvailableElevation().clear();
            getAvailableElevation().addAll((Collection<? extends Double>) newValue);
            return;
        case RenderPackage.VIEWPORT_MODEL__CURRENT_ELEVATION:
            setCurrentElevation((Double) newValue);
            return;
        }
        super.eSet(featureID, newValue);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public void eUnset(int featureID) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__CRS:
            unsetCRS();
            return;
        case RenderPackage.VIEWPORT_MODEL__BOUNDS:
            setBounds(BOUNDS_EDEFAULT);
            return;
        case RenderPackage.VIEWPORT_MODEL__CENTER:
            setCenter(CENTER_EDEFAULT);
            return;
        case RenderPackage.VIEWPORT_MODEL__HEIGHT:
            setHeight(HEIGHT_EDEFAULT);
            return;
        case RenderPackage.VIEWPORT_MODEL__WIDTH:
            setWidth(WIDTH_EDEFAULT);
            return;
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            setMapInternal((Map) null);
            return;
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            setRenderManagerInternal((RenderManager) null);
            return;
        case RenderPackage.VIEWPORT_MODEL__PREFERRED_SCALE_DENOMINATORS:
            setPreferredScaleDenominators((SortedSet<Double>) null);
            return;
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_TIMESTEPS:
            getAvailableTimesteps().clear();
            return;
        case RenderPackage.VIEWPORT_MODEL__CURRENT_TIMESTEP:
            setCurrentTimestep(CURRENT_TIMESTEP_EDEFAULT);
            return;
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_ELEVATION:
            getAvailableElevation().clear();
            return;
        case RenderPackage.VIEWPORT_MODEL__CURRENT_ELEVATION:
            setCurrentElevation(CURRENT_ELEVATION_EDEFAULT);
            return;
        }
        super.eUnset(featureID);
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    @Override
    public boolean eIsSet(int featureID) {
        switch (featureID) {
        case RenderPackage.VIEWPORT_MODEL__CRS:
            return isSetCRS();
        case RenderPackage.VIEWPORT_MODEL__BOUNDS:
            return BOUNDS_EDEFAULT == null ? bounds != null : !BOUNDS_EDEFAULT.equals(bounds);
        case RenderPackage.VIEWPORT_MODEL__CENTER:
            return CENTER_EDEFAULT == null ? getCenter() != null : !CENTER_EDEFAULT
                    .equals(getCenter());
        case RenderPackage.VIEWPORT_MODEL__HEIGHT:
            return getHeight() != HEIGHT_EDEFAULT;
        case RenderPackage.VIEWPORT_MODEL__WIDTH:
            return getWidth() != WIDTH_EDEFAULT;
        case RenderPackage.VIEWPORT_MODEL__ASPECT_RATIO:
            return getAspectRatio() != ASPECT_RATIO_EDEFAULT;
        case RenderPackage.VIEWPORT_MODEL__PIXEL_SIZE:
            return PIXEL_SIZE_EDEFAULT == null ? getPixelSize() != null : !PIXEL_SIZE_EDEFAULT
                    .equals(getPixelSize());
        case RenderPackage.VIEWPORT_MODEL__MAP_INTERNAL:
            return getMapInternal() != null;
        case RenderPackage.VIEWPORT_MODEL__RENDER_MANAGER_INTERNAL:
            return renderManagerInternal != null;
        case RenderPackage.VIEWPORT_MODEL__PREFERRED_SCALE_DENOMINATORS:
            return preferredScaleDenominators != null;
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_TIMESTEPS:
            return availableTimesteps != null && !availableTimesteps.isEmpty();
        case RenderPackage.VIEWPORT_MODEL__CURRENT_TIMESTEP:
            return CURRENT_TIMESTEP_EDEFAULT == null ? currentTimestep != null
                    : !CURRENT_TIMESTEP_EDEFAULT.equals(currentTimestep);
        case RenderPackage.VIEWPORT_MODEL__AVAILABLE_ELEVATION:
            return availableElevation != null && !availableElevation.isEmpty();
        case RenderPackage.VIEWPORT_MODEL__CURRENT_ELEVATION:
            return CURRENT_ELEVATION_EDEFAULT == null ? currentElevation != null
                    : !CURRENT_ELEVATION_EDEFAULT.equals(currentElevation);
        }
        return super.eIsSet(featureID);
    }

    /**
     * Returns the system wide default CRS
     */
    public static CoordinateReferenceSystem getDefaultCRS() {
        try {
            IPreferenceStore store = ProjectPlugin.getPlugin().getPreferenceStore();
            int i = store.getInt(PreferenceConstants.P_DEFAULT_CRS);
            if (i == -1)
                return CRS.decode("EPSG:4326");//$NON-NLS-1$
            return CRS.decode("EPSG:" + i); //$NON-NLS-1$
        } catch (FactoryException e) {
            return ViewportModel.BAD_DEFAULT;
        }
    }

    /**
     * FIXME, This method was added as a work around for the fact that we do not have the ability to
     * chain or batch commands.
     *
     * @param firing
     */
    public void setFiringEvents(boolean firing) {
        if (firing) {
            eFlags |= EDELIVER;
        } else {
            eFlags &= ~EDELIVER;

        }
    }

    /**
     * @see org.locationtech.udig.project.internal.render.ViewportModel#isInitialized()
     * @uml.property name="initialized"
     */
    public boolean isInitialized() {
        return initialized;
    }

    /**
     * @param initialized The initialized to set.
     * @uml.property name="initialized"
     */
    public void setInitialized(boolean initialized) {
        this.initialized = initialized;
    }

    /**
     * @see org.locationtech.udig.project.render.IViewportModel#getMap()
     */
    public IMap getMap() {
        return getMapInternal();
    }

    public double getScaleDenominator() {
        if (!validState()) {
            return -1;
        }
        RenderManager renderManager = getRenderManagerInternal();
        ReferencedEnvelope bounds2 = getBounds();
        if (renderManager == null || renderManager.getMapDisplay() == null)
            return -1;

        IMapDisplay display = renderManager.getMapDisplay();
        return ScaleUtils.calculateScaleDenominator(bounds2, display.getDisplaySize(),
                display.getDPI());

    }

    public synchronized SortedSet<Double> getDefaultPreferredScaleDenominators() {
        if (defaultScaleDenominators == null) {
            TreeSet<Double> scales = new TreeSet<Double>();
            scales.add(1000000.0);
            scales.add(100000.0);
            scales.add(50000.0);
            scales.add(20000.0);
            scales.add(10000.0);
            scales.add(5000.0);
            scales.add(2500.0);
            scales.add(1000.0);
            defaultScaleDenominators = Collections.unmodifiableSortedSet(scales);
        }

        return defaultScaleDenominators;
    }

    public SortedSet<Double> getPreferredScaleDenominators() {
        if (preferredScaleDenominators == null) {
            return getDefaultPreferredScaleDenominators();
        }
        return preferredScaleDenominators;
    }

    public void setPreferredScaleDenominators(SortedSet<Double> newPreferredScaleDenominators) {
        SortedSet<Double> oldPreferredScaleDenominators = preferredScaleDenominators;
        if (newPreferredScaleDenominators == getDefaultPreferredScaleDenominators()) {
            preferredScaleDenominators = null;
        } else {
            preferredScaleDenominators = Collections.unmodifiableSortedSet(new TreeSet<Double>(
                    newPreferredScaleDenominators));
        }
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__PREFERRED_SCALE_DENOMINATORS,
                    oldPreferredScaleDenominators, preferredScaleDenominators));
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public List<DateTime> getAvailableTimesteps() {
        if (availableTimesteps == null) {
            availableTimesteps = new EDataTypeUniqueEList<DateTime>(DateTime.class, this,
                    RenderPackage.VIEWPORT_MODEL__AVAILABLE_TIMESTEPS);
        }
        return availableTimesteps;
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public DateTime getCurrentTimestep() {
        return currentTimestep;
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public void setCurrentTimestep(DateTime newCurrentTimestep) {
        DateTime oldCurrentTimestep = currentTimestep;
        currentTimestep = newCurrentTimestep;
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__CURRENT_TIMESTEP, oldCurrentTimestep,
                    currentTimestep));
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public List<Double> getAvailableElevation() {
        if (availableElevation == null) {
            availableElevation = new EDataTypeUniqueEList<Double>(Double.class, this,
                    RenderPackage.VIEWPORT_MODEL__AVAILABLE_ELEVATION);
        }
        return availableElevation;
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public Double getCurrentElevation() {
        return currentElevation;
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     */
    public void setCurrentElevation(Double newCurrentElevation) {
        Double oldCurrentElevation = currentElevation;
        currentElevation = newCurrentElevation;
        if (eNotificationRequired())
            eNotify(new ENotificationImpl(this, Notification.SET,
                    RenderPackage.VIEWPORT_MODEL__CURRENT_ELEVATION, oldCurrentElevation,
                    currentElevation));
    }

    /**
     * This method will calculate the current width based on ScaleUtils and
     * the current RenderManager.
     */
    public void setScale(double scaleDenominator) {
        RenderManager rm = getRenderManagerInternal();
        IMapDisplay display = rm.getMapDisplay();
        ReferencedEnvelope newExtents = ScaleUtils.calculateBoundsFromScale(scaleDenominator,
                display.getDisplaySize(), display.getDPI(), getBounds());
        setWidth(newExtents.getWidth());
    }

    /**
     * Calculates new map bounds according to the given scale, DPI, and display dimensions
     */
    public void setScale(double scaleDenominator, int dpi, int displayWidth, int displayHeight) {

        ReferencedEnvelope newExtents = ScaleUtils.calculateBoundsFromScale(scaleDenominator,
                new Dimension(displayWidth, displayHeight), dpi, getBounds());
        setWidth(newExtents.getWidth());
    }

    CopyOnWriteArraySet<IViewportModelListener> listeners = new CopyOnWriteArraySet<IViewportModelListener>();

    public void addViewportModelListener(IViewportModelListener listener) {
        listeners.add(listener);
    }

    public void removeViewportModelListener(IViewportModelListener listener) {
        listeners.remove(listener);
    }

    private void notifyListeners(ViewportModelEvent event) {
        for (IViewportModelListener listener : listeners) {
            try {
                listener.changed(event);
            } catch (Throwable t) {
                ProjectPlugin.log("", t); //$NON-NLS-1$
            }
        }
    }

    private boolean boundsChanging = false;

    public void setIsBoundsChanging(boolean changing) {
        this.boundsChanging = changing;
    }

    public boolean isBoundsChanging() {
        return this.boundsChanging;
    }
}
TOP

Related Classes of org.locationtech.udig.project.internal.render.impl.ViewportModelImpl

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.