View Javadoc

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 }