/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2013, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.display.canvas;
import org.geotoolkit.display.container.GraphicContainer;
import org.geotoolkit.display.canvas.control.CanvasMonitor;
import org.geotoolkit.display.canvas.control.FailOnErrorMonitor;
import org.geotoolkit.factory.Hints;
import static org.apache.sis.util.ArgumentChecks.*;
/**
* Manages the display and user manipulation of {@link Graphic} instances. A newly constructed
* {@code Canvas} is initial empty. To make something appears, {@link Graphic}s must be added
* using the {@link AbstractContainer#add(org.opengis.display.primitive.Graphic) } method.
* The visual content depends of the {@code Graphic}
* subclass. The contents are usually symbols, features or images, but some implementations
* can also manage non-geographic elements like a map scale.
* <p>
* This base class and the more specialized {@link ReferencedCanvas} subclass do not assume a
* two-dimensional rendering. Those same base classes could be used for a 3D rendering engine
* as well. {@link ReferencedCanvas2D} is the first subclass targeting specifically 2D rendering.
* <p>
* In GeotoolKit implementation, there is four {@linkplain CoordinateReferenceSystem coordinate
* reference systems} involved in rendering. {@code AbstractCanvas} declares abstract methods
* for three of them, but the actual CRS management is performed in the {@link ReferencedCanvas}
* subclass. The CRS are enumerated below (arrows are {@linkplain MathTransform transforms}):
*
* <p align="center"> data CRS <img src="doc-files/right.png">
* {@linkplain #getObjectiveCRS objective CRS} <img src="doc-files/right.png">
* {@linkplain #getDisplayCRS display CRS} <img src="doc-files/right.png">
* {@linkplain #getDeviceCRS device CRS}
* </p>
*
* @module
* @since 2.3
* @version $Id$
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
*/
public abstract class AbstractCanvas<T extends GraphicContainer> extends Canvas {
/**
* The name of the {@linkplain PropertyChangeEvent property change event} fired when the
* {@linkplain AbstractCanvas#getMonitor canvas monitor} changed.
*/
public static final String MONITOR_KEY = "monitor";
/**
* The name of the {@linkplain PropertyChangeEvent property change event} fired when the
* {@linkplain AbstractCanvas#getRenderState canvas state} changed.
*/
public static final String RENDERSTATE_KEY = "renderstate";
public static final Boolean ON_HOLD = Boolean.FALSE;
public static final Boolean RENDERING = Boolean.TRUE;
/**
* Small number for floating point compare.
*/
protected static final double EPS = 1E-12;
/**
* Container used by this canvas
*/
protected T container;
/**
* The monitor assigned to this canvas, can not be null.
*/
protected CanvasMonitor monitor = new FailOnErrorMonitor();
/**
* Creates an initial empty canvas.
*
* @param hints The initial set of hints, or {@code null} if none.
*/
protected AbstractCanvas(final Hints hints) {
super(hints);
}
/**
* Set the graphics container for this canvas.
*/
public void setContainer(final T container){
this.container = container;
}
/**
* Get the current graphics container used by the canvas, or null
* if the container has not be defined.
*/
public T getContainer(){
return container;
}
/**
* Returns the monitor assigned to this {@code Canvas}, it can not be null.
*
* @return CanvasMonitor monitor of this canvas
*/
public synchronized CanvasMonitor getMonitor() {
return monitor;
}
/**
* Sets the monitor of this {@code Canvas}. The monitor can not be null.
* <p>
* This method fires a {@value #TITLE_PROPERTY}
* property change event.
*
* @param monitor The canvas monitor.
*/
public void setMonitor(final CanvasMonitor monitor) {
ensureNonNull("canvas monitor", monitor);
final CanvasMonitor old;
synchronized (this) {
old = this.monitor;
this.monitor = monitor;
}
firePropertyChange(MONITOR_KEY, old, monitor);
}
/**
* Clears all cached data. Invoking this method may help to release some resources for other
* applications. It should be invoked when we know that the map is not going to be rendered
* for a while. For example it may be invoked from {@link java.applet.Applet#stop}. Note
* that this method doesn't changes the renderer setting; it will just slow down the first
* rendering after this method call.
*
* @see #dispose
*/
public void clearCache() {
if(container != null) container.clearCache();
}
/**
* Method that may be called when a {@code Canvas} is no longer needed. {@code AbstractCanvas}
* defines this method to invoke {@link Graphic#dispose} for all graphics. The results
* of referencing a canvas or any of its graphics after a call to {@code dispose()} are
* undefined.
* <p>
* Subclasses may use this method to release resources or to return the object to an object
* pool. It is an error to reference a {@code Canvas} after its dispose method has been called.
*
* @see AbstractGraphic#dispose
* @see javax.media.jai.PlanarImage#dispose
*/
@Override
public synchronized void dispose() {
clearCache();
if(container != null) container.dispose();
super.dispose();
}
//--------------Canvas Listeners convinient methods-------------------------
protected void fireRenderingStateChanged(final boolean newState){
firePropertyChange(RENDERSTATE_KEY, !newState, newState);
}
}