package com.revolsys.swing.map.layer.grid; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.util.List; import java.util.Map; import javax.measure.Measure; import javax.measure.unit.NonSI; import javax.swing.Icon; import javax.swing.ImageIcon; import com.revolsys.awt.WebColors; import com.revolsys.collection.map.MapEx; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.geometry.model.GeometryFactory; import com.revolsys.geometry.model.Polygon; import com.revolsys.gis.grid.RectangularMapGrid; import com.revolsys.gis.grid.RectangularMapTile; import com.revolsys.io.BaseCloseable; import com.revolsys.swing.Icons; import com.revolsys.swing.component.Form; import com.revolsys.swing.map.Viewport2D; import com.revolsys.swing.map.layer.AbstractLayerRenderer; import com.revolsys.swing.map.layer.record.style.GeometryStyle; import com.revolsys.swing.map.layer.record.style.TextStyle; import com.revolsys.swing.menu.MenuFactory; import com.revolsys.swing.menu.Menus; import com.revolsys.util.Cancellable; public class GridLayerRenderer extends AbstractLayerRenderer<GridLayer> { static { final MenuFactory menu = MenuFactory.getMenu(GridLayerRenderer.class); Menus.addMenuItem(menu, "layer", "View/Edit Style", "palette", GridLayerRenderer::showProperties, false); } private static final Icon ICON = Icons.getIcon("style_geometry"); private GeometryStyle geometryStyle = new GeometryStyle(); private TextStyle textStyle; private GridLayerRenderer() { super("gridLayerRenderer", "Grid Style"); this.geometryStyle = GeometryStyle.line(WebColors.LightGray); this.geometryStyle.setPolygonFillOpacity(0); this.textStyle = new TextStyle(); this.textStyle.setTextName("[formattedName]"); this.textStyle.setTextSize(Measure.valueOf(12, NonSI.PIXEL)); this.textStyle.setTextPlacementType("auto"); this.textStyle.setTextHorizontalAlignment("center"); this.textStyle.setTextVerticalAlignment("middle"); setIcon(ICON); } public GridLayerRenderer(final GridLayer layer) { this(); setLayer(layer); } public GridLayerRenderer(final Map<String, ? extends Object> properties) { this(); setProperties(properties); } @Override public GridLayerRenderer clone() { final GridLayerRenderer clone = (GridLayerRenderer)super.clone(); if (this.geometryStyle != null) { clone.setGeometryStyle(this.geometryStyle.clone()); } if (this.textStyle != null) { clone.setTextStyle(this.textStyle.clone()); } return clone; } public GeometryStyle getGeometryStyle() { return this.geometryStyle; } @Override public Icon getIcon() { Icon icon = super.getIcon(); if (icon == ICON) { icon = newIcon(); setIcon(icon); } return icon; } public TextStyle getTextStyle() { return this.textStyle; } public Icon newIcon() { final GeometryStyle geometryStyle = getGeometryStyle(); final BufferedImage image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); final Graphics2D graphics = image.createGraphics(); this.textStyle.drawTextIcon(graphics, 8); final Color color = geometryStyle.getLineColor(); graphics.setColor(color); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); final Shape shape = new Rectangle2D.Double(0, 0, 15, 15); graphics.draw(shape); graphics.dispose(); return new ImageIcon(image); } @Override public Form newStylePanel() { return new GridLayerStylePanel(this); } @Override public void propertyChange(final PropertyChangeEvent event) { final Object source = event.getSource(); if (source == this.geometryStyle) { refreshIcon(); } else if (source == this.textStyle) { refreshIcon(); } super.propertyChange(event); } protected void refreshIcon() { final Icon icon = newIcon(); setIcon(icon); } @Override public void render(final Viewport2D viewport, final Cancellable cancellable, final GridLayer layer) { try { final double scaleForVisible = viewport.getScaleForVisible(); if (layer.isVisible(scaleForVisible)) { final BoundingBox boundingBox = viewport.getBoundingBox(); final RectangularMapGrid grid = layer.getGrid(); final List<RectangularMapTile> tiles = grid.getTiles(boundingBox); final Graphics2D graphics = viewport.getGraphics(); if (graphics != null) { final Font font = graphics.getFont(); for (final RectangularMapTile tile : cancellable.cancellable(tiles)) { final BoundingBox tileBoundingBox = tile.getBoundingBox(); final BoundingBox intersectBoundingBox = boundingBox.intersection(tileBoundingBox); if (!intersectBoundingBox.isEmpty()) { final GeometryFactory geometryFactory = viewport.getGeometryFactory(); final Polygon polygon = tile.getPolygon(geometryFactory, 50); try ( BaseCloseable transformCloseable = viewport.setUseModelCoordinates(graphics, true)) { viewport.drawGeometryOutline(polygon, this.geometryStyle); } try ( BaseCloseable transformClosable = viewport.setUseModelCoordinates(false)) { viewport.drawText(tile, polygon, this.textStyle); } } graphics.setFont(font); } } } } catch (final IllegalArgumentException e) { } } public void setGeometryStyle(final GeometryStyle geometryStyle) { this.geometryStyle = geometryStyle; if (this.geometryStyle != null) { this.geometryStyle.removePropertyChangeListener(this); } this.geometryStyle = geometryStyle; if (this.geometryStyle != null) { this.geometryStyle.addPropertyChangeListener(this); } firePropertyChange("geometryStyle", null, geometryStyle); refreshIcon(); } public void setTextStyle(final TextStyle textStyle) { this.textStyle = textStyle; if (this.textStyle != null) { this.textStyle.removePropertyChangeListener(this); } this.textStyle = textStyle; if (this.textStyle != null) { this.textStyle.addPropertyChangeListener(this); } firePropertyChange("textStyle", null, textStyle); refreshIcon(); } @Override public MapEx toMap() { final MapEx map = super.toMap(); addToMap(map, "geometryStyle", this.geometryStyle); addToMap(map, "textStyle", this.textStyle); return map; } }