/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, 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.display2d.canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import javax.swing.JComponent;
import org.geotoolkit.display.container.GraphicContainer;
import org.geotoolkit.factory.Hints;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
/**
* Canvas directly painting on a swing component.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class J2DCanvasSwing extends J2DCanvas{
private final JComponent component = new J2DComponent();
private Envelope wishedEnvelope = null;
public J2DCanvasSwing(final CoordinateReferenceSystem crs){
this(crs,null);
}
public J2DCanvasSwing(final CoordinateReferenceSystem crs, final Hints hints){
super(crs,hints);
component.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
setDisplayBounds(new Rectangle(component.getWidth(), component.getHeight()));
if(!component.getBounds().isEmpty()){
//first time we affect the size
if(wishedEnvelope!=null){
try {
setVisibleArea(wishedEnvelope);
} catch (NoninvertibleTransformException ex) {
getLogger().log(Level.SEVERE, null, ex);
} catch (TransformException ex) {
getLogger().log(Level.SEVERE, null, ex);
}
wishedEnvelope = null;
}
}
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
}
public JComponent getComponent(){
return component;
}
/**
* {@inheritDoc }
*/
@Override
public BufferedImage getSnapShot(){
return null;
}
@Override
public void repaint(final Shape displayArea) {
component.repaint();
}
private void paint(final Graphics2D output, final Shape displayArea){
//finish any previous painting
getMonitor().stopRendering();
final Dimension dim = component.getSize();
monitor.renderingStarted();
fireRenderingStateChanged(RENDERING);
Rectangle clipBounds = output.getClipBounds();
/*
* Sets a flag for avoiding some "refresh()" events while we are actually painting.
* For example some implementation of the GraphicPrimitive2D.paint(...) method may
* detects changes since the last rendering and invokes some kind of invalidate(...)
* methods before the graphic rendering begin. Invoking those methods may cause in some
* indirect way a call to GraphicPrimitive2D.refresh(), which will trig an other widget
* repaint. This second repaint is usually not needed, since Graphics usually managed
* to update their informations before they start their rendering. Consequently,
* disabling repaint events while we are painting help to reduces duplicated rendering.
*/
if (clipBounds == null) {
clipBounds = new Rectangle(dim);
}
output.setClip(clipBounds);
output.addRenderingHints(getHints(true));
final RenderingContext2D context = prepareContext(context2D, output,null);
//paint background if there is one.
if(painter != null){
painter.paint(context2D);
}
final GraphicContainer container = getContainer();
if(container != null){
render(context, container.flatten(true));
}
/**
* End painting, erase dirtyArea
*/
fireRenderingStateChanged(ON_HOLD);
monitor.renderingFinished();
}
private final class J2DComponent extends JComponent{
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D output = (Graphics2D) g;
final Shape displayArea = new Rectangle(getSize());
J2DCanvasSwing.this.paint(output, displayArea);
}
}
@Override
public void setVisibleArea(final Envelope env) throws NoninvertibleTransformException, TransformException {
if(component.getBounds().isEmpty()){
//we don't know our size yet, store the information for later
wishedEnvelope = env;
}else{
super.setVisibleArea(env);
}
}
}