1 /*** 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that the following conditions are 4 * met : 5 * 6 * . Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * 9 * . Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * . The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: HexagonCanvas.java,v 1.4 2005/09/10 14:06:22 mat007 Exp $ 29 */ 30 31 package jtge.sample.grid; 32 33 import java.awt.Color; 34 import java.awt.Dimension; 35 import java.awt.Graphics; 36 import java.awt.Graphics2D; 37 import java.awt.Image; 38 import java.awt.Point; 39 import java.awt.Polygon; 40 import java.awt.font.FontRenderContext; 41 import java.awt.geom.Rectangle2D; 42 import java.util.Iterator; 43 import javax.swing.JComponent; 44 import jtge.util.grid.Coordinate; 45 import jtge.util.grid.IGrid; 46 import jtge.util.grid.builder.IHexagonBuilder; 47 48 /*** 49 * Displays a grid. 50 * 51 * @author Jean-Laurent 52 * @version $Id: HexagonCanvas.java,v 1.4 2005/09/10 14:06:22 mat007 Exp $ 53 */ 54 public class HexagonCanvas extends JComponent 55 { 56 private static final long serialVersionUID = -8171784620344147733L; 57 /*** 58 * The displayed grid. 59 */ 60 private final IGrid grid; 61 /*** 62 * The associated builder. 63 */ 64 private final IHexagonBuilder builder; 65 /*** 66 * The canvas size in pixels. 67 */ 68 private final int width, height; 69 /*** 70 * The offscreen buffer. 71 */ 72 private Image offscreen; 73 /*** 74 * The current selected coordinate. 75 */ 76 private Coordinate highlight; 77 /*** 78 * The border size in pixels. 79 */ 80 private final int border; 81 82 /*** 83 * Create an hexagon canvas. 84 * 85 * @param grid the grid 86 * @param builder the builder 87 * @param border the border size in pixels 88 */ 89 public HexagonCanvas( final IGrid grid, final IHexagonBuilder builder, final int border ) 90 { 91 this.grid = grid; 92 this.builder = builder; 93 this.border = border; 94 width = builder.computeWidth( grid.getWidth() ) + border * 2; 95 height = builder.computeHeight( grid.getHeight() ) + border * 2; 96 setPreferredSize( new Dimension( width, height ) ); 97 } 98 99 /*** 100 * Convert a point to a coordinate. 101 * 102 * @param point the point to convert 103 * @return the converted coordinate or null if out of the map 104 */ 105 public final Coordinate fromPixel( final Point point ) 106 { 107 final Point translated = (Point)point.clone(); 108 translated.translate( -border, -border ); 109 return builder.fromPixel( translated, grid ); 110 } 111 112 private void drawHighlight( final Graphics gc ) 113 { 114 if( highlight != null ) 115 { 116 gc.setColor( Color.RED ); 117 final Polygon polygon = builder.buildHexagon( highlight ); 118 polygon.translate( border, border ); 119 gc.drawPolygon( polygon ); 120 } 121 } 122 123 /*** 124 * {@inheritDoc} 125 */ 126 protected final void paintComponent( final Graphics gc ) 127 { 128 if( offscreen == null ) 129 offscreen = createOffscreen(); 130 gc.drawImage( offscreen, 0, 0, this ); 131 drawHighlight( gc ); 132 } 133 134 private Image createOffscreen() 135 { 136 final Image image = createImage( width, height ); 137 final Graphics gc = image.getGraphics(); 138 drawBackground( gc ); 139 drawGrid( gc ); 140 gc.dispose(); 141 image.flush(); 142 return image; 143 } 144 145 private void drawGrid( final Graphics gc ) 146 { 147 final Iterator iterator = grid.linearIterator(); 148 while( iterator.hasNext() ) 149 { 150 final Coordinate coordinate = (Coordinate)iterator.next(); 151 final Polygon polygon = builder.buildHexagon( coordinate ); 152 polygon.translate( border, border ); 153 gc.setColor( Color.LIGHT_GRAY ); 154 gc.fillPolygon( polygon ); 155 gc.setColor( Color.BLACK ); 156 gc.drawPolygon( polygon ); 157 drawCoordinate( gc, coordinate, polygon ); 158 } 159 } 160 161 private void drawBackground( final Graphics gc ) 162 { 163 gc.setColor( Color.WHITE ); 164 gc.fillRect( 0, 0, width, height ); 165 } 166 167 private void drawCoordinate( final Graphics gc, final Coordinate coordinate, final Polygon polygon ) 168 { 169 final FontRenderContext context = ((Graphics2D)gc).getFontRenderContext(); 170 final Rectangle2D bounds = getFont().getStringBounds( coordinate.toString(), context ); 171 final Rectangle2D bounds2 = polygon.getBounds2D(); 172 final double x = bounds2.getX() + bounds2.getWidth() / 2 - bounds.getX() - bounds.getWidth() / 2; 173 final double y = bounds2.getY() + bounds2.getHeight() / 2 - bounds.getY() - bounds.getHeight() / 2; 174 gc.drawString( coordinate.toString(), (int)x, (int)y ); 175 } 176 177 /*** 178 * Highlight the given coordinate. 179 * 180 * @param coordinate the coordinate to highlight 181 */ 182 public final void select( final Coordinate coordinate ) 183 { 184 highlight = coordinate; 185 repaint(); 186 } 187 }