/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.geotools.swing; import java.awt.Graphics2D; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; 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}. */ public class RenderingTask implements Callable<RenderingTask.Status>, RenderListener { private static long NEXT_ID = 1L; /** * Constants to indicate the result of a rendering task */ public static enum Status { PENDING, COMPLETED, CANCELLED, FAILED; } private final long taskId; private final MapContent mapContent; private final GTRenderer renderer; private final Graphics2D graphics; private final AtomicBoolean running; private final AtomicBoolean cancelled; private final AtomicBoolean failed; private long numFeaturesRendered; /** * Creates a new rendering task. * * @param mapContent * @param renderer * @param graphics */ public RenderingTask(MapContent mapContent, GTRenderer renderer, Graphics2D graphics) { if (mapContent == null) { throw new IllegalArgumentException("mapContent must not be null"); } if (renderer == null) { throw new IllegalArgumentException("renderer must not be null"); } if (graphics == null) { throw new IllegalArgumentException("graphics must not be null"); } this.taskId = NEXT_ID++; this.mapContent = mapContent; this.renderer = renderer; this.graphics = graphics; running = new AtomicBoolean(false); cancelled = new AtomicBoolean(false); failed = new AtomicBoolean(false); numFeaturesRendered = 0; } /** * Gets the unique ID value assigned to this task. * * @return ID value */ public long getId() { return taskId; } /** * Called by the executor to run this rendering task. * * @return result of the task: completed, cancelled or failed * @throws Exception */ public Status call() throws Exception { if (!isCancelled()) { try { renderer.addRenderListener(this); running.set(true); renderer.paint(graphics, mapContent.getViewport().getScreenArea(), mapContent.getViewport().getBounds(), mapContent.getViewport().getWorldToScreen()); } finally { renderer.removeRenderListener(this); running.set(false); } } if (isCancelled()) { return Status.CANCELLED; } else if (isFailed()) { return Status.FAILED; } else { return Status.COMPLETED; } } /** * Cancel the rendering task if it is running. If called before * being run the task will be abandoned. */ public synchronized void cancel() { cancelled.set(true); if (isRunning()) { renderer.stopRendering(); running.set(false); } } /** * Called by the renderer when each feature is drawn. * * @param feature the feature just drawn */ public void featureRenderer(SimpleFeature feature) { numFeaturesRendered++ ; } /** * Called by the renderer on error * * @param e cause of the error */ public void errorOccurred(Exception e) { running.set(false); failed.set(true); } public boolean isRunning() { return running.get(); } public boolean isCancelled() { return cancelled.get(); } public boolean isFailed() { return failed.get(); } }