/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2011, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.swing; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.map.MapContent; import org.geotools.renderer.GTRenderer; import org.geotools.renderer.RenderListener; import org.opengis.feature.simple.SimpleFeature; /** * A rendering task to be run by a {@code RenderingExecutor}. * * @author Michael Bedward * @since 8.0 * * @source $URL$ * @version $Id$ */ public class RenderingTask implements Callable<Boolean>, RenderListener { private final Graphics2D destinationGraphics; private final Rectangle deviceArea; private final ReferencedEnvelope worldArea; private final AffineTransform worldToScreenTransform; private final GTRenderer renderer; private final AtomicBoolean running; private final AtomicBoolean failed; private final AtomicBoolean cancelled; /** * Creates a new rendering task. * * @param mapContent * @param renderer * @param graphics */ public RenderingTask(MapContent mapContent, Graphics2D destinationGraphics, GTRenderer renderer) { if (mapContent == null) { throw new IllegalArgumentException("mapContent must not be null"); } if (renderer == null) { throw new IllegalArgumentException("renderer must not be null"); } if (destinationGraphics == null) { throw new IllegalArgumentException("graphics must not be null"); } this.destinationGraphics = destinationGraphics; this.deviceArea = mapContent.getViewport().getScreenArea(); this.worldArea = mapContent.getViewport().getBounds(); this.worldToScreenTransform = mapContent.getViewport().getWorldToScreen(); this.renderer = renderer; running = new AtomicBoolean(false); failed = new AtomicBoolean(false); cancelled = new AtomicBoolean(false); } public void cancel() { if (running.get()) { renderer.stopRendering(); } cancelled.set(true); } /** * Called by the executor to run this rendering task. * * @return result of the task: completed or failed * @throws Exception */ @Override public Boolean call() throws Exception { if (!cancelled.get()) { try { renderer.addRenderListener(this); running.set(true); renderer.paint(destinationGraphics, deviceArea, worldArea, worldToScreenTransform); } finally { renderer.removeRenderListener(this); running.set(false); } } return !(isFailed() || isCancelled()); } /** * Called by the renderer when each feature is drawn. This * implementation does nothing. * * @param feature the feature just drawn */ @Override public void featureRenderer(SimpleFeature feature) {} /** * Called by the renderer on error * * @param e cause of the error */ @Override public void errorOccurred(Exception e) { running.set(false); failed.set(true); } public boolean isRunning() { return running.get(); } public boolean isFailed() { return failed.get(); } public boolean isCancelled() { return cancelled.get(); } }