Mega Code Archive

 
Categories / Java / Design Pattern
 

MVC Implementation

/*  * 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);   } }