package cellularautomata;
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
public class SimpleApplet extends Applet
{
public static final String VERSION = "1.3";
private ImageCanvas _imageCanvas;
private StateComponentMap _stateMap;
private Label _status;
private Button _drawButton;
private TextField _maxIterField;
private TextField _zoomField;
private ScrollPane _scrollPane;
private StateComponent[] _stateComponents;
private byte[] _colorMap;
public void init()
{
super.init();
Color background = getColorParameter("background", Color.white);
Color foreground = getColorParameter("foreground", Color.black);
_colorMap = new byte[] {(byte)background.getRed(),
(byte)background.getGreen(),
(byte)background.getBlue(),
(byte)foreground.getRed(),
(byte)foreground.getGreen(),
(byte)foreground.getBlue()};
_stateMap = new StateComponentMap(2);
_stateComponents = new StateComponent[8];
initStateComponents();
setBackground(background);
setForeground(foreground);
setLayout(new BorderLayout());
Panel topPanel = new Panel(new GridLayout(2,1));
Panel heightPanel = new Panel(new FlowLayout());
Panel statePanel = new Panel(new FlowLayout());
int maxIter = getWidth()/2;
topPanel.add(heightPanel);
topPanel.add(statePanel);
_imageCanvas = new ImageCanvas(maxIter,1);
_scrollPane = new ScrollPane();
_scrollPane.add(_imageCanvas);
_maxIterField = new TextField(new Integer(maxIter).toString());
_zoomField = new TextField("1.0");
_drawButton = new Button("Redraw!");
heightPanel.add(new Label("zoom:"));
heightPanel.add(_zoomField);
heightPanel.add(
new Label("number of iterations:"));
heightPanel.add(_maxIterField);
heightPanel.add(_drawButton);
statePanel.add(
new Label("automata states (click a state to change):"));
for (int i=0; i<_stateComponents.length; i++)
{
StateComponent component = _stateComponents[i];
statePanel.add(component);
_stateMap.put(component);
}
_status = new Label(
"copyright 2003 (c) Fabien Le Floc'h <fabien@31416.org>");
add(BorderLayout.NORTH,topPanel);
add(BorderLayout.CENTER,_scrollPane);
add(BorderLayout.SOUTH,_status);
}
public boolean action(Event e, Object what)
{
if (e.target == _drawButton)
{
String w = _maxIterField.getText();
String z = _zoomField.getText();
try
{
int maxIter = Integer.parseInt(w);
float zoom = Float.parseFloat(z);
int position = Math.round(maxIter*zoom) -
((int)_scrollPane.getViewportSize().getWidth()/2);
_imageCanvas.setSize(maxIter,zoom);
_imageCanvas.repaint();
_scrollPane.layout();
_scrollPane.setScrollPosition(position,0);
return true;
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
return false;
}
private void initStateComponents()
{
byte w = 0;
byte b = 1;
_stateComponents[0] = new StateComponent(b,b,b,b);
_stateComponents[1] = new StateComponent(b,b,w,b);
_stateComponents[2] = new StateComponent(b,w,b,w);
_stateComponents[3] = new StateComponent(b,w,w,b);
_stateComponents[4] = new StateComponent(w,b,b,b);
_stateComponents[5] = new StateComponent(w,b,w,w);
_stateComponents[6] = new StateComponent(w,w,b,b);
_stateComponents[7] = new StateComponent(w,w,w,w);
}
public String getAppletInfo()
{
return "Simple celullar automata v. " + VERSION +
"Written by F. Le Floc'h <fabien@31416.org>.";
}
protected Color getColorParameter(String name, Color defaultColor)
{
String value = this.getParameter(name);
try
{
return new Color(Integer.parseInt(value, 16));
}
catch (Exception e)
{
return defaultColor;
}
}
public String[][] getParameterInfo()
{
return info;
}
private static final String[][] info =
{
{"foreground", "hexadecimal color value", "foreground color"},
{"background", "hexadecimal color value", "background color"}
};
private class ImageCanvas extends Canvas
{
private Image _image;
private int _maxIter;
private float _zoom;
public ImageCanvas(int maxIter, float zoom)
{
this.setBounds(0,0,maxIter*2,maxIter);
_maxIter = maxIter;
_zoom = zoom;
}
public void setSize(int maxIter, float zoom)
{
_maxIter = maxIter;
_zoom = zoom;
_image = null;
int height = Math.round(maxIter*zoom);
this.setBounds(0,0,2*height,height);
}
public void paint(Graphics g)
{
if (_image == null)
{
System.gc();
int height = Math.round(_maxIter*_zoom);
_image = this.createImage(height*2,height);
}
g.drawImage(_image, 0, 0, this);
}
public Image createImage(int width, int height)
{
int maxX = _maxIter*2;
byte[] pixels = new byte[maxX*_maxIter];
int index = 0;
for (;index<maxX;index++)
{
pixels[index] = 0;
}
pixels[_maxIter] = 1;
for (int y=1; y<_maxIter; y++)
{
pixels[index] = 0;
pixels[index+maxX-1] = 0;
index++;
for (int x=1; x<maxX-1; x++)
{
pixels[index] = _stateMap.get(pixels,index-maxX);
index++;
}
index++;
}
MemoryImageSource mis = new MemoryImageSource(
maxX,_maxIter,
new IndexColorModel(8,2,_colorMap,0,false,-1),
pixels,0,maxX);
mis.setFullBufferUpdates(false);
Image image = super.createImage(mis);
if (_zoom != 1)
{
image = image.getScaledInstance(
width,height,Image.SCALE_SMOOTH);
}
return image;
}
}
private static class StateComponent extends Canvas
{
Image _initialState;
byte _result;
int _width, _height;
byte _left, _middle, _right;
public StateComponent(byte left, byte middle, byte right, byte result)
{
_initialState = null;
_result = result;
_width = 9;
_height = 9;
_left = left;
_middle = middle;
_right = right;
this.setBounds(0,0,3*(_width+1),2*(_height+1));
}
public Image createImage(int width, int height)
{
Image image = super.createImage(width,height);
Graphics g = image.getGraphics();
drawState(g,0,0,_left);
drawState(g,_width,0,_middle);
drawState(g,2*_width,0,_right);
return image;
}
protected void drawState(Graphics g, int x, int y, byte state)
{
g.drawRect(x,y,_width,_height);
if (state > 0)
{
g.fillRect(x,y,_width,_height);
}
}
public byte getLeft()
{
return _left;
}
public byte getMiddle()
{
return _middle;
}
public byte getRight()
{
return _right;
}
public byte getResult()
{
return _result;
}
public void paint(Graphics g)
{
if (_initialState == null)
{
_initialState = this.createImage(3*_width+1,2*_height+1);
}
g.drawImage(_initialState,0,0,this);
drawState(g,_width,_height,_result);
}
public boolean mouseDown(Event e, int x, int y)
{
if (_result == 0) _result =1;
else _result = 0;
repaint();
return true;
}
}
public static class StateComponentMap
{
private int _nbColors;
private int _nbStates;
private StateComponent[][][] _stateTable;
public StateComponentMap(int nbColors)
{
_nbColors = nbColors;
_stateTable = new StateComponent[nbColors][nbColors][nbColors];
}
public int getSize()
{
return _stateTable.length;
}
public void put(StateComponent component)
{
_stateTable[component.getLeft()][component.getMiddle()]
[component.getRight()] = component;
}
public byte get(int left, int middle, int right)
{
return _stateTable[left][middle][right].getResult();
}
public byte get(byte[] lastLine, int i)
{
return get(lastLine[i-1],lastLine[i],lastLine[i+1]);
}
}
}