Design Pattern Java

/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
 * MVC Implementation
 * 
 * @author Ian Darwin, http://www.darwinsys.com/
 * @version $Id: MVCDemo.java,v 1.3 2004/03/21 00:44:36 ian Exp $
 */
public class MVCDemo {
  /** "main program" method - construct and show */
  public static void main(String[] av) {
    // Create the data model
    final Model model = new Model();
    // create a JFrame to hold it all.
    final JFrame f = new JFrame("MVC");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container cp = f.getContentPane();
    JPanel tp = new JPanel();
    cp.add(tp, BorderLayout.NORTH);
    tp.add(new JLabel("New value:"));
    final JTextField tf = new JTextField(10);
    tp.add(tf);
    tf.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        model.add(tf.getText());
        tf.setText("");
      }
    });
    JPanel p = new JPanel();
    // The first View is a JTextArea subclassed to have
    // an easy way of setting the data from a java.util.List
    final TextView tv = new TextView();
    model.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        Object o = evt.getSource();
        Model m = (Model) o;
        tv.setListData(m.getData());
      }
    });
    tv.setBackground(Color.RED);
    tv.setSize(100, 100);
    p.add(tv);
    // The second View is the simplistic Grapher program from
    // the Java Cookbook "Graphics" chapter (../graphics/Grapher.java)
    final Grapher vv = new Grapher();
    model.addChangeListener(new ChangeListener() {
      public void stateChanged(ChangeEvent evt) {
        Object o = evt.getSource();
        Model m = (Model) o;
        vv.setListData(m.getData());
      }
    });
    vv.setBackground(Color.YELLOW);
    vv.setSize(100, 100);
    p.add(vv);
    cp.add(p, BorderLayout.CENTER);
    f.pack();
    f.setLocation(100, 100);
    f.setVisible(true);
  }
}
class TextView extends JTextArea {
  public TextView() {
    super(20, 20);
  }
  public void setListData(ArrayList l) {
    setText("");
    for (int i = 0; i < l.size(); i++) {
      append((String) l.get(i));
      append("\n");
    }
  }
}
class Model {
  private ArrayList list = new ArrayList();
  public void add(String s) {
    list.add(s);
    fireChange();
  }
  public ArrayList getData() {
    return list;
  }
  // Sun recommends using javax.swing.EventListenerList, but this is easier
  ArrayList changeListeners = new ArrayList();
  public void addChangeListener(ChangeListener cl) {
    changeListeners.add(cl);
  }
  public void removeChangeListener(ChangeListener cl) {
    changeListeners.remove(cl);
  }
  protected void fireChange() {
    ChangeEvent evt = new ChangeEvent(this);
    for (int i = 0; i < changeListeners.size(); i++) {
      ChangeListener cl = (ChangeListener) changeListeners.get(i);
      cl.stateChanged(evt);
    }
  }
}
class Grapher extends JPanel {
  /** Multiplier for range to allow room for a border */
  public final static double BORDERFACTOR = 1.1f;
  /** The list of Point points. */
  protected ArrayList data;
  /** The minimum and maximum X values */
  protected double minx = Integer.MAX_VALUE, maxx = Integer.MIN_VALUE;
  /** The minimum and maximum Y values */
  protected double miny = Integer.MAX_VALUE, maxy = Integer.MIN_VALUE;
  /** The range of X and Y values */
  protected double xrange, yrange;
  public Grapher() {
    data = new ArrayList();
    figure();
  }
  /**
   * Set the list data from a list of Strings, where the x coordinate is
   * incremented automatically, and the y coordinate is made from the String
   * in the list.
   */
  public void setListDataFromYStrings(ArrayList newData) {
    data.clear();
    for (int i = 0; i < newData.size(); i++) {
      Point2D p = new Point2D.Double();
      p.setLocation(i, java.lang.Double.parseDouble((String) newData
          .get(i)));
      data.add(p);
    }
    figure();
  }
  /** Set the list from an existing List, as from GraphReader.read() */
  public void setListData(ArrayList newData) {
    data = newData;
    figure();
  }
  /** Compute new data when list changes */
  private void figure() {
    // find min & max
    for (int i = 0; i < data.size(); i++) {
      Point2D d = (Point2D) data.get(i);
      if (d.getX() < minx)
        minx = d.getX();
      if (d.getX() > maxx)
        maxx = d.getX();
      if (d.getY() < miny)
        miny = d.getY();
      if (d.getY() > maxy)
        maxy = d.getY();
    }
    // Compute ranges
    xrange = (maxx - minx) * BORDERFACTOR;
    yrange = (maxy - miny) * BORDERFACTOR;
  }
  /**
   * Called when the window needs painting. Computes X and Y range, scales.
   */
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Dimension s = getSize();
    if (data.size() < 2) {
      g.drawString("Insufficient data: " + data.size(), 10, 40);
      return;
    }
    // Compute scale factors
    double xfact = s.width / xrange;
    double yfact = s.height / yrange;
    // Scale and plot the data
    for (int i = 0; i < data.size(); i++) {
      Point2D d = (Point2D) data.get(i);
      double x = (d.getX() - minx) * xfact;
      double y = (d.getY() - miny) * yfact;
      // Draw a 5-pixel rectangle centered, so -2 both x and y.
      // AWT numbers Y from 0 down, so invert:
      g.drawRect(((int) x) - 2, s.height - 2 - (int) y, 5, 5);
    }
  }
  public Dimension getPreferredSize() {
    return new Dimension(150, 150);
  }
  public static void main(String[] args) throws IOException {
    final JFrame f = new JFrame("Grapher");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Grapher grapher = new Grapher();
    f.setContentPane(grapher);
    f.setLocation(100, 100);
    f.pack();
    ArrayList data = new ArrayList();
        data.add("a");
    grapher.setListData(data);
    f.setVisible(true);
  }
}