FileDocCategorySizeDatePackage
ThreeX.javaAPI DocExample12001Mon Apr 23 17:09:18 BST 2001Coop7t2

ThreeX.java

package Coop7t2;

//Title:      Creative OO 7 : Threads / Concurrency
//Copyright:  Copyright (c) 2001
//Author:     John Fenton
//Company:    LMU
//Description:Finally contains "the works".

import java.awt.*;
import java.awt.event.*;
import java.math.*;

public class ThreeX
{
	public ThreeX()
	{
		ViewCl presentationObj = new ViewCl();
	}

	public static void main (String[] args)
	{
		ThreeX threeXObj = new ThreeX();
	}
}
		
class ViewCl extends Frame
{
  private ControllerCl dialogueObj;
  private ModelCl applicationObj;
  private Label lab1,lab2,lab3,lab4,lab5;
  private GridBagLayout m;
  private GridBagConstraints con;
  private Panel pan1;
  protected Checkbox cb1;
  protected TextField tf1;
  protected TextField tf2;
  protected TextField tf3;
  protected TextField tf4;
  protected TextField tf5;
  protected Button butStart;
  protected Button butCancel;
  protected Button butStop;

  public ViewCl()
  {
    dialogueObj = new ControllerCl(this);
    applicationObj = new ModelCl(this);
    dialogueObj.getAppObj(applicationObj);
    applicationObj.getDialObj(dialogueObj);
		setSize(700,600);
		setTitle("Three X Plus One Application");
		drawInterface();
		addWindowListener(new WindowAdapter()
		{
			public void windowClosing (WindowEvent we)
			{
				System.exit(0);
			}
		});
		setVisible(true);
    setCaret();
  }

	public void drawInterface()
	{
      m = new GridBagLayout();
      pan1 = new Panel();
      lab1 = new Label("Enter number to try:");
      con = new GridBagConstraints();
      con.gridx = 0;
      con.gridy = 0;
      con.gridwidth = GridBagConstraints.REMAINDER;
      con.ipady = 20;
      con.anchor = GridBagConstraints.WEST;
      m.setConstraints(lab1,con);
      tf1 = new TextField(50);
      tf1.setEditable(true);
      tf1.addActionListener(dialogueObj);
      con.gridx = 0;
      con.gridy = 1;
      con.ipady = 5;
      con.weightx = 0.5;
      con.fill = GridBagConstraints.HORIZONTAL;
      m.setConstraints(tf1,con);
      butStart = new Button("   Start   ");
      butStart.addActionListener(dialogueObj);
      con.gridx = 1;
      con.gridy = 2;
      con.gridwidth = 1;
      con.fill = GridBagConstraints.NONE;
      con.anchor = GridBagConstraints.WEST;
      con.insets = new Insets(10,10,10,10);
      m.setConstraints(pan1,con);
      butStart.setBackground(new Color(192,255,192));
      pan1.add(butStart);
      butCancel = new Button("Cancel");
      butCancel.addActionListener(dialogueObj);
      butCancel.setBackground(new Color(192,192,224));
      pan1.add(butCancel);
      butStop = new Button("   Stop   ");
      butStop.addActionListener(dialogueObj);
      butStop.setBackground(new Color(224,192,192));
      pan1.add(butStop);
      cb1 = new Checkbox("Automatically increment",false);
      pan1.add(cb1);
      con.insets = new Insets(0,0,0,0);
      lab2 = new Label("Current number being tested : ");
      con.gridx = 0;
      con.gridy = 3;
      con.ipady = 20;
      con.gridwidth = GridBagConstraints.REMAINDER;
      con.anchor = GridBagConstraints.WEST;
      m.setConstraints(lab2,con);
      tf2 = new TextField(50);
      tf2.setEditable(false);
      con.gridy = 4;
      con.ipady = 5;
      con.fill = GridBagConstraints.HORIZONTAL;
      m.setConstraints(tf2,con);
      lab3 = new Label("Largest number generated (on current number) so far: ");
      con.gridy = 5;
      con.ipady = 20;
      con.gridwidth = GridBagConstraints.REMAINDER;
      con.anchor = GridBagConstraints.WEST;
      m.setConstraints(lab3,con);
      tf3 = new TextField(50);
      tf3.setEditable(false);
      con.gridy = 6;
      con.ipady = 5;
      m.setConstraints(tf3,con);
      lab4 = new Label("Smallest number generated (on current number) so far : ");
      con.gridy = 7;
      con.ipady = 20;
      m.setConstraints(lab4,con);
      tf4 = new TextField(50);
      con.gridy = 8;
      con.ipady = 5;
      m.setConstraints(tf4,con);
      lab5 = new Label("Total number of iterations : ");
      con.gridy = 9;
      con.ipady = 20;
      con.gridwidth = GridBagConstraints.REMAINDER;
      con.anchor = GridBagConstraints.WEST;
      m.setConstraints(lab5,con);
      tf5 = new TextField(50);
      tf5.setEditable(false);
      //con.gridx = 0;
      con.gridy = 10;
      con.ipady = 5;
      m.setConstraints(tf5,con);
      setLayout(m);
      add(lab1);
      add(tf1);
      add(pan1);
      add(lab2);
      add(tf2);
      add(lab3);
      add(tf3);
      add(lab4);
      add(tf4);
      add(lab5);
      add(tf5);
	}

  public void setCaret()
  {
    tf1.setCaretPosition(0);
    tf1.requestFocus();
  }

  public void clearStartingNumber()
  {
     tf1.setText("");
     setCaret();
  }

  public String getData()
  {
    String s = tf1.getText();
    return s;
  }
}

class ControllerCl implements ActionListener
{
  private ViewCl viewObj;
  private ModelCl appObj;
  public Thread workingThread1; //..............................(3)
  public Thread workingThread2;

  public ControllerCl(ViewCl vO)
  {
    viewObj = vO;
  }

  public void getAppObj(ModelCl mO)
  {
    appObj = mO;
  }

  public void actionPerformed(ActionEvent ae)
  {
    boolean validData;
    if(ae.getSource() == viewObj.butStart)
    {
       validData = appObj.getAndValidateData();
       if (validData == true)
       {
          appObj.initialise();
          if (viewObj.cb1.getState() == true)
          {
            if (workingThread1 == null)
            {
              workingThread1 = new Thread(appObj,"Thread1");//................(4)
              workingThread1.start(); //............................(5)
            //appObj.repeatedlyCalculate();
            }
          }
          else
          {
            workingThread2 = new Thread(appObj,"Thread2");
            workingThread2.start();
          }
       }
    }
    if(ae.getSource() == viewObj.tf1)
    {
       String mess = "Please press the Start button when ready";
       MessageDialogue md = new MessageDialogue(viewObj, mess);
       md.show();
    }
    if(ae.getSource() == viewObj.butCancel)
    {
       viewObj.clearStartingNumber();
       viewObj.setCaret();
    }
    if(ae.getSource() == viewObj.butStop)
    {
       appObj.stopProcessing();
       if ((workingThread1 != null) && (workingThread1.isAlive()))
       {
         workingThread1 = null; //............................(6)
       }
       if ((workingThread2 != null) && (workingThread2.isAlive()))
       {
         workingThread2 = null; //............................(6)
       }
    }
  }
}

class ModelCl implements Runnable  //..................(1)
{
  private String startingNumStr,biggestSoFarStr,smallestSoFarStr,itsStr,workingNumStr;
  private BigInteger startingNumBI,biggestSoFarBI,smallestSoFarBI,workingBI;
  private BigInteger copyOfBI,anotherCopyOfBI,itsBI;
  private final BigInteger oneBI = BigInteger.ONE;  //quicker without this?
  private final BigInteger zeroBI = BigInteger.ZERO;
  protected ViewCl viewObj;
  protected ControllerCl dialObj;
  private boolean carryOn;

  public ModelCl(ViewCl vO)
  {
    viewObj = vO;
  }

  public void getDialObj(ControllerCl cO)
  {
    dialObj = cO;
  }

  public boolean getAndValidateData( )
  {
    try
    {
       startingNumStr = viewObj.getData( );
       startingNumStr.trim();
       if (startingNumStr.equals(""))
       {
          throw new NoDataException( );
       }
    }
    catch (NoDataException nde)
    {
        String mess = "No data entered!";
        MessageDialogue md = new MessageDialogue(viewObj, mess);
        md.show();
        return false;
    }

    try
    {
       startingNumBI = new BigInteger(startingNumStr);
    }
    catch (NumberFormatException nfe)
    {
       String mess = "Not a valid number";
       MessageDialogue md = new MessageDialogue(viewObj, mess);
       md.show();
       return false;
    }

    int i = startingNumBI.signum();
    if ( i < 1 )
    {
        String mess = "Must be a positive number greater than 0";
        MessageDialogue md = new MessageDialogue(viewObj, mess);
        md.show();
        return false;
    }
    carryOn = true;
    return true;
  }

  public void initialise()
  {
    viewObj.tf2.setText(startingNumStr);
    biggestSoFarStr = startingNumStr;
    viewObj.tf3.setText(biggestSoFarStr);
    smallestSoFarStr = startingNumStr;
    viewObj.tf4.setText(smallestSoFarStr);
    biggestSoFarBI = startingNumBI;
    smallestSoFarBI = startingNumBI;
    workingBI = startingNumBI;
    itsBI = zeroBI;
  }

  public void reinitialise()
  {
    workingBI = anotherCopyOfBI.add(oneBI);
    workingNumStr = workingBI.toString();
    viewObj.tf2.setText(workingNumStr);
    biggestSoFarStr = workingNumStr;
    viewObj.tf3.setText(biggestSoFarStr);
    smallestSoFarStr = workingNumStr;
    viewObj.tf4.setText(smallestSoFarStr);
    biggestSoFarBI = workingBI;
    smallestSoFarBI = workingBI;
    itsBI = zeroBI;
  }

  public void stopProcessing()
  {
    carryOn = false;
  }

  public void run() //.....................................(2)
  {
    //calculate();
    if (Thread.currentThread() == dialObj.workingThread1)
    {
      repeatedlyCalculate();
    }
    if (Thread.currentThread() == dialObj.workingThread2)
    {
      calculate();
    }
  }

  public void repeatedlyCalculate()
  {
    calculate();
    do
    {
      reinitialise();
      calculate();
    } while (carryOn == true);
  }


  public void calculate()
  {
    anotherCopyOfBI = workingBI;
    while((workingBI.equals(oneBI) != true) && (carryOn == true))
    {
      copyOfBI = workingBI;
      if((workingBI.testBit(0)) != false) //if bit0 not 0 it's odd
      {
        workingBI = workingBI.shiftLeft(1);
        workingBI = workingBI.add(copyOfBI); //*3
        workingBI = workingBI.add(oneBI);    //+1
        int comp = workingBI.compareTo(biggestSoFarBI);
        if (comp == 1)
        {
          biggestSoFarBI = workingBI;
          biggestSoFarStr = biggestSoFarBI.toString();
          viewObj.tf3.setText(biggestSoFarStr);
        }
      }
      else
      {
        workingBI = workingBI.shiftRight(1); // it's even so divide by 2
        int comp = workingBI.compareTo(smallestSoFarBI);
        if (comp == -1)
        {
          smallestSoFarBI = workingBI;
          smallestSoFarStr = smallestSoFarBI.toString();
          viewObj.tf4.setText(smallestSoFarStr);
        }
      }
      itsBI = itsBI.add(oneBI);
      itsStr = itsBI.toString();
      viewObj.tf5.setText(itsStr);
      //try
      //{
      // Thread.sleep(500); //allow user time to read data
      //}
      //catch(InterruptedException ie)
      //{
      //}
    }
  }
}

class NoDataException extends Exception
{
   public NoDataException()
   {
   }
}

class MessageDialogue extends Dialog implements ActionListener
{
  Button okBut;
  Label messageLab,blank1,blank2;

  public MessageDialogue(Frame parent, String message)
  {
    super(parent, "Error, error :", true); //true = modal
    messageLab = new Label(message);
    add(messageLab, BorderLayout.NORTH);
    blank1 = new Label("                    ");
    add(blank1,BorderLayout.WEST);
    blank2 = new Label("                    ");
    add(blank2, BorderLayout.EAST);
    okBut = new Button("OK");
    okBut.addActionListener(this);
    add(okBut, BorderLayout.CENTER);
    pack();
    Point p = parent.getLocationOnScreen();
    p.translate(parent.getSize().width/2-120,parent.getSize().height/2-50);
    setLocation(p);
  }
  public void actionPerformed(ActionEvent ae)
  {
    setVisible(false);
  }
}//end of program