//

// StOPMI example for controlling and displaying a motor status

//

// NOTE!!! I've encapsulated 4 classes in one file here.  Normally, you would

// have 4 individual files for each class, but I've placed all classes in 1 file

// for ease of reading!

//

import cern.stopmi.OPGeneric.OPSkel;

import java.util.Vector;

import java.beans.*;

import cern.stopmi.beans.*;

import java.awt.*;

import java.awt.event.*;



/**

 * The Motor class, simply runs in the background, fireing PropertyChange events

 * to all interested listeners.  It also provides a function to 'reset' the

 * counter to zero called reset().

 * Normally this would be _real_ equipment, and not just an counter (Integer)!

 */

class Motor extends Thread{

  transient private Vector listeners = new Vector();

  private Integer motorPosition = new Integer(0);



  public Motor(){

    // simply start a thread that fires property changed events every 1 second

    this.start();

  }

  public void run(){

    // forever!

    while(true){

      try{sleep(1000);}catch(InterruptedException ie){}

      Integer newValue = new Integer(motorPosition.intValue()+1);

      // tell listeners that the motor hsa moved

      firePropertyChange("MOTOR_MOVED",motorPosition,newValue);

      // remember new position for next time

      motorPosition = newValue;

    }

  }



  public void reset(){

    motorPosition = new Integer(0);

  }



// IGNORE THIS - The following 2 functions simple manage the listeners & events

  public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {

    listeners.addElement(listener);

  }

  public void firePropertyChange(String propertyName,

                                 Object oldValue, Object newValue) {

    synchronized (this) {

      Vector targs = (Vector) listeners.clone();

      PropertyChangeEvent evt =

        new PropertyChangeEvent(this, propertyName, oldValue, newValue);



      for (int i = 0; i < targs.size(); i++) {

        PropertyChangeListener t = (PropertyChangeListener)targs.elementAt(i);

        t.propertyChange(evt);

      }

    }

  }

////////////////

}



/**

 * MyPanel contains 2 GUI components.

 * 'text' and 'button'

 */

class MyPanel extends OPPanel{

  public OPTextField text = new OPTextField();

  public OPButton button = new OPButton();



  public MyPanel(){

    button.setText("Click to reset");

    this.setLayout(new BorderLayout());

    add("Center",button);

    add("South",text);

  }

}



/**

 * I want MyController to respond to button presses from MyPanel, and also

 * PropertyChange events from the motor...

 */

class MyController extends cern.stopmi.OPGeneric.OPController

                   implements PropertyChangeListener, ActionListener{

  public void propertyChange(PropertyChangeEvent evt){

    // check its the motor

    if(evt.getSource().getClass() == Motor.class){

      // check its our property

      if(evt.getPropertyName().compareTo("MOTOR_MOVED")==0){

        // get reference to our panel

        MyPanel pan = (MyPanel)(this.getOPPanel(MyPanel.class));

        // access public 'text' variable to set new counter value

        pan.text.setText("Current motor position :: "+evt.getNewValue());

      }

    }

  }



  public void actionPerformed(ActionEvent evt){

    // determine which parent OPPanel of the component who fired the event

    OPPanel caller = this.getOPPanel(evt.getSource());

    // Is it MyPanel?

    if(caller instanceof MyPanel){

      // We can cast it now

      MyPanel pan = (MyPanel)caller;

      // Check it was the button

      if(evt.getSource() == pan.button){

        // Get reference to the motor

        Motor motor = (Motor)(this.getObject(Motor.class));

        // and reset it

        motor.reset();

      }

    }

  }

}



/**

 * Sample application which extends the OP skeleton

 */

public class Main extends OPSkel {

  public Main() {

    // Create new MyPanel, MyController & Motor

    MyPanel pan = new MyPanel();

    MyController contr = new MyController();

    Motor motor = new Motor();



    // add out panel

    this.getContentPane().add("Center",pan);

    this.validate();



    // register MyPanel and Motor with the controller

    contr.addListenersNeeded(pan);

    contr.addObjectReference(motor);

    // explicitely make the controller listen to the motor...

    motor.addPropertyChangeListener(contr);

  }

  public static void main(String[] args) {

    Main main1 = new Main();

  }

}