package com.revolsys.swing.map.overlay; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import javax.swing.JComponent; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.raster.BufferedGeoreferencedImage; import com.revolsys.raster.GeoreferencedImage; import com.revolsys.swing.map.MapPanel; import com.revolsys.swing.map.Viewport2D; import com.revolsys.swing.map.layer.BaseMapLayerGroup; import com.revolsys.swing.map.layer.Layer; import com.revolsys.swing.map.layer.LayerRenderer; import com.revolsys.swing.map.layer.NullLayer; import com.revolsys.swing.map.layer.Project; import com.revolsys.swing.map.layer.raster.GeoreferencedImageLayerRenderer; import com.revolsys.swing.map.layer.raster.TiledImageLayerRenderer; import com.revolsys.swing.parallel.Invoke; import com.revolsys.util.Property; /** * <p>A lightweight component that users the {@link Layer}'s {@link LayerRenderer} to render the layer.</p> */ public class LayerRendererOverlay extends JComponent implements PropertyChangeListener { private static final Collection<String> IGNORE_PROPERTY_NAMES = new HashSet<>(Arrays .asList("selectionCount", "hasHighlightedRecords", "highlightedCount", "scale", "loaded")); private static final long serialVersionUID = 1L; private GeoreferencedImage image; private LayerRendererOverlaySwingWorker imageWorker; private Layer layer; private boolean loadImage = true; private final Object loadSync = new Object(); private Viewport2D viewport; public LayerRendererOverlay(final MapPanel mapPanel) { this(mapPanel, null); } public LayerRendererOverlay(final MapPanel mapPanel, final Layer layer) { this.viewport = mapPanel.getViewport(); setLayer(layer); Property.addListener(this.viewport, this); Property.addListener(this, mapPanel); } public void dispose() { if (this.layer != null) { Property.removeListener(this.layer, this); this.layer = null; } Property.removeAllListeners(this); this.image = null; this.imageWorker = null; this.viewport = null; } public Layer getLayer() { return this.layer; } public Project getProject() { return this.layer.getProject(); } public Viewport2D getViewport() { return this.viewport; } @Override public void paintComponent(final Graphics g) { if (!(this.layer instanceof NullLayer)) { GeoreferencedImage image; synchronized (this.loadSync) { image = this.image; if ((image == null || this.loadImage) && this.imageWorker == null) { final BoundingBox boundingBox = this.viewport.getBoundingBox(); final int viewWidthPixels = this.viewport.getViewWidthPixels(); final int viewHeightPixels = this.viewport.getViewHeightPixels(); final GeoreferencedImage loadImage = new BufferedGeoreferencedImage(boundingBox, viewWidthPixels, viewHeightPixels); this.imageWorker = new LayerRendererOverlaySwingWorker(this, loadImage); Invoke.worker(this.imageWorker); } } if (image != null) { render((Graphics2D)g); } } } @Override public void propertyChange(final PropertyChangeEvent e) { if (!(e.getSource() instanceof MapPanel)) { final String propertyName = e.getPropertyName(); if (!IGNORE_PROPERTY_NAMES.contains(propertyName)) { if (this.layer instanceof Project) { if (TiledImageLayerRenderer.TILES_LOADED.equals(propertyName)) { return; } } redraw(); } } } public void redraw() { final Container parent = getParent(); if (getWidth() > 0 && getHeight() > 0) { if (parent != null && parent.isVisible()) { if (this.layer != null && this.layer.isExists() && this.layer.isVisible()) { synchronized (this.loadSync) { this.loadImage = true; if (this.imageWorker != null) { this.imageWorker.cancel(true); this.imageWorker = null; } firePropertyChange("imageLoaded", true, false); } } } } } public void refresh() { if (this.layer != null) { this.layer.refresh(); } } private void render(final Graphics2D graphics) { GeoreferencedImageLayerRenderer.render(this.viewport, graphics, this.image, false); } public void setImage(final LayerRendererOverlaySwingWorker imageWorker) { synchronized (this.loadSync) { if (this.imageWorker == imageWorker) { this.image = imageWorker.getReferencedImage(); if (this.image != null) { this.loadImage = false; this.imageWorker = null; } firePropertyChange("imageLoaded", false, true); } } } public void setLayer(final Layer layer) { final Layer old = this.layer; if (old != layer) { if (old != null) { if (old.getParent() instanceof BaseMapLayerGroup) { old.setVisible(false); } Property.removeListener(old, this); } this.layer = layer; if (layer != null) { Property.addListener(layer, this); if (layer.getParent() instanceof BaseMapLayerGroup) { layer.setVisible(true); } if (layer.isInitialized()) { layer.refresh(); } } this.image = null; redraw(); firePropertyChange("layer", old, layer); } } }