Game-of-Life-WSU-CEG4180  v0.1
RefactoringtheGameofLife
CellGridCanvas.java
Go to the documentation of this file.
1 /* This page is part of the Game of Life source code */
2 
3 /**
4  * Copyright 1996-2004 Edwin Martin <edwin@bitstorm.nl>
5  * @author Edwin Martin
6  */
7 
8 package org.bitstorm.gameoflife;
9 
10 import java.awt.Canvas;
11 import java.awt.Color;
12 import java.awt.Dimension;
13 import java.awt.Graphics;
14 import java.awt.Image;
15 import java.awt.event.ComponentEvent;
16 import java.awt.event.ComponentListener;
17 import java.awt.event.MouseAdapter;
18 import java.awt.event.MouseEvent;
19 import java.awt.event.MouseMotionAdapter;
20 import java.util.Enumeration;
21 import java.util.Vector;
22 
23 /**
24  * Subclass of Canvas, which makes the cellgrid visible.
25  * Communicates via CellGrid interface.
26  * @author Edwin Martin
27  */
28 public class CellGridCanvas extends Canvas {
29  private boolean cellUnderMouse;
30  /**
31  * Image for double buffering, to prevent flickering.
32  */
33  private Image offScreenImage;
34  private Graphics offScreenGraphics;
35  private Image offScreenImageDrawed;
36  /**
37  * Image, containing the drawed grid.
38  */
39  private Graphics offScreenGraphicsDrawed;
40  private int cellSize;
41  private CellGrid cellGrid;
42  private Vector listeners;
43  private int newCellSize;
44  private Shape newShape;
45 
46  /**
47  * Constructs a CellGridCanvas.
48  * @param cellGrid the GoL cellgrid
49  * @param cellSize size of cell in pixels
50  */
51  public CellGridCanvas(CellGrid cellGrid, int cellSize) {
52  this.cellGrid = cellGrid;
53  this.cellSize = cellSize;
54 
55  setBackground(new Color(0x999999));
56 
57  addMouseListener(
58  new MouseAdapter() {
59  public void mouseReleased(MouseEvent e) {
60  draw(e.getX(), e.getY());
61  }
62  public void mousePressed(MouseEvent e) {
63  saveCellUnderMouse(e.getX(), e.getY());
64  }
65  });
66 
67  addMouseMotionListener(new MouseMotionAdapter() {
68  public void mouseDragged(MouseEvent e) {
69  draw(e.getX(), e.getY());
70  }
71  });
72  addComponentListener(
73  new ComponentListener() {
74  public void componentResized(ComponentEvent e) {
75  resized();
76  repaint();
77  }
78  public void componentMoved(ComponentEvent e) {}
79  public void componentHidden(ComponentEvent e) {}
80  public void componentShown(ComponentEvent e) {}
81  }
82  );
83 
84  }
85 
86  /**
87  * Set cell size (zoom factor)
88  * @param cellSize Size of cell in pixels
89  */
90  public void setCellSize( int cellSize ) {
91  this.cellSize = cellSize;
92  resized();
93  repaint();
94  }
95 
96  /**
97  * The grid is resized (by window resize or zooming).
98  * Also apply post-resize properties when necessary
99  */
100  public void resized() {
101  if ( newCellSize != 0 ) {
102  cellSize = newCellSize;
103  newCellSize = 0;
104  }
105  Dimension canvasDim = this.size();
106  offScreenImage = null;
107  offScreenImageDrawed = null;
108  cellGrid.resize(canvasDim.width/cellSize, canvasDim.height/cellSize);
109  if ( newShape != null ) {
110  try {
111  setShape( newShape );
112  } catch (ShapeException e) {
113  // ignore
114  }
115  }
116 
117  }
118 
119  /**
120  * Remember state of cell for drawing.
121  *
122  * @param x x-coordinate
123  * @param y y-coordinate
124  */
125  public void saveCellUnderMouse(int x, int y) {
126  try {
127  cellUnderMouse = cellGrid.getCell(x / cellSize, y / cellSize);
128  } catch (java.lang.ArrayIndexOutOfBoundsException e) {
129  // ignore
130  }
131  }
132 
133  /**
134  * Draw in this cell.
135  *
136  * @param x x-coordinate
137  * @param y y-coordinate
138  */
139  public void draw(int x, int y) {
140  try {
141  cellGrid.setCell(x / cellSize, y / cellSize, !cellUnderMouse );
142  repaint();
143  } catch (java.lang.ArrayIndexOutOfBoundsException e) {
144  // ignore
145  }
146  }
147 
148  /**
149  * Use double buffering.
150  * @see java.awt.Component#update(java.awt.Graphics)
151  */
152  public void update(Graphics g) {
153  Dimension d = getSize();
154  if ((offScreenImage == null)) {
155  offScreenImage = createImage(d.width, d.height);
156  offScreenGraphics = offScreenImage.getGraphics();
157  }
158  paint(offScreenGraphics);
159  g.drawImage(offScreenImage, 0, 0, null);
160  }
161 
162  /**
163  * Draw this generation.
164  * @see java.awt.Component#paint(java.awt.Graphics)
165  */
166  public void paint(Graphics g) {
167  // Draw grid on background image, which is faster
168  if (offScreenImageDrawed == null) {
169  Dimension dim = cellGrid.getDimension();
170  Dimension d = getSize();
171  offScreenImageDrawed = createImage(d.width, d.height);
172  offScreenGraphicsDrawed = offScreenImageDrawed.getGraphics();
173  // draw background (MSIE doesn't do that)
174  offScreenGraphicsDrawed.setColor(getBackground());
175  offScreenGraphicsDrawed.fillRect(0, 0, d.width, d.height);
176  offScreenGraphicsDrawed.setColor(Color.gray);
177  offScreenGraphicsDrawed.fillRect(0, 0, cellSize * dim.width - 1, cellSize * dim.height - 1);
178  offScreenGraphicsDrawed.setColor(getBackground());
179  for (int x = 1; x < dim.width; x++) {
180  offScreenGraphicsDrawed.drawLine(x * cellSize - 1, 0, x * cellSize - 1, cellSize * dim.height - 1);
181  }
182  for (int y = 1; y < dim.height; y++) {
183  offScreenGraphicsDrawed.drawLine( 0, y * cellSize - 1, cellSize * dim.width - 1, y * cellSize - 1);
184  }
185  }
186  g.drawImage(offScreenImageDrawed, 0, 0, null);
187  // draw populated cells
188  g.setColor(Color.yellow);
189  Enumeration enum = cellGrid.getEnum();
190  Cell c;
191  while ( enum.hasMoreElements() ) {
192  c = (Cell)enum.nextElement();
193  g.fillRect(c.col * cellSize, c.row * cellSize, cellSize - 1, cellSize - 1);
194  }
195  }
196 
197  /**
198  * This is the preferred size.
199  * @see java.awt.Component#getPreferredSize()
200  */
201  public Dimension getPreferredSize() {
202  Dimension dim = cellGrid.getDimension();
203  return new Dimension( cellSize * dim.width, cellSize * dim.height );
204  }
205 
206  /**
207  * This is the minimum size (size of one cell).
208  * @see java.awt.Component#getMinimumSize()
209  */
210  public Dimension getMinimumSize() {
211  return new Dimension( cellSize, cellSize );
212  }
213 
214  /**
215  * Settings to appy after a window-resize.
216  * @param newShape new shape
217  * @param newCellSize new cellSize
218  */
219  public void setAfterWindowResize( Shape newShape, int newCellSize ) {
220  this.newShape = newShape;
221  this.newCellSize = newCellSize;
222  }
223 
224  /**
225  * Draws shape in grid.
226  *
227  * @param shape name of shape
228  * @return true when shape fits, false otherwise
229  * @throws ShapeException if the shape does not fit on the canvas
230  */
231  public synchronized void setShape(Shape shape) throws ShapeException {
232  int xOffset;
233  int yOffset;
234  int[][] shapeGrid;
235  Dimension dimShape;
236  Dimension dimGrid;
237  int i;
238 
239  // get shape properties
240  //shapeGrid = shape.getShape();
241  dimShape = shape.getDimension();
242  dimGrid = cellGrid.getDimension();
243 
244  if (dimShape.width > dimGrid.width || dimShape.height > dimGrid.height)
245  throw new ShapeException( "Shape doesn't fit on canvas (grid: "+dimGrid.width+"x"+dimGrid.height+", shape: "+dimShape.width+"x"+dimShape.height+")"); // shape doesn't fit on canvas
246 
247  // center the shape
248  xOffset = (dimGrid.width - dimShape.width) / 2;
249  yOffset = (dimGrid.height - dimShape.height) / 2;
250  cellGrid.clear();
251 
252  // draw shape
253  Enumeration cells = shape.getCells();
254  while (cells.hasMoreElements()) {
255  int[] cell = (int[]) cells.nextElement();
256  cellGrid.setCell(xOffset + cell[0], yOffset + cell[1], true);
257  }
258 
259  }
260 }
void setCell(int col, int row, boolean cell)
synchronized void setShape(Shape shape)
boolean getCell(int col, int row)
void setAfterWindowResize(Shape newShape, int newCellSize)
CellGridCanvas(CellGrid cellGrid, int cellSize)
void resize(int col, int row)