package com.igormaznitsa.elife; import com.igormaznitsa.elife.WorldModel.Cell; import java.awt.*; import java.awt.event.*; import java.util.List; import java.util.*; import javax.swing.JComponent; /** * The class implements a visual component allows to show the state of an e-life * world * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @version 1.00 * @see com.igormaznitsa.elife.WorldModel */ public final class ElifeModelViewer extends JComponent implements MouseListener { private static final long serialVersionUID = -6790679443576585996L; private WorldModel WorldModel = null; private static final Color GROUND_COLOR = Color.GREEN; private static final Color GRID_COLOR = Color.BLACK; private final List<ActionListener> actionListeners = new ArrayList<ActionListener>(); private MouseEvent lastMouseEvent; public ElifeModelViewer() { super(); addMouseListener(this); setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); } public final void addActionListener(final ActionListener listener) { if (listener == null) { return; } if (actionListeners.contains(listener)) { return; } actionListeners.add(listener); } public final MouseEvent getLastMouseEvent() { return lastMouseEvent; } public final void removeActionListener(final ActionListener listener) { if (listener == null) { return; } actionListeners.remove(listener); } public final synchronized void setWorldModel(final WorldModel worldModel) { WorldModel p_old = this.WorldModel; this.WorldModel = worldModel; firePropertyChange(TOOL_TIP_TEXT_KEY, p_old, worldModel); repaint(); } @Override protected final synchronized void paintComponent(final Graphics graphics) { final int viewWidth = getWidth(); final int viewHeight = getHeight(); if (viewWidth <= 0 || viewHeight <= 0) { return; } if (this.WorldModel == null) { graphics.setColor(Color.black); graphics.fillRect(WIDTH, WIDTH, viewWidth, viewHeight); graphics.setColor(Color.red); graphics.drawRect(0, 0, viewWidth, viewHeight); graphics.drawLine(0, 0, viewWidth, viewHeight); graphics.drawLine(0, viewHeight, viewWidth, 0); } else { final int i_cellsWidth = this.WorldModel.getColumnNumber(); final int i_cellsHeight = this.WorldModel.getRowNumber(); final Cell[] cellsArray = this.WorldModel.getCellsArray(); final float deltaX = (float) viewWidth / (float) i_cellsWidth; final float deltaY = (float) viewHeight / (float) i_cellsHeight; final int cellWidth = Math.max(1, Math.round(deltaX)); final int cellHeight = Math.max(1, Math.round(deltaY)); graphics.setColor(GROUND_COLOR); graphics.fillRect(0, 0, viewWidth, viewHeight); final int cellLength = cellsArray.length; for (int li = 0; li < cellLength; li++) { final Cell p_cell = cellsArray[li]; final int i_xcell = Math.round(p_cell.cellX * deltaX); final int i_ycell = Math.round(p_cell.cellY * deltaY); graphics.setColor(Color.blue); graphics.fillRect(i_xcell, i_ycell, cellWidth, cellHeight); } graphics.setColor(GRID_COLOR); for (int li = 0; li < i_cellsWidth; li++) { final int outX = Math.round(li * deltaX); graphics.drawLine(outX, 0, outX, viewHeight); } for (int li = 0; li < i_cellsHeight; li++) { final int outY = Math.round(li * deltaY); graphics.drawLine(0, outY, viewWidth, outY); } graphics.setColor(GRID_COLOR); graphics.drawRect(0, 0, viewWidth - 1, viewHeight - 1); // Toolkit.getDefaultToolkit().sync(); } } @Override public void update(final Graphics g) { paintComponent(g); } @Override public void mouseClicked(MouseEvent e) { lastMouseEvent = e; for (final ActionListener listeners : actionListeners) { listeners.actionPerformed(new ActionEvent(this, 0, "CLICKED")); } } @Override public void mousePressed(final MouseEvent e) { lastMouseEvent = e; for (final ActionListener listeners : actionListeners) { listeners.actionPerformed(new ActionEvent(this, 1, "PRESSED")); } } @Override public void mouseReleased(final MouseEvent e) { lastMouseEvent = e; for (final ActionListener listeners : actionListeners) { listeners.actionPerformed(new ActionEvent(this, 2, "RELEASED")); } } public final Point coordToCell(final int coordX, final int coordY) { if (this.WorldModel == null) { return null; } final float calclatedX = (float) getWidth() / this.WorldModel.getColumnNumber(); final float calculatedY = (float) getHeight() / this.WorldModel.getRowNumber(); return new Point((int) (coordX / calclatedX), (int) (coordY / calculatedY)); } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } }