Channels for Inter-Applet Communication
by Steve Ball and John Miller Crawford

Listing One
class Origin {
    public void set(int value) { this.value = value; }
    public int get() { return value; }

    public final static int US = 0;
    public final static int UK = 1;
    public final static int NZ = 2;

    private static int value = US;
}

Listing Two
public class Scribble extends Applet {
    public Scribble() {}
    public void init() {
        setBackground(Color.white);
    }
    public void paint(Graphics g) {
        for (int i = 0; i < lines.size(); ++i)
            drawLine(g, (Line) lines.elementAt(i));
    }
    public boolean mouseDown(Event evt, int x, int y) {
        start = new Point(x, y);
        return true;
    }
    public boolean mouseDrag(Event evt, int x, int y) {
        Line line = new Line(start.x, 
                          start.y, x, y, Palette.getPaletteColor());
        lines.addElement(line);
        drawLine(getGraphics(), line);
        start = new Point(x, y);
        return true;
    }
    private void drawLine(Graphics g, Line line) {
        g.setColor(line.color);
        for (int dx = -1; dx <= 1; ++dx)
            for (int dy = -1; dy <= 1; ++dy)
                g.drawLine(line.x1 + dx, line.y1 + dy, 
                                    line.x2 + dx, line.y2 + dy);
    }
    private Vector lines = new Vector();
    private Point start;
}
class Line extends Rectangle {
    Line(int x1, int y1, int x2, int y2, Color color) {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.color = color;
    }
    int x1, y1, x2, y2;
    Color color;
}
public class Palette extends Applet implements Runnable {
    public Palette() {}
    public void init() {
        size = size();
    }
    public void start() {
        if (selector == null)
            (selector = new Thread(this)).start();
    }
    public void stop() {
        if (selector != null) {
            selector.stop();
            selector = null;
        }
    }
    public void paint(Graphics g) {
        synchronized (colorLock) {
            for (int sqx = 0; sqx < NB_COLUMNS; ++sqx)
                for (int sqy = 0; sqy < NB_ROWS; ++sqy)
                    drawColorSquare(g, sqy * NB_COLUMNS + sqx);
            updateSelection();
        }
    }
    public boolean mouseDown(Event evt, int x, int y) {
        int sqx = x * NB_COLUMNS / size.width;
        int sqy = y * NB_ROWS / size.height;
        if (sqx >= 0 && sqx < NB_COLUMNS && sqy >= 0 && sqy < NB_ROWS)
            synchronized (colorLock) {
                color = colors[colorIndex = sqy * NB_COLUMNS + sqx];
                try {
                    colorLock.notifyAll();
                } catch (InterruptedException e) {
                }
            }
        return true;
    }
    public void run() {
        synchronized (colorLock) {
            for (;;) {
                updateSelection();
                try {
                    colorLock.wait();
                } catch (InterruptedException e) {
                }
            }
        }
    }
    public static Color getPaletteColor() {return color;}
    private void updateSelection() {
      Graphics g=getGraphics();
      drawColorSquare(g,selectedColor);            // remove old selection
      drawColorSquare(g,selectedColor=colorIndex); // highlight new selection
      g.dispose();
    }
    private void drawColorSquare(Graphics g, int index) {
        // must synchronize on colorLock before calling this function
        int sqx = index % NB_COLUMNS;
        int sqy = index / NB_COLUMNS;
        int x1 = sqx * size.width / NB_COLUMNS;
        int x2 = (sqx + 1) * size.width / NB_COLUMNS;
        int y1 = sqy * size.height / NB_ROWS;
        int y2 = (sqy + 1) * size.height / NB_ROWS;

        g.setColor(colors[index]);
        g.fillRect(sqx * size.width / NB_COLUMNS, sqy * size.height / 
                                             NB_ROWS, x2 - x1, y2 - y1);
        g.setColor(index == colorIndex ? Color.white : Color.black);
        g.drawRect(x1, y1, x2 - x1 - 1, y2 - y1 - 1);
    }
    private Dimension size;
    private Thread selector;
    private int selectedColor;
    private static final int NB_COLUMNS = 18;
    private static final int NB_ROWS = 12;
    private static Color[] colors = new Color[216]; // const
    private static Object colorLock = new Object();
    private static Color color;
    private static int colorIndex;  // index of color in colors array

    static {
        for (int i = 0; i < 216; ++i) {
            int red = i / 36 * 0x33;
            int green = i / 6 % 6 * 0x33;
            int blue = i % 6 * 0x33;
            colors[i] = new Color(red, green, blue);
        }
        color = colors[colorIndex = 0];
    }
}

3


