/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.examples.conway.ui; import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.ImageIcon; import org.drools.examples.conway.Cell; import org.drools.examples.conway.CellGrid; import org.drools.examples.conway.CellState; public class CellGridCanvas extends Canvas { private static final long serialVersionUID = 510l; private static final Color BACKGROUND_COLOR = Color.gray; private static final Color GRID_COLOR = CellGridCanvas.BACKGROUND_COLOR.brighter(); private Image offScreenImage; private Image backgroundImage; private final int cellSize; private final CellGrid cellGrid; private final Image liveCellImage = new ImageIcon( CellGridCanvas.class.getResource( "/org/drools/examples/conway/liveCellImage.gif" ) ).getImage(); /** * Constructs a CellGridCanvas. * * @param cellGrid * the GoL cellgrid */ public CellGridCanvas(final CellGrid cellGrid) { this.cellGrid = cellGrid; this.cellSize = this.liveCellImage.getWidth( this ); setBackground( CellGridCanvas.GRID_COLOR ); addMouseListener( new MouseAdapter() { /** * Invoked when a mouse button has been pressed on a component. */ public void mousePressed(final MouseEvent e) { toggleCellAt( e.getX(), e.getY() ); } } ); addMouseMotionListener( new MouseMotionAdapter() { public void mouseDragged(final MouseEvent e) { final Cell cell = getCellAtPoint( e.getX(), e.getY() ); if ( cell != null ) { cellGrid.updateCell( cell, CellState.LIVE ); repaint(); } } } ); } private void toggleCellAt(final int x, final int y) { final Cell cell = getCellAtPoint( x, y ); if ( cell != null ) { if ( cell.getCellState() == CellState.LIVE ) { this.cellGrid.updateCell( cell, CellState.DEAD ); } else { this.cellGrid.updateCell( cell, CellState.LIVE ); } repaint(); } } private Cell getCellAtPoint(final int x, final int y) { Cell cell = null; final int column = x / this.cellSize; final int row = y / this.cellSize; final int numberOfColumns = this.cellGrid.getNumberOfColumns(); final int numberOfRows = this.cellGrid.getNumberOfRows(); if ( column >= 0 && column < numberOfColumns && row >= 0 && row < numberOfRows ) { cell = this.cellGrid.getCellAt( row, column ); } return cell; } /** * Use double buffering. * * @see java.awt.Component#update(java.awt.Graphics) */ public void update(final Graphics g) { final Dimension d = getSize(); if ( (this.offScreenImage == null) ) { this.offScreenImage = createImage( d.width, d.height ); } paint( this.offScreenImage.getGraphics() ); g.drawImage( this.offScreenImage, 0, 0, null ); } /** * Draw this generation. * * @see java.awt.Component#paint(java.awt.Graphics) */ public void paint(final Graphics g) { // Draw grid on background image, which is faster final int numberOfColumns = this.cellGrid.getNumberOfColumns(); final int numberOfRows = this.cellGrid.getNumberOfRows(); if ( this.backgroundImage == null ) { final Dimension d = getSize(); this.backgroundImage = createImage( d.width, d.height ); final Graphics backgroundImageGraphics = this.backgroundImage.getGraphics(); // draw background (MSIE doesn't do that) backgroundImageGraphics.setColor( getBackground() ); backgroundImageGraphics.fillRect( 0, 0, d.width, d.height ); backgroundImageGraphics.setColor( CellGridCanvas.BACKGROUND_COLOR ); backgroundImageGraphics.fillRect( 0, 0, this.cellSize * numberOfColumns - 1, this.cellSize * numberOfRows - 1 ); backgroundImageGraphics.setColor( CellGridCanvas.GRID_COLOR ); for ( int x = 1; x < numberOfColumns; x++ ) { backgroundImageGraphics.drawLine( x * this.cellSize - 1, 0, x * this.cellSize - 1, this.cellSize * numberOfRows - 1 ); } for ( int y = 1; y < numberOfRows; y++ ) { backgroundImageGraphics.drawLine( 0, y * this.cellSize - 1, this.cellSize * numberOfColumns - 1, y * this.cellSize - 1 ); } } g.drawImage( this.backgroundImage, 0, 0, null ); // draw populated cells for ( int row = 0; row < numberOfRows; row++ ) { for ( int column = 0; column < numberOfColumns; column++ ) { final Cell cell = this.cellGrid.getCellAt( row, column ); if ( cell.getCellState() == CellState.LIVE ) { g.drawImage( this.liveCellImage, column * this.cellSize, row * this.cellSize, this ); } } } } /** * This is the preferred size. * * @see java.awt.Component#getPreferredSize() */ public Dimension getPreferredSize() { final int numberOfColumns = this.cellGrid.getNumberOfColumns(); final int numberOfRows = this.cellGrid.getNumberOfRows(); return new Dimension( this.cellSize * numberOfColumns, this.cellSize * numberOfRows ); } /** * This is the minimum size (size of one cell). * * @see java.awt.Component#getMinimumSize() */ public Dimension getMinimumSize() { return new Dimension( this.cellSize, this.cellSize ); } }